External MCP connectors
Attach external MCP servers to iCog so the chat tool loop can call their tools.
iCog can act as an MCP client. You attach an external MCP server (by URL), iCog contacts it to discover its tools, and those tools become available to the chat tool loop. You decide which tools iCog may use and whether each one runs automatically or asks for confirmation first.
This is the inverse of Build an MCP client, which connects your tools to iCog. Here, iCog connects to your MCP servers.
All endpoints are under https://api.cognitivx.io and mounted at
/api/connectors/mcp. Every endpoint authenticates with a key created at
developers.cognitivx.io/keys:
Authorization: Bearer <key>or
X-API-Key: <key>The one exception is GET /api/connectors/mcp/oauth/callback, which the OAuth
provider's browser redirect hits directly (no key). It validates a state token
instead.
This page covers the iCog-as-MCP-client surface only. First-party OAuth
connectors (Gmail, Google Drive, GitHub) live under a separate /api/connectors
prefix and are not documented here.
Lifecycle
Create a connector with a server URL and an auth type. For none and
bearer connectors iCog contacts the server immediately and discovers its tools.
For oauth2 connectors the connector is saved as pending and you start the
OAuth flow next.
Authorize (OAuth only). Call POST /{id}/oauth/start, open the returned
authorization_url, and let the provider redirect back. iCog exchanges the code,
then discovers tools.
Tune which tools are enabled and their trust tier (auto runs without
asking, confirm asks first) with PATCH /{id}/tools/{tool_name}.
Use the tools. The chat tool loop loads every connected connector's
enabled tools automatically for that user. There is no per-request opt-in.
Connector status values
A connector's status reflects the last discovery or OAuth attempt:
| Status | Meaning |
|---|---|
pending | Created, awaiting OAuth authorization or first discovery. |
connected | Reachable; tools discovered. Its enabled tools are live in chat. |
error | Last contact failed. status_detail carries the reason. |
List the catalog
One-line: return the curated directory of suggested servers shown in the add dialog.
GET /api/connectors/mcp/catalog
Auth: Authorization: Bearer <key> or X-API-Key: <key>
The catalog is a static list of seed cards. Adding one just prefills the same create flow a custom URL uses. It does not create anything.
curl https://api.cognitivx.io/api/connectors/mcp/catalog \
-H "Authorization: Bearer $ICOG_API_KEY"{
"items": [
{
"key": "deepwiki",
"name": "DeepWiki",
"description": "Ask questions about any public GitHub repository's docs.",
"server_url": "https://mcp.deepwiki.com/mcp",
"transport": "streamable_http",
"auth_type": "none",
"icon": "book-open"
},
{
"key": "context7",
"name": "Context7",
"description": "Up-to-date code docs and examples for popular libraries.",
"server_url": "https://mcp.context7.com/mcp",
"transport": "streamable_http",
"auth_type": "bearer",
"icon": "library"
},
{
"key": "custom",
"name": "Custom server",
"description": "Connect any MCP server by URL.",
"server_url": "",
"transport": "streamable_http",
"auth_type": "none",
"icon": "plug"
}
]
}List your connectors
One-line: return all of your attached connectors, each with its discovered tools embedded.
GET /api/connectors/mcp
Auth: Authorization: Bearer <key> or X-API-Key: <key>
curl https://api.cognitivx.io/api/connectors/mcp \
-H "Authorization: Bearer $ICOG_API_KEY"{
"connectors": [
{
"id": "8f3c2b1a-0d44-4e9a-9c2e-1a2b3c4d5e6f",
"slug": "deepwiki",
"display_name": "DeepWiki",
"server_url": "https://mcp.deepwiki.com/mcp",
"transport": "streamable_http",
"auth_type": "none",
"status": "connected",
"status_detail": null,
"has_credentials": false,
"last_connected_at": "2026-06-16T18:04:11.220190+00:00",
"created_at": "2026-06-16T18:04:10.880431+00:00",
"tools": [
{
"tool_name": "ask_question",
"description": "Ask a question about a GitHub repository's docs.",
"input_schema": {
"type": "object",
"properties": {
"repo": { "type": "string" },
"question": { "type": "string" }
},
"required": ["repo", "question"]
},
"enabled": true,
"trust_tier": "confirm"
}
]
}
]
}Credentials are never returned. has_credentials tells you whether a token is
stored; trust_tier is auto (runs without asking) or confirm (asks first).
Create a connector
One-line: attach a server; for non-OAuth connectors iCog discovers its tools immediately.
POST /api/connectors/mcp
Auth: Authorization: Bearer <key> or X-API-Key: <key>
Returns 201 Created.
| Field | Type | Required | Description |
|---|---|---|---|
display_name | string | yes | Human label, 1 to 80 chars. Also seeds the connector slug. |
server_url | string | yes | The MCP server endpoint, 1 to 2000 chars. |
transport | string | no | MCP transport. Defaults to streamable_http. Must be a valid transport. |
auth_type | string | no | none, bearer, or oauth2. Defaults to none. |
access_token | string | no | Bearer token. Required when auth_type is bearer. |
When auth_type is bearer you must include access_token, or the request
fails with 400. When auth_type is oauth2 you leave access_token out and
start the OAuth flow afterward.
curl -X POST https://api.cognitivx.io/api/connectors/mcp \
-H "Authorization: Bearer $ICOG_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"display_name": "DeepWiki",
"server_url": "https://mcp.deepwiki.com/mcp",
"transport": "streamable_http",
"auth_type": "none"
}'The @cognitivx/sdk namespaces do not include a connectors helper, so call the
endpoint with the configured client.
import { configureApiClient, apiClient } from '@cognitivx/sdk';
configureApiClient({ apiKey: process.env.ICOG_API_KEY! });
const { data } = await apiClient.POST('/api/connectors/mcp', {
body: {
display_name: 'DeepWiki',
server_url: 'https://mcp.deepwiki.com/mcp',
transport: 'streamable_http',
auth_type: 'none',
},
});For a none or bearer connector, the response includes the discovery result:
{
"connector": {
"id": "8f3c2b1a-0d44-4e9a-9c2e-1a2b3c4d5e6f",
"slug": "deepwiki",
"display_name": "DeepWiki",
"server_url": "https://mcp.deepwiki.com/mcp",
"transport": "streamable_http",
"auth_type": "none",
"status": "connected",
"status_detail": null,
"has_credentials": false,
"last_connected_at": "2026-06-16T18:04:11.220190+00:00",
"created_at": "2026-06-16T18:04:10.880431+00:00",
"tools": [
{
"tool_name": "ask_question",
"description": "Ask a question about a GitHub repository's docs.",
"input_schema": { "type": "object", "properties": {} },
"enabled": true,
"trust_tier": "confirm"
}
]
},
"discovery": {
"tool_count": 1,
"tools": ["ask_question"]
},
"error": null
}If discovery fails (bad URL, dead server, wrong token), the connector is still
saved so you can fix it and retry with POST /{id}/test. The status becomes
error and discovery is empty:
{
"connector": {
"id": "8f3c2b1a-0d44-4e9a-9c2e-1a2b3c4d5e6f",
"slug": "deepwiki",
"display_name": "DeepWiki",
"server_url": "https://mcp.deepwiki.com/mcp",
"transport": "streamable_http",
"auth_type": "none",
"status": "error",
"status_detail": "connection refused",
"has_credentials": false,
"last_connected_at": null,
"created_at": "2026-06-16T18:04:10.880431+00:00",
"tools": []
},
"discovery": {},
"error": "connection refused"
}For an oauth2 connector, no discovery runs yet. The response flags that
authorization is required:
{
"connector": {
"id": "8f3c2b1a-0d44-4e9a-9c2e-1a2b3c4d5e6f",
"slug": "linear",
"display_name": "Linear",
"server_url": "https://mcp.linear.app/mcp",
"transport": "streamable_http",
"auth_type": "oauth2",
"status": "pending",
"status_detail": "Authorization required",
"has_credentials": false,
"last_connected_at": null,
"created_at": "2026-06-16T18:04:10.880431+00:00",
"tools": []
},
"discovery": {},
"error": null,
"oauth_required": true
}Errors
| Status | When |
|---|---|
400 | transport is not a valid transport, auth_type is not none/bearer/oauth2, or auth_type is bearer with no access_token. |
422 | Missing display_name or server_url, or a field violates its length bounds. |
Authorize an OAuth connector
One-line: begin the OAuth 2.0 (Authorization Code + PKCE) handshake and get the URL to open.
POST /api/connectors/mcp/{connector_id}/oauth/start
Auth: Authorization: Bearer <key> or X-API-Key: <key>
iCog discovers the server's OAuth endpoints, registers a client via Dynamic
Client Registration if needed, generates PKCE plus a state token, and returns
the authorization URL. Open it in a browser or popup.
curl -X POST \
https://api.cognitivx.io/api/connectors/mcp/8f3c2b1a-0d44-4e9a-9c2e-1a2b3c4d5e6f/oauth/start \
-H "Authorization: Bearer $ICOG_API_KEY"{
"authorization_url": "https://mcp.linear.app/oauth/authorize?response_type=code&client_id=icog-...&redirect_uri=https%3A%2F%2Fapi.cognitivx.io%2Fapi%2Fconnectors%2Fmcp%2Foauth%2Fcallback&code_challenge=...&state=..."
}After the user consents, the provider redirects to
GET /api/connectors/mcp/oauth/callback. That endpoint validates state,
exchanges the code for tokens, discovers tools, and bounces the browser to
/connectors?section=mcp&oauth=success on the frontend (or oauth=error with an
oauth_error message on failure). You do not call the callback yourself.
Errors
| Status | When |
|---|---|
404 | No connector with that id belongs to you. |
400 | The server has no dynamic registration endpoint and no pre-registered client_id, or another OAuth discovery error. The connector is marked error. |
Test (re-discover) a connector
One-line: re-contact the server and refresh its tool list.
POST /api/connectors/mcp/{connector_id}/test
Auth: Authorization: Bearer <key> or X-API-Key: <key>
Use this after fixing a URL or token, or to pick up tools the server added. New tools land enabled with a heuristic trust tier; tools that vanished are removed; your enabled/trust choices on surviving tools are preserved.
curl -X POST \
https://api.cognitivx.io/api/connectors/mcp/8f3c2b1a-0d44-4e9a-9c2e-1a2b3c4d5e6f/test \
-H "Authorization: Bearer $ICOG_API_KEY"{
"ok": true,
"tool_count": 2,
"tools": ["ask_question", "read_wiki_structure"]
}Errors
| Status | When |
|---|---|
404 | No connector with that id belongs to you. |
502 | The MCP server could not be reached. The message carries the server's error. |
Toggle a tool
One-line: enable/disable a tool or change whether it runs automatically.
PATCH /api/connectors/mcp/{connector_id}/tools/{tool_name}
Auth: Authorization: Bearer <key> or X-API-Key: <key>
| Field | Type | Required | Description |
|---|---|---|---|
enabled | boolean | no | Whether the chat tool loop may offer this tool. Omit to leave unchanged. |
trust_tier | string | no | auto (run without asking) or confirm (ask first). Omit to leave unchanged. |
Send only the fields you want to change. Both are optional, but trust_tier, if
present, must be auto or confirm.
curl -X PATCH \
https://api.cognitivx.io/api/connectors/mcp/8f3c2b1a-0d44-4e9a-9c2e-1a2b3c4d5e6f/tools/ask_question \
-H "Authorization: Bearer $ICOG_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "enabled": true, "trust_tier": "auto" }'{ "ok": true }Errors
| Status | When |
|---|---|
400 | trust_tier is present but not auto or confirm. |
404 | The connector or tool was not found for your account. |
Remove a connector
One-line: delete a connector and all its discovered tools.
DELETE /api/connectors/mcp/{connector_id}
Auth: Authorization: Bearer <key> or X-API-Key: <key>
curl -X DELETE \
https://api.cognitivx.io/api/connectors/mcp/8f3c2b1a-0d44-4e9a-9c2e-1a2b3c4d5e6f \
-H "Authorization: Bearer $ICOG_API_KEY"{ "ok": true }Errors
| Status | When |
|---|---|
404 | No connector with that id belongs to you. |
How tools reach the chat loop
When iCog runs a chat turn for you, it loads every connected connector's
enabled tools and hands them to the model. Tool names are namespaced
{slug}__{tool} (sanitized to the model's function-name charset) so two servers
can expose tools with the same name without colliding.
Trust tier governs execution. An auto tool runs immediately; a confirm tool
pauses for your approval before it executes. At discovery time, read-ish tools
(names containing get, list, search, read, and similar) default to
auto; everything else defaults to confirm. Override per tool with the toggle
endpoint above.
LLM providers
The provider catalog is a separate, read-only endpoint.
GET /api/providers
Auth: none (public).
One-line: list the LLM providers and model ids iCog can route to.
curl https://api.cognitivx.io/api/providers{
"providers": [
{
"id": "claude",
"name": "Anthropic Claude",
"models": [
{ "id": "claude-sonnet-4-6", "name": "Claude Sonnet 4.6" },
{ "id": "claude-haiku-4-5", "name": "Claude Haiku 4.5" }
]
},
{
"id": "gemini",
"name": "Google Gemini",
"models": [
{ "id": "gemini-2.5-flash", "name": "Gemini 2.5 Flash" },
{ "id": "gemini-2.5-pro", "name": "Gemini 2.5 Pro" }
]
},
{
"id": "vertex",
"name": "Vertex Model Garden",
"models": [
{ "id": "claude-sonnet-4-6", "name": "Claude Sonnet 4.6 (Vertex)" },
{ "id": "gemini-2.5-flash", "name": "Gemini 2.5 Flash (Vertex)" }
]
}
]
}This catalog is static. It returns 200 with the list above and takes no
parameters.