Skip to main content
Set mcp=True to serve an MCP server at /mcp alongside the REST API. ChatGPT and Claude connect as hosted custom connectors. Claude Code, Claude Desktop, Codex, and Cursor connect from your machine through Agno Connect.
mcp_server.py
The MCP server needs fastmcp from the mcp extra. Building the app without it raises an ImportError. Install it along with the example’s other dependencies (the os extra for AgentOS and anthropic for the model):

Connect MCP Clients

The server uses the Streamable HTTP transport. Choose the connection method based on where the client runs.

ChatGPT and Claude

Deploy AgentOS to a public HTTPS URL. In ChatGPT or Claude, open Settings → Connectors → Add custom connector and enter:
The endpoint must be publicly reachable over HTTPS. For ChatGPT and Claude, a secured MCP endpoint must use OAuth. Their connector UIs do not accept bearer tokens. Hosted apps cannot reach an AgentOS running only on localhost. Configure MCP OAuth on the AgentOS:
Set AGENTOS_URL to the exact public origin and set MCP_CONNECT_SECRET. Leave the connector’s optional OAuth client ID and client secret fields empty, then enter MCP_CONNECT_SECRET on the consent page. See the built-in OAuth example for the complete setup.

Local MCP Clients

Run Agno Connect on the machine where Claude Code, Claude Desktop, Codex, or Cursor is installed:
Agno Connect discovers /mcp, configures each detected client, handles the configured authentication flow, and verifies the connection with an MCP handshake. Pass the AgentOS base URL without /mcp. Use the deployed base URL to connect local clients to a remote AgentOS. See agno connect for client selection, credentials, and project-scoped configuration. An Agno agent can operate the server through MCPTools. See Enable AgentOS MCP for a complete server and client pair.

Built-in Tools

The 8 built-in tools are scoped to what an LLM client needs to operate the instance. Session writes and memory CRUD stay on the REST API; register anything else as a custom tool. Behavior shared by the run tools:
  • Omit session_id to start a fresh session; the new ID comes back in structuredContent. Pass a session_id from get_sessions to continue that conversation.
  • Long runs send MCP progress notifications: tool calls for agents and teams, step counts for workflows.
  • A result with status=PAUSED carries its unresolved requirements. Resolve them and pass them to continue_run.
  • db_id on the session tools is only needed when get_agentos_config lists multiple databases.

MCPConfig

Pass mcp=MCPConfig(...) to register custom tools, scope the built-ins, gate the server, and add transport protection:
A config with default_tools=False and no tools raises at construction, because it would mount a server with zero tools.

Result Modes

MCP tool results land in the consuming model’s context window, so the default keeps them small.

Custom Tools

Declare a user_id parameter and AgentOS fills it with the authenticated caller’s ID (the JWT subject). The parameter is hidden from the client-facing tool schema, so callers cannot spoof it. Tools that need the full request can declare a FastMCP Context parameter, which FastMCP injects natively. Combine tools=[...] with default_tools=False to expose a focused tool surface instead of the built-ins. Publishing an agent, team, or workflow also adds its scoped lifecycle tools unless lifecycle_tools=False.

Authentication

AgentOS applies its configured authentication to the REST routes and MCP server. Without a security key, JWT authorization, or mcp_auth, /mcp accepts anonymous calls and restricts requests to localhost hosts by default. Configure authentication before deploying the endpoint. With authorization=True, each tool call is checked against the scopes of its equivalent REST route: run_agent requires the same scopes as POST /agents/{id}/runs, get_sessions the same as GET /sessions. See Security & Auth. The authorize gate on MCPConfig layers on top of authentication and can reject callers per request. It receives a verified user_id from JWT, service-account, or mcp_auth credentials. Open and security-key requests carry no user identity, so the gate receives None. Make sure your gate handles None, and return False to reject callers without an identity.

Transport Security

fastmcp’s built-in Host/Origin guard is disabled on /mcp, so MCPConfig.allowed_hosts acts as the transport guard instead:
  • Left unset, the default depends on your auth mode. A server with required authentication (a security key, JWT, or mcp_auth) skips host validation, because every request already has to prove itself. An open server gets localhost-only validation, since that is exactly the setup DNS rebinding attacks target.
  • When set, the request Host (and Origin, when present) must match your list or the localhost defaults (localhost, 127.0.0.1, [::1]). Anything else is rejected with 400 before it reaches the MCP machinery. *.example.com wildcard patterns are supported.
This is DNS-rebinding protection: it stops a malicious web page from driving an always-on local MCP server through a rebound DNS name. List only your deploy or tunnel host; localhost works out of the box.

Developer Resources