Skip to content

feat(eve): add pluggable-auth MCP agent channel#1203

Draft
allenzhou101 wants to merge 6 commits into
mainfrom
allenzhou/mcp-channel-pluggable-auth
Draft

feat(eve): add pluggable-auth MCP agent channel#1203
allenzhou101 wants to merge 6 commits into
mainfrom
allenzhou/mcp-channel-pluggable-auth

Conversation

@allenzhou101

@allenzhou101 allenzhou101 commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add a stateless Streamable HTTP MCP channel backed by one protocol-neutral durable invocation service
  • make the primary authoring API mcpChannel({ auth: bearerAuth(verifyToken, options) })
  • define a provider-neutral McpAuth strategy that packages the portable MCP SDK AuthInfo verifier, required scopes, protected-resource metadata/challenges, and optional SessionAuthContext projection
  • fail closed when auth is omitted; anonymous exposure requires explicit publicMcpAuth()
  • let external integrations return strategies directly, such as auth: vercelMcpAuth() or auth: betterAuthMcpAuth(auth), without adding provider behavior to eve
  • keep mcpChannel options limited to auth plus transport/exposure concerns such as path; its MCP server name and agent_start description derive from compiled root-agent metadata
  • keep structured output on the agent definition or an individual agent_start invocation, rather than channel identity
  • support authenticated gateways by verifying a signed forwarded bearer identity and optionally setting the canonical public MCP resource
  • expose agent_start, agent_get, agent_update, agent_cancel, plus agent_send for conversation-mode continuation

Authoring API

import type { AuthInfo } from "@modelcontextprotocol/sdk/server/auth/types.js";
import { bearerAuth, mcpChannel } from "eve/channels/mcp";

async function verifyToken(
  request: Request,
  bearerToken?: string,
): Promise<AuthInfo | undefined> {
  if (!bearerToken) return undefined;
  return myTokenVerifier(request, bearerToken);
}

export default mcpChannel({
  auth: bearerAuth(verifyToken, {
    requiredScopes: ["agent:invoke"],
    protectedResource: {
      authorizationServers: ["https://vercel.com"],
    },
  }),
});

Design rationale

This preserves the verifier contract established by mcp-handler's withMcpAuth, while fitting eve's compiled channel-definition model. mcpChannel consumes one declarative auth strategy instead of requiring callers to wrap a compiled channel.

The strategy owns only generic MCP protocol policy. Provider token verification, Vercel introspection, Better Auth, DCR/CIMD, OAuth token issuance, and provider-specific resource-server behavior remain external and swappable.

A channel is already attached to the compiled root agent, so duplicating { description, outputSchema } in mcpChannel creates two sources of truth. The runtime supplies the compiled agent name and description to the MCP adapter. Per-invocation outputSchema continues to flow through agent_start; an authored default remains part of the agent definition and is enforced by the existing runtime.

Verified bearer material remains request-local; only a token-free SessionAuthContext identity projection crosses into the eve session. A gateway integration must verify a signed forwarded identity through the same strategy contract rather than trusting an identity header.

The implementation builds on:

  • origin/mcp-agent/transport-spike
  • origin/mcp-agent/invocation-service
  • origin/mcp-agent/channel-demo
  • complementary headless invocation work in #1144

Verification

  • focused MCP unit tests: 4 files / 17 tests passed
  • pnpm --filter eve run typecheck
  • pnpm --filter eve run build
  • pnpm run docs:check
  • focused oxlint
  • focused oxfmt --check

Coverage includes fail-closed omission, explicit public mode, portable verifier and custom identity projection, required scopes and 401/403 challenges, protected-resource derivation/overrides, compiled agent metadata, and MCP transport.

Security and limitations

  • Bearer strategies are always required-auth; there is no implicit anonymous fallback.
  • publicMcpAuth() is intentionally conspicuous and should only be used for deliberate public exposure.
  • Invocation IDs remain unguessable capability handles. Any endpoint-authorized caller holding a handle can inspect/update/cancel it; per-principal invocation ownership is not added in this slice.
  • Auth policy is separate from the runtime capability ceiling. This PR does not add per-token tool, connection, cost, or delegated-resource limits.
  • Invocation reads currently reconstruct state from the durable event stream. A compact durable projection remains a follow-up optimization.
  • Native MCP Tasks mapping and provider/gateway-specific implementations remain external or follow-up work.
  • Real external OAuth provider provisioning and Claude Code login were not exercised in this local verification pass.

OwenKephart and others added 4 commits July 24, 2026 17:48
Signed-off-by: owenkephart <owen.kephart@vercel.com>
Signed-off-by: owenkephart <owen.kephart@vercel.com>
Signed-off-by: owenkephart <owen.kephart@vercel.com>
Signed-off-by: Allen Zhou <46854522+allenzhou101@users.noreply.github.com>
@vercel

vercel Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
eve-docs Ready Ready Preview, Comment, Open in v0 Jul 25, 2026 1:10am
eve-docs-1644 Ready Ready Preview, Comment, Open in v0 Jul 25, 2026 1:10am
eve-docs-4759 Ready Ready Preview, Comment, Open in v0 Jul 25, 2026 1:10am

Signed-off-by: Allen Zhou <46854522+allenzhou101@users.noreply.github.com>
Signed-off-by: Allen Zhou <46854522+allenzhou101@users.noreply.github.com>
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.

2 participants