Using sessions via MCP

Use this guide when you are building an application with Composio and want to expose one user's session over MCP. The application creates and configures the session, then passes its hosted MCP endpoint to a compatible client.

By default, Composio gives your agent tools it can call directly through a provider package. That is what the Quickstart uses. Set mcp: true when an MCP transport fits your application better. No provider package is required for this route.

Connecting an existing agent instead?

If you use Codex or Claude Code and did not explicitly choose MCP, install the native Composio agent plugin. If you explicitly want MCP in an existing client, use Composio Connect.

Want to bring tools from your own remote MCP server into Composio instead? See Custom MCP.

The MCP endpoint

If you use a scoped project API key, enable Session management to create and configure sessions and Session tool execution for session-linked MCP access. See API key permissions for access levels and routes.

Opt into MCP by passing mcp: true when you create the session. The session then exposes its hosted MCP server. Read the URL and headers off session.mcp:

from composio import Composio

composio = Composio()
session = composio.sessions.create(user_id="user_123", mcp=True)

mcp_url = session.mcp.url
mcp_headers = session.mcp.headers

You don't need a provider package to use the MCP endpoint, so you can drop it from your Composio() setup if MCP is all you need.

Resuming a stored session? Pass the same flag, composio.use(sessionId, { mcp: true }) (TypeScript) or composio.use(session_id, mcp=True) (Python), to surface session.mcp on the reused session.

The MCP endpoint and session.tools() are backed by the same session. Toolkits, auth configs, and connected accounts you set when configuring the session apply to both.

What the MCP headers carry

session.mcp.headers holds the credential the SDK used to create or load the session, and nothing else. No other default header and no ambient COMPOSIO_API_KEY is copied in.

SDK credentialExported headerWhat it can reach
Project API key (apiKey, COMPOSIO_API_KEY, or the project key stored by composio login)x-api-keyThat one project
User API key only (apiKey: null with userApiKey in TypeScript, disable_api_key=True with user_api_key in Python, or an x-user-api-key default header)x-user-api-keyEvery project the user can reach across your organization

Treat the exported config as a secret and store it where you keep the project API key. A user-only session exports the user's organization-wide key, which makes it the broader credential: prefer a project-key session when an MCP client only needs one project. The SDK also exports x-org-id and x-project-id when the instance is scoped to a consumer project (see Run sessions in your organization's consumer project).

The SDK attaches the headers only when the MCP URL has the same origin as the API base URL it talks to, whatever the scheme, so a custom baseURL works as long as it serves the session MCP endpoint. For any other destination, create() and use() called with mcp: true (TypeScript) or mcp=True (Python) raise ComposioMCPDestinationError or MCPDestinationError; the error names both origins and never the key. Without the MCP flag the session is still returned, session.mcp.headers is empty, and the SDK logs a warning naming both origins, so agents that only use native tools keep working. The SDK never connects to the MCP URL itself and never follows redirects for it. Configure your MCP client so it does not forward these headers to a different origin either.

Requires @composio/core ≥ 0.19.1 (TypeScript) or composio ≥ 0.22.1 (Python). Earlier releases only exported a project key, so a session driven with a user API key had no usable MCP headers. Pass session.mcp.headers through as returned instead of assembling an x-api-key header from an environment variable yourself.

A single URL for a fixed set of tools

Combine mcp: true with the direct-tools preset to get one MCP URL that serves exactly the tools you list, with no search or meta tools in front of them. This is the closest equivalent to a classic hosted MCP server scoped to a handful of tools.

from composio import Composio, SESSION_PRESET_DIRECT_TOOLS

composio = Composio()

session = composio.sessions.create(
    user_id="user_123",
    toolkits=["gmail"],
    tools={"gmail": {"enable": ["GMAIL_FETCH_EMAILS", "GMAIL_CREATE_EMAIL_DRAFT"]}},
    session_preset=SESSION_PRESET_DIRECT_TOOLS,
    mcp=True,
)

# A single MCP URL that exposes just these two tools
print(session.mcp.url)

Any MCP client pointed at that URL sees only GMAIL_FETCH_EMAILS and GMAIL_CREATE_EMAIL_DRAFT. See Configuring Sessions for the full set of toolkit, tool, and auth filters.

Wire it into your framework

Pass session.mcp.url and session.mcp.headers to your framework's MCP client.

For complete CrewAI and LangChain scripts, follow the Python MCP research agent example.

from agents import Agent, HostedMCPTool

agent = Agent(
    name="Assistant",
    tools=[
        HostedMCPTool(
            tool_config={
                "type": "mcp",
                "server_label": "composio",
                "server_url": session.mcp.url,
                "headers": session.mcp.headers,
                "require_approval": "never",
            }
        )
    ],
)

Trade-offs

MCP is the more portable option. Any MCP-compatible client connects with just a URL, and it's supported across more frameworks and apps (Claude Desktop, Cursor, the OpenAI Responses API, and others) without a provider package.

The trade-off is that the MCP client talks to Composio's server directly, so anything the SDK does around tool execution doesn't apply:

  • Tool-call modifiers don't run. beforeExecute / afterExecute hooks and modifySchema transforms live in the SDK's execution path. Over MCP the client executes tools against the server and bypasses them, so you can't intercept, reshape, log, or gate calls the way you can with tools your agent calls directly.
  • Session-bound custom tools and toolkits don't work. Tools created with experimental_createTool / experimental_createToolkit in TypeScript, or composio.experimental.tool / composio.experimental.Toolkit in Python, run in your process. The MCP server only exposes Composio's hosted tools, so your local custom tools aren't available over the endpoint.

If you need any of those, call tools directly through a provider instead of over MCP.

Next

Configuring Sessions

Restrict toolkits, set custom auth configs, and select connected accounts