Skip to content

Send a stored MCP token with the scheme it names - #332

Open
nicklaunches wants to merge 1 commit into
CopilotKit:mainfrom
nicklaunches:pr/mcp-token-scheme
Open

Send a stored MCP token with the scheme it names#332
nicklaunches wants to merge 1 commit into
CopilotKit:mainfrom
nicklaunches:pr/mcp-token-scheme

Conversation

@nicklaunches

Copy link
Copy Markdown

The problem

Every token stored against a custom MCP server is sent as Authorization: Bearer <token>, with no
way to say otherwise. Some vendors forward that header straight through to an API that only speaks
Basic auth. Those servers still answer initialize and tools/list to anything, so the Plugins
page reports the connector connected, the tools are listed and offered to Bots, and then every real
tool call comes back 401. DataForSEO's hosted MCP server behaves exactly this way, and the failure
is invisible until somebody reads a tool result.

There was no workaround from the UI: whatever the operator pasted, the header said Bearer.

What changed

authorizationHeader() in server/src/plugins/mcp.ts decides the header a stored token becomes.
A token that already names its scheme, meaning it starts with Basic or Bearer followed by a
credential, is sent as written. A bare token is still sent as Bearer <token>, so every connector
that works today keeps working and nothing needs re-entering.

The scheme travels with the credential instead of becoming another column on the server row. That
keeps rotation to one field: pasting a new token can change how it is presented and no other part
of the connector has to know.

A scheme word with nothing after it is treated as a bare token, since that is far more likely to be
a credential that happens to read like the word than a header with a missing value.

How it was verified

  • server/tests/plugin-mcp-authorization.test.ts covers the five cases: a bare token, a token
    already carrying Basic, one already carrying Bearer, surrounding whitespace, and a scheme
    word with no credential after it. 5 pass, 0 fail.
  • bun run typecheck clean across app, server and worker.
  • bunx biome check clean on the changed files.

🤖 Generated with Claude Code

Every token stored against a custom MCP server went out as Bearer.
A vendor that forwards the Authorization header to an API which only
speaks Basic still answers the handshake and the tool listing, so the
connector looked connected and its tools were offered, and every real
call came back 401. DataForSEO's hosted server behaves exactly that way.

A token that already begins with Basic or Bearer is now sent as written;
a bare token is still Bearer, so nothing already working changes. The
scheme travels with the credential rather than as another setting on the
server row, so rotating a token can change how it is presented and
nothing else has to know.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WaHWJ1niprhBc5NzJ9pxme
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant