add-mcp 0.3.2 → 0.3.5
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 +34 -45
- package/dist/index.js +88 -67
- 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,26 +59,17 @@ 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
|
-
###
|
|
45
|
-
|
|
46
|
-
```bash
|
|
47
|
-
# Install to specific agents
|
|
48
|
-
npx add-mcp https://mcp.example.com/mcp -a cursor -a claude-code
|
|
49
|
-
|
|
50
|
-
# Install with SSE transport
|
|
51
|
-
npx add-mcp https://mcp.neon.tech/sse --transport sse
|
|
52
|
-
|
|
53
|
-
# Install with custom server name
|
|
54
|
-
npx add-mcp @modelcontextprotocol/server-postgres --name postgres
|
|
62
|
+
### Additional Commands
|
|
55
63
|
|
|
56
|
-
|
|
57
|
-
npx add-mcp https://mcp.example.com/mcp -g -a claude-code -y
|
|
64
|
+
Besides the implicit add command, `add-mcp` also supports the following commands:
|
|
58
65
|
|
|
59
|
-
|
|
60
|
-
|
|
66
|
+
| Command | Description |
|
|
67
|
+
| ------------- | ------------------------------------------------------------ |
|
|
68
|
+
| `list-agents` | List all supported coding agents with scope (project/global) |
|
|
61
69
|
|
|
62
|
-
|
|
63
|
-
|
|
70
|
+
```bash
|
|
71
|
+
# List all supported agents
|
|
72
|
+
npx add-mcp list-agents
|
|
64
73
|
```
|
|
65
74
|
|
|
66
75
|
### Installation Scope
|
|
@@ -92,12 +101,12 @@ The CLI automatically detects agents based on your environment:
|
|
|
92
101
|
|
|
93
102
|
## Transport Types
|
|
94
103
|
|
|
95
|
-
|
|
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:
|
|
96
105
|
|
|
97
|
-
| Transport | Flag | Description
|
|
98
|
-
| --------- | ------------------ |
|
|
99
|
-
| **HTTP** | `--transport http` | Streamable HTTP (default
|
|
100
|
-
| **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) |
|
|
101
110
|
|
|
102
111
|
Local servers (npm packages, commands) always use **stdio** transport.
|
|
103
112
|
|
|
@@ -121,37 +130,17 @@ MCP servers can be installed to any of these agents:
|
|
|
121
130
|
|
|
122
131
|
The CLI uses smart detection to find agents in your project directory and globally installed agents. See [Smart Detection](#smart-detection) for details.
|
|
123
132
|
|
|
124
|
-
### Transport Support
|
|
125
|
-
|
|
126
|
-
Not all agents support all transport types:
|
|
127
|
-
|
|
128
|
-
| Agent | stdio | http | sse |
|
|
129
|
-
| -------------- | ----- | ---- | --- |
|
|
130
|
-
| Claude Code | ✓ | ✓ | ✓ |
|
|
131
|
-
| Claude Desktop | ✓ | ✓ | ✓ |
|
|
132
|
-
| Codex | ✓ | ✓ | ✓ |
|
|
133
|
-
| Cursor | ✓ | ✓ | ✓ |
|
|
134
|
-
| Gemini CLI | ✓ | ✓ | ✓ |
|
|
135
|
-
| Goose | ✓ | ✓ | ✗ |
|
|
136
|
-
| OpenCode | ✓ | ✓ | ✓ |
|
|
137
|
-
| VS Code | ✓ | ✓ | ✓ |
|
|
138
|
-
| Zed | ✓ | ✓ | ✓ |
|
|
139
|
-
|
|
140
133
|
## What are MCP Servers?
|
|
141
134
|
|
|
142
135
|
[Model Context Protocol (MCP)](https://modelcontextprotocol.io/) servers extend your coding agent's capabilities by providing tools, resources, and context. MCP servers can:
|
|
143
136
|
|
|
137
|
+
- Integrate with external services (Notion, Linear, GitHub, etc.)
|
|
144
138
|
- Connect to databases (PostgreSQL, MySQL, etc.)
|
|
145
|
-
- Integrate with external services (GitHub, Linear, Notion)
|
|
146
139
|
- Provide file system access
|
|
147
140
|
- Offer specialized tools for your workflow
|
|
148
141
|
|
|
149
142
|
## Troubleshooting
|
|
150
143
|
|
|
151
|
-
### Transport mismatch error
|
|
152
|
-
|
|
153
|
-
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.
|
|
154
|
-
|
|
155
144
|
### Server not loading
|
|
156
145
|
|
|
157
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
|
|
@@ -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
|
},
|
|
@@ -296,11 +296,41 @@ function isPackageName(input) {
|
|
|
296
296
|
}
|
|
297
297
|
return false;
|
|
298
298
|
}
|
|
299
|
+
var commonTlds = /* @__PURE__ */ new Set([
|
|
300
|
+
"com",
|
|
301
|
+
"org",
|
|
302
|
+
"net",
|
|
303
|
+
"io",
|
|
304
|
+
"dev",
|
|
305
|
+
"ai",
|
|
306
|
+
"tech",
|
|
307
|
+
"co",
|
|
308
|
+
"app",
|
|
309
|
+
"cloud",
|
|
310
|
+
"sh",
|
|
311
|
+
"run"
|
|
312
|
+
]);
|
|
313
|
+
function extractBrandFromHostname(hostname) {
|
|
314
|
+
const parts = hostname.split(".");
|
|
315
|
+
const meaningfulParts = parts.filter((part) => {
|
|
316
|
+
const lower = part.toLowerCase();
|
|
317
|
+
if (commonTlds.has(lower)) return false;
|
|
318
|
+
if (lower === "mcp" || lower === "api" || lower === "www") return false;
|
|
319
|
+
return true;
|
|
320
|
+
});
|
|
321
|
+
if (meaningfulParts.length > 0) {
|
|
322
|
+
return meaningfulParts[0];
|
|
323
|
+
}
|
|
324
|
+
if (parts.length >= 2) {
|
|
325
|
+
return parts[parts.length - 2];
|
|
326
|
+
}
|
|
327
|
+
return "mcp-server";
|
|
328
|
+
}
|
|
299
329
|
function inferName(input, type) {
|
|
300
330
|
if (type === "remote") {
|
|
301
331
|
try {
|
|
302
332
|
const url = new URL(input);
|
|
303
|
-
return url.hostname
|
|
333
|
+
return extractBrandFromHostname(url.hostname);
|
|
304
334
|
} catch {
|
|
305
335
|
return "mcp-server";
|
|
306
336
|
}
|
|
@@ -380,6 +410,38 @@ import { join as join2, dirname as dirname4 } from "path";
|
|
|
380
410
|
import { readFileSync, writeFileSync, existsSync as existsSync2, mkdirSync } from "fs";
|
|
381
411
|
import { dirname } from "path";
|
|
382
412
|
import * as jsonc from "jsonc-parser";
|
|
413
|
+
|
|
414
|
+
// src/formats/utils.ts
|
|
415
|
+
function deepMerge(target, source) {
|
|
416
|
+
const result = { ...target };
|
|
417
|
+
for (const key in source) {
|
|
418
|
+
const sourceValue = source[key];
|
|
419
|
+
const targetValue = result[key];
|
|
420
|
+
if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
|
|
421
|
+
result[key] = deepMerge(
|
|
422
|
+
targetValue && typeof targetValue === "object" ? targetValue : {},
|
|
423
|
+
sourceValue
|
|
424
|
+
);
|
|
425
|
+
} else {
|
|
426
|
+
result[key] = sourceValue;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
return result;
|
|
430
|
+
}
|
|
431
|
+
function getNestedValue(obj, path) {
|
|
432
|
+
const keys = path.split(".");
|
|
433
|
+
let current = obj;
|
|
434
|
+
for (const key of keys) {
|
|
435
|
+
if (current && typeof current === "object" && key in current) {
|
|
436
|
+
current = current[key];
|
|
437
|
+
} else {
|
|
438
|
+
return void 0;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return current;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
// src/formats/json.ts
|
|
383
445
|
function detectIndent(text) {
|
|
384
446
|
let result = null;
|
|
385
447
|
jsonc.visit(text, {
|
|
@@ -423,34 +485,6 @@ function writeJsonConfig(filePath, config, configKey) {
|
|
|
423
485
|
}
|
|
424
486
|
writeFileSync(filePath, JSON.stringify(mergedConfig, null, 2));
|
|
425
487
|
}
|
|
426
|
-
function deepMerge(target, source) {
|
|
427
|
-
const result = { ...target };
|
|
428
|
-
for (const key in source) {
|
|
429
|
-
const sourceValue = source[key];
|
|
430
|
-
const targetValue = result[key];
|
|
431
|
-
if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
|
|
432
|
-
result[key] = deepMerge(
|
|
433
|
-
targetValue && typeof targetValue === "object" ? targetValue : {},
|
|
434
|
-
sourceValue
|
|
435
|
-
);
|
|
436
|
-
} else {
|
|
437
|
-
result[key] = sourceValue;
|
|
438
|
-
}
|
|
439
|
-
}
|
|
440
|
-
return result;
|
|
441
|
-
}
|
|
442
|
-
function getNestedValue(obj, path) {
|
|
443
|
-
const keys = path.split(".");
|
|
444
|
-
let current = obj;
|
|
445
|
-
for (const key of keys) {
|
|
446
|
-
if (current && typeof current === "object" && key in current) {
|
|
447
|
-
current = current[key];
|
|
448
|
-
} else {
|
|
449
|
-
return void 0;
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
return current;
|
|
453
|
-
}
|
|
454
488
|
function setNestedValue(obj, path, value) {
|
|
455
489
|
const keys = path.split(".");
|
|
456
490
|
const lastKey = keys.pop();
|
|
@@ -486,7 +520,7 @@ function writeYamlConfig(filePath, config) {
|
|
|
486
520
|
if (existsSync3(filePath)) {
|
|
487
521
|
existingConfig = readYamlConfig(filePath);
|
|
488
522
|
}
|
|
489
|
-
const mergedConfig =
|
|
523
|
+
const mergedConfig = deepMerge(existingConfig, config);
|
|
490
524
|
const content = yaml.dump(mergedConfig, {
|
|
491
525
|
indent: 2,
|
|
492
526
|
lineWidth: -1,
|
|
@@ -494,22 +528,6 @@ function writeYamlConfig(filePath, config) {
|
|
|
494
528
|
});
|
|
495
529
|
writeFileSync2(filePath, content);
|
|
496
530
|
}
|
|
497
|
-
function deepMerge2(target, source) {
|
|
498
|
-
const result = { ...target };
|
|
499
|
-
for (const key in source) {
|
|
500
|
-
const sourceValue = source[key];
|
|
501
|
-
const targetValue = result[key];
|
|
502
|
-
if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
|
|
503
|
-
result[key] = deepMerge2(
|
|
504
|
-
targetValue && typeof targetValue === "object" ? targetValue : {},
|
|
505
|
-
sourceValue
|
|
506
|
-
);
|
|
507
|
-
} else {
|
|
508
|
-
result[key] = sourceValue;
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
return result;
|
|
512
|
-
}
|
|
513
531
|
|
|
514
532
|
// src/formats/toml.ts
|
|
515
533
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, existsSync as existsSync4, mkdirSync as mkdirSync3 } from "fs";
|
|
@@ -532,26 +550,10 @@ function writeTomlConfig(filePath, config) {
|
|
|
532
550
|
if (existsSync4(filePath)) {
|
|
533
551
|
existingConfig = readTomlConfig(filePath);
|
|
534
552
|
}
|
|
535
|
-
const mergedConfig =
|
|
553
|
+
const mergedConfig = deepMerge(existingConfig, config);
|
|
536
554
|
const content = TOML.stringify(mergedConfig);
|
|
537
555
|
writeFileSync3(filePath, content);
|
|
538
556
|
}
|
|
539
|
-
function deepMerge3(target, source) {
|
|
540
|
-
const result = { ...target };
|
|
541
|
-
for (const key in source) {
|
|
542
|
-
const sourceValue = source[key];
|
|
543
|
-
const targetValue = result[key];
|
|
544
|
-
if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
|
|
545
|
-
result[key] = deepMerge3(
|
|
546
|
-
targetValue && typeof targetValue === "object" ? targetValue : {},
|
|
547
|
-
sourceValue
|
|
548
|
-
);
|
|
549
|
-
} else {
|
|
550
|
-
result[key] = sourceValue;
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
return result;
|
|
554
|
-
}
|
|
555
557
|
|
|
556
558
|
// src/formats/index.ts
|
|
557
559
|
function writeConfig(filePath, config, format, configKey) {
|
|
@@ -655,7 +657,7 @@ function installServer(serverName, serverConfig, agentTypes, options = {}) {
|
|
|
655
657
|
// package.json
|
|
656
658
|
var package_default = {
|
|
657
659
|
name: "add-mcp",
|
|
658
|
-
version: "0.3.
|
|
660
|
+
version: "0.3.5",
|
|
659
661
|
description: "Add MCP servers to your favorite coding agents with a single command.",
|
|
660
662
|
author: "Andre Landgraf <andre@neon.tech>",
|
|
661
663
|
license: "Apache-2.0",
|
|
@@ -782,7 +784,26 @@ program.name("add-mcp").description(
|
|
|
782
784
|
).option("--type <type>", "Alias for --transport").option("-y, --yes", "Skip confirmation prompts").option("--all", "Install to all agents").action(async (target, options) => {
|
|
783
785
|
await main(target, options);
|
|
784
786
|
});
|
|
787
|
+
program.command("list-agents").description("List all supported coding agents").action(() => {
|
|
788
|
+
listAgents();
|
|
789
|
+
});
|
|
785
790
|
program.parse();
|
|
791
|
+
function listAgents() {
|
|
792
|
+
showLogo();
|
|
793
|
+
console.log();
|
|
794
|
+
console.log(`${DIM}Supported agents:${RESET}`);
|
|
795
|
+
console.log();
|
|
796
|
+
const allAgentTypes = getAgentTypes();
|
|
797
|
+
for (const agentType of allAgentTypes) {
|
|
798
|
+
const agent = agents[agentType];
|
|
799
|
+
const hasProjectSupport = supportsProjectConfig(agentType);
|
|
800
|
+
const scope = hasProjectSupport ? "project, global" : "global";
|
|
801
|
+
console.log(
|
|
802
|
+
` ${TEXT}${agent.displayName}${RESET} ${DIM}(${scope})${RESET}`
|
|
803
|
+
);
|
|
804
|
+
}
|
|
805
|
+
console.log();
|
|
806
|
+
}
|
|
786
807
|
async function main(target, options) {
|
|
787
808
|
showLogo();
|
|
788
809
|
if (!target) {
|