modelcontextprotocol / modelcontextprotocol/typescript-sdk

Server SDK support for signaling token expiry (401) from tool handlers

Open
#1,294 3 comments 3 reactions 1 assignee View on GitHub

@pcarleton is already working on this.

Since Dec 15, 2025.

auth enhancement P1 ready for work
Dominant language
TypeScript
Stars
13.4k
Forks
2.2k
Avg merge
3d 15h
Merged PRs (30d)
4

Description

Summary

Tool handlers that call upstream APIs with delegated OAuth tokens have no way to signal that the token has expired and needs refresh. When an upstream API returns 401, the tool handler can only throw an error, which the SDK wraps in a JSON-RPC error response with HTTP 200. The client never sees HTTP 401 and therefore never triggers token refresh.

Use Case

Consider an MCP server that wraps Gmail's API:

  1. User authenticates via OAuth, server receives access token
  2. User calls gmail_search_messages tool
  3. Server makes request to Gmail API with the access token
  4. Gmail API returns 401 (token expired)
  5. Tool handler throws an error
  6. Problem: SDK catches this and returns JSON-RPC error with HTTP 200
  7. Client receives the error but doesn't know it's an auth error that requires token refresh

The MCP client SDK only triggers token refresh when it sees HTTP 401 responses. Since tool errors are always wrapped in HTTP 200 JSON-RPC responses, the client never refreshes.

Proposed Solution

Similar to #1151 (scope challenges with 403), tool handlers should be able to signal auth errors that result in HTTP 401:

server.registerTool(
  'gmail_search',
  { ... },
  async (args, context) => {
    const response = await callGmailAPI(args);
    
    if (response.status === 401) {
      // Signal that upstream auth failed - should result in HTTP 401
      throw new TokenExpiredError();
      // or: context.signalTokenExpired();
    }
    
    return { content: [...] };
  }
);

This would allow the SDK to return HTTP 401 instead of wrapping in a JSON-RPC error, triggering the client's token refresh flow.

Related

  • #1151 - Server SDK support for scope challenges on tool calls (same pattern for 403)
  • #1039 - Support upscoping on insufficient_scope 403 like in Python SDK

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.