Skip to content

MCPServerEntry response headers get swallowed by VirtualMCPServer #6743

Description

@JeremiasRy

Hi!

In a setup where we have VirtualMCPServer and MCPServerEntry's, response headers sent by the upstream server seem to be swallowed by the VirtualMCPServer.

Example tool that throws:

mcpRouter.all('/mcp', async (ctx, _) => {
  const body = ctx.request.body;
  const isToolCall =
    typeof body === 'object' && body !== null && 'method' in body && body.method === 'tools/call';
  if (isToolCall) {
    ctx.status = 403;
    ctx.set(
      'WWW-Authenticate',
      'Bearer error="insufficient_scope", error_description="mcp header experiment", scope="mcp.write"',
    );
    ctx.body = {
      error: 'insufficient_scope',
      error_description: 'mcp header experiment',
    };
    return;
  }
  // SNIP
});

When calling straight to the server responds as such:

HTTP/2 403
server: nginx
date: Wed, 16 Sep 2026 08:41:31 GMT
content-type: application/json; charset=utf-8
content-length: 74
vary: Accept-Encoding
www-authenticate: Bearer error="insufficient_scope", error_description="mcp header experiment", scope="mcp.write" <-- BINGO!
strict-transport-security: max-age=31622400; includeSubDomains
access-control-allow-credentials: true
access-control-allow-methods: OPTIONS
access-control-allow-headers: accept, content-type
access-control-expose-headers: x-request-id, content-disposition

But going through the VirtualMCPServer our header gets swallowed:

HTTP/2 403
server: nginx
date: Wed, 16 Sep 2026 08:42:24 GMT
content-type: application/json
content-length: 94
vary: Accept-Encoding
strict-transport-security: max-age=31622400; includeSubDomains
access-control-allow-credentials: true
access-control-allow-methods: OPTIONS
access-control-allow-headers: accept, content-type
access-control-expose-headers: x-request-id, content-disposition

I couldn't find any configuration options to allow for passthrough response headers, only passthrough request headers. Could this be something that could be added to the project? I'm also willing to contribute if this ranks low in your current priorities.

Thanks!

Activity

  1. changed the title [-]McpServer response headers get swallowed by VMcpServer[/-] [+]MCPServerEntry response headers get swallowed by VirtualMCPServer[/+] on Oct 2, 2026
  2. Sanskarzz commented on Oct 4, 2026

    @Sanskarzz
    Collaborator

    Thanks for reporting this, @JeremiasRy , and for offering to contribute! Assigning this to you.

    The current vMCP code does lose upstream WWW-Authenticate scope challenges. This needs a bit of design around vMCP auth before implementation: incoming client authentication and outgoing backend authentication are separate, so we need to agree on how backend scope challenges should reach the client.

    Could you share your operator/vMCP version, redacted manifests and auth configuration, and the full downstream response body? That will help clarify the setup and the reported 403.

    Happy to work and address through the design with you before you start a PR.

    cc @jerm-dro @jhrozek as the vMCP owner, for input on the auth behavior and proposed approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

kubernetesItems related to Kubernetes

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions