The list is not a whitelist
There is no per-client code in this server. Nothing checks aclientInfo name,
nothing branches on a user agent, and no client is registered with us before it
connects. POST /mcp is a standard Model Context
Protocol server over Streamable HTTP, and
anything that speaks the protocol connects — a named editor, a chat platform,
an automation node, a shell script, or forty lines you wrote against an MCP SDK
this afternoon.
The one thing that is client-shaped is a pair of tools,
search and fetch,
which carry the fixed schemas ChatGPT’s connector surface requires. They are
listed to every client identically and are ordinary tools everywhere else. That
is the whole of the special-casing.The four facts
Give a client these and you are done.
Three more things save an afternoon:
- No
Mcp-Session-Idis ever issued. If your client is waiting for one, it will not arrive and it does not need one. GET /mcpandDELETE /mcpreturn 405. There is no stream to open and no session to tear down. A test client reporting 405 is reporting a working server.- Neither an older client nor a newer one is locked out. This server is
dual-era:
2026-07-28has no handshake and every request declares its own revision, whileinitializestill works and still negotiates for everything before it. TheMCP-Protocol-Versionheader alone decides which you get, so the value in the table is what a client sends today and nothing about that has changed. What earns a 400 is a client asserting a revision we do not speak — and that 400 lists what we do, so it is one retry, not a guess. Protocol revisions has the detail.
Editors and coding agents
Verified against each project’s own documentation on 2026-09-07. Where a client has changed its format recently, this is the current one.Windsurf — serverUrl, and the Cascade rebrand
Windsurf — serverUrl, and the Cascade rebrand
The remote form takes
serverUrl (or url); a command key is what makes
a server local, and there is no separate transport flag. ${env:VAR} and
${file:/path} both expand, so the key need not sit in the file. Note that
Windsurf’s MCP documentation now lives under Devin Desktop and is labelled
as applying to the legacy Cascade agent — if your Windsurf is newer than
that, check its own current docs before trusting this block.Zed — drop the header and you get OAuth instead
Zed — drop the header and you get OAuth instead
Zed’s own documentation says that when a remote server has no configured
Authorization header, it prompts you through the standard MCP OAuth flow.
Since Zed documents no environment-variable expansion in
context_servers, that is the better option here: omit headers
entirely and let Zed authenticate, rather than writing a workspace key
into settings.json. Project-scoped context_servers in
.zed/settings.json are not documented — treat this as user-level config.Cline — type is effectively required
Cline — type is effectively required
Omitting
type falls back to the legacy sse transport for backward
compatibility, and we serve no SSE stream, so the connection simply fails.
Set "type": "streamableHttp" — camelCase, which matches no other client on
this page. Cline’s own docs disagree with each other about where the settings
file lives, so open it from the MCP Servers → Configure button rather
than typing a path.Continue — mcpServers is a list, and secrets come from .env
Continue — mcpServers is a list, and secrets come from .env
Not an object, unlike almost everywhere else.
${{ secrets.NAME }} resolves
from .env at the workspace root, then .continue/.env, then
~/.continue/.env. It does not read your shell environment: Continue’s
own FAQ says the IDE extensions cannot, so exporting the variable in your
profile and expecting it to arrive will not work.Goose — uri, not url, and SSE is gone
Goose — uri, not url, and SSE is gone
The config key is
uri (the deeplink form uses url, which is a good way to
lose ten minutes). streamable_http uses underscores. Goose has removed SSE
support entirely, which for this server changes nothing. A token referenced
as ${IMPELLABS_API_KEY} must also be named in env_keys, or the
substitution has nothing to substitute from.Junie vs JetBrains AI Assistant
Junie vs JetBrains AI Assistant
These are two different products with two different answers, and the
distinction matters. Junie documents
url plus a headers map, with
Authorization: Bearer token as its own worked example — so the block above
is the documented shape. AI Assistant is configured only through
Settings | Tools | AI Assistant | Model Context Protocol, documents a
url-only remote server, and documents no way to set a header at all.
See below.Chat platforms and automation
Warp has no transport field at all — it infers it from the URL. It also
documents
${VAR} expansion only for a CLI server’s args, not for a URL
server’s headers, so expect to paste the key literally and prefer a narrowly
scoped one accordingly.n8n
n8n is not a config file; it is a node. Add the MCP Client Tool node and set:Node version 1.2 and later default to HTTP Streamable; version 1 predates it
and speaks SSE only, which we do not serve. n8n’s documentation page for this
node still describes only the old SSE Endpoint field — if that is what you
see, the node on your canvas is an old version, and adding a fresh one gives
you the transport selector.
Where we could not verify a config
A wrong config block costs more than a missing one, so these are named rather than guessed at.
If your client is not on this page at all, it is very likely fine. Give it the
four facts at the top.
Anything built on an MCP SDK
Forty lines is a client. Both official SDKs connect to this server with no adapter, no bridge and nothing registered on our side.Two details that cost time rather than failing loudly. In Python, a bare
httpx2.AsyncClient() defaults to a 5-second total timeout — pass one
explicitly, as above. And Client("https://…") accepts a bare URL string but
builds its own transport with no HTTP client, so it cannot carry an
Authorization header; pass the transport object.Whichever era your SDK is on
The snippets above are handshake-era clients, which is what both SDKs do by default and what every shipping client sends today. They keep working exactly as written. But this server is dual-era — it also answers the current2026-07-28, in which there is no handshake at all — so an SDK on either side
of that line connects:
- An SDK that speaks
2025-06-18runsinitialize, which is answered in the newest handshake revision we speak rather than refused over an unrecognised version string. Nothing about that path changed when the modern era was added, and nothing about it is going to. - An SDK that probes for a modern server first finds one.
server/discoveris answered here — in either era, so even a probe that forgot theMCP-Protocol-Versionheader gets told what we speak — and an unsupported revision comes back as-32022, the code a dual-era client reads to decide it is talking to a modern server rather than falling back toinitialize. - A client that goes modern must then send the header, two required
_metakeys and the mirroredMcp-Method/Mcp-Nameheaders on every request. Protocol revisions is the page for that.
Rate limits and transport constraints
What a client gets refused for, and which refusals are worth retrying.
What is the same in every client
None of the above changes what a model may do. The client decides how the connection is spelled; the credential decides what it can reach, and that is checked inside the dispatcher on every single call.Tools
What is callable, and how to get the authoritative list for your own key.
Credits
What a tool call costs, and what an empty wallet returns.

