mcp-agents 0.6.6 → 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.
- package/README.md +6 -30
- package/package.json +7 -2
- package/server.js +47 -3
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), [
|
|
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
|
-
| `
|
|
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` | `
|
|
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
|
|
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`)
|
|
@@ -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
|
|
@@ -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.
|
|
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.
|
|
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
|
@@ -50,12 +50,13 @@ const CLI_BACKENDS = {
|
|
|
50
50
|
extraProperties: {},
|
|
51
51
|
},
|
|
52
52
|
gemini: {
|
|
53
|
-
command: "
|
|
53
|
+
command: "agy",
|
|
54
54
|
toolName: "gemini",
|
|
55
55
|
description:
|
|
56
|
-
"Run
|
|
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
|
-
|
|
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
|
}
|