Connector servers¶
Building a server¶
agent_connector_sdk.mcp.server.create_mcp_server(name, *, version, ...) parses
the standard command line, refuses unsafe exposure, configures authentication,
and returns (args, mcp, middlewares). The caller adds the middlewares.
| Argument | Purpose |
|---|---|
version |
reported to clients; required |
content |
a ConnectorContent to serve as MCP primitives |
server_registry |
a ServerRegistry whose lease the server renews while it runs |
credential_resolver |
resolves secret references in authentication flags |
Every server gets a GET /health route, per-caller rate limiting, and error
handling that never returns tracebacks.
Declared connectors¶
A connector package declares a Connector value and calls
agent_connector_sdk.run(); the SDK builds the server above from it. Anything
the server does beyond the plain bootstrap is a typed Connector field, applied
through fastmcp's own API:
| Field | Applied as |
|---|---|
tool_registry |
(tag, toggle_setting, registrar) entries, used instead of tools |
action_tools, action_prefixes |
registrars whose action-routed tools are served one typed tool per action, named <prefix>_<action> |
inline_tools |
functions or fastmcp Tool values, added with FastMCP.add_tool |
routes |
Route(path, handler, methods, name), added with FastMCP.custom_route; never /health or /ready |
readiness |
an async probe returning Readiness(ready, detail), served at GET /ready (200 or 503) |
extra_registrations |
callables that receive a RegistrationContext(server, name, version, settings, client_factory, auth) |
content_root |
a package-relative directory holding skills/, prompts/, ontology/ and connectors/ |
A container that reads a reference-only configuration directory declares it in
pyproject.toml. The shared container renderer adds a read-only bind mount. The
conformance plugin checks the table against CONFIG_MOUNTS_SCHEMA from
agent_connector_sdk.config_mounts:
[[tool.pipelines.container.config_mounts]]
source = "${CONNECTOR_CONFIG_DIR:?set-CONNECTOR_CONFIG_DIR}"
target = "/etc/connector"
Change subscriptions¶
Every server built by create_mcp_server serves subscriptions/listen, so
clients such as the connector-sync runner learn about changes without polling.
agent_connector_sdk.mcp.change_events publishes them:
| Function | Publishes |
|---|---|
announce_content_changed(mcp) |
the tool, prompt and resource lists changed |
announce_resource_updated(mcp, uri) |
the resource at uri was updated |
serve_change_subscriptions(mcp, bus=None) |
serves listen streams on a server not built by the factory; returns the bus |
change_bus(mcp) |
the server's bus, for a shared cross-replica implementation |
A connector that publishes announce_resource_updated for a data resource lets
the runner sync that resource's presets as soon as it changes.
Network exposure¶
A streamable-http or sse listener outside loopback is refused unless it has
all three of: an authentication mode other than none, a TLS boundary (a
certificate and key, or --tls-terminated with --trusted-proxy-cidrs), and an
exact --allowed-hosts list.
Build the serving boundary once and pass it intact to FastMCP:
from agent_connector_sdk.mcp.network import build_network_serving_config
serving = build_network_serving_config(args)
if serving is None:
mcp.run(transport="stdio")
else:
mcp.run(
transport=args.transport,
host=args.host,
port=args.port,
**serving.fastmcp_run_kwargs(),
)
The typed configuration enforces exact Host and browser/WebSocket Origin allowlists, a bounded request body with a read timeout, and the immediate-peer CIDR for TLS-stop ingress. Its Uvicorn policy disables forwarded-header trust and bounds concurrency, listen backlog, keepalive, graceful shutdown, and the incomplete HTTP-event buffer. Direct TLS certificate and key paths are validated before the listener starts.
| Bound | Default | Setting / flag |
|---|---|---|
| request body | 4 MiB | MCP_MAX_REQUEST_BYTES / --max-request-bytes |
| body read timeout | 30 s | MCP_REQUEST_BODY_TIMEOUT_SECONDS / --request-body-timeout-seconds |
| concurrent connections | 128 | MCP_MAX_CONNECTIONS / --max-connections |
| listen backlog | 256 | MCP_LISTEN_BACKLOG / --listen-backlog |
| keepalive timeout | 5 s | MCP_KEEPALIVE_TIMEOUT_SECONDS / --keepalive-timeout-seconds |
| graceful shutdown | 15 s | MCP_GRACEFUL_SHUTDOWN_TIMEOUT_SECONDS / --graceful-shutdown-timeout-seconds |
Invalid values refuse startup; they never fall back to an unbounded listener.
Authentication¶
--auth-type |
Needs |
|---|---|
static |
--static-tokens-ref naming a JSON token map |
jwt |
--token-issuer, --token-audience, and a JWKS URI, public key, or --token-secret-ref for HMAC; comma lists configure multiple realms |
oauth-proxy |
upstream endpoints, client id, --oauth-upstream-client-secret-ref, base URL and JWT settings |
oidc-proxy |
--oidc-config-url, client id, --oidc-client-secret-ref, base URL and token audience |
remote-oauth |
authorization servers, base URL and JWT settings |
An unknown mode is an error, never an unauthenticated server. With
--public-base-url, JWT servers publish RFC 9728 protected-resource metadata.
Tool surface¶
register_tool_surface(mcp, service=..., client_cls=Api, get_client=...)
registers one MCP tool per API operation: one per public method of the client
class, named <prefix>_<operation>. A fleet gateway scales the catalog through
lazy find and load. The SDK tags every tool gated, and the gateway reveals it on demand.
| Tool property | Source |
|---|---|
| Name | <prefix>_<method>; prefix is tool_prefix or the service name without -mcp/-agent/-api/-server |
| Input schema | the OpenAPI operation manifest (manifest=), else the method signature and type hints |
| Description | the manifest summary, else the docstring |
| Annotations | the HTTP verb: GET is read-only; DELETE is destructive; PUT and DELETE are idempotent; other verbs are not read-only |
Registrars (tools_module, tool_registry or registrars) add the tools that
are not client-method wrappers, such as ingest tools; each honours a
<TAG>TOOL setting. With a client, the SDK splits a registrar tool that routes
an action string into one typed tool per action. An action that an operation
tool serves stays with that tool. register_action_tools(mcp, entries, prefixes=...)
splits action tools with or without a client. action_dispatch=True keeps them
whole for compatibility. No environment mode selects the surface. A destructive
operation asks the connected user to confirm and is cancelled when it cannot.
Visibility¶
MCP_ENABLED_TOOLS, MCP_DISABLED_TOOLS, MCP_ENABLED_TAGS and
MCP_DISABLED_TAGS set the server policy. HTTP clients may narrow it with query
parameters or x-mcp-* headers, never widen it. A malformed filter exposes
nothing.