Writing Orchestration Scripts
Relevant source files
The following files were used as context for generating this wiki page:
Orchestration scripts in the MCP Server Code Execution Mode bridge allow Large Language Models (LLMs) to compose complex workflows by writing Python code that interacts with multiple Model Context Protocol (MCP) servers. Unlike traditional MCP implementations where the LLM calls individual tools one by one, this bridge enables a "Code-First" approach where a single script can handle discovery, logic, retries, and multi-step data processing within a secure, rootless container sandbox.
Sources: README.md:89-106, ARCHITECTURE.md:47-66
Discovery-First Workflow
Orchestration begins with discovery. Instead of preloading all tool schemas—which can consume up to 30,000 tokens—the bridge uses a discovery-first architecture. Scripts use the mcp.runtime module to find available servers and hydrate only the necessary tool documentation on demand.
Discovery Logic Flow
The following diagram illustrates how an orchestration script identifies and prepares tools for execution.
The script first identifies available servers, retrieves the specific tool schemas needed, and then invokes the tools via generated proxies.
Sources: README.md:108-135, mcp_server_code_execution_mode.py:657-735
Key Discovery Functions
| Function | Purpose | Return Type |
|---|---|---|
runtime.discovered_servers() | Lists all servers known to the bridge. | tuple[str, ...] |
runtime.list_servers_sync() | Returns cached list of loaded servers. | tuple[str, ...] |
runtime.query_tool_docs(server) | Fetches documentation for a specific server's tools. | list[dict] |
runtime.search_tool_docs(query) | Performs fuzzy search across all loaded servers. | list[dict] |
runtime.describe_server(name) | Provides metadata (e.g., cwd) for a specific server. | dict |
Sources: GUIDE.md:310-345, mcp_server_code_execution_mode.py:657-735
Orchestrating MCP Tool Calls
Once tools are discovered, scripts interact with them using auto-generated proxies (e.g., mcp_filesystem, mcp_github). These proxies reside in the mcp.servers namespace and are exported to the global scope of the execution environment.
Tool Invocation Pattern
Orchestration scripts must use await for tool calls, as all bridged MCP communication is asynchronous.
# Example: Migrating data between systems
import mcp.runtime as runtime
# 1. Access the auto-generated proxies
source_files = await mcp_filesystem.list_directory(path='/data')
for file in source_files:
content = await mcp_filesystem.read_file(path=file)
# 2. Process data locally in the sandbox
if "urgent" in content.lower():
# 3. Pipe to another MCP server
await mcp_slack.post_message(channel="#alerts", text=f"Urgent: {file}")
Sources: README.md:468-500, GUIDE.md:230-260, mcp_server_code_execution_mode.py:750-775
Persistent State and Memory
Orchestration scripts often require state that persists across multiple tool invocations or even separate run_python calls. The bridge provides two mechanisms for this:
1. Persistent Sessions
Variables, imports, and function definitions created in one code block are retained in the sandbox for subsequent calls within the same session.
Sources: README.md:225-235, STATUS.md:25-30
2. Persistent Memory System
For cross-session persistence (surviving container restarts), scripts use the memory API. Data is stored as JSON in /projects/memory/ within the container, mapping to the host's ~/MCPs/user_tools/memory/ directory.
The memory system allows scripts to track progress, save user preferences, or store expensive computation results across separate executions.
Sources: README.md:264-285, GUIDE.md:355-400, mcp_server_code_execution_mode.py:530-610
Memory API Reference
| Function | Description |
|---|---|
save_memory(key, value) | Saves JSON-serializable data to disk. |
load_memory(key, default) | Retrieves data, returning default if not found. |
update_memory(key, fn) | Updates memory atomically using a provided function. |
list_memories() | Returns a list of all stored keys and metadata. |
Sources: GUIDE.md:365-390, mcp_server_code_execution_mode.py:530-610
Security and Isolation Context
Orchestration scripts run in a highly constrained environment. When writing scripts, developers must account for the following architectural limits:
- Network Isolation: Scripts cannot make direct HTTP requests or socket connections. All external interaction must go through MCP tools.
- Read-Only Root: The filesystem is immutable except for
/tmpand/workspace(tmpfs) and the persistent/projectsmount. - Timeouts: Scripts have a default timeout (30s), though this can be overridden up to a maximum (120s) in the
run_pythoncall.
Best Practices for Scripts
- Use
runtime.capability_summary(): Instead of exploratory code to see what the environment can do, call this to get a concise manual. - Explicit Loading: Only request the servers needed in the
serversparameter ofrun_pythonto keep the sandbox environment lean. - Atomic Memory Updates: Use
update_memorywith a lambda when modifying shared state to prevent race conditions. - Error Handling: Wrap tool calls in
try...exceptblocks, specifically catchingruntime.MCPErrorfor failed tool invocations.
Sources: GUIDE.md:520-560, mcp_server_code_execution_mode.py:650-655, tests/test_entrypoint.py:270-300