Skip to content

Conversation

@thinhtpt-dev
Copy link
Contributor

@thinhtpt-dev thinhtpt-dev commented Jan 6, 2026

Summary

Fix issue OAuth Flow was not triggered when using StreamableHTTP with Direct connection type.

Note: Inspector V2 is under development to address architectural and UX improvements. During this time, V1 contributions should focus on bug fixes and MCP spec compliance. See CONTRIBUTING.md for more details.

Type of Change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Documentation update
  • Refactoring (no functional changes)
  • Test updates
  • Build/CI improvements

Changes Made

Added StreamableHTTPError handling to is401Error() so 401 responses from the Streamable HTTP transport now trigger the existing auth-retry flow, keeping OAuth re-auth logic consistent across transport types.

Related Issues

Fixes #982 and #960

Testing

  • Tested in UI mode
  • Tested in CLI mode
  • Tested with STDIO transport
  • Tested with SSE transport
  • Tested with Streamable HTTP transport
  • Added/updated automated tests
  • Manual testing performed

Test Results and/or Instructions

How to test this fix:

  1. Set up an MCP server with OAuth protection that returns a WWW-Authenticate header on 401
  2. Start the Inspector and select "Streamable HTTP" transport
  3. Enter the OAuth-protected MCP server URL
  4. Select "Direct" option in Connection Type
  5. Click Connect
  6. Expected (with fix): OAuth flow is triggered - user is redirected to Authorization page
  7. Before fix: Shows "Connection Error - Check if your MCP server is running and proxy token is correct"

Checklist

  • Code follows the style guidelines (ran npm run prettier-fix)
  • Self-review completed
  • Code is commented where necessary
  • Documentation updated (README, comments, etc.)

Breaking Changes

Additional Context

@thinhtpt-dev thinhtpt-dev marked this pull request as ready for review January 6, 2026 07:15
@thinhtpt-dev
Copy link
Contributor Author

Hi @cliffhall, can you help us take a look this pull request? Thank you.

@cliffhall
Copy link
Member

Hi @cliffhall, can you help us take a look this pull request? Thank you.

Hi @thinhtpt-dev! Thanks for this, and it does seem to solve the problem, but for Direct mode only. Still trying to figure out where Via Proxy is dropping the ball and hoping to get a single PR to fix it.

Copy link
Member

@cliffhall cliffhall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merged an extra check that fixes it for Via Proxy connection mode as well.

@cliffhall cliffhall dismissed their stale review January 7, 2026 19:08

Merged my fix directly

cliffhall
cliffhall previously approved these changes Jan 7, 2026
@cliffhall cliffhall enabled auto-merge January 7, 2026 19:12
cliffhall

This comment was marked as duplicate.

cliffhall

This comment was marked as resolved.

cliffhall

This comment was marked as duplicate.

Copy link
Member

@cliffhall cliffhall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works fine. I had to add an extra check that in the is401Error function that checks for "Missing Authorization header" which is what's coming back when it fails with Via Proxy connection type.

@evalstate
Copy link
Member

Tested against OAuth Servers in both modes, LGTM.

@cliffhall cliffhall merged commit fc8066e into modelcontextprotocol:main Jan 7, 2026
4 checks passed
@jacopoc
Copy link

jacopoc commented Jan 8, 2026

@cliffhall I have tested the latest changes with my Keycloak and I can confirm that they have fixed the Direct mode.
However I am still facing the same issue when I use the Proxy mode. In the console the following error is logged by the proxy:

New StreamableHttp connection request
Query parameters: {"url":"http://localhost:3000/mcp","transportType":"streamable-http"}
Created StreamableHttp client transport
Client <-> Proxy  sessionId: 4dc97ac4-4423-455e-ab48-53afba02e52a
Error from MCP server: StreamableHTTPError: Streamable HTTP error: Error POSTing to endpoint: {"jsonrpc":"2.0","error":{"code":-32001,"message":"Authorization required"},"id":null}
    at StreamableHTTPClientTransport.send (.../node_modules/@modelcontextprotocol/sdk/src/client/streamableHttp.ts:551:23)
    at process.processTicksAndRejections (node:internal/process/task_queues:105:5) {
  code: 401
}

@jacopoc
Copy link

jacopoc commented Jan 8, 2026

@cliffhall I have also tested the latest changes with https://example-server.modelcontextprotocol.io/mcp and I am getting different results.

In particular, Proxy mode works fine, whereas in Direct mode, after the redirection and successful user authentication/authorization, the connection fails with the following generic error displayed under the Connect button:
Connection Error - Check if your MCP server is running and proxy token is correct

I've noticed, but I don't know if it is relevant, that in the Developers tools of the browser the following request returns a 400 Bad Request error:

Request URL: https://example-server.modelcontextprotocol.io/mcp
Request Method: POST
Request body: {method: "notifications/initialized", jsonrpc: "2.0"}

@cliffhall
Copy link
Member

@cliffhall I have also tested the latest changes with https://example-server.modelcontextprotocol.io/mcp and I am getting different results.

In particular, Proxy mode works fine, whereas in Direct mode, after the redirection and successful user authentication/authorization, the connection fails with the following generic error displayed under the Connect button: Connection Error - Check if your MCP server is running and proxy token is correct

@jacopoc I'm looking into why the example-remote-server is failing at this. It may be because it has not had an SDK update.

In the meantime, if you have the Typescript SDK checked out, you can do:

  • npm run examples:simple-server:w
    or
  • tsx src/examples/server/simpleStreamableHttp.ts --oauth

This will run a local server with OAuth. Then hit it with the Inspector at http://localhost:3000/mcp and it should work fine. That's why I suspect the example-remote-server might benefit from upgrading the SDK.

@jacopoc
Copy link

jacopoc commented Jan 8, 2026

@cliffhall Following your notes, I have tested the latest version of the Inspector with the latest version of the simple server that is part of the v1.x branch of the Typescript SDK.
I confirm it works in Proxy mode but I couldn't test the Direct mode because it returns a CORS error.

@cliffhall
Copy link
Member

cliffhall commented Jan 8, 2026

Following your notes, I have tested the latest version of the Inspector with the latest version of the simple server that is part of the v1.x branch of the Typescript SDK. I confirm it works in Proxy mode but I couldn't test the Direct mode because it returns a CORS error.

@jacopoc woops, sorry about that. You have to open up CORS in src/server/express.ts

import cors from "cors";

...

export function createMcpExpressApp(options: CreateMcpExpressAppOptions = {}): Express {
    const { host = '127.0.0.1', allowedHosts } = options;

    const app = express();
    app.use(express.json());
    app.use(
      cors({
        origin: "*", // use "*" with caution in production
        methods: "GET,POST,DELETE",
        preflightContinue: false,
        optionsSuccessStatus: 204,
        exposedHeaders: ["mcp-session-id", "last-event-id", "mcp-protocol-version"],
      })
    );
...
Screenshot 2026-01-08 at 4 09 27 PM

@jacopoc
Copy link

jacopoc commented Jan 9, 2026

@cliffhall Thank you, I confirm it works with the test server. I am going to dig deeper to figure out the reason Proxy mode fails to work with my Keycloak instance and let you know if I find anything relevant for this project.

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.

v0.18.0 in Streamable HTTP direct failed on OAuth 401

4 participants