Skip to content

Connect over MCP ​

Configure connects agents to approved context and app tools through MCP. An agent can retrieve updates and save new context throughout the connection, across conversations. Configure exposes configure_* tools through two MCP endpoints. Choose the endpoint for your authentication method and the user your agent serves.

Choose how your agent connects ​

You want toEndpointCredential
Let any AI assistant you message connect itself, from a URL you give itconnect.configure.devNone up front. The assistant opens a session and sends you one link to approve. See Any assistant can connect itself.
Give your own Claude, ChatGPT, Cursor or Codex your approved Configure contextmcp.configure.devOAuth managed by the MCP client. Your app does not manage tokens.
Give your product's users access to their approved contextapi.configure.dev/mcpA per-user session your server creates with mcpSession()
Run one agent for yourself, headless, with no browserapi.configure.dev/mcpX-API-Key plus X-Agent, your own credentials
Connect a person's own headless agent (no browser, no API key)mcp.configure.devThe person approves one link. See Connect a headless agent.

Use the personal connection for an agent you already use. Use a per-user server session when your product serves multiple users. Each endpoint accepts only its documented credential types.

Any assistant can connect itself ​

An assistant that can send an HTTP POST request can connect to Configure. It does not need to be a listed app or have a connector settings screen. Give it the URL:

text
https://connect.configure.dev

connect.configure.dev and mcp.configure.dev are the same server. Each answers on its own name, so either works anywhere on this page. The assistant connects in two JSON-RPC calls, POSTed with Content-Type: application/json and Accept: application/json, text/event-stream:

  1. initialize opens a session. Its clientInfo names the assistant on the approval screen: the title if one is sent, otherwise the name. The Mcp-Session-Id response header identifies the session on each later request.

    json
    {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"Your product name"}}}
  2. configure_connect on that session returns a connect_url.

    json
    {"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"configure_connect","arguments":{}}}

You open the connect_url, sign in and approve. Nothing in your profile is readable before that. After approval, the profile tools work on the same session. For a connection that outlasts the session, see Connect a headless agent.

Connect an app you already use ​

Use this option to connect your personal Claude, ChatGPT, or coding agent. No application code is required.

text
https://mcp.configure.dev
ClientHow
Claude Codeclaude mcp add --transport http configure https://mcp.configure.dev
Codexnpx -y @configure-ai/mcp login --personal --client codex
Claude, ChatGPT, Cursor, anything that does OAuthAdd https://mcp.configure.dev as a remote MCP server in its connector settings.

The configure_* tools appear in the client. You sign in inside the conversation. When a tool requires authorization, its result includes a connect_url. Open that URL to authorize access. Repeat this for as many agents as you like. Each approved agent accesses the same user profile.

Use a connection token when the client has no OAuth ​

Claude, ChatGPT, Codex, and any client registered through dynamic client registration run the OAuth flow themselves. No additional connection credential is required. A host without its own OAuth client needs a durable credential instead. Configure supports two credential formats. Choose the format accepted by your MCP client:

Your client's settings screen hasUse
A field for request headershttps://mcp.configure.dev with Authorization: Bearer <token>
Only a server URL boxhttps://mcp.configure.dev/u/<token>

The token is a long-lived, scoped cfg_agt_ credential. The user creates it after they approve, on the sign-in page that connect_url opens. In the URL form, the token is part of the URL. Keep the entire URL secret. Anyone with the URL can use its access grant.

Configure reads the clientInfo your host sends at initialize to tell which case applies. configure_connect includes this guidance in its result only for clients that need it.

Connect from your own server ​

Everything below uses api.configure.dev/mcp. The tools and the protocol are the same. Your developer credentials replace the browser sign-in. mcp.configure.dev cannot serve this case, because OAuth needs a person at a browser.

Serve one user: yourself ​

Examples are a personal assistant, a cron job, or a headless agent on someone's platform. Use this option when the agent serves only you. Send your own credentials and call the server directly:

bash
curl -X POST https://api.configure.dev/mcp \
  -H "X-API-Key: $CONFIGURE_API_KEY" \
  -H "X-Agent: $CONFIGURE_AGENT" \
  -H 'content-type: application/json' \
  -H 'accept: application/json, text/event-stream' \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

200 means the key and the agent name match. 401 means they do not. A key is issued for one agent handle, so CONFIGURE_AGENT must be the handle the key was created for.

Serve many users: one session each ​

Your product serves people other than you. Create a short-lived session for each user on your server, and pass the result to the model:

ts
// A session is minted for any user you name. Whether they have connected comes
// from read().profile.linked, and only connect() mints a link.
const session = await profile.mcpSession();

const response = await anthropic.beta.messages.create({
  model: "claude-opus-5",
  max_tokens: 16000,
  betas: ["mcp-client-2025-11-20"],
  system: systemPrompt,
  messages: turnMessages,
  mcp_servers: session.mcp_servers,
  tools: session.mcp_servers.map((s) => ({ type: "mcp_toolset", mcp_server_name: s.name })),
});

The session returns { ok, linked, continued, session, mcp_url, mcp_servers, message, livemode }. It has no connect_url. Only profile.connect() returns one. Do not treat the session's linked as proof the user connected. In the sandbox it is true for a user who never connected, while read() reports correctly.

Each entry in mcp_servers is { type: "url", url, name, authorization_token }. It provides a Streamable HTTP endpoint and bearer token for the MCP client. The same session works with:

  • Anthropic's mcp_servers
  • OpenAI's mcp tool on the Responses API
  • the Vercel AI SDK's createMCPClient
  • the MCP TypeScript SDK's StreamableHTTPClientTransport, with the bearer in requestInit.headers

The Quickstart shows each one. Always use one session per user. The bearer token identifies the user.

Pass mcp_servers to the model. If you create a session and do not pass it, the tools never appear in the model's list, and the model cannot use them.

Why one shared connection cannot work ​

An MCP connection carries exactly one identity. It comes from the credential, never from tool arguments. No Configure tool accepts a user ID as input, and every write is attributed on the server.

If a tool took a user_id argument, the model would choose whose memory to read. One prompt injection in a retrieved email could then expose another user's memory. The credential keeps identity out of the model's reach. Do not share one session across users. The per-user session is what keeps your users' profiles apart.

Serve one person with no browser ​

This is for a cron job or scheduled agent that acts for one person other than you and cannot run OAuth. It takes three unauthenticated calls. npx -y @configure-ai/mcp login --personal runs them for you:

  1. POST /v1/mcp/personal/sessions with { "client": "<your name>" } returns a sessionId and a browserUrl. The person opens the URL once and approves.
  2. GET /v1/mcp/personal/sessions/<id> returns installationId and refreshToken after they approve. Store both.
  3. POST /v1/mcp/personal/token with those two values returns a 15-minute access token. Call POST /v1/mcp/personal with that token as a bearer, plus X-Configure-MCP-Installation: <installationId>.

The card is an MCP app ​

configure_connect returns a result a host can render, as well as a link. The rendering is an MCP app, a page Configure serves that the host shows in an iframe. Hosts that support MCP apps show the card inline. It has the heading "Connect your accounts", the Claude, ChatGPT, Gemini, and Grok marks, and Connect and Not now. Other hosts fall back to the connect_url in the result. That is why the result always carries both.

Configure provides the card. Its Connect button opens the same hosted flow described in the Quickstart. Clients without MCP app support show the connection URL instead.

Match the credential to the host ​

Each host rejects the other host's credentials:

HostAcceptsRejects
mcp.configure.devOAuth grants, and cfg_agt_ connection tokensAPI keys, created session tokens
api.configure.dev/mcpX-API-Key plus X-Agent, created session tokensOAuth access tokens

An endpoint mismatch can become visible only when a tool is called. mcp.configure.dev completes initialize and lists 9 tools for an API key, or for no credential at all. It refuses only when a tool is called. Check the endpoint before checking the credential.

Read the tool list correctly ​

The credential determines which tools are available:

  • Your API key alone: 9 tools, configure_connect plus the eight profile tools. You get only what the credential was explicitly granted.
  • A per-user session: the full catalog of 17 tools: configure_connect, eight profile tools (profile_read, profile_search, profile_remember, profile_remember_many, profile_forget, profile_commit, profile_import, project_share), six reads (gmail_search, calendar_get, drive_search, notion_search, sheets_search, sheets_read), and two actions (email_send, calendar_create_event), all prefixed configure_. The session lists all of them whether or not that user has connected yet. Sheets writes are SDK and REST only. See Connected apps.

The seventeen tool definitions contain approximately 45,000 characters of JSON. They are included in the model's context on every turn. To send fewer, use profile.tools({ connectors, actions }) on the SDK path.

Distinguish tool availability from authorization. The session decides which tools are listed. What the user approved decides which calls run. A session lists the full catalog whether or not the user connected each app, or connected at all. A call without user authorization returns an authorization response with a connection URL.

So configure_notion_search appears as soon as you create a session, before the user connects Notion. Calling it before they connect returns tool_not_connected and a connect link. Handle this response by showing the connection URL to the user.

Listing the full catalog lets the model request connections for apps that are not yet authorized.

Apply these checks in your integration:

  • A tool count is not an auth check. Tools being present says nothing about what will execute.
  • Most clients cache the tool list at connect time. A user who links after connecting needs a fresh connection before the fuller list appears.

Ongoing connections and MCP events ​

An MCP connection lets an agent retrieve approved context and contribute new context over time. Manual imports add existing context. MCP tool calls and SDK conversation commits provide subsequent updates. An agent's cached context follows its integration's refresh schedule.

MCP Events adds subscription-based delivery: an MCP server sends matching updates to a subscribed ChatGPT chat through a webhook. Users select what to monitor and how the agent should respond. The specification requires event discovery and subscription methods in addition to tools.

The Configure endpoints documented here expose tools. This repository does not currently implement events/list, events/subscribe, or events/unsubscribe. Verify event support in the specific integration before relying on subscription delivery. MCP Events does not provide automatic access to a user's ChatGPT conversations.

Handle refusals ​

Handle each authorization response according to its error category:

  • authorization_required arrives as a successful tool result with a connect_url and expires_at. It means the user is not signed in. It never means "no data on this user". Show the link verbatim.
  • A connector call for an unconnected app fails with tool_not_connected. The error payload carries the connection URL for authorization. Give the user that link. Never build one yourself.
  • -32009 commit_required means a profile read requires a corresponding conversation commit. Commit the turn, then retry. configure_connect does not fix this.

The full failure table is in the Quickstart.

Infrastructure to connect agents, apps, and chats