@vespermcp/mcp-server 1.1.0 → 1.1.1

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.
@@ -5,171 +5,217 @@ export class ConfigManager {
5
5
  getHomeDir() {
6
6
  return os.homedir();
7
7
  }
8
- getConfigPaths() {
8
+ /**
9
+ * All known coding agent configuration paths.
10
+ * Based on the `add-mcp` standard used by the MCP ecosystem.
11
+ */
12
+ getAllAgents() {
9
13
  const home = this.getHomeDir();
10
14
  const isWin = process.platform === "win32";
11
- const appData = process.env.APPDATA || "";
12
- return {
13
- "claude-desktop": {
15
+ const isMac = process.platform === "darwin";
16
+ const appData = process.env.APPDATA || path.join(home, "AppData", "Roaming");
17
+ const agents = [
18
+ // Claude Code: ~/.claude.json
19
+ {
20
+ name: "Claude Code",
21
+ path: path.join(home, ".claude.json"),
22
+ format: "json-mcpServers",
23
+ serverType: "stdio",
24
+ },
25
+ // Claude Desktop: %APPDATA%/Claude/claude_desktop_config.json
26
+ {
14
27
  name: "Claude Desktop",
15
28
  path: isWin
16
29
  ? path.join(appData, "Claude", "claude_desktop_config.json")
17
- : path.join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json"),
18
- key: "mcpServers"
30
+ : isMac
31
+ ? path.join(home, "Library", "Application Support", "Claude", "claude_desktop_config.json")
32
+ : path.join(home, ".config", "claude", "claude_desktop_config.json"),
33
+ format: "json-mcpServers",
34
+ serverType: "stdio",
19
35
  },
20
- "cursor": {
36
+ // Cursor: ~/.cursor/mcp.json
37
+ {
21
38
  name: "Cursor",
22
- path: isWin
23
- ? path.join(appData, "Cursor", "User", "globalStorage", "rohit-gohri.cursor-mcp", "mcp.json")
24
- : path.join(home, "Library", "Application Support", "Cursor", "User", "globalStorage", "rohit-gohri.cursor-mcp", "mcp.json"),
25
- key: "mcpServers"
39
+ path: path.join(home, ".cursor", "mcp.json"),
40
+ format: "json-mcpServers",
41
+ serverType: "stdio",
26
42
  },
27
- "cursor-project": {
28
- name: "Cursor (Project-specific)",
29
- path: path.join(process.cwd(), ".cursor", "mcp.json"),
30
- key: "mcpServers"
31
- },
32
- "vscode-copilot": {
33
- name: "VS Code (Copilot)",
43
+ // VS Code: %APPDATA%/Code/User/mcp.json (uses "servers" key, NOT "mcpServers")
44
+ {
45
+ name: "VS Code",
34
46
  path: isWin
35
- ? path.join(appData, "Code", "User", "globalStorage", "github.copilot-chat", "mcp.json")
36
- : path.join(home, "Library", "Application Support", "Code", "User", "globalStorage", "github.copilot-chat", "mcp.json"),
37
- key: "mcpServers"
47
+ ? path.join(appData, "Code", "User", "mcp.json")
48
+ : isMac
49
+ ? path.join(home, "Library", "Application Support", "Code", "User", "mcp.json")
50
+ : path.join(home, ".config", "Code", "User", "mcp.json"),
51
+ format: "json-servers",
52
+ serverType: "stdio",
38
53
  },
39
- "vscode-global": {
40
- name: "VS Code (Standard MCP)",
41
- path: isWin
42
- ? path.join(appData, "Code", "User", "globalStorage", "mcp-servers", "mcp.json")
43
- : path.join(home, "Library", "Application Support", "Code", "User", "globalStorage", "mcp-servers", "mcp.json"),
44
- key: "mcpServers"
54
+ // Codex: ~/.codex/config.toml
55
+ {
56
+ name: "Codex",
57
+ path: path.join(home, ".codex", "config.toml"),
58
+ format: "toml",
59
+ serverType: "stdio",
45
60
  },
46
- "vscode-settings": {
47
- name: "VS Code (Settings.json)",
48
- path: isWin
49
- ? path.join(appData, "Code", "User", "settings.json")
50
- : path.join(home, "Library", "Application Support", "Code", "User", "settings.json"),
51
- key: "github.copilot.chat.mcp.servers"
52
- }
53
- };
61
+ // Antigravity / Gemini CLI: ~/.gemini/settings.json
62
+ {
63
+ name: "Antigravity",
64
+ path: path.join(home, ".gemini", "settings.json"),
65
+ format: "json-mcpServers",
66
+ serverType: "stdio",
67
+ },
68
+ ];
69
+ return agents;
54
70
  }
71
+ /**
72
+ * Detect which agents are installed on this machine.
73
+ */
55
74
  detectIDEs() {
56
- const paths = this.getConfigPaths();
75
+ const agents = this.getAllAgents();
57
76
  const detected = [];
58
- const termProgram = (process.env.TERM_PROGRAM || "").toLowerCase();
59
- const appData = process.env.APPDATA || "";
60
- const home = this.getHomeDir();
61
- for (const [key, cp] of Object.entries(paths)) {
62
- const isClaude = key === "claude-desktop";
63
- const isCursor = key === "cursor" || key === "cursor-project";
64
- const isVSCode = key.startsWith("vscode");
65
- const isCopilot = key === "vscode-copilot";
66
- const isMac = process.platform === "darwin";
67
- const hasClaudeFolder = fs.existsSync(path.join(appData, "Claude")) || (isMac && fs.existsSync(path.join(home, "Library", "Application Support", "Claude")));
68
- const hasCursorFolder = fs.existsSync(path.join(appData, "Cursor")) || fs.existsSync(path.join(home, ".cursor")) || (isMac && fs.existsSync(path.join(home, "Library", "Application Support", "Cursor")));
69
- const hasCodeFolder = fs.existsSync(path.join(appData, "Code")) || fs.existsSync(path.join(home, ".vscode")) || (isMac && fs.existsSync(path.join(home, "Library", "Application Support", "Code")));
70
- const hasCopilotFolder = hasCodeFolder || fs.existsSync(path.join(home, ".copilot"));
71
- const isCurrentIDE = (isCursor && termProgram.includes("cursor")) ||
72
- (isClaude && termProgram.includes("claude")) ||
73
- (isVSCode && termProgram === "vscode" && hasCodeFolder);
74
- // Detection logic
75
- if ((isClaude && hasClaudeFolder) ||
76
- (isCursor && hasCursorFolder) ||
77
- (isVSCode && hasCodeFolder) ||
78
- isCurrentIDE ||
79
- fs.existsSync(cp.path)) {
80
- let displayName = cp.name;
81
- if (isCurrentIDE) {
82
- displayName += " (Current Terminal)";
83
- }
84
- detected.push({ ...cp, name: displayName });
77
+ for (const agent of agents) {
78
+ const configDir = path.dirname(agent.path);
79
+ const configExists = fs.existsSync(agent.path);
80
+ const dirExists = fs.existsSync(configDir);
81
+ if (configExists || dirExists) {
82
+ detected.push(agent);
85
83
  }
86
84
  }
87
- return detected.filter((v, i, a) => a.findIndex(t => t.path === v.path) === i);
85
+ return detected;
88
86
  }
89
- getVesperExecutableConfig() {
87
+ /**
88
+ * Build the server config object for Vesper.
89
+ */
90
+ getServerConfig() {
90
91
  const isWin = process.platform === "win32";
91
- // Try to find absolute paths for maximum reliability in VS Code/Copilot
92
- try {
93
- const nodeExe = process.execPath;
94
- // index.js is in build/index.js relative to ConfigManager in build/config/config-manager.js
95
- const vesperScript = path.resolve(__dirname, "../../index.js");
96
- if (fs.existsSync(vesperScript)) {
97
- return {
98
- command: nodeExe,
99
- args: [vesperScript]
100
- };
101
- }
102
- }
103
- catch (e) {
104
- // Fallback to npx
105
- }
106
92
  return {
107
93
  command: isWin ? "npx.cmd" : "npx",
108
- args: ["-y", "@vespermcp/mcp-server@latest"]
94
+ args: ["-y", "@vespermcp/mcp-server@latest"],
109
95
  };
110
96
  }
111
- async installTo(configPath) {
97
+ /**
98
+ * Install Vesper to a single agent configuration.
99
+ */
100
+ async installTo(agent) {
112
101
  try {
113
- console.log(`[Vesper Setup] Installing to ${configPath.name} at ${configPath.path}...`);
102
+ console.log(`[Vesper Setup] Installing to ${agent.name}...`);
103
+ if (agent.format === "toml") {
104
+ return this.installToToml(agent);
105
+ }
106
+ // JSON-based agents
114
107
  let config = {};
115
- if (fs.existsSync(configPath.path)) {
108
+ if (fs.existsSync(agent.path)) {
116
109
  try {
117
- const content = fs.readFileSync(configPath.path, "utf-8").trim();
110
+ const content = fs.readFileSync(agent.path, "utf-8").trim();
118
111
  config = content ? JSON.parse(content) : {};
119
112
  }
120
113
  catch (e) {
121
- console.warn(`[Vesper Setup] Could not parse ${configPath.path}, starting fresh`);
114
+ console.warn(`[Vesper Setup] Could not parse ${agent.path}, starting fresh`);
122
115
  config = {};
123
116
  }
124
117
  }
125
118
  else {
126
- console.log(`[Vesper Setup] Creating directory: ${path.dirname(configPath.path)}`);
127
- fs.mkdirSync(path.dirname(configPath.path), { recursive: true });
128
- }
129
- // Handle nested keys (e.g., "github.copilot.chat.mcp.servers")
130
- const keys = configPath.key.split('.');
131
- let current = config;
132
- for (let i = 0; i < keys.length - 1; i++) {
133
- if (!current[keys[i]])
134
- current[keys[i]] = {};
135
- current = current[keys[i]];
119
+ fs.mkdirSync(path.dirname(agent.path), { recursive: true });
136
120
  }
137
- const lastKey = keys[keys.length - 1];
138
- const mcpServers = current[lastKey] || {};
139
- // Use the most robust command format available (absolute paths if running from npx/installed)
140
- const vesperExec = this.getVesperExecutableConfig();
141
- const serverConfig = {
142
- command: vesperExec.command,
143
- args: vesperExec.args,
144
- env: {
145
- "HF_TOKEN": "YOUR_HUGGINGFACE_TOKEN_HERE",
146
- }
121
+ const vesperConfig = this.getServerConfig();
122
+ const serverEntry = {
123
+ command: vesperConfig.command,
124
+ args: vesperConfig.args,
147
125
  };
148
- mcpServers["vesper"] = serverConfig;
149
- // Also add alias for easy upgrading
150
- mcpServers["@vespermcp/mcp-server"] = serverConfig;
151
- current[lastKey] = mcpServers;
152
- // If we are writing to settings.json or a copilot-specific file, sync to native mcp.servers key too
153
- if (configPath.key.includes("copilot") || configPath.path.includes("settings.json")) {
154
- if (!config["mcp.servers"])
155
- config["mcp.servers"] = {};
156
- config["mcp.servers"]["vesper"] = serverConfig;
157
- config["mcp.servers"]["@vespermcp/mcp-server"] = serverConfig;
126
+ // Determine the correct key based on agent format
127
+ if (agent.format === "json-servers") {
128
+ // VS Code native MCP format: { "servers": { "vesper": { "type": "stdio", "command": ..., "args": ... } } }
129
+ if (!config.servers)
130
+ config.servers = {};
131
+ config.servers["vesper"] = {
132
+ type: "stdio",
133
+ ...serverEntry,
134
+ };
135
+ console.log(` ✓ Added to "servers" key (VS Code native format)`);
158
136
  }
159
- const content = JSON.stringify(config, null, 2);
160
- if (process.env.VESPER_DEBUG) {
161
- console.log(`[Vesper Setup] Writing to ${configPath.path}:`);
162
- console.log(content);
137
+ else {
138
+ // Standard mcpServers format: { "mcpServers": { "vesper": { "command": ..., "args": ... } } }
139
+ if (!config.mcpServers)
140
+ config.mcpServers = {};
141
+ config.mcpServers["vesper"] = serverEntry;
142
+ console.log(` ✓ Added to "mcpServers" key`);
163
143
  }
164
- fs.writeFileSync(configPath.path, content, "utf8");
165
- // Verify write
166
- const finalSize = fs.statSync(configPath.path).size;
167
- console.log(`[Vesper Setup] Successfully wrote ${finalSize} bytes to ${configPath.name}`);
144
+ fs.writeFileSync(agent.path, JSON.stringify(config, null, 2), "utf8");
145
+ const size = fs.statSync(agent.path).size;
146
+ console.log(` ✓ ${agent.name}: ${agent.path} (${size} bytes)`);
168
147
  return true;
169
148
  }
170
149
  catch (error) {
171
- console.error(`Failed to install to ${configPath.name}:`, error);
150
+ console.error(`Failed to install to ${agent.name}:`, error);
172
151
  return false;
173
152
  }
174
153
  }
154
+ /**
155
+ * Install to TOML-based agents (Codex).
156
+ */
157
+ installToToml(agent) {
158
+ try {
159
+ let content = "";
160
+ if (fs.existsSync(agent.path)) {
161
+ content = fs.readFileSync(agent.path, "utf-8");
162
+ }
163
+ else {
164
+ fs.mkdirSync(path.dirname(agent.path), { recursive: true });
165
+ }
166
+ // Check if vesper is already configured
167
+ if (content.includes("[mcp_servers.vesper]")) {
168
+ console.log(` ✓ ${agent.name}: Already configured`);
169
+ return true;
170
+ }
171
+ const vesperConfig = this.getServerConfig();
172
+ const isWin = process.platform === "win32";
173
+ const tomlEntry = `
174
+ [mcp_servers.vesper]
175
+ command = "${vesperConfig.command}"
176
+ args = [${vesperConfig.args.map(a => `"${a}"`).join(", ")}]
177
+ `;
178
+ content += tomlEntry;
179
+ fs.writeFileSync(agent.path, content, "utf8");
180
+ console.log(` ✓ ${agent.name}: ${agent.path}`);
181
+ return true;
182
+ }
183
+ catch (error) {
184
+ console.error(` ✗ Failed to install to ${agent.name}:`, error);
185
+ return false;
186
+ }
187
+ }
188
+ /**
189
+ * Install Vesper to ALL detected agents automatically.
190
+ */
191
+ async installToAll() {
192
+ const agents = this.detectIDEs();
193
+ const success = [];
194
+ const failed = [];
195
+ console.log(`\n📦 Installing Vesper to ${agents.length} detected agents...\n`);
196
+ for (const agent of agents) {
197
+ const result = await this.installTo(agent);
198
+ if (result) {
199
+ success.push(agent.name);
200
+ }
201
+ else {
202
+ failed.push(agent.name);
203
+ }
204
+ }
205
+ console.log(`\n┌─────────────────────────────────────────────┐`);
206
+ console.log(`│ Installation Summary │`);
207
+ console.log(`├─────────────────────────────────────────────┤`);
208
+ if (success.length > 0) {
209
+ for (const name of success) {
210
+ console.log(`│ ✓ ${name.padEnd(40)}│`);
211
+ }
212
+ }
213
+ if (failed.length > 0) {
214
+ for (const name of failed) {
215
+ console.log(`│ ✗ ${name.padEnd(40)}│`);
216
+ }
217
+ }
218
+ console.log(`└─────────────────────────────────────────────┘\n`);
219
+ return { success, failed };
220
+ }
175
221
  }
package/build/index.js CHANGED
@@ -24,7 +24,6 @@ import { ImageAnalyzer } from "./quality/image-analyzer.js";
24
24
  import { MediaAnalyzer } from "./quality/media-analyzer.js";
25
25
  import { QualityOrchestrator } from "./quality/quality-orchestrator.js";
26
26
  import { ConfigManager } from "./config/config-manager.js";
27
- import { Selector } from "./utils/selector.js";
28
27
  import os from "os";
29
28
  // Determine absolute paths relative to the compiled script
30
29
  const __filename = fileURLToPath(import.meta.url);
@@ -782,52 +781,21 @@ async function main() {
782
781
  async function runSetupWizard(silent = false) {
783
782
  const configManager = new ConfigManager();
784
783
  if (!silent) {
785
- console.log(`\n🚀 Welcome to Vesper MCP Setup!`);
786
- console.log(`--------------------------------`);
787
- console.log(`Searching for IDE configurations...`);
784
+ console.log(`\n🚀 Vesper MCP - Universal Setup`);
785
+ console.log(`================================`);
786
+ console.log(`Installing to all detected coding agents...\n`);
788
787
  }
789
- const ides = configManager.detectIDEs();
790
- if (ides.length === 0) {
788
+ const result = await configManager.installToAll();
789
+ if (result.success.length === 0 && result.failed.length === 0) {
791
790
  if (!silent) {
792
- console.log("\n❌ No supported IDEs detected.");
793
- console.log("I checked for:");
794
- console.log(" - Cursor (Global & Project)");
795
- console.log(" - Claude Desktop");
796
- console.log(" - VS Code (Standard MCP, Copilot Chat, Cline, Roo Code)");
797
- console.log("\nIf you are using VS Code or Cursor, please make sure they are installed.");
798
- console.log("For project-specific setup, run this command inside your project folder.");
791
+ console.log("\n❌ No supported agents detected.");
792
+ console.log("Supported agents: Claude Code, Claude Desktop, Cursor, VS Code, Codex, Antigravity");
793
+ console.log("\nMake sure at least one is installed, then try again.");
799
794
  }
800
795
  return;
801
796
  }
802
- if (silent) {
803
- for (const ide of ides) {
804
- await configManager.installTo(ide);
805
- }
806
- return;
807
- }
808
- console.log(`\nFound ${ides.length} potential application(s):`);
809
- const selector = new Selector("Select applications to configure for Vesper:", ides.map(ide => ({
810
- name: ide.name,
811
- value: ide,
812
- selected: true
813
- })));
814
- const selectedIDEs = await selector.run();
815
- if (selectedIDEs.length > 0) {
816
- console.log(`\nInstalling to ${selectedIDEs.length} application(s)...\n`);
817
- for (const ide of selectedIDEs) {
818
- process.stdout.write(`Installing to ${ide.name}... `);
819
- const success = await configManager.installTo(ide);
820
- if (success) {
821
- process.stdout.write("✅\n");
822
- }
823
- else {
824
- process.stdout.write("❌ (Check permissions or if file is in use)\n");
825
- }
826
- }
827
- console.log("\n✨ Setup complete! Please RESTART your IDE(s) to apply changes.");
828
- }
829
- else {
830
- console.log("\nSetup skipped. No applications selected.");
797
+ if (!silent) {
798
+ console.log("✨ Setup complete! Please RESTART your IDE(s) to apply changes.");
831
799
  }
832
800
  }
833
801
  main().catch((error) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vespermcp/mcp-server",
3
- "version": "1.1.0",
3
+ "version": "1.1.1",
4
4
  "description": "AI-powered dataset discovery, quality analysis, and preparation MCP server with multimodal support (text, image, audio, video)",
5
5
  "type": "module",
6
6
  "main": "build/index.js",