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 to | Endpoint | Credential |
|---|---|---|
| Let any AI assistant you message connect itself, from a URL you give it | connect.configure.dev | None 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 context | mcp.configure.dev | OAuth managed by the MCP client. Your app does not manage tokens. |
| Give your product's users access to their approved context | api.configure.dev/mcp | A per-user session your server creates with mcpSession() |
| Run one agent for yourself, headless, with no browser | api.configure.dev/mcp | X-API-Key plus X-Agent, your own credentials |
| Connect a person's own headless agent (no browser, no API key) | mcp.configure.dev | The 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.devconnect.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:
initializeopens a session. ItsclientInfonames the assistant on the approval screen: thetitleif one is sent, otherwise thename. TheMcp-Session-Idresponse 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"}}}configure_connecton that session returns aconnect_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| Client | How |
|---|---|
| Claude Code | claude mcp add --transport http configure https://mcp.configure.dev |
| Codex | npx -y @configure-ai/mcp login --personal --client codex |
| Claude, ChatGPT, Cursor, anything that does OAuth | Add 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 has | Use |
|---|---|
| A field for request headers | https://mcp.configure.dev with Authorization: Bearer <token> |
| Only a server URL box | https://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
mcptool on the Responses API - the Vercel AI SDK's
createMCPClient - the MCP TypeScript SDK's
StreamableHTTPClientTransport, with the bearer inrequestInit.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:
POST /v1/mcp/personal/sessionswith{ "client": "<your name>" }returns asessionIdand abrowserUrl. The person opens the URL once and approves.GET /v1/mcp/personal/sessions/<id>returnsinstallationIdandrefreshTokenafter they approve. Store both.POST /v1/mcp/personal/tokenwith those two values returns a 15-minute access token. CallPOST /v1/mcp/personalwith that token as a bearer, plusX-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:
| Host | Accepts | Rejects |
|---|---|---|
mcp.configure.dev | OAuth grants, and cfg_agt_ connection tokens | API keys, created session tokens |
api.configure.dev/mcp | X-API-Key plus X-Agent, created session tokens | OAuth 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_connectplus 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 prefixedconfigure_. 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_requiredarrives as a successful tool result with aconnect_urlandexpires_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. -32009commit_requiredmeans a profile read requires a corresponding conversation commit. Commit the turn, then retry.configure_connectdoes not fix this.
The full failure table is in the Quickstart.