Checkpoint Docs
Govern

Migrating MCP to MCP-I

Add identity, authorization, and governance to an existing MCP server

Starting Fresh?

If you don't have an existing MCP server, the fastest path is:

  • One-click deploy from the Checkpoint dashboard — creates a GitHub repo, Cloudflare Worker, and MCP-I identity in minutes
  • npx @kya-os/create-mcpi-app — scaffolds a ready-to-deploy MCP-I server locally

Both options give you a fully configured MCP-I server with identity, consent, and proof verification out of the box. The rest of this guide is for adding MCP-I to an existing MCP server.


Why Add MCP-I?

Standard MCP provides tool discovery and invocation — but it has no built-in concept of who is calling a tool, whether they're authorized, or what they did afterward.

MCP-I adds an identity and authorization layer inside your MCP server runtime:

  • Agent Identity — Every agent gets a persistent DID (Decentralized Identifier)
  • Delegated Authorization — Users grant scoped permissions to agents via OAuth-style flows
  • Cryptographic Proofs — Each request carries a signed proof of identity and authorization
  • Audit Trail — Every tool invocation is logged with non-repudiable proof
  • Constraint Enforcement — Time windows, IP restrictions, rate limits, and budget controls
Standard MCP:   Agent → Tool Request → MCP Server → Response

MCP-I:          Agent → Tool Request → MCP Server (verify proof → execute) → Response

                                  Same process, no extra hop

MCP-I runs inside your MCP server — it is not a separate service or proxy. Proof verification happens in-process within the same runtime, adding no network latency and no extra infrastructure. Agents never see your keys or PII — the MCP-I layer handles cryptographic verification transparently at the protocol level, outside the agent's context window.

What Changes

AspectStandard MCPMCP-I
Agent identityNone (anonymous)DID (did:key:z6Mk...)
AuthorizationNoneDelegations with scopes
Request signingNoneEd25519 detached JWS
Access controlApplication-levelPer-tool scope requirements
Audit trailApplication-levelBuilt-in cryptographic proofs
ConsentNoneUser-facing consent flows
RevocationNoneDelegation revocation + status lists

Your tools, prompts, and business logic stay the same. MCP-I adds a verification step at the protocol layer before your tool code runs — agents are unaware of the cryptographic details.

Migration Approaches

There are two ways to add MCP-I to your existing server:

Add @kya-os/bouncer-middleware to your existing Express/Node.js server. This is the fastest path — you keep your existing MCP server and add proof verification as middleware.

Best for: Existing Node.js/Express MCP servers where you want to add authorization without rewriting.

Approach B: MCP-I Cloudflare Adapter

Use @kya-os/mcp-i-cloudflare to build a new MCP-I server on Cloudflare Workers with identity, proofs, and consent built in.

Best for: New servers, or when migrating to edge deployment on Cloudflare Workers.


Approach A: Add Bouncer Middleware

Step 1: Install the package

npm install @kya-os/bouncer-middleware

Step 2: Create a Checkpoint project

  1. Go to the Checkpoint dashboard
  2. Create a new project
  3. Copy your Project ID and API Key

Step 3: Protect your tool endpoints

Add the middleware to routes that should require MCP-I authorization:

import express from 'express';
import { createBouncerMiddleware } from '@kya-os/bouncer-middleware';

const app = express();
app.use(express.json());

// Protected tool — requires MCP-I proof with specific scopes
app.post(
  '/tools/checkout',
  createBouncerMiddleware({
    apiKey: process.env.CHECKPOINT_API_KEY!,
    projectId: process.env.CHECKPOINT_PROJECT_ID!,
    requiredScopes: ['cart:write', 'payment:process'],
    reputationThreshold: 60,
  }),
  (req, res) => {
    const { agentDid, scopes, reputation } = req.bouncer;
    // Process checkout with verified agent identity
    res.json({ success: true, agent: agentDid });
  }
);

// Public tool — no MCP-I proof required
app.get('/tools/list-products', (req, res) => {
  res.json({ products: [...] });
});

Step 4: Configure tools in the dashboard

Navigate to Project → Control Access → Tools and define which tools require delegations:

{
  "checkout": {
    "requiresDelegation": true,
    "scopes": ["cart:write", "payment:process"]
  },
  "list-products": {
    "requiresDelegation": false
  }
}

Configure how users authorize agents under Project → Control Access → Consent. Choose an authentication method and customize the consent page branding.

Step 6: Test the flow

  1. An agent initiates the OAuth flow to get a delegation
  2. The user sees the consent page and approves
  3. The agent receives a delegation reference
  4. The agent creates a signed proof and includes it in the X-MCP-Proof header
  5. Your middleware verifies the proof automatically

Middleware Configuration Reference

interface BouncerConfig {
  /** Checkpoint API key (required) */
  apiKey: string;

  /** Checkpoint project ID (required) */
  projectId: string;

  /** API base URL (default: 'https://kya.vouched.id') */
  apiUrl?: string;

  /** Minimum reputation score 0-100 (optional) */
  reputationThreshold?: number;

  /** Scopes the agent must have in its delegation (optional) */
  requiredScopes?: string[];

  /** Custom error handler (optional) */
  onError?: (error: BouncerError, req: Request) => void;

  /** Enable debug logging (optional) */
  debug?: boolean;
}

What the Middleware Does

The middleware performs these checks on every request:

  1. Extracts the proof from the X-MCP-Proof header
  2. Decodes the base64url JWT payload
  3. Verifies the Ed25519 signature with Checkpoint
  4. Checks the proof hasn't expired
  5. Fetches and validates the referenced delegation
  6. Validates delegation constraints (IP, origin, time windows)
  7. Checks required scopes
  8. Checks agent reputation against the threshold
  9. Attaches verified data to req.bouncer

After verification, req.bouncer contains:

{
  proof: MCPIProofPayload;   // Full decoded proof
  agentDid: string;          // Agent's DID
  delegation?: Delegation;   // Delegation details
  reputation?: number;       // Agent reputation score (0-100)
  scopes: string[];          // Granted scopes
}

Approach B: MCP-I Cloudflare Adapter

Step 1: Scaffold a new MCP-I server

npx @kya-os/create-mcpi-app my-server

Or deploy via the Checkpoint dashboard — see Deploying an MCP-I Server.

Step 2: Define your tools

import { MCPICloudflareServer } from '@kya-os/mcp-i-cloudflare';
import { defineConfig } from '@kya-os/mcp-i-cloudflare';

export function getRuntimeConfig(env: CloudflareEnv) {
  return defineConfig({
    vars: {
      ENVIRONMENT: env.ENVIRONMENT || 'production',
      AGENTSHIELD_API_KEY: env.AGENTSHIELD_API_KEY,
    },
  });
}

export default {
  async fetch(request: Request, env: CloudflareEnv, ctx: ExecutionContext) {
    const server = new MCPICloudflareServer({
      env,
      config: getRuntimeConfig(env),
    });
    return server.handleRequest(request, ctx);
  },
};

Step 3: Configure tool protection

Define which tools require authorization in the Checkpoint dashboard, or via the API. See Tool Protection for details.

Step 4: Deploy

Deploy to Cloudflare Workers using wrangler deploy or via GitHub Actions (auto-configured if you used the dashboard deployment flow).


Designing Your Scopes

When migrating, you need to define scopes for your tools. Follow the resource:action pattern:

files:read        — Read files
files:write       — Create and modify files
files:delete      — Delete files
cart:read         — View shopping cart
cart:write        — Modify cart contents
payment:process   — Execute payments
admin:manage      — Administrative operations

Checkpoint does not enforce implicit scope hierarchies. files:write does not include files:read. If a tool needs both, list both in the tool's scope requirements.

Scope Design Guidelines

GuidelineExample
Use resource:action formatfiles:write, not writeFiles
Keep scopes granularSeparate read and write rather than a single access scope
Group by resourcecart:read, cart:write, cart:delete
Use admin: prefix for privileged operationsadmin:manage, admin:audit
Avoid overly broad scopes* grants full access — use sparingly

Migration Checklist

Use this checklist to track your migration progress:

  • Create a Checkpoint project and obtain API credentials
  • Install @kya-os/bouncer-middleware or @kya-os/mcp-i-cloudflare
  • Design scopes for your existing tools
  • Add proof verification to sensitive tool endpoints
  • Configure tool requirements in the Checkpoint dashboard
  • Choose an authentication method (OAuth, Consent Only, Credentials)
  • Customize the consent page branding
  • Test the full flow: OAuth → consent → delegation → proof → tool call
  • Monitor proof verification in the dashboard
  • Review delegation activity and configure constraints

Error Handling

When proof verification fails, the middleware returns structured errors. Handle these in your client:

CodeHTTPMeaning
MISSING_PROOF401No X-MCP-Proof header — agent needs to authenticate first
INVALID_PROOF400Malformed proof structure
EXPIRED_PROOF401Proof has passed its expiration time
INVALID_SIGNATURE401Ed25519 signature verification failed
DELEGATION_NOT_FOUND404Referenced delegation does not exist
DELEGATION_EXPIRED403Delegation has passed its expiration
DELEGATION_REVOKED403Delegation was explicitly revoked
INSUFFICIENT_SCOPES403Agent lacks required scopes
REPUTATION_TOO_LOW403Agent reputation below threshold
CONSTRAINT_VIOLATION403Delegation constraint not satisfied (IP, time, etc.)

When an agent receives a MISSING_PROOF or DELEGATION_EXPIRED error, it should initiate a new OAuth flow to obtain a fresh delegation.

Next Steps