MCP server for spawning AI coding agents (Kimi, Codex, and more)
Project description
Moonbridge
Your MCP client just got a team.
Spawn AI coding agents from Claude Code, Cursor, or any MCP client. Run 10 approaches in parallel for a fraction of the cost.
uvx moonbridge
Quick Start
-
Install at least one supported CLI:
Adapter Install Authenticate Kimi (default) uv tool install --python 3.13 kimi-clikimi loginCodex npm install -g @openai/codexSet OPENAI_API_KEYOpenCode curl -fsSL https://opencode.ai/install | bashopencode auth loginGemini CLI npm install -g @google/gemini-cliRun geminilogin flow or setGEMINI_API_KEY -
Add to MCP config (
~/.mcp.json):{ "mcpServers": { "moonbridge": { "type": "stdio", "command": "uvx", "args": ["moonbridge"] } } }
-
Use it. Your MCP client now has
spawn_agentandspawn_agents_paralleltools.
Security Warning (Read First)
Moonbridge executes agentic CLIs (Kimi/Codex/OpenCode/Gemini). A malicious or careless prompt can cause an agent to run shell commands, read accessible files, or exfiltrate data via network calls.
Moonbridge adds guardrails (MOONBRIDGE_ALLOWED_DIRS, environment allowlists, optional
MOONBRIDGE_SANDBOX=1), but these are not equivalent to OS-level containment.
For untrusted prompts or shared environments, run Moonbridge inside a container or VM with least-privilege filesystem and network access.
Updating
Moonbridge checks for updates on startup (cached for 24h). To update manually:
# If using uvx (recommended)
uvx moonbridge --refresh
# If installed as a tool
uv tool upgrade moonbridge
Disable update checks for CI/automation:
export MOONBRIDGE_SKIP_UPDATE_CHECK=1
When to Use Moonbridge
| Task | Why Moonbridge |
|---|---|
| Parallel exploration | Run 10 approaches simultaneously, pick the best |
| Frontend/UI work | Kimi excels at visual coding and component design |
| Tests and documentation | Cost-effective for high-volume tasks |
| Refactoring | Try multiple strategies in one request |
Best for: Tasks that benefit from parallel execution or volume.
How it Works
Connection Flow
- MCP client (Claude Code, Cursor, etc.) connects to Moonbridge over stdio
- Client discovers available tools via
list_tools - Client calls
spawn_agentorspawn_agents_parallel
Spawn Process
- Moonbridge validates the prompt and working directory
- Resolves which adapter to use (Kimi, Codex, OpenCode, Gemini)
- Adapter builds the CLI command with appropriate flags
- Spawns subprocess in a separate process group
- Captures stdout/stderr, enforces timeout
- Returns structured JSON result
Parallel Execution
spawn_agents_parallelruns up to 10 agents concurrently viaasyncio.gather- Each agent is independent (separate process, separate output)
- All results returned together when the last agent finishes (or times out)
MCP Client → stdio → Moonbridge → adapter → CLI subprocess
→ CLI subprocess (parallel)
→ CLI subprocess (parallel)
Tools
| Tool | Use case |
|---|---|
spawn_agent |
Single task: "Write tests for auth.ts" |
spawn_agents_parallel |
Go wide: 10 agents, 10 approaches, pick the best |
check_status |
Verify an adapter CLI is installed and authenticated |
list_adapters |
Show available adapters and their status |
list_models |
Show known/dynamic model options for an adapter |
Example: Parallel Exploration
{
"agents": [
{"prompt": "Refactor to React hooks"},
{"prompt": "Refactor to Zustand"},
{"prompt": "Refactor to Redux Toolkit"}
]
}
Three approaches. One request. You choose the winner.
Tool Parameters
spawn_agent
| Parameter | Type | Required | Description |
|---|---|---|---|
prompt |
string | Yes | Task description for the agent |
adapter |
string | No | Backend to use: kimi, codex, opencode, gemini (default from MOONBRIDGE_ADAPTER, fallback kimi) |
model |
string | No | Model override (e.g., gpt-5.2-codex, openrouter/minimax/minimax-m2.5, gemini-2.5-pro). For opencode, models use provider/model. |
thinking |
boolean | No | Enable reasoning mode (Kimi only) |
reasoning_effort |
string | No | Reasoning budget: low, medium, high, xhigh (Codex only, default xhigh) |
timeout_seconds |
integer | No | Override default timeout (30-3600) |
spawn_agents_parallel
| Parameter | Type | Required | Description |
|---|---|---|---|
agents |
array | Yes | List of agent configs (max 10) |
agents[].prompt |
string | Yes | Task for this agent |
agents[].adapter |
string | No | Backend for this agent |
agents[].model |
string | No | Model override for this agent (codex default: gpt-5.3-codex; opencode uses provider/model; gemini default: gemini-2.5-pro) |
agents[].thinking |
boolean | No | Enable reasoning (Kimi only) |
agents[].reasoning_effort |
string | No | Reasoning budget (Codex only, default xhigh) |
agents[].timeout_seconds |
integer | No | Timeout for this agent |
check_status
| Parameter | Type | Required | Description |
|---|---|---|---|
adapter |
string | No | Adapter to check explicitly. Defaults to MOONBRIDGE_ADAPTER when omitted. |
list_models
| Parameter | Type | Required | Description |
|---|---|---|---|
adapter |
string | No | Adapter to inspect. Defaults to MOONBRIDGE_ADAPTER when omitted. |
provider |
string | No | Provider filter for OpenCode model catalogs (e.g., openrouter). |
refresh |
boolean | No | Refresh model catalog for adapters that support dynamic discovery. |
Response Format
All tools return JSON with these fields:
| Field | Type | Description |
|---|---|---|
status |
string | success, error, timeout, auth_error, or cancelled |
output |
string | stdout from the agent |
stderr |
string|null | stderr if any |
returncode |
int | Process exit code (-1 for timeout/error) |
duration_ms |
int | Execution time in milliseconds |
agent_index |
int | Agent index (0 for single, 0-N for parallel) |
message |
string? | Human-readable error context (when applicable) |
raw |
object? | Optional structured metadata (e.g., sandbox diff) |
When output is too large, Moonbridge truncates it and adds raw.output_limit metadata
with original sizes.
Configuration
Environment Variables
| Variable | Description |
|---|---|
MOONBRIDGE_ADAPTER |
Default adapter (default: kimi) |
MOONBRIDGE_TIMEOUT |
Default timeout in seconds (30-3600) |
MOONBRIDGE_KIMI_TIMEOUT |
Kimi-specific default timeout |
MOONBRIDGE_CODEX_TIMEOUT |
Codex-specific default timeout |
MOONBRIDGE_OPENCODE_TIMEOUT |
OpenCode-specific default timeout |
MOONBRIDGE_GEMINI_TIMEOUT |
Gemini-specific default timeout |
MOONBRIDGE_MODEL |
Global default model override |
MOONBRIDGE_KIMI_MODEL |
Kimi-specific model override |
MOONBRIDGE_CODEX_MODEL |
Codex-specific model override |
MOONBRIDGE_OPENCODE_MODEL |
OpenCode-specific model override |
MOONBRIDGE_GEMINI_MODEL |
Gemini-specific model override |
MOONBRIDGE_MAX_AGENTS |
Maximum parallel agents |
MOONBRIDGE_MAX_OUTPUT_CHARS |
Max chars returned per agent across stdout+stderr (default 120000; timeout tails are per stream) |
MOONBRIDGE_ALLOWED_DIRS |
Colon-separated allowlist of working directories |
MOONBRIDGE_STRICT |
Set to 1 to require ALLOWED_DIRS (exits if unset) |
MOONBRIDGE_SANDBOX |
Set to 1 to run agents in a temp copy of cwd |
MOONBRIDGE_SANDBOX_KEEP |
Set to 1 to keep sandbox dir for inspection |
MOONBRIDGE_SANDBOX_MAX_DIFF |
Max diff size in bytes (default 500000) |
MOONBRIDGE_SANDBOX_MAX_COPY |
Max sandbox copy size in bytes (default 500MB) |
MOONBRIDGE_LOG_LEVEL |
Set to DEBUG for verbose logging |
Security
Moonbridge inherits the security model of the selected adapter CLI. Kimi, Codex, OpenCode, and Gemini are agentic CLIs; prompts can trigger command execution, file access, and network activity within the process permissions.
1. Threat Model (Prompt Injection Included)
If an attacker can influence prompt input sent through MCP, they can attempt to make the agent:
- read sensitive files (for example
~/.sshor.env), - run destructive shell commands,
- exfiltrate data over the network.
Moonbridge does not inspect prompt intent. Treat prompt input as potentially untrusted.
2. Directory Restrictions (MOONBRIDGE_ALLOWED_DIRS)
Default: agents can operate in any directory. Set MOONBRIDGE_ALLOWED_DIRS to restrict: colon-separated allowed paths. Symlinks resolved via os.path.realpath before checking. Strict mode (MOONBRIDGE_STRICT=1) exits on startup if no valid allowed directories are configured.
export MOONBRIDGE_ALLOWED_DIRS="/home/user/projects:/home/user/work"
export MOONBRIDGE_STRICT=1 # require restrictions
3. Environment Sanitization
Only whitelisted env vars are passed to spawned agents. Each adapter defines its own allowlist (PATH, HOME, plus adapter-specific like OPENAI_API_KEY for Codex). Your shell environment (secrets, tokens, SSH keys) is not inherited by default.
4. Input Validation
Model parameters are validated to prevent flag injection (values starting with - are rejected). Prompts are capped at 100,000 characters and cannot be empty.
5. Process Isolation and Sandbox Mode
Agents run in separate process groups (start_new_session=True). Orphan cleanup on exit. Sandbox mode available (MOONBRIDGE_SANDBOX=1) for copy-on-run isolation.
Not OS-level sandboxing. Agents can still read or write arbitrary host files they can access.
6. Hardened Deployment Checklist
- Set
MOONBRIDGE_ALLOWED_DIRSto the smallest possible set. - Enable
MOONBRIDGE_STRICT=1so missing restrictions fail closed. - Enable
MOONBRIDGE_SANDBOX=1to avoid direct workspace mutation. - Run Moonbridge in a container/VM for strong isolation.
- Do not expose Moonbridge to untrusted clients without additional auth controls.
Troubleshooting
"CLI not found"
Install the CLI for your chosen adapter:
# Kimi
uv tool install --python 3.13 kimi-cli
which kimi
# Codex
npm install -g @openai/codex
which codex
# OpenCode
curl -fsSL https://opencode.ai/install | bash
which opencode
# Gemini
npm install -g @google/gemini-cli
which gemini
"auth_error" responses
Authenticate with your chosen CLI:
# Kimi
kimi login
# Codex
export OPENAI_API_KEY=sk-...
# OpenCode
opencode auth login
# Gemini
gemini # complete login flow, or set GEMINI_API_KEY
Timeout errors
Adapters have sensible defaults: Codex=1800s, Kimi=600s, OpenCode=1200s, Gemini=1200s.
For exceptionally long tasks, override explicitly:
{"prompt": "...", "timeout_seconds": 3600}
Or set per-adapter defaults via environment:
export MOONBRIDGE_CODEX_TIMEOUT=2400 # 40 minutes
export MOONBRIDGE_KIMI_TIMEOUT=900 # 15 minutes
export MOONBRIDGE_OPENCODE_TIMEOUT=1200 # 20 minutes
export MOONBRIDGE_GEMINI_TIMEOUT=1200 # 20 minutes
Timeout Best Practices
| Task Type | Recommended |
|---|---|
| Quick query, status | 60-180s |
| Simple edits | 300-600s |
| Feature implementation | 1200-1800s |
| Large refactor | 1800-3600s |
Priority resolution: explicit param > adapter env > adapter default > global env > 600s fallback
"MOONBRIDGE_ALLOWED_DIRS is not set" warning
By default, Moonbridge warns at startup if no directory restrictions are configured. This is expected for local development. For shared/production environments, set allowed directories:
export MOONBRIDGE_ALLOWED_DIRS="/path/to/project:/another/path"
Sandbox Mode (Copy-on-Run)
Enable sandbox mode to run agents in a temporary copy of the working directory:
export MOONBRIDGE_SANDBOX=1
When enabled:
- Agents run in a temp copy of
cwd. - Host files stay unchanged by default.
- A unified diff + summary is included in
raw.sandbox.
Optional:
export MOONBRIDGE_SANDBOX_KEEP=1 # keep temp dir
export MOONBRIDGE_SANDBOX_MAX_DIFF=200000
export MOONBRIDGE_SANDBOX_MAX_COPY=300000000
Limitations: this is not OS-level isolation. Agents can still read/write arbitrary host paths if they choose to. Use containers/VMs for strong isolation.
To enforce restrictions (exit instead of warn):
export MOONBRIDGE_STRICT=1
Permission denied on working directory
Verify the directory is in your allowlist:
export MOONBRIDGE_ALLOWED_DIRS="/path/to/project:/another/path"
Debug logging
Enable verbose logging:
export MOONBRIDGE_LOG_LEVEL=DEBUG
Platform Support
macOS and Linux only. Windows is not supported.
License
MIT. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file moonbridge-0.16.0.tar.gz.
File metadata
- Download URL: moonbridge-0.16.0.tar.gz
- Upload date:
- Size: 104.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0d2e8dd66cd6961cc0cc7be9ece16f493ac5fce60ddff46447881fd6119d2f95
|
|
| MD5 |
ef65e20d3b129394daea53786055e546
|
|
| BLAKE2b-256 |
6f8c7c3a4d6c9282b70ba5e6cde1a8f67da9894dfd1b2d68a50d5cfa724080d5
|
Provenance
The following attestation bundles were made for moonbridge-0.16.0.tar.gz:
Publisher:
publish.yml on misty-step/moonbridge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
moonbridge-0.16.0.tar.gz -
Subject digest:
0d2e8dd66cd6961cc0cc7be9ece16f493ac5fce60ddff46447881fd6119d2f95 - Sigstore transparency entry: 975326448
- Sigstore integration time:
-
Permalink:
misty-step/moonbridge@71351487a37f948a98a0000a30ccaff65d4bd2f7 -
Branch / Tag:
refs/tags/moonbridge-v0.16.0 - Owner: https://github.com/misty-step
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@71351487a37f948a98a0000a30ccaff65d4bd2f7 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file moonbridge-0.16.0-py3-none-any.whl.
File metadata
- Download URL: moonbridge-0.16.0-py3-none-any.whl
- Upload date:
- Size: 33.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
549b973c223122553ab0c66fe18c39681a56d44f4a763aaca2ff364e725f0695
|
|
| MD5 |
175cedeccb7e2468727419b02b80643a
|
|
| BLAKE2b-256 |
cae4d17b81adb0e305a58601e5d7ba7c08810ff2eeade0203c263401091884f7
|
Provenance
The following attestation bundles were made for moonbridge-0.16.0-py3-none-any.whl:
Publisher:
publish.yml on misty-step/moonbridge
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
moonbridge-0.16.0-py3-none-any.whl -
Subject digest:
549b973c223122553ab0c66fe18c39681a56d44f4a763aaca2ff364e725f0695 - Sigstore transparency entry: 975326450
- Sigstore integration time:
-
Permalink:
misty-step/moonbridge@71351487a37f948a98a0000a30ccaff65d4bd2f7 -
Branch / Tag:
refs/tags/moonbridge-v0.16.0 - Owner: https://github.com/misty-step
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@71351487a37f948a98a0000a30ccaff65d4bd2f7 -
Trigger Event:
workflow_dispatch
-
Statement type: