MCP Migration Guide
Migrate an existing bare MCP server to a signed, sandboxed MPP package.
Overview
If you have an existing MCP server — whether built with the TypeScript SDK, Python SDK, or another framework — this guide walks you through wrapping it as an MPP package. The process takes 15–30 minutes for a typical server.
Your existing MCP logic does not change. MPP wraps around the outside.
Step 1: Audit Your Capabilities
Before writing the manifest, list everything your server currently accesses:
# Find all fs module usage
grep -r "fs\." src/ --include="*.ts"
# Find all network calls
grep -r "fetch\|axios\|http\." src/ --include="*.ts"
# Find all process.env reads
grep -r "process\.env" src/ --include="*.ts"
This becomes the basis for your capability declaration. Be accurate — under-declaration causes sandbox violations; over-declaration flags your package to security reviewers.
Step 2: Add the MPP Manifest
Create mpp.manifest.json at your project root:
{
"name": "@yourorg/your-existing-server",
"version": "1.0.0",
"description": "Your existing server description",
"publisher": "Your Name <you@yourdomain.com>",
"entrypoint": "dist/index.js",
"mcp_version": "2024-11-05",
"capabilities": {
"filesystem": {
"read": ["$HOME/.config/your-server"],
"write": ["/tmp/your-server-cache"]
},
"network": {
"outbound": ["api.yourdomain.com"]
},
"env": ["YOUR_API_KEY", "LOG_LEVEL"]
}
}
Step 3: Generate Your Signing Key
mpp keys generate
This creates an Ed25519 key pair in ~/.mpp/keys/. The public key is registered with the MPP Registry under your account. The private key never leaves your machine.
Step 4: Build and Sign
npm run build # your existing build step
mpp sign # signs the manifest with your private key
Step 5: Publish
mpp publish
Step 6: Update Consumers
If agents or platform code currently loads your server directly (e.g., via stdio transport or a local path), update them to use the MPP runtime:
// Before — loading bare MCP server
const transport = new StdioServerTransport();
// After — loading via MPP runtime (auto-verified + sandboxed)
const result = await mppRuntime.invoke({
package: "@yourorg/your-existing-server@1.0.0",
method: "yourToolMethod",
args: { ... },
});
Handling Sandbox Violations
During testing, you may see errors like:
SandboxViolation: Attempted fs.readFileSync('/etc/passwd') — not in capability manifest
This means your audit in Step 1 missed a capability. Add the path to your manifest, bump the patch version, re-sign, and re-publish.
These violations are intentional — the sandbox catches accesses you may not have noticed before.
Common Issues
ENOENT: no such file or directory in sandbox
The tool is trying to access a path not declared in capabilities.filesystem.read. Add the path to the manifest.
NetworkError: blocked by sandbox
An outbound HTTP call to a hostname not in capabilities.network.outbound. Add the hostname.
EnvAccessBlocked: process.env.SECRET
The tool reads an env var not listed in capabilities.env. Add the variable name.
Rollback Strategy
Keep your existing bare MCP server running alongside the MPP-wrapped version during migration. Use feature flags or platform-level configuration to switch consumers one at a time. MPP packages are backwards-compatible with all MCP clients.