mcp-agents 0.6.5 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +8 -32
  2. package/package.json +7 -2
  3. package/server.js +48 -4
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # mcp-agents
2
2
 
3
- MCP server that wraps AI CLI tools — [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [Gemini CLI](https://github.com/google-gemini/gemini-cli), and [Codex CLI](https://github.com/openai/codex) — so any MCP client can call them as tools.
3
+ MCP server that wraps AI CLI tools — [Claude Code](https://docs.anthropic.com/en/docs/claude-code), [Antigravity CLI](https://antigravity.google/) (`agy`), and [Codex CLI](https://github.com/openai/codex) — so any MCP client can call them as tools.
4
4
 
5
5
  ## Prerequisites
6
6
 
@@ -10,7 +10,7 @@ MCP server that wraps AI CLI tools — [Claude Code](https://docs.anthropic.com/
10
10
  | CLI | Install |
11
11
  |-----|---------|
12
12
  | `claude` | [Claude Code docs](https://docs.anthropic.com/en/docs/claude-code) |
13
- | `gemini` | `npm install -g @anthropic-ai/gemini-cli` |
13
+ | `agy` | [Google Antigravity](https://antigravity.google/) |
14
14
  | `codex` | `npm install -g @openai/codex` |
15
15
 
16
16
  Only the CLI you select with `--provider` needs to be present.
@@ -37,9 +37,6 @@ mcp-agents
37
37
  # Specific provider
38
38
  mcp-agents --provider claude
39
39
  mcp-agents --provider gemini
40
-
41
- # Optional: enable Gemini sandbox mode
42
- mcp-agents --provider gemini --sandbox true
43
40
  ```
44
41
 
45
42
  The server speaks [JSON-RPC over stdio](https://modelcontextprotocol.io/docs/concepts/transports#stdio). It prints `[mcp-agents] ready (provider: <name>)` to stderr when it's listening.
@@ -51,7 +48,7 @@ Each `--provider` flag maps to a single exposed tool:
51
48
  | Provider | Tool name | CLI command |
52
49
  |----------|-----------|-------------|
53
50
  | `claude` | `claude_code` | `claude -p --output-format json` |
54
- | `gemini` | `gemini` | `gemini [-s] -p <prompt>` |
51
+ | `gemini` | `gemini` | `agy --sandbox -p <prompt>` |
55
52
  | `codex` | *(pass-through)* | `codex mcp-server` |
56
53
 
57
54
  ### `claude_code` parameters
@@ -69,12 +66,13 @@ Claude calls run with `--output-format json`; the server parses the JSON payload
69
66
 
70
67
  | Parameter | Type | Required | Description |
71
68
  |-----------|------|----------|-------------|
72
- | `prompt` | `string` | yes | The prompt to send to Gemini CLI |
73
- | `sandbox` | `boolean` | no | Run in sandbox mode (`-s` flag, default: false) |
69
+ | `prompt` | `string` | yes | The prompt to send to the Antigravity CLI (`agy`) |
74
70
  | `timeout_ms` | `integer` | no | Timeout in ms (default: 300 000 / 5 minutes) |
75
71
 
76
72
  Any additional `tools/call` arguments are ignored (for example `model` or `model_reasoning_effort`).
77
73
 
74
+ `agy` always runs with `--sandbox` (terminal restrictions enabled); there is no per-call sandbox toggle.
75
+
78
76
  ### `codex` (pass-through)
79
77
 
80
78
  The codex provider passes through to Codex's native MCP server (`codex mcp-server`)
@@ -85,7 +83,7 @@ or Gemini during bridge calls.
85
83
 
86
84
  | CLI Flag | Default | Codex config key |
87
85
  |----------|---------|-----------------|
88
- | `--model` | `gpt-5.4` | `model` |
86
+ | `--model` | `gpt-5.5` | `model` |
89
87
  | `--model_reasoning_effort` | `xhigh` | `model_reasoning_effort` |
90
88
 
91
89
  Hardcoded defaults: `sandbox_mode=read-only`, `approval_policy=never`,
@@ -121,19 +119,6 @@ Add entries to your project's `.mcp.json` (requires `npm i -g mcp-agents`):
121
119
  }
122
120
  ```
123
121
 
124
- Optional Gemini sandbox mode in `.mcp.json`:
125
-
126
- ```json
127
- {
128
- "mcpServers": {
129
- "gemini": {
130
- "command": "mcp-agents",
131
- "args": ["--provider", "gemini", "--sandbox", "true"]
132
- }
133
- }
134
- }
135
- ```
136
-
137
122
  Override codex defaults at server startup:
138
123
 
139
124
  ```json
@@ -141,7 +126,7 @@ Override codex defaults at server startup:
141
126
  "mcpServers": {
142
127
  "codex": {
143
128
  "command": "mcp-agents",
144
- "args": ["--provider", "codex", "--model", "gpt-5.4", "--model_reasoning_effort", "medium"]
129
+ "args": ["--provider", "codex", "--model", "gpt-5.5", "--model_reasoning_effort", "medium"]
145
130
  }
146
131
  }
147
132
  }
@@ -188,15 +173,6 @@ args = ["--provider", "gemini"]
188
173
  tool_timeout_sec = 300
189
174
  ```
190
175
 
191
- Optional Gemini sandbox mode in Codex config:
192
-
193
- ```toml
194
- [mcp_servers.gemini]
195
- command = "mcp-agents"
196
- args = ["--provider", "gemini", "--sandbox", "true"]
197
- tool_timeout_sec = 300
198
- ```
199
-
200
176
  Then in a Codex session you can call the `claude_code` or `gemini` tools, which shell out to the respective CLIs.
201
177
 
202
178
  ## Development
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcp-agents",
3
- "version": "0.6.5",
3
+ "version": "0.7.0",
4
4
  "description": "MCP server that wraps AI CLI tools (Claude Code, Gemini CLI, Codex CLI) for use by any MCP client",
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,7 +27,12 @@
27
27
  },
28
28
  "author": "Thomas Witt",
29
29
  "dependencies": {
30
- "@modelcontextprotocol/sdk": "^1.0.0"
30
+ "@modelcontextprotocol/sdk": "^1.29.0"
31
+ },
32
+ "overrides": {
33
+ "fast-uri": "^3.1.2",
34
+ "hono": "^4.12.22",
35
+ "ip-address": "^10.2.0"
31
36
  },
32
37
  "engines": {
33
38
  "node": ">=18"
package/server.js CHANGED
@@ -27,7 +27,7 @@ const VERSION = JSON.parse(
27
27
  ).version;
28
28
 
29
29
  const DEFAULT_TIMEOUT_MS = 300_000;
30
- const DEFAULT_CODEX_MODEL = "gpt-5.4";
30
+ const DEFAULT_CODEX_MODEL = "gpt-5.5";
31
31
  const DEFAULT_CODEX_MODEL_REASONING_EFFORT = "xhigh";
32
32
  const MAX_BUFFER_BYTES = 10 * 1024 * 1024;
33
33
  const CLAUDE_EMPTY_OUTPUT_MAX_ATTEMPTS = 2;
@@ -50,12 +50,13 @@ const CLI_BACKENDS = {
50
50
  extraProperties: {},
51
51
  },
52
52
  gemini: {
53
- command: "gemini",
53
+ command: "agy",
54
54
  toolName: "gemini",
55
55
  description:
56
- "Run Gemini CLI with a prompt. Always runs in sandbox mode with --approval-mode=plan.",
56
+ "Run the Antigravity CLI (`agy`, Google's Gemini-backed agent) with a prompt. Always runs in --sandbox mode (terminal restrictions enabled).",
57
57
  stdinPrompt: false,
58
- buildArgs: (prompt) => ["-s", "--approval-mode=plan", "-p", prompt],
58
+ isolateCwd: true,
59
+ buildArgs: (prompt) => ["--sandbox", "-p", prompt],
59
60
  extraProperties: {},
60
61
  },
61
62
  codex: {
@@ -209,6 +210,7 @@ function parseArgs() {
209
210
  * @param {{
210
211
  * timeoutMs?: number,
211
212
  * stdinData?: string,
213
+ * cwd?: string,
212
214
  * onSpawn?: (childInfo: { pid?: number, killGroup: () => void }) => void,
213
215
  * onSettled?: (pid?: number) => void,
214
216
  * }} [opts]
@@ -217,6 +219,7 @@ function parseArgs() {
217
219
  function runCli(command, args, opts = {}) {
218
220
  const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
219
221
  const stdinData = opts.stdinData;
222
+ const cwd = opts.cwd;
220
223
  const onSpawn = opts.onSpawn;
221
224
  const onSettled = opts.onSettled;
222
225
  const startedAt = Date.now();
@@ -229,6 +232,7 @@ function runCli(command, args, opts = {}) {
229
232
  let settled = false;
230
233
 
231
234
  const child = spawn(command, args, {
235
+ cwd,
232
236
  detached: true,
233
237
  stdio: ["pipe", "pipe", "pipe"],
234
238
  env: { ...process.env, NO_COLOR: "1" },
@@ -307,6 +311,18 @@ function runCli(command, args, opts = {}) {
307
311
  });
308
312
  }
309
313
 
314
+ /**
315
+ * Create a fresh, empty working directory under the OS temp dir for an
316
+ * agentic CLI. Agentic CLIs (e.g. agy/Antigravity) treat their cwd as a
317
+ * workspace and write project files into it; running them here keeps them
318
+ * from mutating whatever directory the MCP server was started in.
319
+ * @param {string} provider
320
+ * @returns {string}
321
+ */
322
+ function createIsolatedWorkdir(provider) {
323
+ return mkdtempSync(join(tmpdir(), `mcp-agents-${provider}-`));
324
+ }
325
+
310
326
  /**
311
327
  * Resolve the source Codex home used by the parent process.
312
328
  * @returns {string}
@@ -628,10 +644,12 @@ async function main() {
628
644
  const cliArgs = backend.stdinPrompt
629
645
  ? backend.buildArgs(extraOpts)
630
646
  : backend.buildArgs(prompt, extraOpts);
647
+ let isolatedWorkdir;
631
648
  const buildCliOpts = (attemptTimeoutMs) => (
632
649
  {
633
650
  timeoutMs: attemptTimeoutMs,
634
651
  ...(backend.stdinPrompt ? { stdinData: prompt } : {}),
652
+ ...(isolatedWorkdir ? { cwd: isolatedWorkdir } : {}),
635
653
  onSpawn: ({ pid, killGroup }) => {
636
654
  if (!pid) return;
637
655
  activeChildren.set(pid, killGroup);
@@ -653,6 +671,24 @@ async function main() {
653
671
  };
654
672
  }
655
673
 
674
+ if (backend.isolateCwd) {
675
+ try {
676
+ isolatedWorkdir = createIsolatedWorkdir(providerName);
677
+ } catch (err) {
678
+ const msg = err instanceof Error ? err.message : String(err);
679
+ logErr(`[mcp-agents] failed to create isolated workdir: ${msg}`);
680
+ return {
681
+ content: [
682
+ {
683
+ type: "text",
684
+ text: `Failed to prepare isolated working directory: ${msg}`,
685
+ },
686
+ ],
687
+ isError: true,
688
+ };
689
+ }
690
+ }
691
+
656
692
  const startedAt = Date.now();
657
693
  const maxAttempts = providerName === "claude"
658
694
  ? CLAUDE_EMPTY_OUTPUT_MAX_ATTEMPTS
@@ -738,6 +774,14 @@ async function main() {
738
774
  isError: true,
739
775
  };
740
776
  } finally {
777
+ if (isolatedWorkdir) {
778
+ try {
779
+ rmSync(isolatedWorkdir, { recursive: true, force: true });
780
+ } catch (err) {
781
+ const msg = err instanceof Error ? err.message : String(err);
782
+ logErr(`[mcp-agents] failed to clean isolated workdir: ${msg}`);
783
+ }
784
+ }
741
785
  activeRequests -= 1;
742
786
  maybeFinalizeShutdown();
743
787
  }