Worker Bridge
RPC communication with the sandbox
En bref
Le Worker Bridge est un canal de communication securise entre le code isole dans le sandbox et les outils MCP reel. Pensez-y comme un interphone entre deux pieces isolees : une personne dans une piece securisee (le sandbox) peut parler a travers l'interphone pour demander a quelqu'un dans l'autre piece (le processus principal) d'executer des actions pour elle. La personne isolee ne peut jamais quitter sa piece, mais elle peut faire des demandes precises via l'interphone.
Pourquoi c'est important
Le Worker Bridge resout un probleme fondamental : comment permettre au code isole d'etre utile tout en maintenant la securite ?
- Isolation maintenue : le code reste dans le sandbox, mais peut utiliser des outils puissants (filesystem, GitHub, etc.)
- Controle centralise : toutes les actions passent par le bridge qui peut valider, auditer et tracer chaque appel
- API unifiee : le code sandbox utilise simplement
mcp.tool()sans se soucier de la complexite sous-jacente - Debugging facilite : chaque message RPC peut etre logue et inspecte
Sans le bridge, il faudrait soit donner des permissions directes au sandbox (dangereux), soit ne rien pouvoir faire d'utile (inutile). Le bridge offre le meilleur des deux mondes.
What is the Worker Bridge?
The Worker Bridge is the communication layer between PML's main process and the sandboxed code execution environment. It enables isolated code to call MCP tools while maintaining security boundaries.
Architecture
The bridge connects two isolated environments:
Main Process Side
| Component | Role |
|---|---|
| Bridge Handler | Receives RPC, validates requests, returns results |
| MCP Gateway | Routes calls, executes tools, returns data |
Worker Side
| Component | Role |
|---|---|
| MCP Proxy | Provides mcp.server.* API, serializes calls, awaits replies |
| User Code | Calls await mcp.read_file() etc. |
Communication via postMessage between both sides.
Message Protocol
Communication uses a structured RPC protocol:
Request Message
{
"type": "rpc_request",
"id": "req_123",
"method": "call_tool",
"payload": {
"server": "filesystem",
"tool": "read_file",
"args": { "path": "data.json" }
}
}Response Message
Success:
{
"type": "rpc_response",
"id": "req_123",
"success": true,
"result": { "content": "{ ... }" }
}Error:
{
"type": "rpc_response",
"id": "req_123",
"success": false,
"error": { "code": "TOOL_ERROR", "message": "File not found" }
}Message Flow
- User Code calls
mcp.read_file() - Bridge sends RPC Request to Main Process
- Main Process executes the tool
- Main Process returns RPC Response
- Bridge returns value to User Code
MCP Injection
Before code runs, PML injects MCP tool functions into the sandbox:
Injection Process
- Discover available MCP tools from gateway
- Generate proxy functions for each tool
- Inject
mcpobject into worker global scope
// Generated proxy object
mcp = {
filesystem: {
read_file: (args) => bridge.call("filesystem", "read_file", args),
write_file: (args) => bridge.call("filesystem", "write_file", args),
},
github: {
create_issue: (args) => bridge.call("github", "create_issue", args),
},
};Using Injected Tools
In user code, MCP tools are available as:
// Automatically available in sandbox
const content = await mcp.filesystem.read_file({ path: "data.json" });
const parsed = JSON.parse(content);
await mcp.github.create_issue({
title: "Found issue",
body: parsed.error_message
});Tool Discovery
The bridge knows which tools exist by querying the gateway:
Available Tools:
filesystem:
- read_file
- write_file
- list_files
github:
- create_issue
- get_issue
- add_comment
fetch:
- fetch
Each becomes: mcp.{server}.{tool}()Error Handling
The bridge handles various error conditions:
| Error | Handling |
|---|---|
| Tool not found | Clear error with available alternatives |
| Invalid parameters | Schema validation error returned |
| Tool execution failed | Error propagated to calling code |
| Timeout | Request cancelled, error returned |
| Worker crashed | Graceful failure, error logged |
Error Example
// In user code
try {
await mcp.filesystem.read_file({ path: "/nonexistent" });
} catch (error) {
// Error from bridge:
// {
// code: "TOOL_ERROR",
// message: "File not found: /nonexistent",
// tool: "filesystem:read_file"
// }
}Performance
The bridge is optimized for low latency:
| Optimization | Benefit |
|---|---|
| Message pooling | Reduce allocation overhead |
| Binary serialization | Faster than JSON for large data |
| Request batching | Multiple calls in one message |
| Keep-alive workers | Avoid startup cost |
Next
- Tracing - How tool calls are tracked
- Feedback Loop - How execution feeds learning