add-mcp 1.10.0 → 1.10.3
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 +3 -2
- package/dist/{chunk-56AZIA6W.js → chunk-ONLHW5AV.js} +177 -3
- package/dist/index.js +9 -132
- package/dist/lib.d.ts +1 -1
- package/dist/lib.js +1 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Add MCP servers to your favorite coding agents with a single command.
|
|
4
4
|
|
|
5
|
-
Supports **Claude Code**, **Codex**, **Cursor**, **OpenCode**, **VSCode** and [
|
|
5
|
+
Supports **Claude Code**, **Codex**, **Cursor**, **OpenCode**, **VSCode** and [10 more](#supported-agents).
|
|
6
6
|
|
|
7
7
|
## Install an MCP Server
|
|
8
8
|
|
|
@@ -49,9 +49,10 @@ MCP servers can be installed to any of these agents:
|
|
|
49
49
|
| MCPorter | `mcporter` | `config/mcporter.json` | `~/.mcporter/mcporter.json` (or existing `~/.mcporter/mcporter.jsonc`) |
|
|
50
50
|
| OpenCode | `opencode` | `opencode.json` | `~/.config/opencode/opencode.json` |
|
|
51
51
|
| VS Code | `vscode` | `.vscode/mcp.json` | `~/Library/Application Support/Code/User/mcp.json` |
|
|
52
|
+
| Windsurf | `windsurf` | - | `~/.codeium/windsurf/mcp_config.json` |
|
|
52
53
|
| Zed | `zed` | `.zed/settings.json` | `~/Library/Application Support/Zed/settings.json` |
|
|
53
54
|
|
|
54
|
-
**Aliases:** `cline-vscode` → `cline`, `gemini` → `gemini-cli`, `github-copilot` → `vscode`
|
|
55
|
+
**Aliases:** `codeium`, `cascade` → `windsurf`, `cline-vscode` → `cline`, `gemini` → `gemini-cli`, `github-copilot` → `vscode`
|
|
55
56
|
|
|
56
57
|
## Installation Scope
|
|
57
58
|
|
|
@@ -153,6 +153,12 @@ var copilotConfigPath = join2(
|
|
|
153
153
|
process.env.XDG_CONFIG_HOME || join2(home, ".copilot"),
|
|
154
154
|
"mcp-config.json"
|
|
155
155
|
);
|
|
156
|
+
var windsurfConfigPath = join2(
|
|
157
|
+
home,
|
|
158
|
+
".codeium",
|
|
159
|
+
"windsurf",
|
|
160
|
+
"mcp_config.json"
|
|
161
|
+
);
|
|
156
162
|
function transformGooseConfig(serverName, config) {
|
|
157
163
|
if (config.url) {
|
|
158
164
|
const gooseType = config.type === "sse" ? "sse" : "streamable_http";
|
|
@@ -503,6 +509,20 @@ var agents = {
|
|
|
503
509
|
return existsSync(vscodePath);
|
|
504
510
|
}
|
|
505
511
|
},
|
|
512
|
+
windsurf: {
|
|
513
|
+
name: "windsurf",
|
|
514
|
+
displayName: "Windsurf",
|
|
515
|
+
configPath: windsurfConfigPath,
|
|
516
|
+
projectDetectPaths: [],
|
|
517
|
+
// Global only - no project support
|
|
518
|
+
configKey: "mcpServers",
|
|
519
|
+
format: "json",
|
|
520
|
+
supportedTransports: ["stdio", "http", "sse"],
|
|
521
|
+
detectGlobalInstall: async () => {
|
|
522
|
+
return existsSync(join2(home, ".codeium", "windsurf"));
|
|
523
|
+
},
|
|
524
|
+
transformConfig: transformAntigravityConfig
|
|
525
|
+
},
|
|
506
526
|
zed: {
|
|
507
527
|
name: "zed",
|
|
508
528
|
displayName: "Zed",
|
|
@@ -669,6 +689,150 @@ async function selectAgentsInteractive(availableAgents, options) {
|
|
|
669
689
|
return promptForAgents("Select agents to install to", agentChoices, false);
|
|
670
690
|
}
|
|
671
691
|
|
|
692
|
+
// src/source-parser.ts
|
|
693
|
+
function isUrl(input) {
|
|
694
|
+
return input.startsWith("http://") || input.startsWith("https://");
|
|
695
|
+
}
|
|
696
|
+
function looksLikePath(input) {
|
|
697
|
+
if (input.startsWith("/")) return true;
|
|
698
|
+
if (input.startsWith("~/") || input === "~") return true;
|
|
699
|
+
if (input.startsWith("./") || input.startsWith("../")) return true;
|
|
700
|
+
if (/^[A-Za-z]:[\\/]/.test(input)) return true;
|
|
701
|
+
return false;
|
|
702
|
+
}
|
|
703
|
+
function isCommand(input) {
|
|
704
|
+
if (looksLikePath(input)) {
|
|
705
|
+
return true;
|
|
706
|
+
}
|
|
707
|
+
if (input.includes(" ")) {
|
|
708
|
+
return true;
|
|
709
|
+
}
|
|
710
|
+
if (input.startsWith("npx ") || input.startsWith("node ") || input.startsWith("python ")) {
|
|
711
|
+
return true;
|
|
712
|
+
}
|
|
713
|
+
return false;
|
|
714
|
+
}
|
|
715
|
+
function isPackageName(input) {
|
|
716
|
+
if (input.startsWith("@") && input.includes("/")) {
|
|
717
|
+
return true;
|
|
718
|
+
}
|
|
719
|
+
if (/^[a-z0-9][\w.-]*(@[\w.-]+)?$/i.test(input)) {
|
|
720
|
+
return true;
|
|
721
|
+
}
|
|
722
|
+
return false;
|
|
723
|
+
}
|
|
724
|
+
var commonTlds = /* @__PURE__ */ new Set([
|
|
725
|
+
"com",
|
|
726
|
+
"org",
|
|
727
|
+
"net",
|
|
728
|
+
"io",
|
|
729
|
+
"dev",
|
|
730
|
+
"ai",
|
|
731
|
+
"tech",
|
|
732
|
+
"co",
|
|
733
|
+
"app",
|
|
734
|
+
"cloud",
|
|
735
|
+
"sh",
|
|
736
|
+
"run"
|
|
737
|
+
]);
|
|
738
|
+
function extractBrandFromHostname(hostname) {
|
|
739
|
+
const parts = hostname.split(".");
|
|
740
|
+
const meaningfulParts = parts.filter((part) => {
|
|
741
|
+
const lower = part.toLowerCase();
|
|
742
|
+
if (commonTlds.has(lower)) return false;
|
|
743
|
+
if (lower === "mcp" || lower === "api" || lower === "www") return false;
|
|
744
|
+
return true;
|
|
745
|
+
});
|
|
746
|
+
if (meaningfulParts.length > 0) {
|
|
747
|
+
return meaningfulParts[0];
|
|
748
|
+
}
|
|
749
|
+
if (parts.length >= 2) {
|
|
750
|
+
return parts[parts.length - 2];
|
|
751
|
+
}
|
|
752
|
+
return "mcp-server";
|
|
753
|
+
}
|
|
754
|
+
function inferName(input, type) {
|
|
755
|
+
if (type === "remote") {
|
|
756
|
+
try {
|
|
757
|
+
const url = new URL(input);
|
|
758
|
+
return extractBrandFromHostname(url.hostname);
|
|
759
|
+
} catch {
|
|
760
|
+
return "mcp-server";
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
if (type === "command") {
|
|
764
|
+
if (looksLikePath(input)) {
|
|
765
|
+
const segments = input.split(/[\\/]/);
|
|
766
|
+
const base = segments[segments.length - 1] || "mcp-server";
|
|
767
|
+
const withoutExt = base.replace(/\.[^.]+$/, "");
|
|
768
|
+
return extractPackageName(withoutExt || base);
|
|
769
|
+
}
|
|
770
|
+
const parts = input.split(" ");
|
|
771
|
+
let startIndex = 0;
|
|
772
|
+
if (parts[0] === "npx" || parts[0] === "node" || parts[0] === "python") {
|
|
773
|
+
startIndex = 1;
|
|
774
|
+
}
|
|
775
|
+
for (let i = startIndex; i < parts.length; i++) {
|
|
776
|
+
const part = parts[i];
|
|
777
|
+
if (part && !part.startsWith("-")) {
|
|
778
|
+
return extractPackageName(part);
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
return "mcp-server";
|
|
782
|
+
}
|
|
783
|
+
return extractPackageName(input);
|
|
784
|
+
}
|
|
785
|
+
function extractPackageName(input) {
|
|
786
|
+
let name = input;
|
|
787
|
+
const atIndex = name.lastIndexOf("@");
|
|
788
|
+
if (atIndex > 0 && !name.startsWith("@")) {
|
|
789
|
+
name = name.slice(0, atIndex);
|
|
790
|
+
} else if (name.startsWith("@") && name.indexOf("@", 1) > 0) {
|
|
791
|
+
const secondAt = name.indexOf("@", 1);
|
|
792
|
+
name = name.slice(0, secondAt);
|
|
793
|
+
}
|
|
794
|
+
if (name.startsWith("@") && name.includes("/")) {
|
|
795
|
+
const parts = name.split("/");
|
|
796
|
+
name = parts[1] || name;
|
|
797
|
+
}
|
|
798
|
+
name = name.replace(/^mcp-server-/, "");
|
|
799
|
+
name = name.replace(/^server-/, "");
|
|
800
|
+
name = name.replace(/-mcp$/, "");
|
|
801
|
+
return name || "mcp-server";
|
|
802
|
+
}
|
|
803
|
+
function parseSource(input) {
|
|
804
|
+
const trimmed = input.trim();
|
|
805
|
+
if (isUrl(trimmed)) {
|
|
806
|
+
return {
|
|
807
|
+
type: "remote",
|
|
808
|
+
value: trimmed,
|
|
809
|
+
inferredName: inferName(trimmed, "remote")
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
if (isCommand(trimmed)) {
|
|
813
|
+
return {
|
|
814
|
+
type: "command",
|
|
815
|
+
value: trimmed,
|
|
816
|
+
inferredName: inferName(trimmed, "command")
|
|
817
|
+
};
|
|
818
|
+
}
|
|
819
|
+
if (isPackageName(trimmed)) {
|
|
820
|
+
return {
|
|
821
|
+
type: "package",
|
|
822
|
+
value: trimmed,
|
|
823
|
+
inferredName: inferName(trimmed, "package")
|
|
824
|
+
};
|
|
825
|
+
}
|
|
826
|
+
return {
|
|
827
|
+
type: "package",
|
|
828
|
+
value: trimmed,
|
|
829
|
+
inferredName: inferName(trimmed, "package")
|
|
830
|
+
};
|
|
831
|
+
}
|
|
832
|
+
function isRemoteSource(parsed) {
|
|
833
|
+
return parsed.type === "remote";
|
|
834
|
+
}
|
|
835
|
+
|
|
672
836
|
// src/formats/utils.ts
|
|
673
837
|
function deepMerge(target, source) {
|
|
674
838
|
const result = { ...target };
|
|
@@ -959,9 +1123,17 @@ function buildServerConfig(parsed, options = {}) {
|
|
|
959
1123
|
return config2;
|
|
960
1124
|
}
|
|
961
1125
|
if (parsed.type === "command") {
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
1126
|
+
let command;
|
|
1127
|
+
let parsedArgs;
|
|
1128
|
+
if (looksLikePath(parsed.value)) {
|
|
1129
|
+
command = parsed.value;
|
|
1130
|
+
parsedArgs = [];
|
|
1131
|
+
} else {
|
|
1132
|
+
const parts = parsed.value.split(" ");
|
|
1133
|
+
command = parts[0];
|
|
1134
|
+
parsedArgs = parts.slice(1);
|
|
1135
|
+
}
|
|
1136
|
+
const args = [...parsedArgs, ...options.args ?? []];
|
|
965
1137
|
const config2 = {
|
|
966
1138
|
command,
|
|
967
1139
|
args
|
|
@@ -1207,6 +1379,8 @@ export {
|
|
|
1207
1379
|
isTransportSupported,
|
|
1208
1380
|
buildAgentSelectionChoices,
|
|
1209
1381
|
selectAgentsInteractive,
|
|
1382
|
+
parseSource,
|
|
1383
|
+
isRemoteSource,
|
|
1210
1384
|
getNestedValue,
|
|
1211
1385
|
readConfig2 as readConfig,
|
|
1212
1386
|
removeServerFromConfig,
|
package/dist/index.js
CHANGED
|
@@ -13,14 +13,16 @@ import {
|
|
|
13
13
|
getProjectCapableAgents,
|
|
14
14
|
installServer,
|
|
15
15
|
installServerForAgent,
|
|
16
|
+
isRemoteSource,
|
|
16
17
|
isTransportSupported,
|
|
17
18
|
listInstalledServers,
|
|
19
|
+
parseSource,
|
|
18
20
|
removeServerFromConfig,
|
|
19
21
|
saveFindRegistries,
|
|
20
22
|
selectAgentsInteractive,
|
|
21
23
|
supportsProjectConfig,
|
|
22
24
|
updateGitignoreWithPaths
|
|
23
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-ONLHW5AV.js";
|
|
24
26
|
|
|
25
27
|
// src/index.ts
|
|
26
28
|
import { program } from "commander";
|
|
@@ -31,138 +33,12 @@ import { homedir } from "os";
|
|
|
31
33
|
// src/types.ts
|
|
32
34
|
var agentAliases = {
|
|
33
35
|
"cline-vscode": "cline",
|
|
36
|
+
codeium: "windsurf",
|
|
37
|
+
cascade: "windsurf",
|
|
34
38
|
gemini: "gemini-cli",
|
|
35
39
|
"github-copilot": "vscode"
|
|
36
40
|
};
|
|
37
41
|
|
|
38
|
-
// src/source-parser.ts
|
|
39
|
-
function isUrl(input) {
|
|
40
|
-
return input.startsWith("http://") || input.startsWith("https://");
|
|
41
|
-
}
|
|
42
|
-
function isCommand(input) {
|
|
43
|
-
if (input.includes(" ")) {
|
|
44
|
-
return true;
|
|
45
|
-
}
|
|
46
|
-
if (input.startsWith("npx ") || input.startsWith("node ") || input.startsWith("python ")) {
|
|
47
|
-
return true;
|
|
48
|
-
}
|
|
49
|
-
return false;
|
|
50
|
-
}
|
|
51
|
-
function isPackageName(input) {
|
|
52
|
-
if (input.startsWith("@") && input.includes("/")) {
|
|
53
|
-
return true;
|
|
54
|
-
}
|
|
55
|
-
if (/^[a-z0-9][\w.-]*(@[\w.-]+)?$/i.test(input)) {
|
|
56
|
-
return true;
|
|
57
|
-
}
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
var commonTlds = /* @__PURE__ */ new Set([
|
|
61
|
-
"com",
|
|
62
|
-
"org",
|
|
63
|
-
"net",
|
|
64
|
-
"io",
|
|
65
|
-
"dev",
|
|
66
|
-
"ai",
|
|
67
|
-
"tech",
|
|
68
|
-
"co",
|
|
69
|
-
"app",
|
|
70
|
-
"cloud",
|
|
71
|
-
"sh",
|
|
72
|
-
"run"
|
|
73
|
-
]);
|
|
74
|
-
function extractBrandFromHostname(hostname) {
|
|
75
|
-
const parts = hostname.split(".");
|
|
76
|
-
const meaningfulParts = parts.filter((part) => {
|
|
77
|
-
const lower = part.toLowerCase();
|
|
78
|
-
if (commonTlds.has(lower)) return false;
|
|
79
|
-
if (lower === "mcp" || lower === "api" || lower === "www") return false;
|
|
80
|
-
return true;
|
|
81
|
-
});
|
|
82
|
-
if (meaningfulParts.length > 0) {
|
|
83
|
-
return meaningfulParts[0];
|
|
84
|
-
}
|
|
85
|
-
if (parts.length >= 2) {
|
|
86
|
-
return parts[parts.length - 2];
|
|
87
|
-
}
|
|
88
|
-
return "mcp-server";
|
|
89
|
-
}
|
|
90
|
-
function inferName(input, type) {
|
|
91
|
-
if (type === "remote") {
|
|
92
|
-
try {
|
|
93
|
-
const url = new URL(input);
|
|
94
|
-
return extractBrandFromHostname(url.hostname);
|
|
95
|
-
} catch {
|
|
96
|
-
return "mcp-server";
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
if (type === "command") {
|
|
100
|
-
const parts = input.split(" ");
|
|
101
|
-
let startIndex = 0;
|
|
102
|
-
if (parts[0] === "npx" || parts[0] === "node" || parts[0] === "python") {
|
|
103
|
-
startIndex = 1;
|
|
104
|
-
}
|
|
105
|
-
for (let i = startIndex; i < parts.length; i++) {
|
|
106
|
-
const part = parts[i];
|
|
107
|
-
if (part && !part.startsWith("-")) {
|
|
108
|
-
return extractPackageName(part);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
return "mcp-server";
|
|
112
|
-
}
|
|
113
|
-
return extractPackageName(input);
|
|
114
|
-
}
|
|
115
|
-
function extractPackageName(input) {
|
|
116
|
-
let name = input;
|
|
117
|
-
const atIndex = name.lastIndexOf("@");
|
|
118
|
-
if (atIndex > 0 && !name.startsWith("@")) {
|
|
119
|
-
name = name.slice(0, atIndex);
|
|
120
|
-
} else if (name.startsWith("@") && name.indexOf("@", 1) > 0) {
|
|
121
|
-
const secondAt = name.indexOf("@", 1);
|
|
122
|
-
name = name.slice(0, secondAt);
|
|
123
|
-
}
|
|
124
|
-
if (name.startsWith("@") && name.includes("/")) {
|
|
125
|
-
const parts = name.split("/");
|
|
126
|
-
name = parts[1] || name;
|
|
127
|
-
}
|
|
128
|
-
name = name.replace(/^mcp-server-/, "");
|
|
129
|
-
name = name.replace(/^server-/, "");
|
|
130
|
-
name = name.replace(/-mcp$/, "");
|
|
131
|
-
return name || "mcp-server";
|
|
132
|
-
}
|
|
133
|
-
function parseSource(input) {
|
|
134
|
-
const trimmed = input.trim();
|
|
135
|
-
if (isUrl(trimmed)) {
|
|
136
|
-
return {
|
|
137
|
-
type: "remote",
|
|
138
|
-
value: trimmed,
|
|
139
|
-
inferredName: inferName(trimmed, "remote")
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
if (isCommand(trimmed)) {
|
|
143
|
-
return {
|
|
144
|
-
type: "command",
|
|
145
|
-
value: trimmed,
|
|
146
|
-
inferredName: inferName(trimmed, "command")
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
if (isPackageName(trimmed)) {
|
|
150
|
-
return {
|
|
151
|
-
type: "package",
|
|
152
|
-
value: trimmed,
|
|
153
|
-
inferredName: inferName(trimmed, "package")
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
return {
|
|
157
|
-
type: "package",
|
|
158
|
-
value: trimmed,
|
|
159
|
-
inferredName: inferName(trimmed, "package")
|
|
160
|
-
};
|
|
161
|
-
}
|
|
162
|
-
function isRemoteSource(parsed) {
|
|
163
|
-
return parsed.type === "remote";
|
|
164
|
-
}
|
|
165
|
-
|
|
166
42
|
// src/find.ts
|
|
167
43
|
import * as p from "@clack/prompts";
|
|
168
44
|
|
|
@@ -906,7 +782,7 @@ async function runFind(query, options) {
|
|
|
906
782
|
// package.json
|
|
907
783
|
var package_default = {
|
|
908
784
|
name: "add-mcp",
|
|
909
|
-
version: "1.10.
|
|
785
|
+
version: "1.10.3",
|
|
910
786
|
description: "Add MCP servers to your favorite coding agents with a single command.",
|
|
911
787
|
author: "Andre Landgraf <andre@neon.tech>",
|
|
912
788
|
license: "Apache-2.0",
|
|
@@ -957,6 +833,7 @@ var package_default = {
|
|
|
957
833
|
"mcporter",
|
|
958
834
|
"opencode",
|
|
959
835
|
"vscode",
|
|
836
|
+
"windsurf",
|
|
960
837
|
"zed"
|
|
961
838
|
],
|
|
962
839
|
repository: {
|
|
@@ -1823,7 +1700,7 @@ async function main(target, options) {
|
|
|
1823
1700
|
if (headerResult.invalid.length > 0) {
|
|
1824
1701
|
const hint = looksLikeEatenShellVar(headerResult.invalid, ":") ? " (looks like your shell expanded a ${VAR} to an empty string; use single quotes: --header 'Key: ${VAR}' to pass the template literally)" : "";
|
|
1825
1702
|
p2.log.error(
|
|
1826
|
-
`Invalid --header value(s): ${headerResult.invalid.join(", ")}. Use
|
|
1703
|
+
`Invalid --header value(s): ${headerResult.invalid.join(", ")}. Use 'Key: Value' format.${hint}`
|
|
1827
1704
|
);
|
|
1828
1705
|
process.exit(1);
|
|
1829
1706
|
}
|
|
@@ -1837,7 +1714,7 @@ async function main(target, options) {
|
|
|
1837
1714
|
if (envResult.invalid.length > 0) {
|
|
1838
1715
|
const hint = looksLikeEatenShellVar(envResult.invalid, "=") ? " (looks like your shell expanded a ${VAR} to an empty string; use single quotes: --env 'KEY=${VAR}' to pass the template literally)" : "";
|
|
1839
1716
|
p2.log.error(
|
|
1840
|
-
`Invalid --env value(s): ${envResult.invalid.join(", ")}. Use
|
|
1717
|
+
`Invalid --env value(s): ${envResult.invalid.join(", ")}. Use 'KEY=VALUE' format.${hint}`
|
|
1841
1718
|
);
|
|
1842
1719
|
process.exit(1);
|
|
1843
1720
|
}
|
package/dist/lib.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
type AgentType = "antigravity" | "cline" | "cline-cli" | "claude-code" | "claude-desktop" | "codex" | "cursor" | "gemini-cli" | "goose" | "github-copilot-cli" | "mcporter" | "opencode" | "vscode" | "zed";
|
|
1
|
+
type AgentType = "antigravity" | "cline" | "cline-cli" | "claude-code" | "claude-desktop" | "codex" | "cursor" | "gemini-cli" | "goose" | "github-copilot-cli" | "mcporter" | "opencode" | "vscode" | "windsurf" | "zed";
|
|
2
2
|
type ConfigFormat = "json" | "yaml" | "toml";
|
|
3
3
|
interface AgentConfig {
|
|
4
4
|
/** Internal name */
|
package/dist/lib.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "add-mcp",
|
|
3
|
-
"version": "1.10.
|
|
3
|
+
"version": "1.10.3",
|
|
4
4
|
"description": "Add MCP servers to your favorite coding agents with a single command.",
|
|
5
5
|
"author": "Andre Landgraf <andre@neon.tech>",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -51,6 +51,7 @@
|
|
|
51
51
|
"mcporter",
|
|
52
52
|
"opencode",
|
|
53
53
|
"vscode",
|
|
54
|
+
"windsurf",
|
|
54
55
|
"zed"
|
|
55
56
|
],
|
|
56
57
|
"repository": {
|