Extending sessions capabilities
Experimental

Custom MCP

Custom MCP lets you use tools from your remote MCP server in the same session as Composio's built-in toolkits. Register the server, connect it if authentication is required, then add its synced CUSTOM_* toolkit slug to a session.

Custom MCP is experimental. Its setup flow, authentication options, and API contracts may change while we work with early customers.

This is different from Custom Tools and Toolkits. Custom tools run inside your application. A custom MCP server runs outside Composio and exposes its tools over a public HTTPS endpoint.

Custom MCP lifecycle

A Custom MCP moves through this lifecycle:

  1. Deploy your MCP server at a public HTTPS URL.
  2. Register its URL and authentication scheme. Composio creates a project-scoped CUSTOM_* toolkit.
  3. Connect an account if the server uses an API key or DCR OAuth. No-auth servers skip this step.
  4. Sync its tools. The first sync starts automatically; later tool changes require a manual sync.
  5. Use the toolkit in a session. For authenticated servers, explicitly select the connected account.

API-only while Custom MCP is experimental

Use the lifecycle endpoints below to register, sync, and delete Custom MCP toolkits. They aren't included in the public API reference or SDKs yet, and their contracts may change. Dashboard management is coming soon for customers who prefer a UI.

Register a Custom MCP

Call POST /api/v3.1/custom/toolkits/upsert with your public server URL and authentication scheme. Authenticate the request with your Composio project API key.

curl --request POST \
  --url https://backend.composio.dev/api/v3.1/custom/toolkits/upsert \
  --header "x-api-key: $COMPOSIO_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "slug": "ACME",
    "toolkit_config": {
      "name": "Acme",
      "app_url": "https://mcp.example.com/mcp",
      "auth_schemes": [
        {
          "mode": "NO_AUTH"
        }
      ]
    }
  }'

Composio adds the CUSTOM_ prefix and returns the normalized toolkit slug:

{
  "slug": "CUSTOM_ACME"
}

This endpoint only registers new toolkits

Despite upsert in the route name, this endpoint does not update or replace an existing toolkit. If the slug already exists, the request returns 409 Conflict.

To change the server URL, name, or authentication scheme, delete the existing toolkit, then register it again. Deletion also revokes and removes the toolkit's auth configurations and connected accounts.

Complete setup for your authentication mode

Choose the mode that matches your server, then complete any required connection:

AuthenticationUse it whenAfter registration
No authThe server accepts requests without credentials.No connection is required. Initial sync runs automatically.
API keyEach connected account supplies an API key.Create an active connection. Initial sync then starts in the background.
DCR OAuthThe server supports OAuth Dynamic Client Registration.Authorize a connection. Initial sync starts when it becomes active.

For DCR OAuth, the server must support the standard authorization-code flow. Other OAuth grant types aren't supported.

Sync and resync tools

Call POST /api/v3.1/custom/toolkits/sync to fetch the server's current tools:

curl --request POST \
  --url https://backend.composio.dev/api/v3.1/custom/toolkits/sync \
  --header "x-api-key: $COMPOSIO_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "slug": "CUSTOM_ACME",
    "connected_account_id": "ca_custom_acme"
  }'

For an API-key or DCR OAuth server, connected_account_id must identify an active account from the same toolkit and project. For a no-auth server, omit it:

curl --request POST \
  --url https://backend.composio.dev/api/v3.1/custom/toolkits/sync \
  --header "x-api-key: $COMPOSIO_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "slug": "CUSTOM_ACME"
  }'

A successful sync returns the toolkit version and the number of tools discovered:

{
  "slug": "CUSTOM_ACME",
  "version": "20260728_00",
  "synced_count": 12
}

When to sync manually

Composio starts the initial sync automatically:

  • No auth: during registration
  • API key or DCR OAuth: when the first connected account becomes active

Call the sync endpoint only if the initial sync fails or the server's tool definitions change. Later connections don't resync a toolkit that already has tools.

A Custom MCP toolkit can contain at most 500 tools. If the server returns more than 500, the sync fails without importing a partial tool list. The last successful version stays available.

Delete or replace a Custom MCP

The registration endpoint cannot update an existing toolkit. To replace its URL, name, or authentication scheme, delete the toolkit and register it again.

Call DELETE /api/v3.1/custom/toolkits/{slug}:

curl --request DELETE \
  --url https://backend.composio.dev/api/v3.1/custom/toolkits/CUSTOM_ACME \
  --header "x-api-key: $COMPOSIO_API_KEY"
{
  "slug": "CUSTOM_ACME",
  "deleted": true,
  "revoke_job_ids": ["job_123"],
  "auth_configs_soft_deleted": 1,
  "connected_accounts_soft_deleted": 1
}

Deletion also removes connections

Deletion removes the custom toolkit and its tools. It also revokes and removes the toolkit's auth configurations and connected accounts. Any replacement starts with new connections.

Use Custom MCP in a session

Once the toolkit is synced, add its CUSTOM_* slug to a session.

Use a no-auth server

Pass the toolkit slug when you create the session:

from composio import Composio

composio = Composio(api_key="your_api_key")

session = composio.sessions.create(
    user_id="user_123",
    toolkits=["CUSTOM_ACME"],
)

tools = session.tools()

With the default search-first session, your agent can discover the custom tools through COMPOSIO_SEARCH_TOOLS and execute them through the Tool Router.

Use an authenticated server

For API-key and DCR OAuth servers, explicitly select the connected account in the session config. Don't rely on automatic account matching for Custom MCP toolkits yet.

from composio import Composio

composio = Composio(api_key="your_api_key")

session = composio.sessions.create(
    user_id="user_123",
    toolkits=["CUSTOM_ACME"],
    connected_accounts={
        "CUSTOM_ACME": ["ca_custom_acme"],
    },
)

The pinned account must belong to the custom toolkit and be active. Explicit selection ensures tool calls use its credentials.

What you manage and what Composio handles

AreaYou manageComposio handles
ServerDeploying and operating the remote MCP server at a public HTTPS URL.Connecting to the URL for tool discovery and execution. Composio does not host the server.
ToolsImplementing tools and deciding when later definition changes are ready to sync.Starting the initial sync, importing tool schemas, versioning them, and exposing them to sessions.
AuthenticationImplementing the server's API-key or DCR OAuth behavior and completing each required connection.Storing connected-account credentials and sending them when discovering or calling tools.
LifecycleChoosing when to resync, delete, or replace the toolkit.Providing the project-scoped registration, sync, and deletion operations.

Technical behavior

Each registered server becomes a custom toolkit scoped to your project:

  • The toolkit has type: "custom" and the CUSTOM category.
  • Its slug starts with CUSTOM_, such as CUSTOM_ACME.
  • Its tools are available through Tool Router search and toolkit-filtered tool listing.
  • Tool execution is proxied to your MCP server with the selected connected account's credentials.

Custom toolkits use dated registry versions. The v3.1 tools API selects the latest version by default. If you use v3 directly, select the latest version for each operation:

v3 operationSelect the latest version
List toolsAdd the toolkit_versions=latest query parameter.
Retrieve one toolAdd the version=latest query parameter.
Execute one toolSet "version": "latest" in the request body.

See Toolkit Versioning for more examples.

Known gaps