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:
- Deploy your MCP server at a public HTTPS URL.
- Register its URL and authentication scheme. Composio creates a project-scoped
CUSTOM_*toolkit. - Connect an account if the server uses an API key or DCR OAuth. No-auth servers skip this step.
- Sync its tools. The first sync starts automatically; later tool changes require a manual sync.
- 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:
| Authentication | Use it when | After registration |
|---|---|---|
| No auth | The server accepts requests without credentials. | No connection is required. Initial sync runs automatically. |
| API key | Each connected account supplies an API key. | Create an active connection. Initial sync then starts in the background. |
| DCR OAuth | The 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
| Area | You manage | Composio handles |
|---|---|---|
| Server | Deploying 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. |
| Tools | Implementing 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. |
| Authentication | Implementing 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. |
| Lifecycle | Choosing 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 theCUSTOMcategory. - Its slug starts with
CUSTOM_, such asCUSTOM_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 operation | Select the latest version |
|---|---|
| List tools | Add the toolkit_versions=latest query parameter. |
| Retrieve one tool | Add the version=latest query parameter. |
| Execute one tool | Set "version": "latest" in the request body. |
See Toolkit Versioning for more examples.