add-mcp 0.3.4 → 0.4.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 +31 -53
- package/dist/index.js +45 -76
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -10,10 +10,10 @@ Supports **OpenCode**, **Claude Code**, **Codex**, **Cursor**, and [5 more](#sup
|
|
|
10
10
|
npx add-mcp https://mcp.example.com/sse
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
###
|
|
13
|
+
### Usage Examples
|
|
14
14
|
|
|
15
15
|
```bash
|
|
16
|
-
# Remote MCP server (
|
|
16
|
+
# Remote MCP server (streamable HTTP)
|
|
17
17
|
npx add-mcp https://mcp.example.com/mcp
|
|
18
18
|
|
|
19
19
|
# Remote MCP server (SSE transport)
|
|
@@ -22,11 +22,29 @@ npx add-mcp https://mcp.example.com/sse --transport sse
|
|
|
22
22
|
# npm package (runs via npx)
|
|
23
23
|
npx add-mcp @modelcontextprotocol/server-postgres
|
|
24
24
|
|
|
25
|
+
# Non-interactive installation to all detected agents in the project directory
|
|
26
|
+
npx add-mcp https://mcp.example.com/mcp -y
|
|
27
|
+
|
|
28
|
+
# Non-interactive installation to the global Claude Code config
|
|
29
|
+
npx add-mcp https://mcp.example.com/mcp -g -a claude-code -y
|
|
30
|
+
|
|
25
31
|
# Full command with arguments
|
|
26
32
|
npx add-mcp "npx -y @org/mcp-server --flag value"
|
|
27
33
|
|
|
28
34
|
# Node.js script
|
|
29
35
|
npx add-mcp "node /path/to/server.js --port 3000"
|
|
36
|
+
|
|
37
|
+
# Install for Cursor and Claude Code
|
|
38
|
+
npx add-mcp https://mcp.example.com/mcp -a cursor -a claude-code
|
|
39
|
+
|
|
40
|
+
# Install with custom server name
|
|
41
|
+
npx add-mcp @modelcontextprotocol/server-postgres --name postgres
|
|
42
|
+
|
|
43
|
+
# Install to all supported agents
|
|
44
|
+
npx add-mcp mcp-server-github --all
|
|
45
|
+
|
|
46
|
+
# Install to all agents, globally, without prompts
|
|
47
|
+
npx add-mcp mcp-server-github --all -g -y
|
|
30
48
|
```
|
|
31
49
|
|
|
32
50
|
### Options
|
|
@@ -41,7 +59,9 @@ npx add-mcp "node /path/to/server.js --port 3000"
|
|
|
41
59
|
| `-y, --yes` | Skip all confirmation prompts |
|
|
42
60
|
| `--all` | Install to all agents |
|
|
43
61
|
|
|
44
|
-
### Commands
|
|
62
|
+
### Additional Commands
|
|
63
|
+
|
|
64
|
+
Besides the implicit add command, `add-mcp` also supports the following commands:
|
|
45
65
|
|
|
46
66
|
| Command | Description |
|
|
47
67
|
| ------------- | ------------------------------------------------------------ |
|
|
@@ -52,28 +72,6 @@ npx add-mcp "node /path/to/server.js --port 3000"
|
|
|
52
72
|
npx add-mcp list-agents
|
|
53
73
|
```
|
|
54
74
|
|
|
55
|
-
### Examples
|
|
56
|
-
|
|
57
|
-
```bash
|
|
58
|
-
# Install to specific agents
|
|
59
|
-
npx add-mcp https://mcp.example.com/mcp -a cursor -a claude-code
|
|
60
|
-
|
|
61
|
-
# Install with SSE transport
|
|
62
|
-
npx add-mcp https://mcp.neon.tech/sse --transport sse
|
|
63
|
-
|
|
64
|
-
# Install with custom server name
|
|
65
|
-
npx add-mcp @modelcontextprotocol/server-postgres --name postgres
|
|
66
|
-
|
|
67
|
-
# Non-interactive installation (CI/CD friendly)
|
|
68
|
-
npx add-mcp https://mcp.example.com/mcp -g -a claude-code -y
|
|
69
|
-
|
|
70
|
-
# Install to all agents
|
|
71
|
-
npx add-mcp mcp-server-github --all
|
|
72
|
-
|
|
73
|
-
# Install to all agents, globally, without prompts
|
|
74
|
-
npx add-mcp mcp-server-github --all -g -y
|
|
75
|
-
```
|
|
76
|
-
|
|
77
75
|
### Installation Scope
|
|
78
76
|
|
|
79
77
|
| Scope | Flag | Location | Use Case |
|
|
@@ -103,12 +101,12 @@ The CLI automatically detects agents based on your environment:
|
|
|
103
101
|
|
|
104
102
|
## Transport Types
|
|
105
103
|
|
|
106
|
-
|
|
104
|
+
`add-mcp` supports all three transport types: HTTP, SSE, and stdio. Some agents require `type` option to be set to specify the transport type. You can use the `--type` or `--transport` option to specify the transport type:
|
|
107
105
|
|
|
108
|
-
| Transport | Flag | Description
|
|
109
|
-
| --------- | ------------------ |
|
|
110
|
-
| **HTTP** | `--transport http` | Streamable HTTP (default
|
|
111
|
-
| **SSE** | `--transport sse` | Server-Sent Events (
|
|
106
|
+
| Transport | Flag | Description |
|
|
107
|
+
| --------- | ------------------ | ----------------------------------------------------- |
|
|
108
|
+
| **HTTP** | `--transport http` | Streamable HTTP (default) |
|
|
109
|
+
| **SSE** | `--transport sse` | Server-Sent Events (deprecated by MCP but still used) |
|
|
112
110
|
|
|
113
111
|
Local servers (npm packages, commands) always use **stdio** transport.
|
|
114
112
|
|
|
@@ -120,49 +118,29 @@ MCP servers can be installed to any of these agents:
|
|
|
120
118
|
| -------------- | ---------------- | ----------------------- | ----------------------------------------------------------------- |
|
|
121
119
|
| Claude Code | `claude-code` | `.mcp.json` | `~/.claude.json` |
|
|
122
120
|
| Claude Desktop | `claude-desktop` | - | `~/Library/Application Support/Claude/claude_desktop_config.json` |
|
|
123
|
-
| Codex | `codex` |
|
|
121
|
+
| Codex | `codex` | `.codex/config.toml` | `~/.codex/config.toml` |
|
|
124
122
|
| Cursor | `cursor` | `.cursor/mcp.json` | `~/.cursor/mcp.json` |
|
|
125
123
|
| Gemini CLI | `gemini-cli` | `.gemini/settings.json` | `~/.gemini/settings.json` |
|
|
126
124
|
| Goose | `goose` | `.goose/config.yaml` | `~/.config/goose/config.yaml` |
|
|
127
125
|
| OpenCode | `opencode` | `.opencode.json` | `~/.config/opencode/opencode.json` |
|
|
128
126
|
| VS Code | `vscode` | `.vscode/mcp.json` | `~/Library/Application Support/Code/User/mcp.json` |
|
|
129
|
-
| Zed | `zed` |
|
|
127
|
+
| Zed | `zed` | `.zed/settings.json` | `~/Library/Application Support/Zed/settings.json` |
|
|
130
128
|
|
|
131
129
|
**Aliases:** `github-copilot` → `vscode`
|
|
132
130
|
|
|
133
131
|
The CLI uses smart detection to find agents in your project directory and globally installed agents. See [Smart Detection](#smart-detection) for details.
|
|
134
132
|
|
|
135
|
-
### Transport Support
|
|
136
|
-
|
|
137
|
-
Not all agents support all transport types:
|
|
138
|
-
|
|
139
|
-
| Agent | stdio | http | sse |
|
|
140
|
-
| -------------- | ----- | ---- | --- |
|
|
141
|
-
| Claude Code | ✓ | ✓ | ✓ |
|
|
142
|
-
| Claude Desktop | ✓ | ✓ | ✓ |
|
|
143
|
-
| Codex | ✓ | ✓ | ✓ |
|
|
144
|
-
| Cursor | ✓ | ✓ | ✓ |
|
|
145
|
-
| Gemini CLI | ✓ | ✓ | ✓ |
|
|
146
|
-
| Goose | ✓ | ✓ | ✗ |
|
|
147
|
-
| OpenCode | ✓ | ✓ | ✓ |
|
|
148
|
-
| VS Code | ✓ | ✓ | ✓ |
|
|
149
|
-
| Zed | ✓ | ✓ | ✓ |
|
|
150
|
-
|
|
151
133
|
## What are MCP Servers?
|
|
152
134
|
|
|
153
135
|
[Model Context Protocol (MCP)](https://modelcontextprotocol.io/) servers extend your coding agent's capabilities by providing tools, resources, and context. MCP servers can:
|
|
154
136
|
|
|
137
|
+
- Integrate with external services (Notion, Linear, GitHub, etc.)
|
|
155
138
|
- Connect to databases (PostgreSQL, MySQL, etc.)
|
|
156
|
-
- Integrate with external services (GitHub, Linear, Notion)
|
|
157
139
|
- Provide file system access
|
|
158
140
|
- Offer specialized tools for your workflow
|
|
159
141
|
|
|
160
142
|
## Troubleshooting
|
|
161
143
|
|
|
162
|
-
### Transport mismatch error
|
|
163
|
-
|
|
164
|
-
If you get an error about transport not being supported, check that the agent supports your chosen transport type. For example, Goose doesn't support SSE transport.
|
|
165
|
-
|
|
166
144
|
### Server not loading
|
|
167
145
|
|
|
168
146
|
- Verify the server URL is correct and accessible
|
package/dist/index.js
CHANGED
|
@@ -40,9 +40,10 @@ function getPlatformPaths() {
|
|
|
40
40
|
var { appSupport, vscodePath } = getPlatformPaths();
|
|
41
41
|
function transformGooseConfig(serverName, config) {
|
|
42
42
|
if (config.url) {
|
|
43
|
+
const gooseType = config.type === "sse" ? "sse" : "streamable_http";
|
|
43
44
|
return {
|
|
44
45
|
name: serverName,
|
|
45
|
-
type:
|
|
46
|
+
type: gooseType,
|
|
46
47
|
url: config.url,
|
|
47
48
|
enabled: true,
|
|
48
49
|
timeout: 300
|
|
@@ -139,8 +140,8 @@ var agents = {
|
|
|
139
140
|
process.env.CODEX_HOME || join(home, ".codex"),
|
|
140
141
|
"config.toml"
|
|
141
142
|
),
|
|
142
|
-
|
|
143
|
-
|
|
143
|
+
localConfigPath: ".codex/config.toml",
|
|
144
|
+
projectDetectPaths: [".codex"],
|
|
144
145
|
configKey: "mcp_servers",
|
|
145
146
|
format: "toml",
|
|
146
147
|
supportedTransports: ["stdio", "http", "sse"],
|
|
@@ -183,8 +184,7 @@ var agents = {
|
|
|
183
184
|
projectDetectPaths: [".goose"],
|
|
184
185
|
configKey: "extensions",
|
|
185
186
|
format: "yaml",
|
|
186
|
-
supportedTransports: ["stdio", "http"],
|
|
187
|
-
// Goose does not support SSE
|
|
187
|
+
supportedTransports: ["stdio", "http", "sse"],
|
|
188
188
|
detectGlobalInstall: async () => {
|
|
189
189
|
return existsSync(join(home, ".config", "goose"));
|
|
190
190
|
},
|
|
@@ -220,18 +220,15 @@ var agents = {
|
|
|
220
220
|
zed: {
|
|
221
221
|
name: "zed",
|
|
222
222
|
displayName: "Zed",
|
|
223
|
-
configPath: process.platform === "win32" ? join(
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
"settings.json"
|
|
227
|
-
) : join(home, ".config", "zed", "settings.json"),
|
|
228
|
-
projectDetectPaths: [],
|
|
229
|
-
// Global only - no project support
|
|
223
|
+
configPath: process.platform === "darwin" || process.platform === "win32" ? join(appSupport, "Zed", "settings.json") : join(appSupport, "zed", "settings.json"),
|
|
224
|
+
localConfigPath: ".zed/settings.json",
|
|
225
|
+
projectDetectPaths: [".zed"],
|
|
230
226
|
configKey: "context_servers",
|
|
231
227
|
format: "json",
|
|
232
228
|
supportedTransports: ["stdio", "http", "sse"],
|
|
233
229
|
detectGlobalInstall: async () => {
|
|
234
|
-
|
|
230
|
+
const configDir = process.platform === "darwin" || process.platform === "win32" ? join(appSupport, "Zed") : join(appSupport, "zed");
|
|
231
|
+
return existsSync(configDir);
|
|
235
232
|
},
|
|
236
233
|
transformConfig: transformZedConfig
|
|
237
234
|
}
|
|
@@ -410,6 +407,38 @@ import { join as join2, dirname as dirname4 } from "path";
|
|
|
410
407
|
import { readFileSync, writeFileSync, existsSync as existsSync2, mkdirSync } from "fs";
|
|
411
408
|
import { dirname } from "path";
|
|
412
409
|
import * as jsonc from "jsonc-parser";
|
|
410
|
+
|
|
411
|
+
// src/formats/utils.ts
|
|
412
|
+
function deepMerge(target, source) {
|
|
413
|
+
const result = { ...target };
|
|
414
|
+
for (const key in source) {
|
|
415
|
+
const sourceValue = source[key];
|
|
416
|
+
const targetValue = result[key];
|
|
417
|
+
if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
|
|
418
|
+
result[key] = deepMerge(
|
|
419
|
+
targetValue && typeof targetValue === "object" ? targetValue : {},
|
|
420
|
+
sourceValue
|
|
421
|
+
);
|
|
422
|
+
} else {
|
|
423
|
+
result[key] = sourceValue;
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
return result;
|
|
427
|
+
}
|
|
428
|
+
function getNestedValue(obj, path) {
|
|
429
|
+
const keys = path.split(".");
|
|
430
|
+
let current = obj;
|
|
431
|
+
for (const key of keys) {
|
|
432
|
+
if (current && typeof current === "object" && key in current) {
|
|
433
|
+
current = current[key];
|
|
434
|
+
} else {
|
|
435
|
+
return void 0;
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
return current;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// src/formats/json.ts
|
|
413
442
|
function detectIndent(text) {
|
|
414
443
|
let result = null;
|
|
415
444
|
jsonc.visit(text, {
|
|
@@ -453,34 +482,6 @@ function writeJsonConfig(filePath, config, configKey) {
|
|
|
453
482
|
}
|
|
454
483
|
writeFileSync(filePath, JSON.stringify(mergedConfig, null, 2));
|
|
455
484
|
}
|
|
456
|
-
function deepMerge(target, source) {
|
|
457
|
-
const result = { ...target };
|
|
458
|
-
for (const key in source) {
|
|
459
|
-
const sourceValue = source[key];
|
|
460
|
-
const targetValue = result[key];
|
|
461
|
-
if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
|
|
462
|
-
result[key] = deepMerge(
|
|
463
|
-
targetValue && typeof targetValue === "object" ? targetValue : {},
|
|
464
|
-
sourceValue
|
|
465
|
-
);
|
|
466
|
-
} else {
|
|
467
|
-
result[key] = sourceValue;
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
return result;
|
|
471
|
-
}
|
|
472
|
-
function getNestedValue(obj, path) {
|
|
473
|
-
const keys = path.split(".");
|
|
474
|
-
let current = obj;
|
|
475
|
-
for (const key of keys) {
|
|
476
|
-
if (current && typeof current === "object" && key in current) {
|
|
477
|
-
current = current[key];
|
|
478
|
-
} else {
|
|
479
|
-
return void 0;
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
return current;
|
|
483
|
-
}
|
|
484
485
|
function setNestedValue(obj, path, value) {
|
|
485
486
|
const keys = path.split(".");
|
|
486
487
|
const lastKey = keys.pop();
|
|
@@ -516,7 +517,7 @@ function writeYamlConfig(filePath, config) {
|
|
|
516
517
|
if (existsSync3(filePath)) {
|
|
517
518
|
existingConfig = readYamlConfig(filePath);
|
|
518
519
|
}
|
|
519
|
-
const mergedConfig =
|
|
520
|
+
const mergedConfig = deepMerge(existingConfig, config);
|
|
520
521
|
const content = yaml.dump(mergedConfig, {
|
|
521
522
|
indent: 2,
|
|
522
523
|
lineWidth: -1,
|
|
@@ -524,22 +525,6 @@ function writeYamlConfig(filePath, config) {
|
|
|
524
525
|
});
|
|
525
526
|
writeFileSync2(filePath, content);
|
|
526
527
|
}
|
|
527
|
-
function deepMerge2(target, source) {
|
|
528
|
-
const result = { ...target };
|
|
529
|
-
for (const key in source) {
|
|
530
|
-
const sourceValue = source[key];
|
|
531
|
-
const targetValue = result[key];
|
|
532
|
-
if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
|
|
533
|
-
result[key] = deepMerge2(
|
|
534
|
-
targetValue && typeof targetValue === "object" ? targetValue : {},
|
|
535
|
-
sourceValue
|
|
536
|
-
);
|
|
537
|
-
} else {
|
|
538
|
-
result[key] = sourceValue;
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
return result;
|
|
542
|
-
}
|
|
543
528
|
|
|
544
529
|
// src/formats/toml.ts
|
|
545
530
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, existsSync as existsSync4, mkdirSync as mkdirSync3 } from "fs";
|
|
@@ -562,26 +547,10 @@ function writeTomlConfig(filePath, config) {
|
|
|
562
547
|
if (existsSync4(filePath)) {
|
|
563
548
|
existingConfig = readTomlConfig(filePath);
|
|
564
549
|
}
|
|
565
|
-
const mergedConfig =
|
|
550
|
+
const mergedConfig = deepMerge(existingConfig, config);
|
|
566
551
|
const content = TOML.stringify(mergedConfig);
|
|
567
552
|
writeFileSync3(filePath, content);
|
|
568
553
|
}
|
|
569
|
-
function deepMerge3(target, source) {
|
|
570
|
-
const result = { ...target };
|
|
571
|
-
for (const key in source) {
|
|
572
|
-
const sourceValue = source[key];
|
|
573
|
-
const targetValue = result[key];
|
|
574
|
-
if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
|
|
575
|
-
result[key] = deepMerge3(
|
|
576
|
-
targetValue && typeof targetValue === "object" ? targetValue : {},
|
|
577
|
-
sourceValue
|
|
578
|
-
);
|
|
579
|
-
} else {
|
|
580
|
-
result[key] = sourceValue;
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
|
-
return result;
|
|
584
|
-
}
|
|
585
554
|
|
|
586
555
|
// src/formats/index.ts
|
|
587
556
|
function writeConfig(filePath, config, format, configKey) {
|
|
@@ -685,7 +654,7 @@ function installServer(serverName, serverConfig, agentTypes, options = {}) {
|
|
|
685
654
|
// package.json
|
|
686
655
|
var package_default = {
|
|
687
656
|
name: "add-mcp",
|
|
688
|
-
version: "0.
|
|
657
|
+
version: "0.4.0",
|
|
689
658
|
description: "Add MCP servers to your favorite coding agents with a single command.",
|
|
690
659
|
author: "Andre Landgraf <andre@neon.tech>",
|
|
691
660
|
license: "Apache-2.0",
|