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 hopMCP-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
| Aspect | Standard MCP | MCP-I |
|---|---|---|
| Agent identity | None (anonymous) | DID (did:key:z6Mk...) |
| Authorization | None | Delegations with scopes |
| Request signing | None | Ed25519 detached JWS |
| Access control | Application-level | Per-tool scope requirements |
| Audit trail | Application-level | Built-in cryptographic proofs |
| Consent | None | User-facing consent flows |
| Revocation | None | Delegation 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:
Approach A: Bouncer Middleware (Recommended)
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-middlewareStep 2: Create a Checkpoint project
- Go to the Checkpoint dashboard
- Create a new project
- 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
}
}Step 5: Set up a consent flow
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
- An agent initiates the OAuth flow to get a delegation
- The user sees the consent page and approves
- The agent receives a delegation reference
- The agent creates a signed proof and includes it in the
X-MCP-Proofheader - 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:
- Extracts the proof from the
X-MCP-Proofheader - Decodes the base64url JWT payload
- Verifies the Ed25519 signature with Checkpoint
- Checks the proof hasn't expired
- Fetches and validates the referenced delegation
- Validates delegation constraints (IP, origin, time windows)
- Checks required scopes
- Checks agent reputation against the threshold
- 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-serverOr 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 operationsCheckpoint 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
| Guideline | Example |
|---|---|
Use resource:action format | files:write, not writeFiles |
| Keep scopes granular | Separate read and write rather than a single access scope |
| Group by resource | cart:read, cart:write, cart:delete |
Use admin: prefix for privileged operations | admin: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-middlewareor@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:
| Code | HTTP | Meaning |
|---|---|---|
MISSING_PROOF | 401 | No X-MCP-Proof header — agent needs to authenticate first |
INVALID_PROOF | 400 | Malformed proof structure |
EXPIRED_PROOF | 401 | Proof has passed its expiration time |
INVALID_SIGNATURE | 401 | Ed25519 signature verification failed |
DELEGATION_NOT_FOUND | 404 | Referenced delegation does not exist |
DELEGATION_EXPIRED | 403 | Delegation has passed its expiration |
DELEGATION_REVOKED | 403 | Delegation was explicitly revoked |
INSUFFICIENT_SCOPES | 403 | Agent lacks required scopes |
REPUTATION_TOO_LOW | 403 | Agent reputation below threshold |
CONSTRAINT_VIOLATION | 403 | Delegation 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
- Deploying an MCP-I Server — One-click deployment from the dashboard
- Authentication Methods — Choose how users authorize agents
- Tool Protection — Configure per-tool scope requirements
- Proof Verification — How proofs work under the hood
- Consent Flows — Customize the user-facing consent experience