> ## Documentation Index
> Fetch the complete documentation index at: https://docs.impellabs.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# Any MCP client

> The list on this tab is not a whitelist. Four facts, and configs for the clients that ask for one.

**Preview.** The pages beside this one exist because those clients are the ones
people ask about first — not because they are the ones that work.

## The list is not a whitelist

There is no per-client code in this server. Nothing checks a `clientInfo` 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](https://modelcontextprotocol.io) 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.

<Note>
  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.
</Note>

## The four facts

Give a client these and you are done.

|                          | Value                            | Notes                                                                                                                                                                                                                                                                      |
| ------------------------ | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Endpoint**             | `https://api.impellabs.tech/mcp` | One URL. `POST` carries everything.                                                                                                                                                                                                                                        |
| **Transport**            | Streamable HTTP                  | No SSE stream and no stdio. If a client asks you to choose, choose Streamable HTTP.                                                                                                                                                                                        |
| **Authorization**        | `Bearer tgcc_…`                  | Or the full OAuth 2.1 flow, which the server advertises at `/.well-known/oauth-protected-resource`.                                                                                                                                                                        |
| **MCP-Protocol-Version** | `2025-06-18`                     | The whole of `mcpserver/protocol.py: SUPPORTED_PROTOCOL_VERSIONS` is accepted: the current `2026-07-28`, plus the handshake revisions `2025-06-18`, `2025-03-26` and `2024-11-05`. Absent is read as `2025-03-26` — the spec's own rule for clients older than the header. |

Three more things save an afternoon:

* **No `Mcp-Session-Id` is ever issued.** If your client is waiting for one, it
  will not arrive and it does not need one.
* **`GET /mcp` and `DELETE /mcp` return 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-28` has no handshake and every request declares its own
  revision, while `initialize` still works and still negotiates for everything
  before it. The `MCP-Protocol-Version` header 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](/connect/protocol) 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.

<CodeGroup>
  ```json Windsurf theme={null}
  // ~/.codeium/windsurf/mcp_config.json
  {
    "mcpServers": {
      "impellabs": {
        "serverUrl": "https://api.impellabs.tech/mcp",
        "headers": {
          "Authorization": "Bearer ${env:IMPELLABS_API_KEY}"
        }
      }
    }
  }
  ```

  ```json Zed theme={null}
  // ~/.config/zed/settings.json
  // Drop the `headers` block entirely and Zed runs the OAuth flow instead —
  // which is the better option here. See the note below.
  {
    "context_servers": {
      "impellabs": {
        "url": "https://api.impellabs.tech/mcp",
        "headers": {
          "Authorization": "Bearer tgcc_xxxxxxxxxxxx"
        }
      }
    }
  }
  ```

  ```json Cline theme={null}
  // Open it from MCP Servers → Configure, rather than by path.
  {
    "mcpServers": {
      "impellabs": {
        "type": "streamableHttp",
        "url": "https://api.impellabs.tech/mcp",
        "headers": {
          "Authorization": "Bearer tgcc_xxxxxxxxxxxx"
        },
        "disabled": false,
        "autoApprove": []
      }
    }
  }
  ```

  ```yaml Continue theme={null}
  # .continue/mcpServers/impellabs.yaml
  name: ImpelLabs
  version: 0.0.1
  schema: v1
  mcpServers:
    - name: ImpelLabs
      type: streamable-http
      url: https://api.impellabs.tech/mcp
      requestOptions:
        headers:
          Authorization: Bearer ${{ secrets.IMPELLABS_API_KEY }}
  ```

  ```yaml Goose theme={null}
  # ~/.config/goose/config.yaml
  extensions:
    impellabs:
      type: streamable_http
      name: impellabs
      enabled: true
      uri: "https://api.impellabs.tech/mcp"
      headers:
        Authorization: "Bearer ${IMPELLABS_API_KEY}"
      env_keys:
        - IMPELLABS_API_KEY
      timeout: 300
  ```

  ```json Junie theme={null}
  // .junie/mcp/mcp.json — or ~/.junie/mcp/mcp.json for every project
  {
    "mcpServers": {
      "impellabs": {
        "url": "https://api.impellabs.tech/mcp",
        "headers": {
          "Authorization": "Bearer tgcc_xxxxxxxxxxxx"
        }
      }
    }
  }
  ```
</CodeGroup>

Each of those has one thing that catches people:

<AccordionGroup>
  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>

  <Accordion title="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.
  </Accordion>
</AccordionGroup>

## Chat platforms and automation

<CodeGroup>
  ```yaml LibreChat theme={null}
  # librechat.yaml
  mcpServers:
    impellabs:
      type: streamable-http
      url: https://api.impellabs.tech/mcp
      headers:
        Authorization: 'Bearer ${IMPELLABS_API_KEY}'
      requiresOAuth: false
  ```

  ```json Warp theme={null}
  // ~/.warp/.mcp.json, or paste into Settings → Agents → MCP servers → Add
  {
    "mcpServers": {
      "impellabs": {
        "url": "https://api.impellabs.tech/mcp",
        "headers": {
          "Authorization": "Bearer tgcc_xxxxxxxxxxxx"
        }
      }
    }
  }
  ```
</CodeGroup>

<Warning>
  **LibreChat: set `requiresOAuth: false` explicitly.** LibreChat auto-detects
  OAuth by probing the server *without* your configured headers. Ours answers
  that probe with **401 and a `WWW-Authenticate: Bearer` header** — correctly,
  because that is how an OAuth client is meant to discover the flow — and
  LibreChat reads it as "this server is OAuth-protected" and never uses your
  bearer key. The flag is the fix. Also note `type` is not optional: an
  `http(s)://` URL with no `type` defaults to **`sse`**, which we do not serve.
</Warning>

<Note>
  **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.
</Note>

### n8n

n8n is not a config file; it is a node. Add the **MCP Client Tool** node and set:

| Field            | Value                                                                                  |
| ---------------- | -------------------------------------------------------------------------------------- |
| Server Transport | **HTTP Streamable** (stored as `httpStreamable`)                                       |
| Endpoint         | `https://api.impellabs.tech/mcp`                                                       |
| Authentication   | **Bearer Auth**                                                                        |
| Credential       | A **Bearer Auth** credential (`httpBearerAuth`) whose Bearer Token is your `tgcc_` key |

<Note>
  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.
</Note>

## 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.

| Client                              | What is missing                                                                                                                                                                                                     |
| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **JetBrains AI Assistant**          | Connects to Streamable HTTP servers by URL, but documents no key for request headers and no config file path. If you need a bearer token inside a JetBrains IDE, [Junie](#editors-and-coding-agents) documents one. |
| **Cline (VS Code extension)**       | The settings file path is documented inconsistently. Open it from the extension's own **Configure** button.                                                                                                         |
| **Continue, Goose (global folder)** | Documented at workspace level; the global equivalents are implied rather than written down.                                                                                                                         |

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.

<CodeGroup>
  ```python python theme={null}
  # pip install mcp        (verified against mcp 2.1.1)
  import asyncio

  import httpx2
  from mcp import Client
  from mcp.client.streamable_http import streamable_http_client

  URL = "https://api.impellabs.tech/mcp"


  async def main() -> None:
      async with httpx2.AsyncClient(
          headers={"Authorization": "Bearer tgcc_xxxxxxxxxxxx"},
          timeout=httpx2.Timeout(30.0, read=300.0),
      ) as http:
          async with Client(streamable_http_client(URL, http_client=http)) as client:
              for tool in (await client.list_tools()).tools:
                  print(tool.name)


  asyncio.run(main())
  ```

  ```typescript typescript theme={null}
  // npm install @modelcontextprotocol/client   (verified against 2.0.0)
  import { Client, StreamableHTTPClientTransport } from "@modelcontextprotocol/client";

  const client = new Client({ name: "my-client", version: "1.0.0" });

  const transport = new StreamableHTTPClientTransport(
    new URL("https://api.impellabs.tech/mcp"),
    { requestInit: { headers: { Authorization: "Bearer tgcc_xxxxxxxxxxxx" } } },
  );

  await client.connect(transport);
  const { tools } = await client.listTools();
  for (const tool of tools) console.log(tool.name);
  await client.close();
  ```
</CodeGroup>

<Warning>
  **Both SDKs shipped a v2 that renamed exactly these things**, so most tutorials
  you will find describe the older shape and will not run. If you are on the v1
  line, translate: Python's transport was `streamablehttp_client`, yielded a
  three-tuple and took a `headers=` kwarg; TypeScript's package was the
  monolithic `@modelcontextprotocol/sdk` with deep `.js` import paths. The
  snippets above are the current form.
</Warning>

<Note>
  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.
</Note>

### 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 current
`2026-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-18`** runs `initialize`, 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/discover`
  is answered here — in *either* era, so even a probe that forgot the
  `MCP-Protocol-Version` header 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 to `initialize`.
* **A client that goes modern** must then send the header, two required `_meta`
  keys and the mirrored `Mcp-Method` / `Mcp-Name` headers on every request.
  [Protocol revisions](/connect/protocol) is the page for that.

<Card title="Rate limits and transport constraints" icon="gauge" href="/connect/limits" horizontal>
  What a client gets refused for, and which refusals are worth retrying.
</Card>

## 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.

<Warning>
  `mcp:connect` lists the tools and calls none of them. Every tool demands its
  own scope on top, and scopes never imply one another — a key that may read
  agents cannot run one. Mint a key per client, holding only what you want that
  client reaching unattended. See
  [Authentication](/connect/authentication).
</Warning>

<CardGroup cols={2}>
  <Card title="Tools" icon="wrench" href="/connect/tools">
    What is callable, and how to get the authoritative list for your own key.
  </Card>

  <Card title="Credits" icon="coins" href="/connect/credits">
    What a tool call costs, and what an empty wallet returns.
  </Card>
</CardGroup>
