A supervised proxy that merges catalogs from MCP backends.
Start a proxy with backend specifications, then pass runtime/2 to a Snodo
transport. Backend tools and prompts use the configured name prefix. Resource
URIs use mcp-proxy://<backend-id>/ so a read always reaches one backend.
The proxy keeps one atomic catalog snapshot for discovery and routing.
{:ok, proxy} =
Snodo.Proxy.start_link(
backends: [
[id: "search", target: {:http, "http://127.0.0.1:4001/mcp"}],
[id: "files", target: {:stdio, "file-server", []}]
]
)
runtime = Snodo.Proxy.runtime(proxy)
{:ok, listener} = Snodo.Transport.StreamableHTTP.Server.start_link(runtime: runtime)A backend may also use any custom Snodo.Client transport target, or
{:direct, runtime} for an in-process server. Backends that disconnect are
retried every second. A rejected or conflicting catalog update retains the
last accepted catalog and appears in health/1.
Summary
Functions
Adds and connects a backend, rejecting duplicate IDs or catalog collisions.
Returns an OTP child specification for a proxy.
Returns each configured backend's connection and catalog status.
Refreshes one backend's catalog immediately.
Removes a backend and its published catalog entries.
Builds a server runtime backed by the proxy's current catalog.
Starts the proxy supervisor and its configured backends.
Functions
Adds and connects a backend, rejecting duplicate IDs or catalog collisions.
@spec child_spec(keyword()) :: Supervisor.child_spec()
Returns an OTP child specification for a proxy.
Returns each configured backend's connection and catalog status.
Refreshes one backend's catalog immediately.
Removes a backend and its published catalog entries.
@spec runtime(pid(), keyword()) :: Snodo.Server.Runtime.t()
Builds a server runtime backed by the proxy's current catalog.
:name defaults to "snodo-proxy", :version to the package version, and
:authorization accepts a Snodo.Authorization policy. The proxy applies
that policy to the merged catalog at discovery and invocation time.
@spec start_link(keyword()) :: Supervisor.on_start()
Starts the proxy supervisor and its configured backends.