Skip to content

MCP Server Integration

MCP (Model Context Protocol) servers should require OAuth access tokens for tool calls.

Authentication Flow

For every tool request:

  1. Parse bearer token from Authorization header
  2. Validate issuer, audience, signature, expiry, tenant, and scope
  3. Require subject type agent or delegated actor context
  4. Map each tool to one or more scopes
  5. Enforce resource-level tenant checks
  6. Record high-impact tool calls in audit logs

Tool Policy Design

Example tool policy:

Tool: search_docs
Audience: https://mcp.example.com
Scope: tools:search
Allowed subject: agent or delegated agent

Tool: delete_project
Audience: https://mcp.example.com
Scope: projects:delete
Allowed subject: delegated agent only
Extra condition: human approval and fresh user session

Token Validation

Use Verify Tokens for backend claim checks.

Key claims to verify:

  • iss: Must be your SigID issuer
  • aud: Must match your MCP server
  • sub: Agent ID or user ID (for delegated)
  • act: Agent ID (present for delegated tokens)
  • scope: Must include required tool scopes

Example Implementation

import { validateAccessToken } from "@sigid/client";

export async function validateMcpRequest(authHeader: string) {
  const [scheme, token] = authHeader.trim().split(/\s+/, 2);
  if (scheme?.toLowerCase() !== "bearer" || !token) {
    throw new Error("Bearer access token required");
  }

  const requiredScopes = getRequiredScopesForTool("search_docs");
  const claims = await validateAccessToken(token, {
    issuer: process.env.SIGID_ISSUER_URL!,
    audience: "https://mcp.example.com",
    tenantId: process.env.SIGID_TENANT_ID!,
    scopes: requiredScopes,
    allowedSubjectTypes: ["agent"],
    allowDelegation: true,
  });

  return claims;
}

Scope Mapping

Map tools to scopes:

Tool Required Scope Subject Type
search_docs tools:search agent or delegated
read_project projects:read agent or delegated
write_project projects:write delegated only
delete_project projects:delete delegated + approval
sign_transaction wallet:sign delegated + approval

The example uses validateAccessToken() from the public @sigid/client package. In a Next.js route handler, you can also use requireAccessToken() from @sigid/next to extract the bearer token from the request before running the same issuer, audience, tenant, scope, and subject checks.

Audit Logging

Log all tool calls with:

  • Agent or user ID
  • Tool name
  • Parameters (redacted if sensitive)
  • Timestamp
  • Result

See Also