add-mcp 0.1.1 → 0.2.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 +28 -13
- package/dist/index.js +175 -70
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
# add-mcp
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
<!-- agent-list:start -->
|
|
3
|
+
Add MCP servers to your favorite coding agents with a single command.
|
|
6
4
|
|
|
7
5
|
Supports **OpenCode**, **Claude Code**, **Codex**, **Cursor**, and [5 more](#supported-agents).
|
|
8
6
|
|
|
9
|
-
<!-- agent-list:end -->
|
|
10
|
-
|
|
11
7
|
## Install an MCP Server
|
|
12
8
|
|
|
13
9
|
```bash
|
|
@@ -43,7 +39,7 @@ npx add-mcp "node /path/to/server.js --port 3000"
|
|
|
43
39
|
| `--type <type>` | Alias for `--transport` |
|
|
44
40
|
| `-n, --name <name>` | Server name (auto-inferred if not provided) |
|
|
45
41
|
| `-y, --yes` | Skip all confirmation prompts |
|
|
46
|
-
| `--all` | Install to all agents
|
|
42
|
+
| `--all` | Install to all agents |
|
|
47
43
|
|
|
48
44
|
### Examples
|
|
49
45
|
|
|
@@ -60,8 +56,11 @@ npx add-mcp @modelcontextprotocol/server-postgres --name postgres
|
|
|
60
56
|
# Non-interactive installation (CI/CD friendly)
|
|
61
57
|
npx add-mcp https://mcp.example.com/mcp -g -a claude-code -y
|
|
62
58
|
|
|
63
|
-
# Install to all agents
|
|
59
|
+
# Install to all agents
|
|
64
60
|
npx add-mcp mcp-server-github --all
|
|
61
|
+
|
|
62
|
+
# Install to all agents, globally, without prompts
|
|
63
|
+
npx add-mcp mcp-server-github --all -g -y
|
|
65
64
|
```
|
|
66
65
|
|
|
67
66
|
### Installation Scope
|
|
@@ -71,6 +70,26 @@ npx add-mcp mcp-server-github --all
|
|
|
71
70
|
| **Project** | (default) | `.cursor/mcp.json` etc. | Committed with your project, shared with team |
|
|
72
71
|
| **Global** | `-g` | `~/.cursor/mcp.json` | Available across all projects |
|
|
73
72
|
|
|
73
|
+
### Smart Detection
|
|
74
|
+
|
|
75
|
+
The CLI automatically detects agents based on your environment:
|
|
76
|
+
|
|
77
|
+
**Default (project mode):**
|
|
78
|
+
|
|
79
|
+
- Detects project-level config files (`.cursor/`, `.vscode/`, `.mcp.json`, etc.)
|
|
80
|
+
- Also detects globally-installed agents that only support global config (Claude Desktop, Codex, Zed)
|
|
81
|
+
- Agents are routed appropriately: project-capable agents use project config, global-only agents use global config
|
|
82
|
+
|
|
83
|
+
**With `-g` (global mode):**
|
|
84
|
+
|
|
85
|
+
- Detects all globally-installed agents
|
|
86
|
+
- All agents use global config
|
|
87
|
+
|
|
88
|
+
**No agents detected:**
|
|
89
|
+
|
|
90
|
+
- Interactive mode: Shows error with guidance to use `--global` or run in a project
|
|
91
|
+
- With `--yes`: Installs to all project-capable agents
|
|
92
|
+
|
|
74
93
|
## Transport Types
|
|
75
94
|
|
|
76
95
|
MCP supports different transport mechanisms for remote servers:
|
|
@@ -86,8 +105,6 @@ Local servers (npm packages, commands) always use **stdio** transport.
|
|
|
86
105
|
|
|
87
106
|
MCP servers can be installed to any of these agents:
|
|
88
107
|
|
|
89
|
-
<!-- supported-agents:start -->
|
|
90
|
-
|
|
91
108
|
| Agent | `--agent` | Project Path | Global Path |
|
|
92
109
|
| -------------- | ---------------- | ----------------------- | ----------------------------------------------------------------- |
|
|
93
110
|
| Claude Code | `claude-code` | `.mcp.json` | `~/.claude.json` |
|
|
@@ -95,16 +112,14 @@ MCP servers can be installed to any of these agents:
|
|
|
95
112
|
| Codex | `codex` | - | `~/.codex/config.toml` |
|
|
96
113
|
| Cursor | `cursor` | `.cursor/mcp.json` | `~/.cursor/mcp.json` |
|
|
97
114
|
| Gemini CLI | `gemini-cli` | `.gemini/settings.json` | `~/.gemini/settings.json` |
|
|
98
|
-
| Goose | `goose` |
|
|
115
|
+
| Goose | `goose` | `.goose/config.yaml` | `~/.config/goose/config.yaml` |
|
|
99
116
|
| OpenCode | `opencode` | `.opencode.json` | `~/.config/opencode/opencode.json` |
|
|
100
117
|
| VS Code | `vscode` | `.vscode/mcp.json` | `~/Library/Application Support/Code/User/mcp.json` |
|
|
101
118
|
| Zed | `zed` | - | `~/.config/zed/settings.json` |
|
|
102
119
|
|
|
103
|
-
<!-- supported-agents:end -->
|
|
104
|
-
|
|
105
120
|
**Aliases:** `github-copilot` → `vscode`
|
|
106
121
|
|
|
107
|
-
The CLI
|
|
122
|
+
The CLI uses smart detection to find agents in your project directory and globally installed agents. See [Smart Detection](#smart-detection) for details.
|
|
108
123
|
|
|
109
124
|
### Transport Support
|
|
110
125
|
|
package/dist/index.js
CHANGED
|
@@ -111,10 +111,11 @@ var agents = {
|
|
|
111
111
|
displayName: "Claude Code",
|
|
112
112
|
configPath: join(home, ".claude.json"),
|
|
113
113
|
localConfigPath: ".mcp.json",
|
|
114
|
+
projectDetectPaths: [".mcp.json", ".claude"],
|
|
114
115
|
configKey: "mcpServers",
|
|
115
116
|
format: "json",
|
|
116
117
|
supportedTransports: ["stdio", "http", "sse"],
|
|
117
|
-
|
|
118
|
+
detectGlobalInstall: async () => {
|
|
118
119
|
return existsSync(join(home, ".claude"));
|
|
119
120
|
}
|
|
120
121
|
},
|
|
@@ -122,10 +123,12 @@ var agents = {
|
|
|
122
123
|
name: "claude-desktop",
|
|
123
124
|
displayName: "Claude Desktop",
|
|
124
125
|
configPath: join(appSupport, "Claude", "claude_desktop_config.json"),
|
|
126
|
+
projectDetectPaths: [],
|
|
127
|
+
// Global only - no project support
|
|
125
128
|
configKey: "mcpServers",
|
|
126
129
|
format: "json",
|
|
127
130
|
supportedTransports: ["stdio", "http", "sse"],
|
|
128
|
-
|
|
131
|
+
detectGlobalInstall: async () => {
|
|
129
132
|
return existsSync(join(appSupport, "Claude"));
|
|
130
133
|
}
|
|
131
134
|
},
|
|
@@ -136,10 +139,12 @@ var agents = {
|
|
|
136
139
|
process.env.CODEX_HOME || join(home, ".codex"),
|
|
137
140
|
"config.toml"
|
|
138
141
|
),
|
|
142
|
+
projectDetectPaths: [],
|
|
143
|
+
// Global only - no project support
|
|
139
144
|
configKey: "mcp_servers",
|
|
140
145
|
format: "toml",
|
|
141
146
|
supportedTransports: ["stdio", "http", "sse"],
|
|
142
|
-
|
|
147
|
+
detectGlobalInstall: async () => {
|
|
143
148
|
return existsSync(join(home, ".codex"));
|
|
144
149
|
},
|
|
145
150
|
transformConfig: transformCodexConfig
|
|
@@ -149,10 +154,11 @@ var agents = {
|
|
|
149
154
|
displayName: "Cursor",
|
|
150
155
|
configPath: join(home, ".cursor", "mcp.json"),
|
|
151
156
|
localConfigPath: ".cursor/mcp.json",
|
|
157
|
+
projectDetectPaths: [".cursor"],
|
|
152
158
|
configKey: "mcpServers",
|
|
153
159
|
format: "json",
|
|
154
160
|
supportedTransports: ["stdio", "http", "sse"],
|
|
155
|
-
|
|
161
|
+
detectGlobalInstall: async () => {
|
|
156
162
|
return existsSync(join(home, ".cursor"));
|
|
157
163
|
}
|
|
158
164
|
},
|
|
@@ -161,10 +167,11 @@ var agents = {
|
|
|
161
167
|
displayName: "Gemini CLI",
|
|
162
168
|
configPath: join(home, ".gemini", "settings.json"),
|
|
163
169
|
localConfigPath: ".gemini/settings.json",
|
|
170
|
+
projectDetectPaths: [".gemini"],
|
|
164
171
|
configKey: "mcpServers",
|
|
165
172
|
format: "json",
|
|
166
173
|
supportedTransports: ["stdio", "http", "sse"],
|
|
167
|
-
|
|
174
|
+
detectGlobalInstall: async () => {
|
|
168
175
|
return existsSync(join(home, ".gemini"));
|
|
169
176
|
}
|
|
170
177
|
},
|
|
@@ -172,11 +179,13 @@ var agents = {
|
|
|
172
179
|
name: "goose",
|
|
173
180
|
displayName: "Goose",
|
|
174
181
|
configPath: join(home, ".config", "goose", "config.yaml"),
|
|
182
|
+
localConfigPath: ".goose/config.yaml",
|
|
183
|
+
projectDetectPaths: [".goose"],
|
|
175
184
|
configKey: "extensions",
|
|
176
185
|
format: "yaml",
|
|
177
186
|
supportedTransports: ["stdio", "http"],
|
|
178
187
|
// Goose does not support SSE
|
|
179
|
-
|
|
188
|
+
detectGlobalInstall: async () => {
|
|
180
189
|
return existsSync(join(home, ".config", "goose"));
|
|
181
190
|
},
|
|
182
191
|
transformConfig: transformGooseConfig
|
|
@@ -186,10 +195,11 @@ var agents = {
|
|
|
186
195
|
displayName: "OpenCode",
|
|
187
196
|
configPath: join(home, ".config", "opencode", "opencode.json"),
|
|
188
197
|
localConfigPath: ".opencode.json",
|
|
198
|
+
projectDetectPaths: [".opencode.json", ".opencode"],
|
|
189
199
|
configKey: "mcp",
|
|
190
200
|
format: "json",
|
|
191
201
|
supportedTransports: ["stdio", "http", "sse"],
|
|
192
|
-
|
|
202
|
+
detectGlobalInstall: async () => {
|
|
193
203
|
return existsSync(join(home, ".config", "opencode"));
|
|
194
204
|
},
|
|
195
205
|
transformConfig: transformOpenCodeConfig
|
|
@@ -199,10 +209,11 @@ var agents = {
|
|
|
199
209
|
displayName: "VS Code",
|
|
200
210
|
configPath: join(vscodePath, "mcp.json"),
|
|
201
211
|
localConfigPath: ".vscode/mcp.json",
|
|
212
|
+
projectDetectPaths: [".vscode"],
|
|
202
213
|
configKey: "mcpServers",
|
|
203
214
|
format: "json",
|
|
204
215
|
supportedTransports: ["stdio", "http", "sse"],
|
|
205
|
-
|
|
216
|
+
detectGlobalInstall: async () => {
|
|
206
217
|
return existsSync(vscodePath);
|
|
207
218
|
}
|
|
208
219
|
},
|
|
@@ -214,10 +225,12 @@ var agents = {
|
|
|
214
225
|
"Zed",
|
|
215
226
|
"settings.json"
|
|
216
227
|
) : join(home, ".config", "zed", "settings.json"),
|
|
228
|
+
projectDetectPaths: [],
|
|
229
|
+
// Global only - no project support
|
|
217
230
|
configKey: "context_servers",
|
|
218
231
|
format: "json",
|
|
219
232
|
supportedTransports: ["stdio", "http", "sse"],
|
|
220
|
-
|
|
233
|
+
detectGlobalInstall: async () => {
|
|
221
234
|
return existsSync(join(home, ".config", "zed")) || existsSync(join(process.env.APPDATA || "", "Zed"));
|
|
222
235
|
},
|
|
223
236
|
transformConfig: transformZedConfig
|
|
@@ -226,14 +239,46 @@ var agents = {
|
|
|
226
239
|
function getAgentTypes() {
|
|
227
240
|
return Object.keys(agents);
|
|
228
241
|
}
|
|
229
|
-
|
|
230
|
-
|
|
242
|
+
function supportsProjectConfig(agentType) {
|
|
243
|
+
return agents[agentType].localConfigPath !== void 0;
|
|
244
|
+
}
|
|
245
|
+
function getProjectCapableAgents() {
|
|
246
|
+
return Object.keys(agents).filter(
|
|
247
|
+
(type) => supportsProjectConfig(type)
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
function detectProjectAgents(cwd) {
|
|
251
|
+
const dir = cwd || process.cwd();
|
|
252
|
+
const detected = [];
|
|
231
253
|
for (const [type, config] of Object.entries(agents)) {
|
|
232
|
-
if (
|
|
233
|
-
|
|
254
|
+
if (!config.localConfigPath) continue;
|
|
255
|
+
for (const detectPath of config.projectDetectPaths) {
|
|
256
|
+
if (existsSync(join(dir, detectPath))) {
|
|
257
|
+
detected.push(type);
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
234
260
|
}
|
|
235
261
|
}
|
|
236
|
-
return
|
|
262
|
+
return detected;
|
|
263
|
+
}
|
|
264
|
+
async function detectGlobalOnlyAgents() {
|
|
265
|
+
const detected = [];
|
|
266
|
+
for (const [type, config] of Object.entries(agents)) {
|
|
267
|
+
if (config.localConfigPath) continue;
|
|
268
|
+
if (await config.detectGlobalInstall()) {
|
|
269
|
+
detected.push(type);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
return detected;
|
|
273
|
+
}
|
|
274
|
+
async function detectAllGlobalAgents() {
|
|
275
|
+
const detected = [];
|
|
276
|
+
for (const [type, config] of Object.entries(agents)) {
|
|
277
|
+
if (await config.detectGlobalInstall()) {
|
|
278
|
+
detected.push(type);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
return detected;
|
|
237
282
|
}
|
|
238
283
|
function isTransportSupported(agentType, transport) {
|
|
239
284
|
return agents[agentType].supportedTransports.includes(transport);
|
|
@@ -601,24 +646,26 @@ function installServerForAgent(serverName, serverConfig, agentType, options = {}
|
|
|
601
646
|
function installServer(serverName, serverConfig, agentTypes, options = {}) {
|
|
602
647
|
const results = /* @__PURE__ */ new Map();
|
|
603
648
|
for (const agentType of agentTypes) {
|
|
649
|
+
const routing = options.routing?.get(agentType);
|
|
650
|
+
const installOptions = {
|
|
651
|
+
local: routing === "local",
|
|
652
|
+
cwd: options.cwd
|
|
653
|
+
};
|
|
604
654
|
const result = installServerForAgent(
|
|
605
655
|
serverName,
|
|
606
656
|
serverConfig,
|
|
607
657
|
agentType,
|
|
608
|
-
|
|
658
|
+
installOptions
|
|
609
659
|
);
|
|
610
660
|
results.set(agentType, result);
|
|
611
661
|
}
|
|
612
662
|
return results;
|
|
613
663
|
}
|
|
614
|
-
function getAgentsWithLocalSupport() {
|
|
615
|
-
return Object.entries(agents).filter(([_, config]) => config.localConfigPath !== void 0).map(([type, _]) => type);
|
|
616
|
-
}
|
|
617
664
|
|
|
618
665
|
// package.json
|
|
619
666
|
var package_default = {
|
|
620
667
|
name: "add-mcp",
|
|
621
|
-
version: "0.
|
|
668
|
+
version: "0.2.0",
|
|
622
669
|
description: "Install MCP servers onto coding agents (Claude Code, Cursor, VS Code, OpenCode, Codex)",
|
|
623
670
|
author: "Andre Landgraf <andre@neon.tech>",
|
|
624
671
|
license: "Apache-2.0",
|
|
@@ -634,8 +681,8 @@ var package_default = {
|
|
|
634
681
|
fmt: "prettier --write .",
|
|
635
682
|
build: "tsup src/index.ts --format esm --dts --clean",
|
|
636
683
|
dev: "tsx src/index.ts",
|
|
637
|
-
test: "tsx tests/source-parser.test.ts && tsx tests/installer.test.ts && tsx tests/e2e/install.test.ts",
|
|
638
|
-
"test:unit": "tsx tests/source-parser.test.ts && tsx tests/installer.test.ts",
|
|
684
|
+
test: "tsx tests/source-parser.test.ts && tsx tests/agents.test.ts && tsx tests/installer.test.ts && tsx tests/e2e/install.test.ts",
|
|
685
|
+
"test:unit": "tsx tests/source-parser.test.ts && tsx tests/agents.test.ts && tsx tests/installer.test.ts",
|
|
639
686
|
"test:e2e": "tsx tests/e2e/install.test.ts",
|
|
640
687
|
typecheck: "tsc --noEmit",
|
|
641
688
|
prepublishOnly: "npm run build"
|
|
@@ -717,15 +764,11 @@ program.name("add-mcp").description(
|
|
|
717
764
|
).option(
|
|
718
765
|
"-t, --transport <type>",
|
|
719
766
|
"Transport type for remote servers (http, sse)"
|
|
720
|
-
).option("--type <type>", "Alias for --transport").option("-y, --yes", "Skip confirmation prompts").option("--all", "Install to all agents
|
|
767
|
+
).option("--type <type>", "Alias for --transport").option("-y, --yes", "Skip confirmation prompts").option("--all", "Install to all agents").action(async (target, options) => {
|
|
721
768
|
await main(target, options);
|
|
722
769
|
});
|
|
723
770
|
program.parse();
|
|
724
771
|
async function main(target, options) {
|
|
725
|
-
if (options.all) {
|
|
726
|
-
options.yes = true;
|
|
727
|
-
options.global = true;
|
|
728
|
-
}
|
|
729
772
|
console.log();
|
|
730
773
|
p.intro(chalk.bgCyan.black(" add-mcp "));
|
|
731
774
|
if (!target) {
|
|
@@ -774,6 +817,7 @@ async function main(target, options) {
|
|
|
774
817
|
});
|
|
775
818
|
let targetAgents;
|
|
776
819
|
const allAgentTypes = getAgentTypes();
|
|
820
|
+
let agentRouting = /* @__PURE__ */ new Map();
|
|
777
821
|
if (options.agent && options.agent.length > 0) {
|
|
778
822
|
const resolved = [];
|
|
779
823
|
const invalid = [];
|
|
@@ -795,16 +839,40 @@ async function main(target, options) {
|
|
|
795
839
|
targetAgents = allAgentTypes;
|
|
796
840
|
p.log.info(`Installing to all ${targetAgents.length} agents`);
|
|
797
841
|
} else {
|
|
798
|
-
spinner2.start("Detecting
|
|
799
|
-
|
|
842
|
+
spinner2.start("Detecting agents...");
|
|
843
|
+
let detectedAgents;
|
|
844
|
+
if (options.global) {
|
|
845
|
+
detectedAgents = await detectAllGlobalAgents();
|
|
846
|
+
} else {
|
|
847
|
+
const projectAgents = detectProjectAgents();
|
|
848
|
+
const globalOnlyAgents = await detectGlobalOnlyAgents();
|
|
849
|
+
detectedAgents = [...projectAgents, ...globalOnlyAgents];
|
|
850
|
+
for (const agent of projectAgents) {
|
|
851
|
+
agentRouting.set(agent, "local");
|
|
852
|
+
}
|
|
853
|
+
for (const agent of globalOnlyAgents) {
|
|
854
|
+
agentRouting.set(agent, "global");
|
|
855
|
+
}
|
|
856
|
+
}
|
|
800
857
|
spinner2.stop(
|
|
801
|
-
`Detected ${
|
|
858
|
+
`Detected ${detectedAgents.length} agent${detectedAgents.length !== 1 ? "s" : ""}`
|
|
802
859
|
);
|
|
803
|
-
if (
|
|
860
|
+
if (detectedAgents.length === 0) {
|
|
804
861
|
if (options.yes) {
|
|
805
|
-
targetAgents =
|
|
806
|
-
|
|
862
|
+
targetAgents = getProjectCapableAgents();
|
|
863
|
+
for (const agent of targetAgents) {
|
|
864
|
+
agentRouting.set(agent, "local");
|
|
865
|
+
}
|
|
866
|
+
p.log.info(
|
|
867
|
+
`Installing to ${targetAgents.length} project-capable agents (none detected)`
|
|
868
|
+
);
|
|
807
869
|
} else {
|
|
870
|
+
if (!options.global) {
|
|
871
|
+
p.log.error(
|
|
872
|
+
"No agents detected in this project. Use --global to install globally, or run in a project with agent config files."
|
|
873
|
+
);
|
|
874
|
+
process.exit(1);
|
|
875
|
+
}
|
|
808
876
|
p.log.warn(
|
|
809
877
|
"No coding agents detected. You can still install MCP servers."
|
|
810
878
|
);
|
|
@@ -823,21 +891,25 @@ async function main(target, options) {
|
|
|
823
891
|
}
|
|
824
892
|
targetAgents = selected;
|
|
825
893
|
}
|
|
826
|
-
} else if (
|
|
827
|
-
targetAgents =
|
|
828
|
-
const agentNames =
|
|
894
|
+
} else if (detectedAgents.length === 1 || options.yes) {
|
|
895
|
+
targetAgents = detectedAgents;
|
|
896
|
+
const agentNames = detectedAgents.map((a) => chalk.cyan(agents[a].displayName)).join(", ");
|
|
829
897
|
p.log.info(`Installing to: ${agentNames}`);
|
|
830
898
|
} else {
|
|
831
|
-
const agentChoices =
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
899
|
+
const agentChoices = detectedAgents.map((a) => {
|
|
900
|
+
const routing = agentRouting.get(a);
|
|
901
|
+
const hint = routing === "local" ? "project" : routing === "global" ? "global" : shortenPath(agents[a].configPath);
|
|
902
|
+
return {
|
|
903
|
+
value: a,
|
|
904
|
+
label: agents[a].displayName,
|
|
905
|
+
hint
|
|
906
|
+
};
|
|
907
|
+
});
|
|
836
908
|
const selected = await p.multiselect({
|
|
837
909
|
message: "Select agents to install to",
|
|
838
910
|
options: agentChoices,
|
|
839
911
|
required: true,
|
|
840
|
-
initialValues:
|
|
912
|
+
initialValues: detectedAgents
|
|
841
913
|
});
|
|
842
914
|
if (p.isCancel(selected)) {
|
|
843
915
|
p.cancel("Installation cancelled");
|
|
@@ -870,47 +942,80 @@ async function main(target, options) {
|
|
|
870
942
|
process.exit(1);
|
|
871
943
|
}
|
|
872
944
|
}
|
|
873
|
-
|
|
874
|
-
if (options.global
|
|
875
|
-
const
|
|
945
|
+
const hasSmartRouting = agentRouting.size > 0;
|
|
946
|
+
if (options.global) {
|
|
947
|
+
for (const agent of targetAgents) {
|
|
948
|
+
agentRouting.set(agent, "global");
|
|
949
|
+
}
|
|
950
|
+
} else if (!hasSmartRouting) {
|
|
876
951
|
const selectedWithLocal = targetAgents.filter(
|
|
877
|
-
(a) =>
|
|
952
|
+
(a) => supportsProjectConfig(a)
|
|
953
|
+
);
|
|
954
|
+
const globalOnlySelected = targetAgents.filter(
|
|
955
|
+
(a) => !supportsProjectConfig(a)
|
|
878
956
|
);
|
|
957
|
+
for (const agent of globalOnlySelected) {
|
|
958
|
+
agentRouting.set(agent, "global");
|
|
959
|
+
}
|
|
879
960
|
if (selectedWithLocal.length > 0) {
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
961
|
+
let installLocally = true;
|
|
962
|
+
if (!options.yes) {
|
|
963
|
+
const scope = await p.select({
|
|
964
|
+
message: "Installation scope",
|
|
965
|
+
options: [
|
|
966
|
+
{
|
|
967
|
+
value: true,
|
|
968
|
+
label: "Project",
|
|
969
|
+
hint: "Install in current directory (committed with your project)"
|
|
970
|
+
},
|
|
971
|
+
{
|
|
972
|
+
value: false,
|
|
973
|
+
label: "Global",
|
|
974
|
+
hint: "Install in home directory (available across all projects)"
|
|
975
|
+
}
|
|
976
|
+
]
|
|
977
|
+
});
|
|
978
|
+
if (p.isCancel(scope)) {
|
|
979
|
+
p.cancel("Installation cancelled");
|
|
980
|
+
process.exit(0);
|
|
981
|
+
}
|
|
982
|
+
installLocally = scope;
|
|
983
|
+
}
|
|
984
|
+
for (const agent of selectedWithLocal) {
|
|
985
|
+
agentRouting.set(agent, installLocally ? "local" : "global");
|
|
898
986
|
}
|
|
899
|
-
installGlobally = scope;
|
|
900
987
|
} else {
|
|
901
|
-
installGlobally = true;
|
|
902
988
|
p.log.info("Selected agents only support global installation");
|
|
903
989
|
}
|
|
904
990
|
}
|
|
905
991
|
const summaryLines = [];
|
|
906
992
|
summaryLines.push(`${chalk.cyan("Server:")} ${serverName}`);
|
|
907
993
|
summaryLines.push(`${chalk.cyan("Type:")} ${sourceType}`);
|
|
908
|
-
|
|
909
|
-
|
|
994
|
+
const localAgents = targetAgents.filter(
|
|
995
|
+
(a) => agentRouting.get(a) === "local"
|
|
910
996
|
);
|
|
911
|
-
|
|
912
|
-
|
|
997
|
+
const globalAgents = targetAgents.filter(
|
|
998
|
+
(a) => agentRouting.get(a) === "global"
|
|
913
999
|
);
|
|
1000
|
+
if (localAgents.length > 0 && globalAgents.length > 0) {
|
|
1001
|
+
summaryLines.push(`${chalk.cyan("Scope:")} Mixed (project + global)`);
|
|
1002
|
+
summaryLines.push(
|
|
1003
|
+
`${chalk.cyan(" Project:")} ${localAgents.map((a) => agents[a].displayName).join(", ")}`
|
|
1004
|
+
);
|
|
1005
|
+
summaryLines.push(
|
|
1006
|
+
`${chalk.cyan(" Global:")} ${globalAgents.map((a) => agents[a].displayName).join(", ")}`
|
|
1007
|
+
);
|
|
1008
|
+
} else if (localAgents.length > 0) {
|
|
1009
|
+
summaryLines.push(`${chalk.cyan("Scope:")} Project`);
|
|
1010
|
+
summaryLines.push(
|
|
1011
|
+
`${chalk.cyan("Agents:")} ${localAgents.map((a) => agents[a].displayName).join(", ")}`
|
|
1012
|
+
);
|
|
1013
|
+
} else {
|
|
1014
|
+
summaryLines.push(`${chalk.cyan("Scope:")} Global`);
|
|
1015
|
+
summaryLines.push(
|
|
1016
|
+
`${chalk.cyan("Agents:")} ${globalAgents.map((a) => agents[a].displayName).join(", ")}`
|
|
1017
|
+
);
|
|
1018
|
+
}
|
|
914
1019
|
console.log();
|
|
915
1020
|
p.note(summaryLines.join("\n"), "Installation Summary");
|
|
916
1021
|
if (!options.yes) {
|
|
@@ -924,7 +1029,7 @@ async function main(target, options) {
|
|
|
924
1029
|
}
|
|
925
1030
|
spinner2.start("Installing MCP server...");
|
|
926
1031
|
const results = installServer(serverName, serverConfig, targetAgents, {
|
|
927
|
-
|
|
1032
|
+
routing: agentRouting
|
|
928
1033
|
});
|
|
929
1034
|
spinner2.stop("Installation complete");
|
|
930
1035
|
console.log();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "add-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Install MCP servers onto coding agents (Claude Code, Cursor, VS Code, OpenCode, Codex)",
|
|
5
5
|
"author": "Andre Landgraf <andre@neon.tech>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
"fmt": "prettier --write .",
|
|
17
17
|
"build": "tsup src/index.ts --format esm --dts --clean",
|
|
18
18
|
"dev": "tsx src/index.ts",
|
|
19
|
-
"test": "tsx tests/source-parser.test.ts && tsx tests/installer.test.ts && tsx tests/e2e/install.test.ts",
|
|
20
|
-
"test:unit": "tsx tests/source-parser.test.ts && tsx tests/installer.test.ts",
|
|
19
|
+
"test": "tsx tests/source-parser.test.ts && tsx tests/agents.test.ts && tsx tests/installer.test.ts && tsx tests/e2e/install.test.ts",
|
|
20
|
+
"test:unit": "tsx tests/source-parser.test.ts && tsx tests/agents.test.ts && tsx tests/installer.test.ts",
|
|
21
21
|
"test:e2e": "tsx tests/e2e/install.test.ts",
|
|
22
22
|
"typecheck": "tsc --noEmit",
|
|
23
23
|
"prepublishOnly": "npm run build"
|