Building a Multi-Tenant Remote MCP Host: Secure V8 Sandboxing
How to host untrusted third-party Model Context Protocol scripts at scale without risking server compromise or resource starvation.
The Security Nightmare of Third-Party Tools
If you are building an agent platform where developers can publish and share their own Model Context Protocol (MCP) servers, you are sitting on a security time bomb.
Standard MCP servers are designed to run locally. They execute shell scripts, read directories, write files, and open raw network sockets. When a user runs Claude Desktop with a local file-system MCP server, the tool runs with the full permissions of the user's host OS.
But the moment you decide to host these MCP servers in the cloud to build a multi-tenant platform (like a hosted tool directory or an integrations hub), the security model changes.
You cannot run untrusted developer code directly on your hosted servers. A single malicious script could:
- Read environment variables containing Stripe secret keys or database credentials.
- Spam external endpoints, getting your hosting IP range blacklisted.
- Initiate endless loops that consume all available CPU and RAM, starving other tenants.
To build a hosted MCP marketplace that scales, you must isolate untrusted tools inside a secure, lightweight sandbox that executes with zero-trust constraints.
Why Virtual Machines are Too Slow for AI Agents
The classic answer to multi-tenant code execution is virtual machines (VMs) or Docker containers.
You spin up an isolated AWS Firecracker microVM or a sandboxed Docker container for each custom tool execution. While this provides secure hardware-level isolation, it introduces massive runtime latency.
Spinning up a fresh container or microVM takes anywhere from 400ms to 3 seconds. For an interactive chat session, this cold-start delay destroys the natural user experience. If your agent is waiting on four different tool scripts to compile, the chat stalls completely.
To keep executions fast and safe, the industry has transitioned to V8 Isolates.
Instead of virtualizing hardware, V8 Isolates run code inside sandboxed Javascript contexts within a single OS process. Each isolate is fully sealed: it has no access to neighboring memory, no filesystem access, and no network sockets unless explicitly bridged by the host environment.
More importantly, a V8 Isolate starts up in under 1 millisecond, allowing you to host thousands of sandboxed scripts with zero latency penalty.
Implementing a Sandboxed V8 Runner in Node.js
To demonstrate how to host untrusted developer tools safely, let's build a secure sandboxed executor using the isolated-vm library in Node.js. This runner isolates execution, restricts memory, and enforces a strict 50ms timeout.
const ivm = require('isolated-vm');
/**
* Securely executes untrusted third-party tool scripts in a V8 sandbox
* @param {string} developerCode - The untrusted Javascript tool script
* @param {object} inputParams - Validated tool inputs passed by the LLM
*/
async function executeSecureTool(developerCode, inputParams) {
// 1. Initialize a new isolate with a strict 128MB memory limit
const isolate = new ivm.Isolate({ memoryLimit: 128 });
const context = await isolate.createContext();
try {
// 2. Set up global context variables safely (no process, no require)
const jail = context.global;
await jail.set('global', jail.derefInto());
await jail.set('input', new ivm.ExternalCopy(inputParams).copyInto());
// 3. Compile and execute the developer's script
const script = await isolate.compileScript(`
// Untrusted developer code runs here
function run() {
${developerCode}
}
// Return output safely
JSON.stringify(run(input));
`);
// 4. Force a strict 50ms CPU execution timeout to prevent infinite loops
const resultJson = await script.run(context, { timeout: 50 });
return JSON.parse(resultJson);
} catch (err) {
if (err.message.includes('Script execution timed out')) {
return { error: 'Tool execution timed out. Limit is 50ms CPU time.' };
}
return { error: `Sandbox error: ${err.message}` };
} finally {
// 5. Always release isolate resources to prevent memory leaks
isolate.dispose();
}
}
// Example usage with a mock third-party script
const untrustedScript = `
// Malicious attempt: try to read environment variables (fails naturally in isolate)
try {
const secrets = process.env;
return secrets;
} catch(e) {
// Correct fallback tool logic
return { doublePrice: input.price * 2 };
}
`;
executeSecureTool(untrustedScript, { price: 45.00 })
.then(console.log)
.catch(console.error);
This runner isolates execution completely. Since the script runs inside V8 without Node's global process, require, or fs objects, it cannot touch the host system. The 50ms CPU limit ensures infinite loops are terminated immediately.
How wmcp.sh Runs Tools Securely at the Edge
This secure, stateless model is the engineering foundation of wmcp.sh.
Our Cloudflare Workers gateway acts as a strict, out-of-band proxy vault. When your agent calls a dynamic tool on our platform, the gateway compiles the API mapping inside Cloudflare V8 Isolates with zero local subprocess overhead. By isolating sensitive PKCE credentials and checking schemas before routing requests, we ensure that your agents run securely in under 50ms without risk of compromise.
Build secure, agentic workflows with confidence.