metamcp-cli 0.1.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 ADDED
@@ -0,0 +1,154 @@
1
+ # metamcp-cli
2
+
3
+ CLI wrapper for [MetaMCP](https://github.com/metatool-ai/metamcp) — auto-detect your IDEs and configure them to use your MetaMCP instance in seconds.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install -g metamcp-cli
9
+ ```
10
+
11
+ > Requires Node.js >= 18 and [uv](https://docs.astral.sh/uv/) (`uvx` must be available for Claude Code / Claude Desktop).
12
+
13
+ ## Quick Start
14
+
15
+ ```bash
16
+ # Interactive wizard — does everything in one step
17
+ metamcp-cli setup
18
+ ```
19
+
20
+ Or step by step:
21
+
22
+ ```bash
23
+ # 1. Connect to your MetaMCP instance
24
+ metamcp-cli init
25
+
26
+ # 2. See what IDEs you have installed
27
+ metamcp-cli scan
28
+
29
+ # 3. List available endpoints
30
+ metamcp-cli endpoints
31
+
32
+ # 4. Configure your IDEs to use an endpoint
33
+ metamcp-cli use my-endpoint
34
+ ```
35
+
36
+ ## Commands
37
+
38
+ | Command | Description |
39
+ |---------|-------------|
40
+ | `setup` | Interactive wizard: connect, pick endpoint, configure IDEs |
41
+ | `init` | Configure MetaMCP instance URL and API key |
42
+ | `scan` | Detect installed MCP clients (IDEs) |
43
+ | `endpoints` | List available MetaMCP endpoints |
44
+ | `namespaces` | List namespaces (requires session auth) |
45
+ | `use <endpoint>` | Configure detected clients to use a MetaMCP endpoint |
46
+ | `status` | Show current configuration and connection status |
47
+
48
+ ## Supported Clients
49
+
50
+ | Client | Config Location | Transport |
51
+ |--------|----------------|-----------|
52
+ | Claude Code | `.mcp.json` (project dir) | `uvx mcp-proxy` (streamable HTTP) |
53
+ | VS Code | `.vscode/mcp.json` (project dir) | SSE |
54
+ | Claude Desktop | Global config | `uvx mcp-proxy` (streamable HTTP) |
55
+ | Cursor | `~/.cursor/mcp.json` | SSE |
56
+ | Windsurf | `~/.codeium/windsurf/mcp_config.json` | SSE |
57
+ | Cline | VS Code extension settings | `npx mcp-remote` |
58
+
59
+ ## Example
60
+
61
+ ```bash
62
+ $ metamcp-cli setup
63
+
64
+ ⚡ MetaMCP Quick Setup
65
+
66
+ ? MetaMCP instance URL: https://metamcp.example.com
67
+ ? API Key: ****
68
+ ✔ Connected to MetaMCP
69
+
70
+ ? Select endpoint to use:
71
+ > my-workspace (production) — Production tools
72
+ dev-tools (development) — Dev and testing
73
+
74
+ ? Select clients to configure:
75
+ [x] Claude Code
76
+ [x] Cursor
77
+
78
+ ✔ Claude Code configured
79
+ ✔ Cursor configured
80
+
81
+ ✓ Setup complete!
82
+ Instance: https://metamcp.example.com
83
+ Endpoint: my-workspace
84
+ Clients: Claude Code, Cursor
85
+ ```
86
+
87
+ ## Generated Configs
88
+
89
+ **Claude Code / Claude Desktop** (`.mcp.json`):
90
+ ```json
91
+ {
92
+ "mcpServers": {
93
+ "metamcp": {
94
+ "command": "uvx",
95
+ "args": [
96
+ "mcp-proxy",
97
+ "--transport",
98
+ "streamablehttp",
99
+ "https://metamcp.example.com/metamcp/my-endpoint/mcp"
100
+ ],
101
+ "env": {
102
+ "API_ACCESS_TOKEN": "sk_mt_your_api_key_here"
103
+ }
104
+ }
105
+ }
106
+ }
107
+ ```
108
+
109
+ **Cursor / VS Code** (SSE):
110
+ ```json
111
+ {
112
+ "mcpServers": {
113
+ "metamcp": {
114
+ "url": "https://metamcp.example.com/metamcp/my-endpoint/sse",
115
+ "headers": {
116
+ "Authorization": "Bearer sk_mt_your_api_key_here"
117
+ }
118
+ }
119
+ }
120
+ }
121
+ ```
122
+
123
+ ## Options
124
+
125
+ ```
126
+ metamcp-cli use <endpoint> --client cursor # Only configure Cursor
127
+ metamcp-cli use <endpoint> --force # Overwrite without asking
128
+ metamcp-cli init --insecure # Allow self-signed certs
129
+ ```
130
+
131
+ ## Prerequisites
132
+
133
+ - A running [MetaMCP](https://github.com/metatool-ai/metamcp) instance
134
+ - An API key generated in the MetaMCP dashboard
135
+ - `uvx` (from [uv](https://docs.astral.sh/uv/)) for Claude Code / Claude Desktop
136
+ - `npx` for Cline
137
+
138
+ ## How It Works
139
+
140
+ 1. Connects to your MetaMCP instance via its public API
141
+ 2. Auto-detects which MCP-compatible IDEs are installed on your system
142
+ 3. Writes the correct MCP server configuration to each client's config file
143
+ 4. Creates backups (`.metamcp-backup`) before modifying any existing config
144
+
145
+ ## Security
146
+
147
+ - Config stored at `~/.metamcp-cli/config.json` with `0600` permissions
148
+ - API keys are never logged to stdout
149
+ - Automatic backup before modifying IDE configs
150
+ - API key input is masked during entry
151
+
152
+ ## License
153
+
154
+ MIT
package/dist/index.js ADDED
@@ -0,0 +1,912 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/index.ts
4
+ import { Command } from "commander";
5
+ import chalk8 from "chalk";
6
+
7
+ // src/commands/init.ts
8
+ import { input, select, password } from "@inquirer/prompts";
9
+ import chalk from "chalk";
10
+ import ora from "ora";
11
+
12
+ // src/api/metamcp.ts
13
+ var MetaMCPClient = class {
14
+ baseUrl;
15
+ apiKey;
16
+ sessionCookie;
17
+ proxyHeaders;
18
+ constructor(baseUrl, apiKey, sessionCookie, proxyHeaders) {
19
+ this.baseUrl = baseUrl.replace(/\/+$/, "");
20
+ this.apiKey = apiKey;
21
+ this.sessionCookie = sessionCookie;
22
+ this.proxyHeaders = proxyHeaders;
23
+ }
24
+ headers() {
25
+ const h = {
26
+ "Content-Type": "application/json",
27
+ ...this.proxyHeaders
28
+ };
29
+ if (this.apiKey) {
30
+ h["Authorization"] = `Bearer ${this.apiKey}`;
31
+ }
32
+ if (this.sessionCookie) {
33
+ h["Cookie"] = this.sessionCookie;
34
+ }
35
+ return h;
36
+ }
37
+ async healthCheck() {
38
+ try {
39
+ const res = await fetch(`${this.baseUrl}/health`, {
40
+ headers: this.headers()
41
+ });
42
+ return res.ok;
43
+ } catch {
44
+ return false;
45
+ }
46
+ }
47
+ async listPublicEndpoints() {
48
+ const res = await fetch(`${this.baseUrl}/metamcp`, {
49
+ headers: this.headers()
50
+ });
51
+ if (!res.ok) {
52
+ throw new Error(
53
+ `Failed to list endpoints: ${res.status} ${res.statusText}`
54
+ );
55
+ }
56
+ const data = await res.json();
57
+ return data.endpoints ?? [];
58
+ }
59
+ async signIn(email, password3) {
60
+ const res = await fetch(`${this.baseUrl}/api/auth/sign-in/email`, {
61
+ method: "POST",
62
+ headers: { "Content-Type": "application/json" },
63
+ body: JSON.stringify({ email, password: password3 }),
64
+ redirect: "manual"
65
+ });
66
+ if (!res.ok && res.status !== 302) {
67
+ throw new Error(`Sign-in failed: ${res.status} ${res.statusText}`);
68
+ }
69
+ const cookies = res.headers.getSetCookie?.() ?? [];
70
+ if (cookies.length === 0) {
71
+ const setCookie = res.headers.get("set-cookie");
72
+ if (setCookie) return setCookie;
73
+ throw new Error("Sign-in succeeded but no session cookie was returned.");
74
+ }
75
+ return cookies.join("; ");
76
+ }
77
+ async listNamespaces() {
78
+ if (!this.sessionCookie) {
79
+ throw new Error(
80
+ "Namespace listing requires session auth. Run `metamcp-cli init` with email/password."
81
+ );
82
+ }
83
+ const res = await fetch(`${this.baseUrl}/trpc/frontend/namespaces.list`, {
84
+ headers: this.headers()
85
+ });
86
+ if (!res.ok) {
87
+ throw new Error(
88
+ `Failed to list namespaces: ${res.status} ${res.statusText}`
89
+ );
90
+ }
91
+ const data = await res.json();
92
+ return data.result?.data ?? [];
93
+ }
94
+ };
95
+
96
+ // src/config/store.ts
97
+ import fs from "fs";
98
+ import path from "path";
99
+ import os from "os";
100
+ var CONFIG_DIR = path.join(os.homedir(), ".metamcp-cli");
101
+ var CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
102
+ function loadConfig() {
103
+ try {
104
+ if (!fs.existsSync(CONFIG_FILE)) return null;
105
+ const raw = fs.readFileSync(CONFIG_FILE, "utf-8");
106
+ return JSON.parse(raw);
107
+ } catch {
108
+ return null;
109
+ }
110
+ }
111
+ function saveConfig(config) {
112
+ if (!fs.existsSync(CONFIG_DIR)) {
113
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
114
+ }
115
+ fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), {
116
+ mode: 384
117
+ });
118
+ }
119
+ function getConfigOrThrow() {
120
+ const config = loadConfig();
121
+ if (!config) {
122
+ throw new Error(
123
+ "MetaMCP CLI is not initialized. Run `metamcp-cli init` first."
124
+ );
125
+ }
126
+ return config;
127
+ }
128
+
129
+ // src/commands/init.ts
130
+ async function initCommand(options) {
131
+ console.log(chalk.bold("\n\u{1F527} MetaMCP CLI Setup\n"));
132
+ if (options.insecure) {
133
+ process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0";
134
+ }
135
+ const url = await input({
136
+ message: "MetaMCP instance URL:",
137
+ default: "http://localhost:12008",
138
+ validate: (val) => {
139
+ try {
140
+ new URL(val);
141
+ return true;
142
+ } catch {
143
+ return "Please enter a valid URL";
144
+ }
145
+ }
146
+ });
147
+ const baseUrl = url.replace(/\/+$/, "");
148
+ const authMethod = await select({
149
+ message: "Authentication method:",
150
+ choices: [
151
+ { name: "API Key", value: "apikey" },
152
+ { name: "Email / Password", value: "credentials" }
153
+ ]
154
+ });
155
+ const config = {
156
+ version: 1,
157
+ instance: { url: baseUrl }
158
+ };
159
+ let apiKey;
160
+ let sessionCookie;
161
+ if (authMethod === "apikey") {
162
+ apiKey = await password({
163
+ message: "API Key:",
164
+ mask: "*"
165
+ });
166
+ config.instance.apiKey = apiKey;
167
+ } else {
168
+ const email = await input({ message: "Email:" });
169
+ const pass = await password({ message: "Password:", mask: "*" });
170
+ const spinner2 = ora("Signing in...").start();
171
+ const client2 = new MetaMCPClient(baseUrl);
172
+ try {
173
+ const cookie = await client2.signIn(email, pass);
174
+ spinner2.succeed("Signed in successfully");
175
+ sessionCookie = cookie;
176
+ config.instance.sessionCookie = cookie;
177
+ } catch (err) {
178
+ spinner2.fail(
179
+ `Sign-in failed: ${err instanceof Error ? err.message : String(err)}`
180
+ );
181
+ process.exit(1);
182
+ }
183
+ }
184
+ const spinner = ora("Validating connection...").start();
185
+ const client = new MetaMCPClient(baseUrl, apiKey, sessionCookie);
186
+ const ok = await client.healthCheck();
187
+ if (!ok) {
188
+ spinner.fail(
189
+ "Could not connect to MetaMCP. Check the URL and ensure the server is running."
190
+ );
191
+ process.exit(1);
192
+ }
193
+ spinner.succeed("Connected to MetaMCP");
194
+ saveConfig(config);
195
+ console.log(chalk.green("\n\u2713 Configuration saved to ~/.metamcp-cli/config.json"));
196
+ console.log(chalk.dim("Next steps:"));
197
+ console.log(chalk.dim(" metamcp-cli setup \u2014 interactive setup wizard"));
198
+ console.log(chalk.dim(" metamcp-cli endpoints \u2014 list available endpoints"));
199
+ console.log(chalk.dim(" metamcp-cli use <name> \u2014 configure your IDEs\n"));
200
+ }
201
+
202
+ // src/commands/scan.ts
203
+ import chalk2 from "chalk";
204
+
205
+ // src/clients/detector.ts
206
+ import fs2 from "fs";
207
+ import path2 from "path";
208
+ import os2 from "os";
209
+ import { execSync } from "child_process";
210
+ function getGlobalConfigPath(macPath, winPath, linuxPath) {
211
+ const home = os2.homedir();
212
+ const platform = process.platform;
213
+ let configPath;
214
+ if (platform === "darwin") {
215
+ configPath = path2.join(home, macPath);
216
+ } else if (platform === "win32") {
217
+ configPath = path2.join(home, winPath);
218
+ } else {
219
+ configPath = path2.join(home, linuxPath);
220
+ }
221
+ return fs2.existsSync(configPath) || fs2.existsSync(path2.dirname(configPath)) ? configPath : null;
222
+ }
223
+ function readJsonSafe(filePath) {
224
+ try {
225
+ if (!fs2.existsSync(filePath)) return null;
226
+ return JSON.parse(fs2.readFileSync(filePath, "utf-8"));
227
+ } catch {
228
+ return null;
229
+ }
230
+ }
231
+ function safeWriteMcpConfig(configPath, serverKey, serverConfig) {
232
+ let existing = {};
233
+ if (fs2.existsSync(configPath)) {
234
+ fs2.copyFileSync(configPath, configPath + ".metamcp-backup");
235
+ existing = JSON.parse(fs2.readFileSync(configPath, "utf-8"));
236
+ }
237
+ if (!existing["mcpServers"] || typeof existing["mcpServers"] !== "object") {
238
+ existing["mcpServers"] = {};
239
+ }
240
+ existing["mcpServers"][serverKey] = serverConfig;
241
+ fs2.mkdirSync(path2.dirname(configPath), { recursive: true });
242
+ fs2.writeFileSync(configPath, JSON.stringify(existing, null, 2));
243
+ }
244
+ function hasMcpEntry(configPath, key) {
245
+ const data = readJsonSafe(configPath);
246
+ if (!data) return false;
247
+ const servers = data["mcpServers"];
248
+ return !!servers && key in servers;
249
+ }
250
+ function removeMcpEntry(configPath, key) {
251
+ if (!fs2.existsSync(configPath)) return;
252
+ const data = JSON.parse(fs2.readFileSync(configPath, "utf-8"));
253
+ if (data.mcpServers && key in data.mcpServers) {
254
+ fs2.copyFileSync(configPath, configPath + ".metamcp-backup");
255
+ delete data.mcpServers[key];
256
+ fs2.writeFileSync(configPath, JSON.stringify(data, null, 2));
257
+ }
258
+ }
259
+ function buildSseConfig(config) {
260
+ const entry = {
261
+ url: `${config.baseUrl}/metamcp/${config.endpointName}/sse`
262
+ };
263
+ if (config.apiKey) {
264
+ entry["headers"] = { Authorization: `Bearer ${config.apiKey}` };
265
+ }
266
+ return entry;
267
+ }
268
+ function buildMcpProxyConfig(config) {
269
+ const url = `${config.baseUrl}/metamcp/${config.endpointName}/mcp`;
270
+ const env = {};
271
+ if (config.apiKey) {
272
+ env["API_ACCESS_TOKEN"] = config.apiKey;
273
+ }
274
+ return {
275
+ command: "uvx",
276
+ args: ["mcp-proxy", "--transport", "streamablehttp", url],
277
+ env
278
+ };
279
+ }
280
+ function buildStdioBridgeConfig(config) {
281
+ const url = `${config.baseUrl}/metamcp/${config.endpointName}/mcp`;
282
+ const args = ["-y", "mcp-remote", url];
283
+ if (config.apiKey) {
284
+ args.push("--header", `Authorization:Bearer ${config.apiKey}`);
285
+ }
286
+ return { command: "npx", args };
287
+ }
288
+ var MCP_KEY = "metamcp";
289
+ function hasBinary(name) {
290
+ try {
291
+ execSync(`which ${name}`, { stdio: "ignore" });
292
+ return true;
293
+ } catch {
294
+ return false;
295
+ }
296
+ }
297
+ function createClaudeDesktop() {
298
+ const slug = "claude-desktop";
299
+ const name = "Claude Desktop";
300
+ const getPath = () => getGlobalConfigPath(
301
+ "Library/Application Support/Claude/claude_desktop_config.json",
302
+ "AppData/Roaming/Claude/claude_desktop_config.json",
303
+ ".config/Claude/claude_desktop_config.json"
304
+ );
305
+ return {
306
+ name,
307
+ slug,
308
+ getConfigPath: getPath,
309
+ isInstalled: () => getPath() !== null,
310
+ hasMetaMCPEntry: () => {
311
+ const p = getPath();
312
+ return p ? hasMcpEntry(p, MCP_KEY) : false;
313
+ },
314
+ writeMetaMCPEntry: (config) => {
315
+ const p = getPath();
316
+ if (!p) throw new Error(`${name} config path not found`);
317
+ safeWriteMcpConfig(p, MCP_KEY, buildMcpProxyConfig(config));
318
+ },
319
+ removeMetaMCPEntry: () => {
320
+ const p = getPath();
321
+ if (p) removeMcpEntry(p, MCP_KEY);
322
+ }
323
+ };
324
+ }
325
+ function createCursor() {
326
+ const slug = "cursor";
327
+ const name = "Cursor";
328
+ const getPath = () => getGlobalConfigPath(
329
+ ".cursor/mcp.json",
330
+ ".cursor/mcp.json",
331
+ ".cursor/mcp.json"
332
+ );
333
+ return {
334
+ name,
335
+ slug,
336
+ getConfigPath: getPath,
337
+ isInstalled: () => getPath() !== null,
338
+ hasMetaMCPEntry: () => {
339
+ const p = getPath();
340
+ return p ? hasMcpEntry(p, MCP_KEY) : false;
341
+ },
342
+ writeMetaMCPEntry: (config) => {
343
+ const p = getPath();
344
+ if (!p) throw new Error(`${name} config path not found`);
345
+ safeWriteMcpConfig(p, MCP_KEY, buildSseConfig(config));
346
+ },
347
+ removeMetaMCPEntry: () => {
348
+ const p = getPath();
349
+ if (p) removeMcpEntry(p, MCP_KEY);
350
+ }
351
+ };
352
+ }
353
+ function createWindsurf() {
354
+ const slug = "windsurf";
355
+ const name = "Windsurf";
356
+ const getPath = () => getGlobalConfigPath(
357
+ ".codeium/windsurf/mcp_config.json",
358
+ ".codeium/windsurf/mcp_config.json",
359
+ ".codeium/windsurf/mcp_config.json"
360
+ );
361
+ return {
362
+ name,
363
+ slug,
364
+ getConfigPath: getPath,
365
+ isInstalled: () => getPath() !== null,
366
+ hasMetaMCPEntry: () => {
367
+ const p = getPath();
368
+ return p ? hasMcpEntry(p, MCP_KEY) : false;
369
+ },
370
+ writeMetaMCPEntry: (config) => {
371
+ const p = getPath();
372
+ if (!p) throw new Error(`${name} config path not found`);
373
+ const entry = {
374
+ serverUrl: `${config.baseUrl}/metamcp/${config.endpointName}/sse`
375
+ };
376
+ safeWriteMcpConfig(p, MCP_KEY, entry);
377
+ },
378
+ removeMetaMCPEntry: () => {
379
+ const p = getPath();
380
+ if (p) removeMcpEntry(p, MCP_KEY);
381
+ }
382
+ };
383
+ }
384
+ function createCline() {
385
+ const slug = "cline";
386
+ const name = "Cline";
387
+ const getPath = () => getGlobalConfigPath(
388
+ "Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json",
389
+ "AppData/Roaming/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json",
390
+ ".config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json"
391
+ );
392
+ return {
393
+ name,
394
+ slug,
395
+ getConfigPath: getPath,
396
+ isInstalled: () => getPath() !== null,
397
+ hasMetaMCPEntry: () => {
398
+ const p = getPath();
399
+ return p ? hasMcpEntry(p, MCP_KEY) : false;
400
+ },
401
+ writeMetaMCPEntry: (config) => {
402
+ const p = getPath();
403
+ if (!p) throw new Error(`${name} config path not found`);
404
+ safeWriteMcpConfig(p, MCP_KEY, buildStdioBridgeConfig(config));
405
+ },
406
+ removeMetaMCPEntry: () => {
407
+ const p = getPath();
408
+ if (p) removeMcpEntry(p, MCP_KEY);
409
+ }
410
+ };
411
+ }
412
+ function createClaudeCode() {
413
+ const slug = "claude-code";
414
+ const name = "Claude Code";
415
+ const getPath = () => path2.join(process.cwd(), ".mcp.json");
416
+ return {
417
+ name,
418
+ slug,
419
+ getConfigPath: getPath,
420
+ isInstalled: () => hasBinary("claude"),
421
+ hasMetaMCPEntry: () => hasMcpEntry(getPath(), MCP_KEY),
422
+ writeMetaMCPEntry: (config) => {
423
+ safeWriteMcpConfig(getPath(), MCP_KEY, buildMcpProxyConfig(config));
424
+ },
425
+ removeMetaMCPEntry: () => removeMcpEntry(getPath(), MCP_KEY)
426
+ };
427
+ }
428
+ function createVSCode() {
429
+ const slug = "vscode";
430
+ const name = "VS Code";
431
+ const getPath = () => path2.join(process.cwd(), ".vscode", "mcp.json");
432
+ return {
433
+ name,
434
+ slug,
435
+ getConfigPath: getPath,
436
+ isInstalled: () => hasBinary("code"),
437
+ hasMetaMCPEntry: () => hasMcpEntry(getPath(), MCP_KEY),
438
+ writeMetaMCPEntry: (config) => {
439
+ safeWriteMcpConfig(getPath(), MCP_KEY, buildSseConfig(config));
440
+ },
441
+ removeMetaMCPEntry: () => removeMcpEntry(getPath(), MCP_KEY)
442
+ };
443
+ }
444
+ var ALL_CLIENTS = [
445
+ createClaudeCode(),
446
+ createVSCode(),
447
+ createClaudeDesktop(),
448
+ createCursor(),
449
+ createWindsurf(),
450
+ createCline()
451
+ ];
452
+ function detectClients() {
453
+ return ALL_CLIENTS.filter((c) => c.isInstalled());
454
+ }
455
+ function getClientBySlug(slug) {
456
+ return ALL_CLIENTS.find((c) => c.slug === slug);
457
+ }
458
+
459
+ // src/commands/scan.ts
460
+ async function scanCommand() {
461
+ console.log(chalk2.bold("\n\u{1F50D} Scanning for MCP clients...\n"));
462
+ const results = [];
463
+ for (const client of ALL_CLIENTS) {
464
+ const installed = client.isInstalled();
465
+ const configPath = client.getConfigPath();
466
+ const hasEntry = installed && client.hasMetaMCPEntry();
467
+ results.push({
468
+ name: client.name,
469
+ slug: client.slug,
470
+ status: installed ? chalk2.green("Found") : chalk2.dim("Not found"),
471
+ path: configPath ?? "-",
472
+ configured: hasEntry ? chalk2.green("Yes") : chalk2.dim("No")
473
+ });
474
+ }
475
+ const nameWidth = 16;
476
+ const statusWidth = 14;
477
+ const configuredWidth = 14;
478
+ console.log(
479
+ chalk2.bold(
480
+ "Client".padEnd(nameWidth) + "Status".padEnd(statusWidth) + "MetaMCP".padEnd(configuredWidth) + "Config Path"
481
+ )
482
+ );
483
+ console.log("\u2500".repeat(80));
484
+ for (const r of results) {
485
+ console.log(
486
+ r.name.padEnd(nameWidth) + r.status.padEnd(statusWidth + 10) + // extra for chalk escape codes
487
+ r.configured.padEnd(configuredWidth + 10) + chalk2.dim(r.path)
488
+ );
489
+ }
490
+ const config = loadConfig();
491
+ if (config) {
492
+ config.detectedClients = {};
493
+ for (const client of ALL_CLIENTS) {
494
+ const p = client.getConfigPath();
495
+ config.detectedClients[client.slug] = {
496
+ configPath: p ?? "",
497
+ detected: client.isInstalled()
498
+ };
499
+ }
500
+ saveConfig(config);
501
+ }
502
+ const found = ALL_CLIENTS.filter((c) => c.isInstalled()).length;
503
+ console.log(chalk2.dim(`
504
+ ${found} client(s) detected.
505
+ `));
506
+ }
507
+
508
+ // src/commands/endpoints.ts
509
+ import chalk3 from "chalk";
510
+ import ora2 from "ora";
511
+
512
+ // src/api/client-from-config.ts
513
+ function clientFromConfig(config) {
514
+ return new MetaMCPClient(
515
+ config.instance.url,
516
+ config.instance.apiKey,
517
+ config.instance.sessionCookie,
518
+ config.instance.proxyHeaders
519
+ );
520
+ }
521
+
522
+ // src/commands/endpoints.ts
523
+ async function endpointsCommand() {
524
+ const config = getConfigOrThrow();
525
+ const client = clientFromConfig(config);
526
+ const spinner = ora2("Fetching endpoints...").start();
527
+ try {
528
+ const endpoints = await client.listPublicEndpoints();
529
+ spinner.stop();
530
+ if (endpoints.length === 0) {
531
+ console.log(chalk3.yellow("\nNo public endpoints found."));
532
+ console.log(chalk3.dim("Create endpoints in the MetaMCP dashboard first.\n"));
533
+ return;
534
+ }
535
+ console.log(chalk3.bold(`
536
+ \u{1F4E1} Endpoints (${endpoints.length})
537
+ `));
538
+ const nameWidth = 20;
539
+ const nsWidth = 20;
540
+ console.log(
541
+ chalk3.bold(
542
+ "Name".padEnd(nameWidth) + "Namespace".padEnd(nsWidth) + "URL"
543
+ )
544
+ );
545
+ console.log("\u2500".repeat(80));
546
+ for (const ep of endpoints) {
547
+ console.log(
548
+ ep.name.padEnd(nameWidth) + (ep.namespace ?? "-").padEnd(nsWidth) + chalk3.dim(ep.endpoints.mcp)
549
+ );
550
+ }
551
+ console.log();
552
+ } catch (err) {
553
+ spinner.fail(
554
+ `Failed to fetch endpoints: ${err instanceof Error ? err.message : String(err)}`
555
+ );
556
+ process.exit(1);
557
+ }
558
+ }
559
+
560
+ // src/commands/namespaces.ts
561
+ import chalk4 from "chalk";
562
+ import ora3 from "ora";
563
+ async function namespacesCommand() {
564
+ const config = getConfigOrThrow();
565
+ const client = clientFromConfig(config);
566
+ const spinner = ora3("Fetching namespaces...").start();
567
+ try {
568
+ const namespaces = await client.listNamespaces();
569
+ spinner.stop();
570
+ if (namespaces.length === 0) {
571
+ console.log(chalk4.yellow("\nNo namespaces found."));
572
+ return;
573
+ }
574
+ console.log(chalk4.bold(`
575
+ \u{1F4E6} Namespaces (${namespaces.length})
576
+ `));
577
+ const nameWidth = 24;
578
+ const scopeWidth = 12;
579
+ console.log(
580
+ chalk4.bold(
581
+ "Name".padEnd(nameWidth) + "Scope".padEnd(scopeWidth) + "Description"
582
+ )
583
+ );
584
+ console.log("\u2500".repeat(70));
585
+ for (const ns of namespaces) {
586
+ console.log(
587
+ ns.name.padEnd(nameWidth) + (ns.isPublic ? "public" : "private").padEnd(scopeWidth) + chalk4.dim(ns.description ?? "-")
588
+ );
589
+ }
590
+ console.log();
591
+ } catch (err) {
592
+ spinner.fail(
593
+ `Failed to fetch namespaces: ${err instanceof Error ? err.message : String(err)}`
594
+ );
595
+ process.exit(1);
596
+ }
597
+ }
598
+
599
+ // src/commands/use.ts
600
+ import chalk5 from "chalk";
601
+ import ora4 from "ora";
602
+ import { confirm, checkbox } from "@inquirer/prompts";
603
+ async function useCommand(endpointName, options) {
604
+ const config = getConfigOrThrow();
605
+ const apiClient = clientFromConfig(config);
606
+ const spinner = ora4("Validating endpoint...").start();
607
+ let endpoints;
608
+ try {
609
+ endpoints = await apiClient.listPublicEndpoints();
610
+ } catch (err) {
611
+ spinner.fail(
612
+ `Failed to fetch endpoints: ${err instanceof Error ? err.message : String(err)}`
613
+ );
614
+ process.exit(1);
615
+ }
616
+ const endpoint = endpoints.find((e) => e.name === endpointName);
617
+ if (!endpoint) {
618
+ spinner.fail(`Endpoint "${endpointName}" not found.`);
619
+ console.log(
620
+ chalk5.dim(
621
+ "Available endpoints: " + endpoints.map((e) => e.name).join(", ")
622
+ )
623
+ );
624
+ process.exit(1);
625
+ }
626
+ spinner.succeed(`Endpoint "${endpointName}" found`);
627
+ let targets;
628
+ if (options.client) {
629
+ const c = getClientBySlug(options.client);
630
+ if (!c) {
631
+ console.log(
632
+ chalk5.red(`Unknown client "${options.client}".`) + chalk5.dim(
633
+ " Available: claude-desktop, cursor, windsurf, cline, claude-code"
634
+ )
635
+ );
636
+ process.exit(1);
637
+ }
638
+ if (!c.isInstalled()) {
639
+ console.log(chalk5.red(`${c.name} is not installed or detected on this system.`));
640
+ process.exit(1);
641
+ }
642
+ targets = [c];
643
+ } else {
644
+ const detected = detectClients();
645
+ if (detected.length === 0) {
646
+ console.log(chalk5.yellow("No MCP clients detected. Run `metamcp-cli scan` to check."));
647
+ process.exit(1);
648
+ }
649
+ const selected = await checkbox({
650
+ message: "Select clients to configure:",
651
+ choices: detected.map((c) => ({
652
+ name: `${c.name}${c.hasMetaMCPEntry() ? chalk5.dim(" (already configured)") : ""}`,
653
+ value: c.slug,
654
+ checked: true
655
+ }))
656
+ });
657
+ if (selected.length === 0) {
658
+ console.log(chalk5.yellow("No clients selected."));
659
+ return;
660
+ }
661
+ targets = selected.map((slug) => getClientBySlug(slug)).filter((c) => c !== void 0);
662
+ }
663
+ const endpointConfig = {
664
+ baseUrl: config.instance.url,
665
+ endpointName,
666
+ apiKey: config.instance.apiKey
667
+ };
668
+ for (const client of targets) {
669
+ const hasExisting = client.hasMetaMCPEntry();
670
+ if (hasExisting && !options.force) {
671
+ const overwrite = await confirm({
672
+ message: `${client.name} already has a MetaMCP config. Overwrite?`,
673
+ default: true
674
+ });
675
+ if (!overwrite) {
676
+ console.log(chalk5.dim(` Skipped ${client.name}`));
677
+ continue;
678
+ }
679
+ }
680
+ try {
681
+ const s = ora4(`Configuring ${client.name}...`).start();
682
+ client.writeMetaMCPEntry(endpointConfig);
683
+ s.succeed(`${client.name} configured`);
684
+ } catch (err) {
685
+ console.log(
686
+ chalk5.red(
687
+ ` Failed to configure ${client.name}: ${err instanceof Error ? err.message : String(err)}`
688
+ )
689
+ );
690
+ }
691
+ }
692
+ config.activeEndpoint = endpointName;
693
+ saveConfig(config);
694
+ console.log(chalk5.green(`
695
+ \u2713 Active endpoint set to "${endpointName}"`));
696
+ console.log(chalk5.dim("Restart your IDE(s) for the changes to take effect.\n"));
697
+ }
698
+
699
+ // src/commands/status.ts
700
+ import chalk6 from "chalk";
701
+ import ora5 from "ora";
702
+ async function statusCommand() {
703
+ const config = loadConfig();
704
+ if (!config) {
705
+ console.log(chalk6.yellow("\nMetaMCP CLI is not initialized."));
706
+ console.log(chalk6.dim("Run `metamcp-cli init` to get started.\n"));
707
+ return;
708
+ }
709
+ console.log(chalk6.bold("\n\u{1F4CA} MetaMCP CLI Status\n"));
710
+ console.log(chalk6.bold("Instance"));
711
+ console.log(` URL: ${config.instance.url}`);
712
+ console.log(
713
+ ` Auth: ${config.instance.apiKey ? "API Key" : config.instance.sessionCookie ? "Session" : chalk6.yellow("Not configured")}`
714
+ );
715
+ const spinner = ora5(" Checking connection...").start();
716
+ const client = clientFromConfig(config);
717
+ const healthy = await client.healthCheck();
718
+ if (healthy) {
719
+ spinner.succeed(" Connection: OK");
720
+ } else {
721
+ spinner.fail(" Connection: Failed");
722
+ }
723
+ console.log(
724
+ `
725
+ ${chalk6.bold("Active Endpoint")}: ${config.activeEndpoint ?? chalk6.dim("none")}`
726
+ );
727
+ console.log(chalk6.bold("\nClients"));
728
+ for (const c of ALL_CLIENTS) {
729
+ const installed = c.isInstalled();
730
+ const configured = installed && c.hasMetaMCPEntry();
731
+ const statusStr = !installed ? chalk6.dim("not found") : configured ? chalk6.green("configured") : chalk6.yellow("detected");
732
+ console.log(` ${c.name.padEnd(16)} ${statusStr}`);
733
+ }
734
+ console.log();
735
+ }
736
+
737
+ // src/commands/setup.ts
738
+ import { input as input2, select as select2, password as password2, checkbox as checkbox2, confirm as confirm2 } from "@inquirer/prompts";
739
+ import chalk7 from "chalk";
740
+ import ora6 from "ora";
741
+ async function setupCommand(options) {
742
+ console.log(chalk7.bold("\n\u26A1 MetaMCP Quick Setup\n"));
743
+ if (options.insecure) {
744
+ process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0";
745
+ }
746
+ let config = loadConfig();
747
+ let apiClient;
748
+ if (config) {
749
+ console.log(chalk7.dim(`Using existing config: ${config.instance.url}`));
750
+ apiClient = clientFromConfig(config);
751
+ const healthy = await apiClient.healthCheck();
752
+ if (!healthy) {
753
+ console.log(chalk7.yellow("Cannot connect to saved instance. Let's reconfigure.\n"));
754
+ config = null;
755
+ }
756
+ }
757
+ if (!config) {
758
+ const url = await input2({
759
+ message: "MetaMCP instance URL:",
760
+ default: "http://localhost:12008",
761
+ validate: (val) => {
762
+ try {
763
+ new URL(val);
764
+ return true;
765
+ } catch {
766
+ return "Please enter a valid URL";
767
+ }
768
+ }
769
+ });
770
+ const baseUrl = url.replace(/\/+$/, "");
771
+ const apiKey = await password2({
772
+ message: "API Key:",
773
+ mask: "*"
774
+ });
775
+ const spinner2 = ora6("Connecting...").start();
776
+ apiClient = new MetaMCPClient(baseUrl, apiKey);
777
+ const healthy = await apiClient.healthCheck();
778
+ if (!healthy) {
779
+ spinner2.fail("Could not connect. Check URL and API key.");
780
+ process.exit(1);
781
+ }
782
+ spinner2.succeed("Connected to MetaMCP");
783
+ config = {
784
+ version: 1,
785
+ instance: { url: baseUrl, apiKey }
786
+ };
787
+ saveConfig(config);
788
+ }
789
+ const spinner = ora6("Fetching endpoints...").start();
790
+ let endpoints;
791
+ try {
792
+ endpoints = await apiClient.listPublicEndpoints();
793
+ } catch (err) {
794
+ spinner.fail(`Failed to fetch endpoints: ${err instanceof Error ? err.message : String(err)}`);
795
+ process.exit(1);
796
+ }
797
+ spinner.stop();
798
+ if (endpoints.length === 0) {
799
+ console.log(chalk7.yellow("\nNo endpoints found. Create one in the MetaMCP dashboard first.\n"));
800
+ process.exit(1);
801
+ }
802
+ const selectedEndpoint = await select2({
803
+ message: "Select endpoint to use:",
804
+ choices: endpoints.map((ep) => ({
805
+ name: `${ep.name}${ep.namespace ? chalk7.dim(` (${ep.namespace})`) : ""}${ep.description ? chalk7.dim(` \u2014 ${ep.description}`) : ""}`,
806
+ value: ep.name
807
+ }))
808
+ });
809
+ const detected = detectClients();
810
+ if (detected.length === 0) {
811
+ console.log(chalk7.yellow("\nNo MCP clients detected on this system."));
812
+ console.log(chalk7.dim("Supported: Claude Desktop, Cursor, Windsurf, Cline, Claude Code\n"));
813
+ config.activeEndpoint = selectedEndpoint;
814
+ saveConfig(config);
815
+ process.exit(1);
816
+ }
817
+ const selectedClients = await checkbox2({
818
+ message: "Select clients to configure:",
819
+ choices: detected.map((c) => ({
820
+ name: `${c.name}${c.hasMetaMCPEntry() ? chalk7.dim(" (already configured)") : ""}`,
821
+ value: c.slug,
822
+ checked: true
823
+ }))
824
+ });
825
+ if (selectedClients.length === 0) {
826
+ console.log(chalk7.yellow("No clients selected."));
827
+ config.activeEndpoint = selectedEndpoint;
828
+ saveConfig(config);
829
+ return;
830
+ }
831
+ const targets = selectedClients.map((slug) => getClientBySlug(slug)).filter((c) => c !== void 0);
832
+ const endpointConfig = {
833
+ baseUrl: config.instance.url,
834
+ endpointName: selectedEndpoint,
835
+ apiKey: config.instance.apiKey
836
+ };
837
+ console.log();
838
+ for (const client of targets) {
839
+ const hasExisting = client.hasMetaMCPEntry();
840
+ if (hasExisting) {
841
+ const overwrite = await confirm2({
842
+ message: `${client.name} already configured. Overwrite?`,
843
+ default: true
844
+ });
845
+ if (!overwrite) {
846
+ console.log(chalk7.dim(` Skipped ${client.name}`));
847
+ continue;
848
+ }
849
+ }
850
+ try {
851
+ const s = ora6(`Configuring ${client.name}...`).start();
852
+ client.writeMetaMCPEntry(endpointConfig);
853
+ s.succeed(`${client.name} configured`);
854
+ } catch (err) {
855
+ console.log(
856
+ chalk7.red(` Failed: ${client.name} \u2014 ${err instanceof Error ? err.message : String(err)}`)
857
+ );
858
+ }
859
+ }
860
+ config.activeEndpoint = selectedEndpoint;
861
+ saveConfig(config);
862
+ console.log(chalk7.green(`
863
+ \u2713 Setup complete!`));
864
+ console.log(chalk7.dim(` Instance: ${config.instance.url}`));
865
+ console.log(chalk7.dim(` Endpoint: ${selectedEndpoint}`));
866
+ console.log(chalk7.dim(` Clients: ${targets.map((c) => c.name).join(", ")}`));
867
+ console.log(chalk7.dim("\nRestart your IDE(s) for changes to take effect.\n"));
868
+ }
869
+
870
+ // src/index.ts
871
+ var program = new Command();
872
+ program.name("metamcp-cli").description("CLI wrapper for MetaMCP \u2014 auto-configure MCP clients").version("0.1.0");
873
+ program.command("setup").description("Interactive setup wizard \u2014 connect, pick endpoint, configure IDEs").option("--insecure", "Allow self-signed SSL certificates").action(async (options) => {
874
+ await withErrorHandling(() => setupCommand(options));
875
+ });
876
+ program.command("init").description("Initialize MetaMCP CLI with your instance URL and credentials").option("--insecure", "Allow self-signed SSL certificates").action(async (options) => {
877
+ await withErrorHandling(() => initCommand(options));
878
+ });
879
+ program.command("scan").description("Detect installed MCP clients (IDEs)").action(async () => {
880
+ await withErrorHandling(scanCommand);
881
+ });
882
+ program.command("endpoints").description("List available MetaMCP endpoints").action(async () => {
883
+ await withErrorHandling(endpointsCommand);
884
+ });
885
+ program.command("namespaces").description("List available MetaMCP namespaces (requires session auth)").action(async () => {
886
+ await withErrorHandling(namespacesCommand);
887
+ });
888
+ program.command("use").argument("<endpoint>", "Name of the MetaMCP endpoint to use").description("Configure detected MCP clients to use a MetaMCP endpoint").option("-c, --client <slug>", "Only configure a specific client").option("-f, --force", "Overwrite existing MetaMCP config without asking").action(async (endpoint, options) => {
889
+ await withErrorHandling(() => useCommand(endpoint, options));
890
+ });
891
+ program.command("status").description("Show current MetaMCP CLI configuration and status").action(async () => {
892
+ await withErrorHandling(statusCommand);
893
+ });
894
+ async function withErrorHandling(fn) {
895
+ try {
896
+ await fn();
897
+ } catch (err) {
898
+ if (err instanceof Error) {
899
+ console.error(chalk8.red(`
900
+ Error: ${err.message}`));
901
+ if (process.env["DEBUG"]) {
902
+ console.error(chalk8.dim(err.stack));
903
+ }
904
+ } else {
905
+ console.error(chalk8.red(`
906
+ Error: ${String(err)}`));
907
+ }
908
+ process.exit(1);
909
+ }
910
+ }
911
+ program.parse();
912
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/commands/init.ts","../src/api/metamcp.ts","../src/config/store.ts","../src/commands/scan.ts","../src/clients/detector.ts","../src/commands/endpoints.ts","../src/api/client-from-config.ts","../src/commands/namespaces.ts","../src/commands/use.ts","../src/commands/status.ts","../src/commands/setup.ts"],"sourcesContent":["import { Command } from 'commander';\nimport chalk from 'chalk';\nimport { initCommand } from './commands/init.js';\nimport { scanCommand } from './commands/scan.js';\nimport { endpointsCommand } from './commands/endpoints.js';\nimport { namespacesCommand } from './commands/namespaces.js';\nimport { useCommand } from './commands/use.js';\nimport { statusCommand } from './commands/status.js';\nimport { setupCommand } from './commands/setup.js';\n\nconst program = new Command();\n\nprogram\n .name('metamcp-cli')\n .description('CLI wrapper for MetaMCP — auto-configure MCP clients')\n .version('0.1.0');\n\nprogram\n .command('setup')\n .description('Interactive setup wizard — connect, pick endpoint, configure IDEs')\n .option('--insecure', 'Allow self-signed SSL certificates')\n .action(async (options) => {\n await withErrorHandling(() => setupCommand(options));\n });\n\nprogram\n .command('init')\n .description('Initialize MetaMCP CLI with your instance URL and credentials')\n .option('--insecure', 'Allow self-signed SSL certificates')\n .action(async (options) => {\n await withErrorHandling(() => initCommand(options));\n });\n\nprogram\n .command('scan')\n .description('Detect installed MCP clients (IDEs)')\n .action(async () => {\n await withErrorHandling(scanCommand);\n });\n\nprogram\n .command('endpoints')\n .description('List available MetaMCP endpoints')\n .action(async () => {\n await withErrorHandling(endpointsCommand);\n });\n\nprogram\n .command('namespaces')\n .description('List available MetaMCP namespaces (requires session auth)')\n .action(async () => {\n await withErrorHandling(namespacesCommand);\n });\n\nprogram\n .command('use')\n .argument('<endpoint>', 'Name of the MetaMCP endpoint to use')\n .description('Configure detected MCP clients to use a MetaMCP endpoint')\n .option('-c, --client <slug>', 'Only configure a specific client')\n .option('-f, --force', 'Overwrite existing MetaMCP config without asking')\n .action(async (endpoint, options) => {\n await withErrorHandling(() => useCommand(endpoint, options));\n });\n\nprogram\n .command('status')\n .description('Show current MetaMCP CLI configuration and status')\n .action(async () => {\n await withErrorHandling(statusCommand);\n });\n\nasync function withErrorHandling(fn: () => Promise<void>): Promise<void> {\n try {\n await fn();\n } catch (err) {\n if (err instanceof Error) {\n console.error(chalk.red(`\\nError: ${err.message}`));\n if (process.env['DEBUG']) {\n console.error(chalk.dim(err.stack));\n }\n } else {\n console.error(chalk.red(`\\nError: ${String(err)}`));\n }\n process.exit(1);\n }\n}\n\nprogram.parse();\n","import { input, select, password } from '@inquirer/prompts';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { MetaMCPClient } from '../api/metamcp.js';\nimport { saveConfig, type MetaMCPConfig } from '../config/store.js';\n\nexport async function initCommand(options: { insecure?: boolean }): Promise<void> {\n console.log(chalk.bold('\\n🔧 MetaMCP CLI Setup\\n'));\n\n if (options.insecure) {\n process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';\n }\n\n const url = await input({\n message: 'MetaMCP instance URL:',\n default: 'http://localhost:12008',\n validate: (val) => {\n try {\n new URL(val);\n return true;\n } catch {\n return 'Please enter a valid URL';\n }\n },\n });\n\n const baseUrl = url.replace(/\\/+$/, '');\n\n const authMethod = await select({\n message: 'Authentication method:',\n choices: [\n { name: 'API Key', value: 'apikey' },\n { name: 'Email / Password', value: 'credentials' },\n ],\n });\n\n const config: MetaMCPConfig = {\n version: 1,\n instance: { url: baseUrl },\n };\n\n let apiKey: string | undefined;\n let sessionCookie: string | undefined;\n\n if (authMethod === 'apikey') {\n apiKey = await password({\n message: 'API Key:',\n mask: '*',\n });\n config.instance.apiKey = apiKey;\n } else {\n const email = await input({ message: 'Email:' });\n const pass = await password({ message: 'Password:', mask: '*' });\n\n const spinner = ora('Signing in...').start();\n const client = new MetaMCPClient(baseUrl);\n\n try {\n const cookie = await client.signIn(email, pass);\n spinner.succeed('Signed in successfully');\n sessionCookie = cookie;\n config.instance.sessionCookie = cookie;\n } catch (err) {\n spinner.fail(\n `Sign-in failed: ${err instanceof Error ? err.message : String(err)}`\n );\n process.exit(1);\n }\n }\n\n // Validate connection\n const spinner = ora('Validating connection...').start();\n const client = new MetaMCPClient(baseUrl, apiKey, sessionCookie);\n const ok = await client.healthCheck();\n\n if (!ok) {\n spinner.fail(\n 'Could not connect to MetaMCP. Check the URL and ensure the server is running.'\n );\n process.exit(1);\n }\n\n spinner.succeed('Connected to MetaMCP');\n\n saveConfig(config);\n console.log(chalk.green('\\n✓ Configuration saved to ~/.metamcp-cli/config.json'));\n console.log(chalk.dim('Next steps:'));\n console.log(chalk.dim(' metamcp-cli setup — interactive setup wizard'));\n console.log(chalk.dim(' metamcp-cli endpoints — list available endpoints'));\n console.log(chalk.dim(' metamcp-cli use <name> — configure your IDEs\\n'));\n}\n","export interface PublicEndpoint {\n name: string;\n description?: string;\n namespace?: string;\n endpoints: {\n mcp: string;\n sse: string;\n api: string;\n };\n}\n\nexport interface Namespace {\n id: string;\n name: string;\n description?: string;\n isPublic: boolean;\n createdAt: string;\n}\n\nexport class MetaMCPClient {\n private baseUrl: string;\n private apiKey?: string;\n private sessionCookie?: string;\n private proxyHeaders?: Record<string, string>;\n\n constructor(\n baseUrl: string,\n apiKey?: string,\n sessionCookie?: string,\n proxyHeaders?: Record<string, string>,\n ) {\n this.baseUrl = baseUrl.replace(/\\/+$/, \"\");\n this.apiKey = apiKey;\n this.sessionCookie = sessionCookie;\n this.proxyHeaders = proxyHeaders;\n }\n\n private headers(): Record<string, string> {\n const h: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...this.proxyHeaders,\n };\n if (this.apiKey) {\n h[\"Authorization\"] = `Bearer ${this.apiKey}`;\n }\n if (this.sessionCookie) {\n h[\"Cookie\"] = this.sessionCookie;\n }\n return h;\n }\n\n async healthCheck(): Promise<boolean> {\n try {\n const res = await fetch(`${this.baseUrl}/health`, {\n headers: this.headers(),\n });\n return res.ok;\n } catch {\n return false;\n }\n }\n\n async listPublicEndpoints(): Promise<PublicEndpoint[]> {\n const res = await fetch(`${this.baseUrl}/metamcp`, {\n headers: this.headers(),\n });\n if (!res.ok) {\n throw new Error(\n `Failed to list endpoints: ${res.status} ${res.statusText}`,\n );\n }\n const data = (await res.json()) as { endpoints?: PublicEndpoint[] };\n return data.endpoints ?? [];\n }\n\n async signIn(email: string, password: string): Promise<string> {\n const res = await fetch(`${this.baseUrl}/api/auth/sign-in/email`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ email, password }),\n redirect: \"manual\",\n });\n\n if (!res.ok && res.status !== 302) {\n throw new Error(`Sign-in failed: ${res.status} ${res.statusText}`);\n }\n\n const cookies = res.headers.getSetCookie?.() ?? [];\n if (cookies.length === 0) {\n const setCookie = res.headers.get(\"set-cookie\");\n if (setCookie) return setCookie;\n throw new Error(\"Sign-in succeeded but no session cookie was returned.\");\n }\n return cookies.join(\"; \");\n }\n\n async listNamespaces(): Promise<Namespace[]> {\n if (!this.sessionCookie) {\n throw new Error(\n \"Namespace listing requires session auth. Run `metamcp-cli init` with email/password.\",\n );\n }\n const res = await fetch(`${this.baseUrl}/trpc/frontend/namespaces.list`, {\n headers: this.headers(),\n });\n if (!res.ok) {\n throw new Error(\n `Failed to list namespaces: ${res.status} ${res.statusText}`,\n );\n }\n const data = (await res.json()) as { result?: { data?: Namespace[] } };\n return data.result?.data ?? [];\n }\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\n\nexport interface DetectedClient {\n configPath: string;\n detected: boolean;\n}\n\nexport interface MetaMCPConfig {\n version: 1;\n instance: {\n url: string;\n apiKey?: string;\n sessionCookie?: string;\n proxyHeaders?: Record<string, string>;\n };\n activeEndpoint?: string;\n detectedClients?: Record<string, DetectedClient>;\n}\n\nconst CONFIG_DIR = path.join(os.homedir(), '.metamcp-cli');\nconst CONFIG_FILE = path.join(CONFIG_DIR, 'config.json');\n\nexport function getConfigDir(): string {\n return CONFIG_DIR;\n}\n\nexport function getConfigPath(): string {\n return CONFIG_FILE;\n}\n\nexport function loadConfig(): MetaMCPConfig | null {\n try {\n if (!fs.existsSync(CONFIG_FILE)) return null;\n const raw = fs.readFileSync(CONFIG_FILE, 'utf-8');\n return JSON.parse(raw) as MetaMCPConfig;\n } catch {\n return null;\n }\n}\n\nexport function saveConfig(config: MetaMCPConfig): void {\n if (!fs.existsSync(CONFIG_DIR)) {\n fs.mkdirSync(CONFIG_DIR, { recursive: true });\n }\n fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), {\n mode: 0o600,\n });\n}\n\nexport function getConfigOrThrow(): MetaMCPConfig {\n const config = loadConfig();\n if (!config) {\n throw new Error(\n 'MetaMCP CLI is not initialized. Run `metamcp-cli init` first.'\n );\n }\n return config;\n}\n","import chalk from 'chalk';\nimport { ALL_CLIENTS } from '../clients/detector.js';\nimport { loadConfig, saveConfig, type MetaMCPConfig } from '../config/store.js';\n\nexport async function scanCommand(): Promise<void> {\n console.log(chalk.bold('\\n🔍 Scanning for MCP clients...\\n'));\n\n const results: { name: string; slug: string; status: string; path: string; configured: string }[] = [];\n\n for (const client of ALL_CLIENTS) {\n const installed = client.isInstalled();\n const configPath = client.getConfigPath();\n const hasEntry = installed && client.hasMetaMCPEntry();\n\n results.push({\n name: client.name,\n slug: client.slug,\n status: installed ? chalk.green('Found') : chalk.dim('Not found'),\n path: configPath ?? '-',\n configured: hasEntry ? chalk.green('Yes') : chalk.dim('No'),\n });\n }\n\n // Print table\n const nameWidth = 16;\n const statusWidth = 14;\n const configuredWidth = 14;\n\n console.log(\n chalk.bold(\n 'Client'.padEnd(nameWidth) +\n 'Status'.padEnd(statusWidth) +\n 'MetaMCP'.padEnd(configuredWidth) +\n 'Config Path'\n )\n );\n console.log('─'.repeat(80));\n\n for (const r of results) {\n console.log(\n r.name.padEnd(nameWidth) +\n r.status.padEnd(statusWidth + 10) + // extra for chalk escape codes\n r.configured.padEnd(configuredWidth + 10) +\n chalk.dim(r.path)\n );\n }\n\n // Cache detected clients in config\n const config = loadConfig();\n if (config) {\n config.detectedClients = {};\n for (const client of ALL_CLIENTS) {\n const p = client.getConfigPath();\n config.detectedClients[client.slug] = {\n configPath: p ?? '',\n detected: client.isInstalled(),\n };\n }\n saveConfig(config);\n }\n\n const found = ALL_CLIENTS.filter((c) => c.isInstalled()).length;\n console.log(chalk.dim(`\\n${found} client(s) detected.\\n`));\n}\n","import fs from 'node:fs';\nimport path from 'node:path';\nimport os from 'node:os';\nimport { execSync } from 'node:child_process';\n\nexport interface EndpointConfig {\n baseUrl: string;\n endpointName: string;\n apiKey?: string;\n}\n\nexport interface MCPClient {\n name: string;\n slug: string;\n getConfigPath(): string | null;\n isInstalled(): boolean;\n hasMetaMCPEntry(): boolean;\n writeMetaMCPEntry(config: EndpointConfig): void;\n removeMetaMCPEntry(): void;\n}\n\nfunction getGlobalConfigPath(\n macPath: string,\n winPath: string,\n linuxPath: string\n): string | null {\n const home = os.homedir();\n const platform = process.platform;\n\n let configPath: string;\n if (platform === 'darwin') {\n configPath = path.join(home, macPath);\n } else if (platform === 'win32') {\n configPath = path.join(home, winPath);\n } else {\n configPath = path.join(home, linuxPath);\n }\n\n return fs.existsSync(configPath) || fs.existsSync(path.dirname(configPath))\n ? configPath\n : null;\n}\n\nfunction readJsonSafe(filePath: string): Record<string, unknown> | null {\n try {\n if (!fs.existsSync(filePath)) return null;\n return JSON.parse(fs.readFileSync(filePath, 'utf-8'));\n } catch {\n return null;\n }\n}\n\nfunction safeWriteMcpConfig(\n configPath: string,\n serverKey: string,\n serverConfig: Record<string, unknown>\n): void {\n let existing: Record<string, unknown> = {};\n if (fs.existsSync(configPath)) {\n fs.copyFileSync(configPath, configPath + '.metamcp-backup');\n existing = JSON.parse(fs.readFileSync(configPath, 'utf-8'));\n }\n\n if (!existing['mcpServers'] || typeof existing['mcpServers'] !== 'object') {\n existing['mcpServers'] = {};\n }\n\n (existing['mcpServers'] as Record<string, unknown>)[serverKey] = serverConfig;\n\n fs.mkdirSync(path.dirname(configPath), { recursive: true });\n fs.writeFileSync(configPath, JSON.stringify(existing, null, 2));\n}\n\nfunction hasMcpEntry(configPath: string, key: string): boolean {\n const data = readJsonSafe(configPath);\n if (!data) return false;\n const servers = data['mcpServers'] as Record<string, unknown> | undefined;\n return !!servers && key in servers;\n}\n\nfunction removeMcpEntry(configPath: string, key: string): void {\n if (!fs.existsSync(configPath)) return;\n const data = JSON.parse(fs.readFileSync(configPath, 'utf-8'));\n if (data.mcpServers && key in data.mcpServers) {\n fs.copyFileSync(configPath, configPath + '.metamcp-backup');\n delete data.mcpServers[key];\n fs.writeFileSync(configPath, JSON.stringify(data, null, 2));\n }\n}\n\nfunction buildSseConfig(config: EndpointConfig): Record<string, unknown> {\n const entry: Record<string, unknown> = {\n url: `${config.baseUrl}/metamcp/${config.endpointName}/sse`,\n };\n if (config.apiKey) {\n entry['headers'] = { Authorization: `Bearer ${config.apiKey}` };\n }\n return entry;\n}\n\nfunction buildMcpProxyConfig(config: EndpointConfig): Record<string, unknown> {\n const url = `${config.baseUrl}/metamcp/${config.endpointName}/mcp`;\n const env: Record<string, string> = {};\n if (config.apiKey) {\n env['API_ACCESS_TOKEN'] = config.apiKey;\n }\n return {\n command: 'uvx',\n args: ['mcp-proxy', '--transport', 'streamablehttp', url],\n env,\n };\n}\n\nfunction buildStdioBridgeConfig(config: EndpointConfig): Record<string, unknown> {\n const url = `${config.baseUrl}/metamcp/${config.endpointName}/mcp`;\n const args = ['-y', 'mcp-remote', url];\n if (config.apiKey) {\n args.push('--header', `Authorization:Bearer ${config.apiKey}`);\n }\n return { command: 'npx', args };\n}\n\nconst MCP_KEY = 'metamcp';\n\nfunction hasBinary(name: string): boolean {\n try {\n execSync(`which ${name}`, { stdio: 'ignore' });\n return true;\n } catch {\n return false;\n }\n}\n\n// --- Client implementations ---\n\nfunction createClaudeDesktop(): MCPClient {\n const slug = 'claude-desktop';\n const name = 'Claude Desktop';\n\n const getPath = () =>\n getGlobalConfigPath(\n 'Library/Application Support/Claude/claude_desktop_config.json',\n 'AppData/Roaming/Claude/claude_desktop_config.json',\n '.config/Claude/claude_desktop_config.json'\n );\n\n return {\n name,\n slug,\n getConfigPath: getPath,\n isInstalled: () => getPath() !== null,\n hasMetaMCPEntry: () => {\n const p = getPath();\n return p ? hasMcpEntry(p, MCP_KEY) : false;\n },\n writeMetaMCPEntry: (config) => {\n const p = getPath();\n if (!p) throw new Error(`${name} config path not found`);\n safeWriteMcpConfig(p, MCP_KEY, buildMcpProxyConfig(config));\n },\n removeMetaMCPEntry: () => {\n const p = getPath();\n if (p) removeMcpEntry(p, MCP_KEY);\n },\n };\n}\n\nfunction createCursor(): MCPClient {\n const slug = 'cursor';\n const name = 'Cursor';\n\n const getPath = () =>\n getGlobalConfigPath(\n '.cursor/mcp.json',\n '.cursor/mcp.json',\n '.cursor/mcp.json'\n );\n\n return {\n name,\n slug,\n getConfigPath: getPath,\n isInstalled: () => getPath() !== null,\n hasMetaMCPEntry: () => {\n const p = getPath();\n return p ? hasMcpEntry(p, MCP_KEY) : false;\n },\n writeMetaMCPEntry: (config) => {\n const p = getPath();\n if (!p) throw new Error(`${name} config path not found`);\n safeWriteMcpConfig(p, MCP_KEY, buildSseConfig(config));\n },\n removeMetaMCPEntry: () => {\n const p = getPath();\n if (p) removeMcpEntry(p, MCP_KEY);\n },\n };\n}\n\nfunction createWindsurf(): MCPClient {\n const slug = 'windsurf';\n const name = 'Windsurf';\n\n const getPath = () =>\n getGlobalConfigPath(\n '.codeium/windsurf/mcp_config.json',\n '.codeium/windsurf/mcp_config.json',\n '.codeium/windsurf/mcp_config.json'\n );\n\n return {\n name,\n slug,\n getConfigPath: getPath,\n isInstalled: () => getPath() !== null,\n hasMetaMCPEntry: () => {\n const p = getPath();\n return p ? hasMcpEntry(p, MCP_KEY) : false;\n },\n writeMetaMCPEntry: (config) => {\n const p = getPath();\n if (!p) throw new Error(`${name} config path not found`);\n const entry: Record<string, unknown> = {\n serverUrl: `${config.baseUrl}/metamcp/${config.endpointName}/sse`,\n };\n safeWriteMcpConfig(p, MCP_KEY, entry);\n },\n removeMetaMCPEntry: () => {\n const p = getPath();\n if (p) removeMcpEntry(p, MCP_KEY);\n },\n };\n}\n\nfunction createCline(): MCPClient {\n const slug = 'cline';\n const name = 'Cline';\n\n const getPath = () =>\n getGlobalConfigPath(\n 'Library/Application Support/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json',\n 'AppData/Roaming/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json',\n '.config/Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json'\n );\n\n return {\n name,\n slug,\n getConfigPath: getPath,\n isInstalled: () => getPath() !== null,\n hasMetaMCPEntry: () => {\n const p = getPath();\n return p ? hasMcpEntry(p, MCP_KEY) : false;\n },\n writeMetaMCPEntry: (config) => {\n const p = getPath();\n if (!p) throw new Error(`${name} config path not found`);\n safeWriteMcpConfig(p, MCP_KEY, buildStdioBridgeConfig(config));\n },\n removeMetaMCPEntry: () => {\n const p = getPath();\n if (p) removeMcpEntry(p, MCP_KEY);\n },\n };\n}\n\nfunction createClaudeCode(): MCPClient {\n const slug = 'claude-code';\n const name = 'Claude Code';\n\n const getPath = () => path.join(process.cwd(), '.mcp.json');\n\n return {\n name,\n slug,\n getConfigPath: getPath,\n isInstalled: () => hasBinary('claude'),\n hasMetaMCPEntry: () => hasMcpEntry(getPath(), MCP_KEY),\n writeMetaMCPEntry: (config) => {\n safeWriteMcpConfig(getPath(), MCP_KEY, buildMcpProxyConfig(config));\n },\n removeMetaMCPEntry: () => removeMcpEntry(getPath(), MCP_KEY),\n };\n}\n\nfunction createVSCode(): MCPClient {\n const slug = 'vscode';\n const name = 'VS Code';\n\n const getPath = () => path.join(process.cwd(), '.vscode', 'mcp.json');\n\n return {\n name,\n slug,\n getConfigPath: getPath,\n isInstalled: () => hasBinary('code'),\n hasMetaMCPEntry: () => hasMcpEntry(getPath(), MCP_KEY),\n writeMetaMCPEntry: (config) => {\n safeWriteMcpConfig(getPath(), MCP_KEY, buildSseConfig(config));\n },\n removeMetaMCPEntry: () => removeMcpEntry(getPath(), MCP_KEY),\n };\n}\n\nexport const ALL_CLIENTS: MCPClient[] = [\n createClaudeCode(),\n createVSCode(),\n createClaudeDesktop(),\n createCursor(),\n createWindsurf(),\n createCline(),\n];\n\nexport function detectClients(): MCPClient[] {\n return ALL_CLIENTS.filter((c) => c.isInstalled());\n}\n\nexport function getClientBySlug(slug: string): MCPClient | undefined {\n return ALL_CLIENTS.find((c) => c.slug === slug);\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { getConfigOrThrow } from '../config/store.js';\nimport { clientFromConfig } from '../api/client-from-config.js';\n\nexport async function endpointsCommand(): Promise<void> {\n const config = getConfigOrThrow();\n const client = clientFromConfig(config);\n\n const spinner = ora('Fetching endpoints...').start();\n\n try {\n const endpoints = await client.listPublicEndpoints();\n spinner.stop();\n\n if (endpoints.length === 0) {\n console.log(chalk.yellow('\\nNo public endpoints found.'));\n console.log(chalk.dim('Create endpoints in the MetaMCP dashboard first.\\n'));\n return;\n }\n\n console.log(chalk.bold(`\\n📡 Endpoints (${endpoints.length})\\n`));\n\n const nameWidth = 20;\n const nsWidth = 20;\n\n console.log(\n chalk.bold(\n 'Name'.padEnd(nameWidth) +\n 'Namespace'.padEnd(nsWidth) +\n 'URL'\n )\n );\n console.log('─'.repeat(80));\n\n for (const ep of endpoints) {\n console.log(\n ep.name.padEnd(nameWidth) +\n (ep.namespace ?? '-').padEnd(nsWidth) +\n chalk.dim(ep.endpoints.mcp)\n );\n }\n console.log();\n } catch (err) {\n spinner.fail(\n `Failed to fetch endpoints: ${err instanceof Error ? err.message : String(err)}`\n );\n process.exit(1);\n }\n}\n","import { MetaMCPClient } from './metamcp.js';\nimport { type MetaMCPConfig } from '../config/store.js';\n\nexport function clientFromConfig(config: MetaMCPConfig): MetaMCPClient {\n return new MetaMCPClient(\n config.instance.url,\n config.instance.apiKey,\n config.instance.sessionCookie,\n config.instance.proxyHeaders,\n );\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { getConfigOrThrow } from '../config/store.js';\nimport { clientFromConfig } from '../api/client-from-config.js';\n\nexport async function namespacesCommand(): Promise<void> {\n const config = getConfigOrThrow();\n const client = clientFromConfig(config);\n\n const spinner = ora('Fetching namespaces...').start();\n\n try {\n const namespaces = await client.listNamespaces();\n spinner.stop();\n\n if (namespaces.length === 0) {\n console.log(chalk.yellow('\\nNo namespaces found.'));\n return;\n }\n\n console.log(chalk.bold(`\\n📦 Namespaces (${namespaces.length})\\n`));\n\n const nameWidth = 24;\n const scopeWidth = 12;\n\n console.log(\n chalk.bold(\n 'Name'.padEnd(nameWidth) +\n 'Scope'.padEnd(scopeWidth) +\n 'Description'\n )\n );\n console.log('─'.repeat(70));\n\n for (const ns of namespaces) {\n console.log(\n ns.name.padEnd(nameWidth) +\n (ns.isPublic ? 'public' : 'private').padEnd(scopeWidth) +\n chalk.dim(ns.description ?? '-')\n );\n }\n console.log();\n } catch (err) {\n spinner.fail(\n `Failed to fetch namespaces: ${err instanceof Error ? err.message : String(err)}`\n );\n process.exit(1);\n }\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { confirm, checkbox } from '@inquirer/prompts';\nimport { getConfigOrThrow, saveConfig } from '../config/store.js';\nimport { clientFromConfig } from '../api/client-from-config.js';\nimport {\n detectClients,\n getClientBySlug,\n type EndpointConfig,\n type MCPClient,\n} from '../clients/detector.js';\n\nexport async function useCommand(\n endpointName: string,\n options: { client?: string; force?: boolean }\n): Promise<void> {\n const config = getConfigOrThrow();\n const apiClient = clientFromConfig(config);\n\n // Validate endpoint exists\n const spinner = ora('Validating endpoint...').start();\n let endpoints;\n try {\n endpoints = await apiClient.listPublicEndpoints();\n } catch (err) {\n spinner.fail(\n `Failed to fetch endpoints: ${err instanceof Error ? err.message : String(err)}`\n );\n process.exit(1);\n }\n\n const endpoint = endpoints.find((e) => e.name === endpointName);\n if (!endpoint) {\n spinner.fail(`Endpoint \"${endpointName}\" not found.`);\n console.log(\n chalk.dim(\n 'Available endpoints: ' + endpoints.map((e) => e.name).join(', ')\n )\n );\n process.exit(1);\n }\n spinner.succeed(`Endpoint \"${endpointName}\" found`);\n\n // Determine which clients to configure\n let targets: MCPClient[];\n\n if (options.client) {\n const c = getClientBySlug(options.client);\n if (!c) {\n console.log(\n chalk.red(`Unknown client \"${options.client}\".`) +\n chalk.dim(\n ' Available: claude-desktop, cursor, windsurf, cline, claude-code'\n )\n );\n process.exit(1);\n }\n if (!c.isInstalled()) {\n console.log(chalk.red(`${c.name} is not installed or detected on this system.`));\n process.exit(1);\n }\n targets = [c];\n } else {\n const detected = detectClients();\n if (detected.length === 0) {\n console.log(chalk.yellow('No MCP clients detected. Run `metamcp-cli scan` to check.'));\n process.exit(1);\n }\n\n const selected = await checkbox({\n message: 'Select clients to configure:',\n choices: detected.map((c) => ({\n name: `${c.name}${c.hasMetaMCPEntry() ? chalk.dim(' (already configured)') : ''}`,\n value: c.slug,\n checked: true,\n })),\n });\n\n if (selected.length === 0) {\n console.log(chalk.yellow('No clients selected.'));\n return;\n }\n\n targets = selected\n .map((slug) => getClientBySlug(slug))\n .filter((c): c is MCPClient => c !== undefined);\n }\n\n const endpointConfig: EndpointConfig = {\n baseUrl: config.instance.url,\n endpointName,\n apiKey: config.instance.apiKey,\n };\n\n // Configure each client\n for (const client of targets) {\n const hasExisting = client.hasMetaMCPEntry();\n\n if (hasExisting && !options.force) {\n const overwrite = await confirm({\n message: `${client.name} already has a MetaMCP config. Overwrite?`,\n default: true,\n });\n if (!overwrite) {\n console.log(chalk.dim(` Skipped ${client.name}`));\n continue;\n }\n }\n\n try {\n const s = ora(`Configuring ${client.name}...`).start();\n client.writeMetaMCPEntry(endpointConfig);\n s.succeed(`${client.name} configured`);\n } catch (err) {\n console.log(\n chalk.red(\n ` Failed to configure ${client.name}: ${err instanceof Error ? err.message : String(err)}`\n )\n );\n }\n }\n\n // Update active endpoint in config\n config.activeEndpoint = endpointName;\n saveConfig(config);\n\n console.log(chalk.green(`\\n✓ Active endpoint set to \"${endpointName}\"`));\n console.log(chalk.dim('Restart your IDE(s) for the changes to take effect.\\n'));\n}\n","import chalk from 'chalk';\nimport ora from 'ora';\nimport { loadConfig } from '../config/store.js';\nimport { clientFromConfig } from '../api/client-from-config.js';\nimport { ALL_CLIENTS } from '../clients/detector.js';\n\nexport async function statusCommand(): Promise<void> {\n const config = loadConfig();\n\n if (!config) {\n console.log(chalk.yellow('\\nMetaMCP CLI is not initialized.'));\n console.log(chalk.dim('Run `metamcp-cli init` to get started.\\n'));\n return;\n }\n\n console.log(chalk.bold('\\n📊 MetaMCP CLI Status\\n'));\n\n // Instance info\n console.log(chalk.bold('Instance'));\n console.log(` URL: ${config.instance.url}`);\n console.log(\n ` Auth: ${config.instance.apiKey ? 'API Key' : config.instance.sessionCookie ? 'Session' : chalk.yellow('Not configured')}`\n );\n\n // Health check\n const spinner = ora(' Checking connection...').start();\n const client = clientFromConfig(config);\n const healthy = await client.healthCheck();\n if (healthy) {\n spinner.succeed(' Connection: OK');\n } else {\n spinner.fail(' Connection: Failed');\n }\n\n // Active endpoint\n console.log(\n `\\n${chalk.bold('Active Endpoint')}: ${config.activeEndpoint ?? chalk.dim('none')}`\n );\n\n // Clients\n console.log(chalk.bold('\\nClients'));\n for (const c of ALL_CLIENTS) {\n const installed = c.isInstalled();\n const configured = installed && c.hasMetaMCPEntry();\n const statusStr = !installed\n ? chalk.dim('not found')\n : configured\n ? chalk.green('configured')\n : chalk.yellow('detected');\n console.log(` ${c.name.padEnd(16)} ${statusStr}`);\n }\n\n console.log();\n}\n","import { input, select, password, checkbox, confirm } from '@inquirer/prompts';\nimport chalk from 'chalk';\nimport ora from 'ora';\nimport { MetaMCPClient } from '../api/metamcp.js';\nimport { loadConfig, saveConfig, type MetaMCPConfig } from '../config/store.js';\nimport { clientFromConfig } from '../api/client-from-config.js';\nimport {\n detectClients,\n getClientBySlug,\n type EndpointConfig,\n type MCPClient,\n} from '../clients/detector.js';\n\nexport async function setupCommand(options: { insecure?: boolean }): Promise<void> {\n console.log(chalk.bold('\\n⚡ MetaMCP Quick Setup\\n'));\n\n if (options.insecure) {\n process.env['NODE_TLS_REJECT_UNAUTHORIZED'] = '0';\n }\n\n // Step 1: Get or create config\n let config = loadConfig();\n let apiClient: MetaMCPClient;\n\n if (config) {\n console.log(chalk.dim(`Using existing config: ${config.instance.url}`));\n apiClient = clientFromConfig(config);\n\n const healthy = await apiClient.healthCheck();\n if (!healthy) {\n console.log(chalk.yellow('Cannot connect to saved instance. Let\\'s reconfigure.\\n'));\n config = null;\n }\n }\n\n if (!config) {\n const url = await input({\n message: 'MetaMCP instance URL:',\n default: 'http://localhost:12008',\n validate: (val) => {\n try { new URL(val); return true; } catch { return 'Please enter a valid URL'; }\n },\n });\n\n const baseUrl = url.replace(/\\/+$/, '');\n\n const apiKey = await password({\n message: 'API Key:',\n mask: '*',\n });\n\n const spinner = ora('Connecting...').start();\n apiClient = new MetaMCPClient(baseUrl, apiKey);\n const healthy = await apiClient.healthCheck();\n\n if (!healthy) {\n spinner.fail('Could not connect. Check URL and API key.');\n process.exit(1);\n }\n spinner.succeed('Connected to MetaMCP');\n\n config = {\n version: 1,\n instance: { url: baseUrl, apiKey },\n };\n saveConfig(config);\n }\n\n // Step 2: Fetch and select endpoint\n const spinner = ora('Fetching endpoints...').start();\n let endpoints;\n try {\n endpoints = await apiClient!.listPublicEndpoints();\n } catch (err) {\n spinner.fail(`Failed to fetch endpoints: ${err instanceof Error ? err.message : String(err)}`);\n process.exit(1);\n }\n spinner.stop();\n\n if (endpoints.length === 0) {\n console.log(chalk.yellow('\\nNo endpoints found. Create one in the MetaMCP dashboard first.\\n'));\n process.exit(1);\n }\n\n const selectedEndpoint = await select({\n message: 'Select endpoint to use:',\n choices: endpoints.map((ep) => ({\n name: `${ep.name}${ep.namespace ? chalk.dim(` (${ep.namespace})`) : ''}${ep.description ? chalk.dim(` — ${ep.description}`) : ''}`,\n value: ep.name,\n })),\n });\n\n // Step 3: Detect and select clients\n const detected = detectClients();\n\n if (detected.length === 0) {\n console.log(chalk.yellow('\\nNo MCP clients detected on this system.'));\n console.log(chalk.dim('Supported: Claude Desktop, Cursor, Windsurf, Cline, Claude Code\\n'));\n // Still save the endpoint selection\n config.activeEndpoint = selectedEndpoint;\n saveConfig(config);\n process.exit(1);\n }\n\n const selectedClients = await checkbox({\n message: 'Select clients to configure:',\n choices: detected.map((c) => ({\n name: `${c.name}${c.hasMetaMCPEntry() ? chalk.dim(' (already configured)') : ''}`,\n value: c.slug,\n checked: true,\n })),\n });\n\n if (selectedClients.length === 0) {\n console.log(chalk.yellow('No clients selected.'));\n config.activeEndpoint = selectedEndpoint;\n saveConfig(config);\n return;\n }\n\n const targets = selectedClients\n .map((slug) => getClientBySlug(slug))\n .filter((c): c is MCPClient => c !== undefined);\n\n // Step 4: Configure clients\n const endpointConfig: EndpointConfig = {\n baseUrl: config.instance.url,\n endpointName: selectedEndpoint,\n apiKey: config.instance.apiKey,\n };\n\n console.log();\n for (const client of targets) {\n const hasExisting = client.hasMetaMCPEntry();\n\n if (hasExisting) {\n const overwrite = await confirm({\n message: `${client.name} already configured. Overwrite?`,\n default: true,\n });\n if (!overwrite) {\n console.log(chalk.dim(` Skipped ${client.name}`));\n continue;\n }\n }\n\n try {\n const s = ora(`Configuring ${client.name}...`).start();\n client.writeMetaMCPEntry(endpointConfig);\n s.succeed(`${client.name} configured`);\n } catch (err) {\n console.log(\n chalk.red(` Failed: ${client.name} — ${err instanceof Error ? err.message : String(err)}`)\n );\n }\n }\n\n // Step 5: Save and show summary\n config.activeEndpoint = selectedEndpoint;\n saveConfig(config);\n\n console.log(chalk.green(`\\n✓ Setup complete!`));\n console.log(chalk.dim(` Instance: ${config.instance.url}`));\n console.log(chalk.dim(` Endpoint: ${selectedEndpoint}`));\n console.log(chalk.dim(` Clients: ${targets.map((c) => c.name).join(', ')}`));\n console.log(chalk.dim('\\nRestart your IDE(s) for changes to take effect.\\n'));\n}\n"],"mappings":"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","names":["chalk","password","spinner","client","chalk","fs","path","os","chalk","chalk","ora","ora","chalk","chalk","ora","ora","chalk","chalk","ora","ora","chalk","chalk","ora","chalk","ora","input","select","password","checkbox","confirm","chalk","ora","chalk","input","password","spinner","ora","select","checkbox","confirm","chalk"]}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "metamcp-cli",
3
+ "version": "0.1.0",
4
+ "description": "CLI wrapper for MetaMCP — auto-configure MCP clients from your MetaMCP instance",
5
+ "type": "module",
6
+ "bin": {
7
+ "metamcp-cli": "./dist/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsup",
11
+ "dev": "tsup --watch",
12
+ "typecheck": "tsc --noEmit"
13
+ },
14
+ "engines": {
15
+ "node": ">=18.0.0"
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "keywords": [
21
+ "mcp",
22
+ "metamcp",
23
+ "cli",
24
+ "model-context-protocol"
25
+ ],
26
+ "license": "MIT",
27
+ "dependencies": {
28
+ "@inquirer/prompts": "^7.5.0",
29
+ "chalk": "^5.4.1",
30
+ "commander": "^13.1.0",
31
+ "ora": "^8.2.0"
32
+ },
33
+ "devDependencies": {
34
+ "@types/node": "^22.15.3",
35
+ "tsup": "^8.4.0",
36
+ "typescript": "^5.8.3"
37
+ }
38
+ }