Documentation
¶
Overview ¶
Package mcpx is a Model Context Protocol (MCP) multiplexer for Go.
It connects to many MCP servers behind a single Multiplexer object and gives the consumer a uniform API to:
- aggregate per-server tool lists (with optional kind-based grouping for prompt generation),
- normalise tool arguments before sending (built-in camelCase / joinArrays / singularResourceType transformers, plus custom ones),
- intercept calls via BeforeCall / AfterCall / ResultTransform / MetaEnricher hooks for policy, observability, sanitisation, and metadata enrichment,
- filter the visible server set per consumer (View) without re-establishing connections.
Three transports are supported out of the box: stdio (subprocess), http (StreamableHTTP), and sse. Authentication is pluggable per outbound HTTP/SSE request: declare an opaque `auth` block per server in JSON, register a single AuthFunc via WithAuthFunc, and dispatch on data["scheme"] inside your function. Subpackage github.com/inhuman/mcp-multiplexer/auth ships ready-made helpers for the two most common shapes (Bearer, custom header).
An opt-in health-check supervisor (WithHealthCheck) pings each server on a configurable interval and reconnects with exponential backoff when a server becomes unreachable. The per-server liveness state is queryable via ServerStatus; CallTool short-circuits with ErrServerDown when a server is marked down, avoiding unnecessary timeouts.
The multiplexer automatically subscribes to notifications/tools/list_changed from each connected server and refreshes the per-server tool cache when the server's tool set changes at runtime (e.g. due to plugins, feature flags, or permission changes). An optional WithOnToolsChanged callback notifies the consumer after each refresh that produces a different tool list.
Per-server call timeouts are supported via ServerConfig.CallTimeout; a zero value inherits the global default set via WithCallTimeout (30 s by default).
Typed observability is available via the Metrics interface (RecordCall, RecordToolList). Register an implementation via WithMetrics; the default is a no-op. Panics inside Metrics methods are recovered by the library. The MCP handshake automatically advertises the consuming module's real version (read from build info); it falls back to "dev" when build info is unavailable. Override both name and version with WithClientIdentity.
The library is logger-agnostic via the Logger interface (4 methods). Adapters for go.uber.org/zap and log/slog are provided as separate packages under log/zaplog and log/sloglog so the core stays dependency-light.
The "singularResourceType" transformer accepts a configurable plural→singular map: extend or override the built-in Kubernetes map globally via WithResourceSingular, or per-server via ServerConfig.ResourceSingular (per-server entries win over global, which in turn wins over built-in).
Runnable examples demonstrating common patterns live in the examples/ directory: examples/basic (multi-server setup), examples/policy (BeforeCallHook gate), and examples/redact (ResultTransformHook PII redaction).
See README.md for usage examples and the project constitution for design principles (zero-dependency core, real-dependency testing, secure defaults).
Index ¶
- Variables
- func BearerRoundTripper(token string, base http.RoundTripper) http.RoundTripper
- func CacheScope(ctx context.Context) string
- func DefaultResourceSingular() map[string]string
- func IsCacheHit(ctx context.Context) bool
- func WithCacheScope(ctx context.Context, scope string) context.Context
- type AfterCallHook
- type ArgsTransformer
- type ArgsTransformers
- type AuthFunc
- type BeforeCallHook
- type Cache
- type CallResult
- type ContentKind
- type ContentPart
- type CustomTransformer
- type ErrInvalidArgs
- type Field
- type KeyFunc
- type KindGroup
- type KindSettings
- type Logger
- type MetaEnricher
- type Metrics
- type Multiplexer
- func (mx *Multiplexer) AllTools() []ToolInfo
- func (mx *Multiplexer) CallTool(ctx context.Context, server, toolName string, argsJSON json.RawMessage) (*CallResult, error)
- func (mx *Multiplexer) Close()
- func (mx *Multiplexer) ConfigHints() map[string][]string
- func (mx *Multiplexer) FilterByNames(names []string) (*View, error)
- func (mx *Multiplexer) KindGroups() []KindGroup
- func (mx *Multiplexer) KindsForServers(names []string) []string
- func (mx *Multiplexer) ServerNames() []string
- func (mx *Multiplexer) ServerStatus() map[string]ServerState
- func (mx *Multiplexer) ToolsForServers(names []string) []ToolInfo
- type MultiplexerConfig
- type OnConnectFunc
- type OnReconnectFunc
- type OnRejectedCallFunc
- type OnToolsChangedFunc
- type Option
- func WithAfterCall(h AfterCallHook) Option
- func WithArgsTransformer(name string, fn CustomTransformer) Option
- func WithAuthFunc(fn AuthFunc) Option
- func WithBeforeCall(h BeforeCallHook) Option
- func WithCache(c Cache) Option
- func WithCacheKey(fn KeyFunc) Option
- func WithCacheSize(n int) Option
- func WithCacheTTL(d time.Duration) Option
- func WithCallTimeout(d time.Duration) Option
- func WithClientIdentity(name, version string) Option
- func WithHTTPRetryMax(n int) Option
- func WithHealthCheck(interval time.Duration) Option
- func WithLogger(l Logger) Option
- func WithMetaEnricher(h MetaEnricher) Option
- func WithMetrics(m Metrics) Option
- func WithOnConnect(fn OnConnectFunc) Option
- func WithOnReconnect(fn OnReconnectFunc) Option
- func WithOnRejectedCall(fn OnRejectedCallFunc) Option
- func WithOnToolsChanged(fn OnToolsChangedFunc) Option
- func WithResourceSingular(m map[string]string) Option
- func WithResultTransform(h ResultTransformHook) Option
- func WithSchemaValidation() Option
- func WithoutCache() Option
- type RejectReason
- type ResultTransformHook
- type ServerConfig
- type ServerState
- type ToolInfo
- type TransportType
- type View
Constants ¶
This section is empty.
Variables ¶
var ErrServerDown = errors.New("mcpx: server is down")
ErrServerDown is returned by Multiplexer.CallTool when the target server is currently unreachable and has been marked down by the health-check supervisor. Use errors.Is to distinguish it from ErrServerNotFound.
var ErrServerNotFound = errors.New("mcpx: server not found")
ErrServerNotFound is returned by CallTool when the named server is not registered.
var ErrToolNotFound = errors.New("mcpx: tool not found")
ErrToolNotFound is returned by CallTool when the named tool is not exposed by the server.
Functions ¶
func BearerRoundTripper ¶
func BearerRoundTripper(token string, base http.RoundTripper) http.RoundTripper
BearerRoundTripper returns an http.RoundTripper that injects an `Authorization: Bearer <token>` header into every request.
This is a low-level helper for users assembling their own *http.Client outside the ServerConfig flow. For the config-driven path, prefer WithAuthFunc together with the auth.Bearer helper from github.com/inhuman/mcp-multiplexer/auth.
func CacheScope ¶ added in v0.4.0
CacheScope retrieves the scope set by WithCacheScope. Returns "" if not set.
func DefaultResourceSingular ¶
DefaultResourceSingular returns a copy of the built-in plural→singular map used by the "singularResourceType" transformer.
func IsCacheHit ¶ added in v0.4.0
IsCacheHit reports whether the current call was served from cache. Valid to call from AfterCallHook; always false from BeforeCallHook.
Types ¶
type AfterCallHook ¶
type AfterCallHook func(ctx context.Context, server, tool string, info ToolInfo, args json.RawMessage, result *CallResult, callErr error, duration time.Duration)
AfterCallHook runs after every tool call, on every code path (success, cache hit, short-circuit, upstream error, ResultTransform error, and all four rejection reasons). Errors returned from this hook are ignored. duration is wall time from CallTool entry.
type ArgsTransformer ¶
type ArgsTransformer string
ArgsTransformer names a transformation applied to tool arguments before sending. Built-in values:
- "camelCase" — converts snake_case map keys to camelCase (needed for MCP servers like mcp/kubernetes that use camelCase).
- "joinArrays" — converts string slices into space-joined strings (some servers expect a single argv string).
- "singularResourceType" — if args contains a "resourceType" string with a known plural form, normalises it to singular (pods→pod, etc.).
Custom names can be registered via WithArgsTransformer.
const ( ArgsTransformerCamelCase ArgsTransformer = "camelCase" ArgsTransformerJoinArrays ArgsTransformer = "joinArrays" ArgsTransformerSingularResource ArgsTransformer = "singularResourceType" )
type ArgsTransformers ¶
type ArgsTransformers []ArgsTransformer
ArgsTransformers is an ordered list of transformer names applied left to right.
type AuthFunc ¶ added in v0.1.0
AuthFunc applies authentication to an outgoing HTTP/SSE request before it reaches the upstream MCP server.
AuthFunc is invoked once per outbound HTTP request — including each retry attempt performed by the underlying retryable HTTP client. Implementations whose token derivation is expensive (for example OAuth2 client-credentials with refresh) should cache the result internally; the library does not memoise across attempts.
The library calls fn on a *cloned* *http.Request so concurrent callers of the same connection do not race on Header / Body mutations. Mutate r in place; mutating r.Header is the common case but adjusting r.Body or r.URL is also allowed.
data is ServerConfig.Auth — the parsed JSON "auth" block, opaque to the library. The function defines its own shape; missing or malformed fields should yield a descriptive error (the library does not validate it).
Returning a non-nil error aborts the request: the upstream server is NOT contacted; the library wraps the error as `mcpx: auth <server>: <err>` and propagates it to the caller of CallTool.
AuthFunc applies only to HTTP and SSE transports. Stdio transports ignore it because they have no HTTP layer.
Register an AuthFunc with WithAuthFunc. See subpackage github.com/inhuman/mcp-multiplexer/auth for ready-made implementations covering the most common cases (Bearer, custom-header).
type BeforeCallHook ¶
type BeforeCallHook func(ctx context.Context, server, tool string, info ToolInfo, args json.RawMessage) (context.Context, *CallResult, error)
BeforeCallHook runs before a tool call is dispatched to the upstream MCP server. Hooks chain in registration order; the first non-nil result or non-nil error stops the chain.
Return semantics (in priority order):
- (_, _, err) where err != nil — abort; both non-nil means error wins.
- (_, result, nil) where result != nil — short-circuit: upstream and ResultTransform are skipped; AfterCall still fires.
- (newCtx, nil, nil) — continue; newCtx replaces ctx if non-nil.
args is the JSON-encoded payload AFTER all transformers and field maps.
type Cache ¶ added in v0.4.0
type Cache interface {
// Get returns a deep copy of the cached result and true on hit.
// Returns nil and false on miss or expiry.
Get(ctx context.Context, key string) (*CallResult, bool)
// Set stores a deep copy of value with the given TTL.
// Set with nil value or zero TTL is a no-op.
Set(ctx context.Context, key string, value *CallResult, ttl time.Duration)
}
Cache is the storage backend for CallTool response caching. Implementations MUST be goroutine-safe and MUST store/return deep copies.
type CallResult ¶
type CallResult struct {
Text string
Parts []ContentPart
IsError bool
}
CallResult is the structured outcome of a tool call.
Text is the joined text content of the result. Parts preserves the original content blocks (text, image, etc.) so callers can format them however they want without losing structure.
func (*CallResult) Clone ¶ added in v0.4.0
func (r *CallResult) Clone() *CallResult
Clone returns a deep copy of r. Each ContentPart is individually copied; Data and Raw byte slices are cloned to independent allocations. Clone on a nil receiver returns nil.
type ContentKind ¶
type ContentKind string
ContentKind identifies the type of content in a CallResult part.
const ( ContentText ContentKind = "text" ContentImage ContentKind = "image" ContentOther ContentKind = "other" )
type ContentPart ¶
type ContentPart struct {
Kind ContentKind
Text string // populated when Kind == ContentText
MIMEType string // populated when Kind == ContentImage
Data []byte // raw image bytes when Kind == ContentImage
Raw []byte // JSON-encoded original for ContentOther
}
ContentPart is one block returned from an MCP tool call.
type CustomTransformer ¶
CustomTransformer is a user-defined argument transformer registered via WithArgsTransformer and selectable from ServerConfig.ArgsTransformers by the same name.
type ErrInvalidArgs ¶
ErrInvalidArgs is returned by CallTool when arguments fail validation. BadFields lists argument paths that contain unresolved placeholder values. SchemaErrors lists JSON Schema violations; populated only when WithSchemaValidation is enabled and args do not conform to the tool schema.
func (*ErrInvalidArgs) Error ¶
func (e *ErrInvalidArgs) Error() string
type KeyFunc ¶ added in v0.4.0
KeyFunc computes the cache key for a call. When registered via WithCacheKey it replaces the built-in canonicalisation entirely.
type KindSettings ¶
type KindSettings struct {
ArgsTransformers ArgsTransformers `json:"args_transformer,omitempty"`
FieldMap map[string]string `json:"field_map,omitempty"`
}
KindSettings holds shared defaults for all servers of a given kind.
type Logger ¶
type Logger interface {
Debug(msg string, fields ...Field)
Info(msg string, fields ...Field)
Warn(msg string, fields ...Field)
Error(msg string, fields ...Field)
}
Logger is the minimal logging interface mcpx uses. Implement it once and pass via WithLogger. Adapters for zap and log/slog ship in subpackages log/zaplog and log/sloglog respectively.
type MetaEnricher ¶
MetaEnricher runs once per tool right after the multiplexer fetches the tool list from a server. It can return an updated ToolInfo with extra labels in Custom or adjusted boolean flags. Original input is never nil.
type Metrics ¶ added in v0.3.0
type Metrics interface {
// RecordCall is invoked after every [Multiplexer.CallTool] invocation.
// dur is the wall-clock time of the upstream MCP call only (argument
// validation and hook overhead are excluded).
// err is nil on success and matches the error returned to the caller.
RecordCall(server, tool string, dur time.Duration, err error)
// RecordToolList is invoked after every successful tool-list fetch —
// both on initial connect and after a live notifications/tools/list_changed
// refresh. count is the number of tools the server currently exposes.
RecordToolList(server string, count int)
}
Metrics is an optional observability sink for the multiplexer. Implement this interface to receive call-level and tool-list events and forward them to any backend (Prometheus, OpenTelemetry, statsd, …). Register via WithMetrics.
Implementations must be safe for concurrent use. Panics inside any method are recovered by the library and do not propagate to callers.
type Multiplexer ¶
type Multiplexer struct {
// contains filtered or unexported fields
}
Multiplexer connects to multiple MCP servers and exposes a unified API for listing and invoking tools across them.
func New ¶
func New(ctx context.Context, cfg MultiplexerConfig, opts ...Option) (*Multiplexer, error)
New connects to all servers in cfg, caches their tool lists, and returns a ready Multiplexer. Errors from individual servers are logged but do not prevent the rest from initialising. Inspect ServerNames() to see which servers are live.
func NewFromSessions ¶
func NewFromSessions(ctx context.Context, sessions map[string]*mcp.ClientSession, opts ...Option) *Multiplexer
NewFromSessions builds a Multiplexer from already-connected MCP sessions. Useful in tests and integration harnesses where sessions are established before the multiplexer is constructed.
Each session is queried for its tool list. The constructed Multiplexer's Close() will close the supplied sessions.
func (*Multiplexer) AllTools ¶
func (mx *Multiplexer) AllTools() []ToolInfo
AllTools returns every (server, tool) pair across all connected servers. Order is non-deterministic.
func (*Multiplexer) CallTool ¶
func (mx *Multiplexer) CallTool(ctx context.Context, server, toolName string, argsJSON json.RawMessage) (*CallResult, error)
CallTool invokes the named tool on the named server with the given JSON arguments. It runs all configured BeforeCall/AfterCall/ResultTransform hooks and consults the response cache when the tool is cacheable. The argsJSON parameter must be a JSON object (or empty/nil).
Errors returned:
- ErrServerNotFound, ErrToolNotFound, ErrServerDown — caller mistake.
- *ErrInvalidArgs — args contain unresolved placeholders or schema violations.
- errors from BeforeCallHook are propagated as-is.
- upstream MCP errors are wrapped via fmt.Errorf("server %s: %w", ...).
func (*Multiplexer) Close ¶
func (mx *Multiplexer) Close()
Close shuts down all MCP sessions and stops underlying subprocesses.
func (*Multiplexer) ConfigHints ¶
func (mx *Multiplexer) ConfigHints() map[string][]string
ConfigHints returns the kind_hints map from MultiplexerConfig (may be nil).
func (*Multiplexer) FilterByNames ¶
func (mx *Multiplexer) FilterByNames(names []string) (*View, error)
FilterByNames returns a view (View) of the multiplexer that exposes only the requested servers. The view shares all sessions and configuration with the parent — no new connections are opened. Closing the view is a no-op; only the parent Multiplexer's Close() shuts down sessions.
Returns an error if any requested server name is unknown.
func (*Multiplexer) KindGroups ¶
func (mx *Multiplexer) KindGroups() []KindGroup
KindGroups returns servers grouped by Kind (or by name if Kind is empty), with deduplicated tool names per group. Groups are sorted by Kind.
func (*Multiplexer) KindsForServers ¶
func (mx *Multiplexer) KindsForServers(names []string) []string
KindsForServers returns unique kinds for the given server names, preserving input order. If a server has no Kind set, its name is used as the kind.
func (*Multiplexer) ServerNames ¶
func (mx *Multiplexer) ServerNames() []string
ServerNames returns the sorted list of live (connected) MCP server names. Servers that are currently down (initial connect failed or lost) are excluded.
func (*Multiplexer) ServerStatus ¶ added in v0.2.0
func (mx *Multiplexer) ServerStatus() map[string]ServerState
ServerStatus returns a snapshot of the liveness state of every registered server. When health-check is disabled (WithHealthCheck not called), all values are ServerStateConnected.
func (*Multiplexer) ToolsForServers ¶
func (mx *Multiplexer) ToolsForServers(names []string) []ToolInfo
ToolsForServers returns ToolInfo for tools across the given server names, in input order with stable per-server ordering. Each (server, tool) pair appears once.
type MultiplexerConfig ¶
type MultiplexerConfig struct {
Servers []ServerConfig `json:"servers"`
// KindSettings provides shared transformer/field-map defaults for every
// server with the matching Kind. Per-server settings take precedence.
KindSettings map[string]KindSettings `json:"kind_settings,omitempty"`
// KindHints is opaque metadata returned via KindGroup.Hints — useful for
// downstream prompt generation, e.g. "kubernetes" -> ["use kubectl_logs for logs"].
KindHints map[string][]string `json:"kind_hints,omitempty"`
}
MultiplexerConfig is the top-level config for New().
type OnConnectFunc ¶ added in v0.4.0
OnConnectFunc is called once per server after the initial successful connection, before New returns. tools is the post-MetaEnricher tool list. Panics are recovered.
type OnReconnectFunc ¶ added in v0.2.0
OnReconnectFunc is called by the health-check supervisor on every reconnect attempt. err is nil when the attempt succeeded, non-nil on failure. It is invoked synchronously from the supervisor goroutine and must not block for extended periods.
type OnRejectedCallFunc ¶ added in v0.4.0
type OnRejectedCallFunc func(ctx context.Context, server, tool string, reason RejectReason, err error)
OnRejectedCallFunc is called when CallTool is rejected before dispatch. It fires before AfterCall on rejection paths. Panics are recovered. reason identifies which rejection path was taken.
type OnToolsChangedFunc ¶ added in v0.2.0
OnToolsChangedFunc is called after a successful tool-list refresh that produces a different set of tools than the previously cached list. server is the name of the server whose tool list changed. before is a snapshot of the tool list prior to the refresh. after is the updated tool list.
The callback runs synchronously from the per-server drain goroutine and must not block for extended periods. Panics inside the callback are recovered by the library; the multiplexer continues operating normally.
type Option ¶
type Option func(*options)
Option configures a Multiplexer at construction time.
func WithAfterCall ¶
func WithAfterCall(h AfterCallHook) Option
WithAfterCall registers a hook that runs after every tool call. Multiple hooks run in registration order; their errors are ignored.
func WithArgsTransformer ¶
func WithArgsTransformer(name string, fn CustomTransformer) Option
WithArgsTransformer registers a custom transformer under the given name. Reference it from ServerConfig.ArgsTransformers (or KindSettings) by name.
func WithAuthFunc ¶ added in v0.1.0
WithAuthFunc registers the global AuthFunc applied to every server whose [ServerConfig.Auth] is non-nil. It is REQUIRED whenever any server has Auth set; otherwise New returns an error before opening any connection.
There is no per-server registry — dispatch on data["scheme"] (or the server name) inside the function if multiple schemes coexist.
Calling WithAuthFunc more than once overwrites the previous value; no chaining is provided.
func WithBeforeCall ¶
func WithBeforeCall(h BeforeCallHook) Option
WithBeforeCall registers a hook that runs before every tool call. Multiple hooks run in registration order and any error aborts the call.
func WithCache ¶ added in v0.4.0
WithCache replaces the built-in LRU with the given Cache implementation. Passing nil keeps the built-in LRU. WithCache and WithoutCache are mutually exclusive — last one registered wins.
func WithCacheKey ¶ added in v0.4.0
WithCacheKey replaces the built-in cache key function. The KeyFunc receives the call context (with scope), server, tool, and canonicalised args.
func WithCacheSize ¶ added in v0.4.0
WithCacheSize sets the maximum number of entries in the built-in LRU. Default: 256. Ignored when WithCache is used.
func WithCacheTTL ¶ added in v0.4.0
WithCacheTTL sets the default TTL for cached results. Default: 30s. Per-tool overrides can be set via ToolInfo.Custom["cache_ttl"].
func WithCallTimeout ¶
WithCallTimeout overrides the per-call timeout. Default: 30s.
func WithClientIdentity ¶
WithClientIdentity overrides the MCP client name/version sent during handshake. Default: "mcpx" / library version.
func WithHTTPRetryMax ¶
WithHTTPRetryMax overrides the maximum retries for HTTP/SSE transports. Default: 5.
func WithHealthCheck ¶ added in v0.2.0
WithHealthCheck enables the liveness supervisor. The supervisor probes each server at the given interval using a ListTools call and reconnects with exponential backoff (1 s → 2 s → … → 60 s) on failure. interval must be positive; zero or negative values cause New to return an error. Without this option the supervisor does not start and Multiplexer.ServerStatus always returns ServerStateConnected for every registered server.
func WithLogger ¶
WithLogger attaches a Logger. Default: NopLogger.
func WithMetaEnricher ¶
func WithMetaEnricher(h MetaEnricher) Option
WithMetaEnricher registers a hook that adjusts ToolInfo metadata after the initial fetch. Multiple enrichers chain in registration order.
func WithMetrics ¶ added in v0.3.0
WithMetrics registers a Metrics implementation that receives call-level and tool-list events. Passing nil is a no-op (leaves the default no-op implementation in place). Calling WithMetrics more than once overwrites the previous value.
func WithOnConnect ¶ added in v0.4.0
func WithOnConnect(fn OnConnectFunc) Option
WithOnConnect registers a callback invoked once per server after the initial successful connection, before New returns. tools is the post-MetaEnricher list. Panics recovered.
func WithOnReconnect ¶ added in v0.2.0
func WithOnReconnect(fn OnReconnectFunc) Option
WithOnReconnect registers a callback invoked on every reconnect attempt. err is nil on success, non-nil on failure. Registering more than once overwrites the previous value. The callback runs synchronously from the supervisor goroutine and must not block for extended periods.
func WithOnRejectedCall ¶ added in v0.4.0
func WithOnRejectedCall(fn OnRejectedCallFunc) Option
WithOnRejectedCall registers an observer called when CallTool is rejected before dispatching to upstream. It fires before AfterCall. Panics recovered.
func WithOnToolsChanged ¶ added in v0.2.0
func WithOnToolsChanged(fn OnToolsChangedFunc) Option
WithOnToolsChanged registers a callback invoked after each successful tool-list refresh that changes the cached tool list for a server. The callback receives the server name and before/after snapshots. Registering more than once overwrites the previous value; passing nil clears any previously registered callback.
func WithResourceSingular ¶ added in v0.3.0
WithResourceSingular merges m into the global custom singular map used by the "singularResourceType" argument transformer. Entries in m override built-in entries with the same key. Passing nil or an empty map is a no-op. Call multiple times to accumulate entries (each call merges, not replaces).
func WithResultTransform ¶
func WithResultTransform(h ResultTransformHook) Option
WithResultTransform registers a hook that may rewrite a successful result's text. Hooks chain in registration order; the first error short-circuits.
func WithSchemaValidation ¶ added in v0.4.0
func WithSchemaValidation() Option
WithSchemaValidation enables JSON Schema validation of tool arguments against each tool's InputSchema before the call is dispatched. When a tool declares no InputSchema the check is skipped. Violations are returned as *ErrInvalidArgs with SchemaErrors populated.
func WithoutCache ¶ added in v0.4.0
func WithoutCache() Option
WithoutCache disables the response cache entirely. Takes priority over WithCache if called after it.
type RejectReason ¶ added in v0.4.0
type RejectReason string
RejectReason identifies why a CallTool request was rejected before reaching the upstream MCP server.
const ( RejectUnknownServer RejectReason = "unknown_server" RejectUnknownTool RejectReason = "unknown_tool" RejectServerDown RejectReason = "server_down" RejectBeforeHookAbort RejectReason = "before_hook_abort" RejectInvalidArgs RejectReason = "invalid_args" )
type ResultTransformHook ¶
type ResultTransformHook func(ctx context.Context, server, tool string, info ToolInfo, result *CallResult) error
ResultTransformHook runs after a successful upstream tool call and mutates *CallResult in place. It can modify Text, Parts, and IsError (e.g. PII redaction, prompt-injection filtering across image parts). Returning an error aborts the call; AfterCall still fires with the error.
type ServerConfig ¶
type ServerConfig struct {
Name string `json:"name"`
// Kind is an optional semantic label grouping servers of the same type
// (e.g. "kubernetes", "gitlab"). Empty kind is treated as a unique kind
// equal to the server name.
Kind string `json:"kind,omitempty"`
Transport TransportType `json:"transport"`
// Stdio only.
Binary string `json:"binary,omitempty"`
Args []string `json:"args,omitempty"`
Env []string `json:"env,omitempty"` // additional env vars for the subprocess
// HTTP/SSE only.
URL string `json:"url,omitempty"`
// CallTimeout is the maximum duration allowed for a single tool call to
// this server. A zero or negative value inherits the multiplexer-wide
// default set via [WithCallTimeout] (default 30 s).
//
// Use a shorter value for local stdio servers and a longer value for HTTP
// servers that may need retries.
CallTimeout time.Duration `json:"call_timeout,omitempty"`
// Auth is an opaque parameter block read verbatim from the JSON "auth"
// field. The library does not interpret its shape — it is forwarded
// as-is to the AuthFunc registered via [WithAuthFunc].
//
// When non-nil and no AuthFunc is registered, [New] returns an error
// before opening any connection. Auth applies only to HTTP and SSE
// transports; stdio servers ignore it.
//
// Helpers covering the two most common shapes
// ({"token":"..."} and {"tokenName":"...","value":"..."}) ship in
// subpackage github.com/inhuman/mcp-multiplexer/auth.
Auth map[string]any `json:"auth,omitempty"`
// ArgsTransformers is an ordered list of transformations applied to tool
// arguments before sending. Built-in names: "camelCase", "joinArrays",
// "singularResourceType". Custom names registered via
// WithArgsTransformer are also resolved here.
ArgsTransformers ArgsTransformers `json:"args_transformer,omitempty"`
// FieldMap renames argument keys (top-level only) before sending.
FieldMap map[string]string `json:"field_map,omitempty"`
// ResourceSingular is an optional per-server override map for the
// "singularResourceType" transformer. Entries here win over both the
// global custom map (WithResourceSingular) and the built-in map.
// A nil value means no per-server override.
ResourceSingular map[string]string `json:"resource_singular,omitempty"`
}
ServerConfig describes one MCP server.
type ServerState ¶ added in v0.2.0
type ServerState string
ServerState reports the observed liveness of a single MCP server. It is set to ServerStateConnected at construction and updated by the health-check supervisor when WithHealthCheck is used.
const ( // ServerStateConnected means the server is reachable and calls proceed normally. ServerStateConnected ServerState = "connected" // ServerStateDown means the last health probe failed; [Multiplexer.CallTool] // returns [ErrServerDown] immediately for this server. ServerStateDown ServerState = "down" )
type ToolInfo ¶
type ToolInfo struct {
Server string
Name string
Description string
InputSchema []byte // raw JSON schema
ReadOnly bool
Write bool
Destructive bool
Idempotent bool
OpenWorld bool
Custom map[string]string
}
ToolInfo holds cached metadata about a single tool from an MCP server.
The boolean flags map to MCP tool annotations (ReadOnlyHint, DestructiveHint, IdempotentHint, OpenWorldHint). Write is a derived flag — true when the tool is not read-only and not destructive (i.e. a non-destructive mutation).
Custom is an open extension point for user-supplied labels added by a MetaEnricher hook (e.g. "category=database", "owner=team-a").
type TransportType ¶
type TransportType string
TransportType selects the underlying MCP transport.
const ( TransportStdio TransportType = "stdio" TransportHTTP TransportType = "http" TransportSSE TransportType = "sse" )
type View ¶
type View struct {
// contains filtered or unexported fields
}
View is a subset of a Multiplexer scoped to a fixed list of server names. Methods mirror the parent's read API so a view can be passed to code that expects a Multiplexer-like surface for a restricted server set.
func (*View) CallTool ¶
func (v *View) CallTool(ctx context.Context, server, tool string, argsJSON json.RawMessage) (*CallResult, error)
CallTool delegates to the parent multiplexer after verifying the server is part of this view. Returns ErrServerNotFound if the server is hidden.
func (*View) ServerNames ¶
ServerNames returns the names visible through this view, in input order.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package auth provides ready-made [mcpx.AuthFunc] implementations for the two most common authentication shapes carried in [mcpx.ServerConfig.Auth].
|
Package auth provides ready-made [mcpx.AuthFunc] implementations for the two most common authentication shapes carried in [mcpx.ServerConfig.Auth]. |
|
examples
|
|
|
basic
command
Package main demonstrates basic mcpx usage: connecting to multiple MCP servers and calling a tool.
|
Package main demonstrates basic mcpx usage: connecting to multiple MCP servers and calling a tool. |
|
policy
command
Package main demonstrates using BeforeCallHook as a policy gate: any tool marked Destructive is blocked before the call reaches the upstream server.
|
Package main demonstrates using BeforeCallHook as a policy gate: any tool marked Destructive is blocked before the call reaches the upstream server. |
|
redact
command
Package main demonstrates using ResultTransformHook for PII redaction: any SSN pattern in tool result text is replaced with [REDACTED].
|
Package main demonstrates using ResultTransformHook for PII redaction: any SSN pattern in tool result text is replaced with [REDACTED]. |
|
internal
|
|
|
testutil/capturelog
Package capturelog provides an in-memory implementation of mcpx.Logger that records every event for later assertion.
|
Package capturelog provides an in-memory implementation of mcpx.Logger that records every event for later assertion. |
|
testutil/dockertarget
command
Command dockertarget is a minimal stdio MCP server used for the transport_integration_test (real subprocess lifecycle) and for the integration_docker test set.
|
Command dockertarget is a minimal stdio MCP server used for the transport_integration_test (real subprocess lifecycle) and for the integration_docker test set. |
|
testutil/mcptest
Package mcptest provides an in-process MCP server factory for use from tests inside the mcp-multiplexer module.
|
Package mcptest provides an in-process MCP server factory for use from tests inside the mcp-multiplexer module. |
|
log
|
|
|
sloglog
Package sloglog adapts a *log/slog.Logger to the mcpx.Logger interface.
|
Package sloglog adapts a *log/slog.Logger to the mcpx.Logger interface. |
|
zaplog
Package zaplog adapts a *go.uber.org/zap.Logger to the mcpx.Logger interface.
|
Package zaplog adapts a *go.uber.org/zap.Logger to the mcpx.Logger interface. |
|
Package policy provides ready-made BeforeCallHook and AfterCallHook builders for common call-control patterns.
|
Package policy provides ready-made BeforeCallHook and AfterCallHook builders for common call-control patterns. |