add-mcp 1.10.0 → 1.10.2

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.
@@ -669,6 +669,150 @@ async function selectAgentsInteractive(availableAgents, options) {
669
669
  return promptForAgents("Select agents to install to", agentChoices, false);
670
670
  }
671
671
 
672
+ // src/source-parser.ts
673
+ function isUrl(input) {
674
+ return input.startsWith("http://") || input.startsWith("https://");
675
+ }
676
+ function looksLikePath(input) {
677
+ if (input.startsWith("/")) return true;
678
+ if (input.startsWith("~/") || input === "~") return true;
679
+ if (input.startsWith("./") || input.startsWith("../")) return true;
680
+ if (/^[A-Za-z]:[\\/]/.test(input)) return true;
681
+ return false;
682
+ }
683
+ function isCommand(input) {
684
+ if (looksLikePath(input)) {
685
+ return true;
686
+ }
687
+ if (input.includes(" ")) {
688
+ return true;
689
+ }
690
+ if (input.startsWith("npx ") || input.startsWith("node ") || input.startsWith("python ")) {
691
+ return true;
692
+ }
693
+ return false;
694
+ }
695
+ function isPackageName(input) {
696
+ if (input.startsWith("@") && input.includes("/")) {
697
+ return true;
698
+ }
699
+ if (/^[a-z0-9][\w.-]*(@[\w.-]+)?$/i.test(input)) {
700
+ return true;
701
+ }
702
+ return false;
703
+ }
704
+ var commonTlds = /* @__PURE__ */ new Set([
705
+ "com",
706
+ "org",
707
+ "net",
708
+ "io",
709
+ "dev",
710
+ "ai",
711
+ "tech",
712
+ "co",
713
+ "app",
714
+ "cloud",
715
+ "sh",
716
+ "run"
717
+ ]);
718
+ function extractBrandFromHostname(hostname) {
719
+ const parts = hostname.split(".");
720
+ const meaningfulParts = parts.filter((part) => {
721
+ const lower = part.toLowerCase();
722
+ if (commonTlds.has(lower)) return false;
723
+ if (lower === "mcp" || lower === "api" || lower === "www") return false;
724
+ return true;
725
+ });
726
+ if (meaningfulParts.length > 0) {
727
+ return meaningfulParts[0];
728
+ }
729
+ if (parts.length >= 2) {
730
+ return parts[parts.length - 2];
731
+ }
732
+ return "mcp-server";
733
+ }
734
+ function inferName(input, type) {
735
+ if (type === "remote") {
736
+ try {
737
+ const url = new URL(input);
738
+ return extractBrandFromHostname(url.hostname);
739
+ } catch {
740
+ return "mcp-server";
741
+ }
742
+ }
743
+ if (type === "command") {
744
+ if (looksLikePath(input)) {
745
+ const segments = input.split(/[\\/]/);
746
+ const base = segments[segments.length - 1] || "mcp-server";
747
+ const withoutExt = base.replace(/\.[^.]+$/, "");
748
+ return extractPackageName(withoutExt || base);
749
+ }
750
+ const parts = input.split(" ");
751
+ let startIndex = 0;
752
+ if (parts[0] === "npx" || parts[0] === "node" || parts[0] === "python") {
753
+ startIndex = 1;
754
+ }
755
+ for (let i = startIndex; i < parts.length; i++) {
756
+ const part = parts[i];
757
+ if (part && !part.startsWith("-")) {
758
+ return extractPackageName(part);
759
+ }
760
+ }
761
+ return "mcp-server";
762
+ }
763
+ return extractPackageName(input);
764
+ }
765
+ function extractPackageName(input) {
766
+ let name = input;
767
+ const atIndex = name.lastIndexOf("@");
768
+ if (atIndex > 0 && !name.startsWith("@")) {
769
+ name = name.slice(0, atIndex);
770
+ } else if (name.startsWith("@") && name.indexOf("@", 1) > 0) {
771
+ const secondAt = name.indexOf("@", 1);
772
+ name = name.slice(0, secondAt);
773
+ }
774
+ if (name.startsWith("@") && name.includes("/")) {
775
+ const parts = name.split("/");
776
+ name = parts[1] || name;
777
+ }
778
+ name = name.replace(/^mcp-server-/, "");
779
+ name = name.replace(/^server-/, "");
780
+ name = name.replace(/-mcp$/, "");
781
+ return name || "mcp-server";
782
+ }
783
+ function parseSource(input) {
784
+ const trimmed = input.trim();
785
+ if (isUrl(trimmed)) {
786
+ return {
787
+ type: "remote",
788
+ value: trimmed,
789
+ inferredName: inferName(trimmed, "remote")
790
+ };
791
+ }
792
+ if (isCommand(trimmed)) {
793
+ return {
794
+ type: "command",
795
+ value: trimmed,
796
+ inferredName: inferName(trimmed, "command")
797
+ };
798
+ }
799
+ if (isPackageName(trimmed)) {
800
+ return {
801
+ type: "package",
802
+ value: trimmed,
803
+ inferredName: inferName(trimmed, "package")
804
+ };
805
+ }
806
+ return {
807
+ type: "package",
808
+ value: trimmed,
809
+ inferredName: inferName(trimmed, "package")
810
+ };
811
+ }
812
+ function isRemoteSource(parsed) {
813
+ return parsed.type === "remote";
814
+ }
815
+
672
816
  // src/formats/utils.ts
673
817
  function deepMerge(target, source) {
674
818
  const result = { ...target };
@@ -959,9 +1103,17 @@ function buildServerConfig(parsed, options = {}) {
959
1103
  return config2;
960
1104
  }
961
1105
  if (parsed.type === "command") {
962
- const parts = parsed.value.split(" ");
963
- const command = parts[0];
964
- const args = [...parts.slice(1), ...options.args ?? []];
1106
+ let command;
1107
+ let parsedArgs;
1108
+ if (looksLikePath(parsed.value)) {
1109
+ command = parsed.value;
1110
+ parsedArgs = [];
1111
+ } else {
1112
+ const parts = parsed.value.split(" ");
1113
+ command = parts[0];
1114
+ parsedArgs = parts.slice(1);
1115
+ }
1116
+ const args = [...parsedArgs, ...options.args ?? []];
965
1117
  const config2 = {
966
1118
  command,
967
1119
  args
@@ -1207,6 +1359,8 @@ export {
1207
1359
  isTransportSupported,
1208
1360
  buildAgentSelectionChoices,
1209
1361
  selectAgentsInteractive,
1362
+ parseSource,
1363
+ isRemoteSource,
1210
1364
  getNestedValue,
1211
1365
  readConfig2 as readConfig,
1212
1366
  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-56AZIA6W.js";
25
+ } from "./chunk-B27GVIBZ.js";
24
26
 
25
27
  // src/index.ts
26
28
  import { program } from "commander";
@@ -35,134 +37,6 @@ var agentAliases = {
35
37
  "github-copilot": "vscode"
36
38
  };
37
39
 
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
40
  // src/find.ts
167
41
  import * as p from "@clack/prompts";
168
42
 
@@ -906,7 +780,7 @@ async function runFind(query, options) {
906
780
  // package.json
907
781
  var package_default = {
908
782
  name: "add-mcp",
909
- version: "1.10.0",
783
+ version: "1.10.2",
910
784
  description: "Add MCP servers to your favorite coding agents with a single command.",
911
785
  author: "Andre Landgraf <andre@neon.tech>",
912
786
  license: "Apache-2.0",
@@ -1823,7 +1697,7 @@ async function main(target, options) {
1823
1697
  if (headerResult.invalid.length > 0) {
1824
1698
  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
1699
  p2.log.error(
1826
- `Invalid --header value(s): ${headerResult.invalid.join(", ")}. Use "Key: Value" format.${hint}`
1700
+ `Invalid --header value(s): ${headerResult.invalid.join(", ")}. Use 'Key: Value' format.${hint}`
1827
1701
  );
1828
1702
  process.exit(1);
1829
1703
  }
@@ -1837,7 +1711,7 @@ async function main(target, options) {
1837
1711
  if (envResult.invalid.length > 0) {
1838
1712
  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
1713
  p2.log.error(
1840
- `Invalid --env value(s): ${envResult.invalid.join(", ")}. Use "KEY=VALUE" format.${hint}`
1714
+ `Invalid --env value(s): ${envResult.invalid.join(", ")}. Use 'KEY=VALUE' format.${hint}`
1841
1715
  );
1842
1716
  process.exit(1);
1843
1717
  }
package/dist/lib.js CHANGED
@@ -10,7 +10,7 @@ import {
10
10
  listInstalledServers,
11
11
  readConfig,
12
12
  removeServerFromConfig
13
- } from "./chunk-56AZIA6W.js";
13
+ } from "./chunk-B27GVIBZ.js";
14
14
 
15
15
  // src/lib.ts
16
16
  import { existsSync } from "fs";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "add-mcp",
3
- "version": "1.10.0",
3
+ "version": "1.10.2",
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",