Secrets and tokens

Verify MCP server tokens with a direct API call first

You will test a token against its target API with a plain HTTP request before passing it into an MCP server or transport. This shows whether a failure comes from the token or from the MCP setup.

  1. Call API directlyConfirm the token works with a plain HTTP request
  2. Configure transportPass headers in the options object
  3. Read header in serverConfirm the server receives the Authorization header
  4. Remove debug loggingKeep credentials out of logs

Why it matters

When an MCP client sends a token and the server never receives it, the cause is often the transport setup rather than the token. In one TypeScript SDK case, the Authorization header never reached the server because the transport was built with three constructor arguments instead of two (issue 495 (opens external site)). Checking the token with a direct request first shows which layer is failing.

Steps

  1. Take the exact token your MCP config will use and call the target API with it from a plain HTTP client, outside any MCP code. Use one request to an endpoint that requires authentication.
  2. If the call returns 401 or 403, fix the token (expired, wrong scope, wrong audience) before you touch the MCP server.
  3. In the TypeScript SDK, pass the server URL as the first argument and put sessionId and requestInit.headers into one options object as the second argument (issue 495 (opens external site)):
const transport = new StreamableHTTPClientTransport(new URL(serverUrl), { sessionId: sessionId, requestInit: { headers: { Authorization: 'Bearer ' + token } } });

This fix was reported rather than officially verified, so confirm it against your own server. 4. Start the MCP server and make one tool call that needs the token. Confirm the server receives the Authorization header before you debug anything else. 5. For reading headers inside a tool, the examples in issue 750 (opens external site) use the fastmcp package, not the plain Python SDK. With fastmcp, define the tool with a Context parameter and read context.request_context.request.headers.get("example-header"). Reading headers directly in the plain Python SDK is tracked separately in issue #2098. 6. Once the call works, remove any temporary logging of requests before you ship.

Common mistakes

Checklist guidance

Work through the checklist below before you rely on a configuration in production.

Checklist

0 of 7 done

Sources

  1. How to pass custom headers to StreamableHTTPClientTransport in @modelcontextprotocol/sdk 1.11.2?
  2. MCP TypeScript SDK: initial access token for OAuth Dynamic Client Registration?
  3. How do MCP tools access HTTP request headers in streamable HTTP mode?
Was this guide useful?