@thingd/cli 0.43.0 → 0.44.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.
@@ -0,0 +1,3 @@
1
+ import type { CliContext } from "../index.js";
2
+ export declare function runMcpConnect(context: CliContext): Promise<void>;
3
+ //# sourceMappingURL=mcp-connect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-connect.d.ts","sourceRoot":"","sources":["../../src/commands/mcp-connect.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAsB9C,wBAAsB,aAAa,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAwKtE"}
@@ -0,0 +1,154 @@
1
+ import { createInterface } from "node:readline/promises";
2
+ import pc from "picocolors";
3
+ import { listInstances, listProjects } from "../lib/cloud-api.js";
4
+ import { readCloudConfig } from "../lib/cloud-config.js";
5
+ import { printMcpConfigJson, updateAntigravityConfig, updateClaudeDesktopConfig, } from "../lib/mcp-config-writer.js";
6
+ async function askQuestion(query) {
7
+ const rl = createInterface({
8
+ input: process.stdin,
9
+ output: process.stderr,
10
+ });
11
+ try {
12
+ return await rl.question(query);
13
+ }
14
+ finally {
15
+ rl.close();
16
+ }
17
+ }
18
+ export async function runMcpConnect(context) {
19
+ const config = readCloudConfig();
20
+ if (!config?.token || !config.url) {
21
+ context.stderr.write(`${pc.red("Not logged in.")} Run ${pc.cyan("thingd cloud login")} first.\n`);
22
+ return;
23
+ }
24
+ // ── Fetch projects ────────────────────────────────────────────────
25
+ let projects;
26
+ try {
27
+ const result = await listProjects(config);
28
+ projects = result.projects;
29
+ }
30
+ catch (err) {
31
+ context.stderr.write(pc.red(`Failed to fetch projects: ${err}\n`));
32
+ return;
33
+ }
34
+ if (projects.length === 0) {
35
+ context.stderr.write(`${pc.red("No projects found.")} Create one with ${pc.cyan("thingd cloud project create <name>")}.\n`);
36
+ return;
37
+ }
38
+ context.stderr.write(`\n${pc.bold("Select a project")}\n`);
39
+ for (let i = 0; i < projects.length; i++) {
40
+ const p = projects[i];
41
+ if (p) {
42
+ context.stderr.write(` [${i + 1}] ${pc.cyan(p.slug)} ${p.name}\n`);
43
+ }
44
+ }
45
+ const projectChoice = await askQuestion(`Select project [1-${projects.length}] (default 1): `);
46
+ const projectIndex = Math.max(0, Math.min(projects.length - 1, (Number(projectChoice.trim()) || 1) - 1));
47
+ const selectedProject = projects[projectIndex];
48
+ if (!selectedProject) {
49
+ return;
50
+ }
51
+ context.stderr.write("\n");
52
+ // ── Fetch instances ───────────────────────────────────────────────
53
+ let instances;
54
+ try {
55
+ const result = await listInstances(config, selectedProject.id);
56
+ instances = result.instances;
57
+ }
58
+ catch (err) {
59
+ context.stderr.write(pc.red(`Failed to fetch instances: ${err}\n`));
60
+ return;
61
+ }
62
+ if (instances.length === 0) {
63
+ context.stderr.write(`${pc.red("No instances found for project.")} Create one with ${pc.cyan(`thingd cloud instance create ${selectedProject.slug} <name>`)}.\n`);
64
+ return;
65
+ }
66
+ context.stderr.write(`${pc.bold("Select an instance")}\n`);
67
+ for (let i = 0; i < instances.length; i++) {
68
+ const inst = instances[i];
69
+ if (inst) {
70
+ context.stderr.write(` [${i + 1}] ${pc.cyan(inst.slug)} ${inst.name} ${pc.dim(inst.mcpUrl || "no URL")}\n`);
71
+ }
72
+ }
73
+ const instanceChoice = await askQuestion(`Select instance [1-${instances.length}] (default 1): `);
74
+ const instanceIndex = Math.max(0, Math.min(instances.length - 1, (Number(instanceChoice.trim()) || 1) - 1));
75
+ const selectedInstance = instances[instanceIndex];
76
+ if (!selectedInstance) {
77
+ return;
78
+ }
79
+ context.stderr.write("\n");
80
+ // ── Pre-fill URL and token ────────────────────────────────────────
81
+ let mcpUrl = selectedInstance.mcpUrl || `${config.url}/mcp/${selectedProject.slug}/${selectedInstance.slug}`;
82
+ let authToken = config.token;
83
+ context.stderr.write(`${pc.bold("MCP Connection Details")}\n`);
84
+ const urlAnswer = await askQuestion(`MCP URL (default ${pc.cyan(mcpUrl)}): `);
85
+ if (urlAnswer.trim()) {
86
+ mcpUrl = urlAnswer.trim();
87
+ }
88
+ const tokenAnswer = await askQuestion(`Auth Token (default ${pc.cyan(`${authToken.slice(0, 8)}...`)}): `);
89
+ if (tokenAnswer.trim()) {
90
+ authToken = tokenAnswer.trim();
91
+ }
92
+ context.stderr.write("\n");
93
+ // ── Build config ──────────────────────────────────────────────────
94
+ const mcpConfig = {
95
+ url: mcpUrl,
96
+ headers: {
97
+ Authorization: `Bearer ${authToken}`,
98
+ },
99
+ };
100
+ // ── Preview ───────────────────────────────────────────────────────
101
+ context.stderr.write(`${pc.bold("Generated Config:")}\n`);
102
+ context.stderr.write(` ${pc.dim(printMcpConfigJson(mcpConfig).replace(/\n/g, "\n "))}\n\n`);
103
+ // ── Where to install ──────────────────────────────────────────────
104
+ context.stderr.write(`${pc.bold("Where would you like to write the MCP configuration?")}\n`);
105
+ context.stderr.write(` [1] Claude Desktop & Antigravity (Default)\n`);
106
+ context.stderr.write(` [2] Claude Desktop only\n`);
107
+ context.stderr.write(` [3] Antigravity only\n`);
108
+ context.stderr.write(` [4] Print raw JSON only\n`);
109
+ context.stderr.write(` [5] Print Cursor-compatible JSON\n\n`);
110
+ const choice = (await askQuestion("Select option [1-5] (default 1): ")).trim() || "1";
111
+ const showClaude = choice === "1" || choice === "2";
112
+ const showAntigravity = choice === "1" || choice === "3";
113
+ const showRaw = choice === "4";
114
+ const showCursor = choice === "5";
115
+ if (showClaude) {
116
+ const result = updateClaudeDesktopConfig(mcpConfig);
117
+ if (result.updated) {
118
+ context.stderr.write(` ${pc.bold("Claude Desktop:")}\n`);
119
+ context.stderr.write(` ${pc.green("✓")} Updated ${pc.cyan(result.path)}\n\n`);
120
+ }
121
+ else if (result.skipped) {
122
+ context.stderr.write(` ${pc.bold("Claude Desktop:")}\n`);
123
+ context.stderr.write(` ${pc.yellow("⊘")} Skipped: ${result.reason}\n\n`);
124
+ }
125
+ }
126
+ if (showAntigravity) {
127
+ const result = updateAntigravityConfig(mcpConfig);
128
+ if (result.updated) {
129
+ context.stderr.write(` ${pc.bold("Antigravity IDE:")}\n`);
130
+ context.stderr.write(` ${pc.green("✓")} Updated ${pc.cyan(result.path)}\n\n`);
131
+ }
132
+ else if (result.skipped) {
133
+ context.stderr.write(` ${pc.bold("Antigravity IDE:")}\n`);
134
+ context.stderr.write(` ${pc.yellow("⊘")} Skipped: ${result.reason}\n\n`);
135
+ }
136
+ }
137
+ if (showCursor) {
138
+ context.stderr.write(` ${pc.bold("Cursor:")}\n`);
139
+ context.stderr.write(` Paste this into Cursor Settings → Features → MCP → Add New MCP Server:\n\n`);
140
+ context.stdout.write(`${printMcpConfigJson(mcpConfig)}\n`);
141
+ }
142
+ if (showRaw) {
143
+ context.stdout.write(`${printMcpConfigJson(mcpConfig)}\n`);
144
+ }
145
+ if (showClaude) {
146
+ context.stderr.write(`\n Restart Claude Desktop or Antigravity to activate.\n\n`);
147
+ }
148
+ else if (showCursor) {
149
+ context.stderr.write(`\n Cursor activates immediately after pasting.\n\n`);
150
+ }
151
+ else if (showRaw) {
152
+ context.stderr.write("\n");
153
+ }
154
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAQA,OAAO,EASL,MAAM,EACN,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAQrB,KAAK,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAEjD,KAAK,YAAY,GAAG;IAClB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7B,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAsCF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAuEF,wBAAsB,MAAM,CAC1B,IAAI,WAAwB,EAC5B,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,MAAM,CAAC,CA6EjB;AAo0BD,wBAAsB,MAAM,CAC1B,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,CAcf;AA4BD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,GAAG,iBAAiB,CAgCxE;AAiDD,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE/E;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAGlF;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMrE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnF;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMrF;AAyFD,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAEpF;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAElE"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAQA,OAAO,EASL,MAAM,EACN,KAAK,YAAY,EAClB,MAAM,aAAa,CAAC;AAQrB,KAAK,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;AAEjD,KAAK,YAAY,GAAG;IAClB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7B,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,MAAM,EAAE,UAAU,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,YAAY,CAAC;IACrB,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAsCF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;CAChB,CAAC;AAwEF,wBAAsB,MAAM,CAC1B,IAAI,WAAwB,EAC5B,OAAO,GAAE,aAAkB,GAC1B,OAAO,CAAC,MAAM,CAAC,CA6EjB;AAo0BD,wBAAsB,MAAM,CAC1B,OAAO,EAAE,UAAU,EACnB,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GACtC,OAAO,CAAC,IAAI,CAAC,CAcf;AA4BD,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,GAAG,iBAAiB,CAgCxE;AAiDD,wBAAgB,OAAO,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjE;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE/E;AAED,wBAAgB,WAAW,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAGlF;AAED,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMrE;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnF;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAMrF;AAyFD,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAEpF;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAElE"}
package/dist/index.js CHANGED
@@ -45,6 +45,7 @@ Usage:
45
45
  thingd install [--raw] [--claude] [--cursor] [--antigravity]
46
46
  thingd doctor
47
47
  thingd mcp [--path <path>] [--driver <driver>]
48
+ thingd mcp connect
48
49
  thingd mcp-http [--path <path>] [--driver <driver>] [--host <host>] [--port <port>] [--auth-token <tok>] [--allow-unauthenticated]
49
50
  thingd search <query> [--collection <name>] [--limit <n>] [--filter <json>]
50
51
  thingd objects list <collection> [--limit <n>] [--offset <n>] [--sort-by <field>] [--sort-dir <asc|desc>] [--filter <json>]
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAwB7C,wBAAsB,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAoKnE"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAqB7C,wBAAsB,UAAU,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAwJnE"}
package/dist/install.js CHANGED
@@ -1,10 +1,10 @@
1
- import { existsSync, readFileSync, realpathSync, writeFileSync } from "node:fs";
2
- import { homedir, platform } from "node:os";
1
+ import { existsSync, realpathSync } from "node:fs";
3
2
  import { dirname, join, resolve } from "node:path";
4
3
  import { createInterface } from "node:readline/promises";
5
4
  import { fileURLToPath } from "node:url";
6
5
  import { NativeThingStore } from "@thingd/sdk";
7
6
  import pc from "picocolors";
7
+ import { printMcpConfigJson, updateAntigravityConfig, updateClaudeDesktopConfig, } from "./lib/mcp-config-writer.js";
8
8
  import { defaultThingdDbPath, ensureThingdDir } from "./paths.js";
9
9
  async function askQuestion(query) {
10
10
  const rl = createInterface({
@@ -136,20 +136,10 @@ export async function runInstall(context) {
136
136
  if (showCursor) {
137
137
  context.stderr.write(` ${pc.bold("Cursor:")}\n`);
138
138
  context.stderr.write(` Paste this into Cursor Settings → Features → MCP → Add New MCP Server:\n\n`);
139
- const fullConfig = {
140
- mcpServers: {
141
- thingd: config,
142
- },
143
- };
144
- context.stdout.write(`${JSON.stringify(fullConfig, null, 2)}\n`);
139
+ context.stdout.write(`${printMcpConfigJson(config)}\n`);
145
140
  }
146
141
  if (showRaw) {
147
- const fullConfig = {
148
- mcpServers: {
149
- thingd: config,
150
- },
151
- };
152
- context.stdout.write(`${JSON.stringify(fullConfig, null, 2)}\n`);
142
+ context.stdout.write(`${printMcpConfigJson(config)}\n`);
153
143
  }
154
144
  if (choice === "1") {
155
145
  context.stderr.write(`\n Restart Claude Desktop or Antigravity to activate. Cursor activates immediately.\n\n`);
@@ -237,75 +227,3 @@ function generateMcpConfig(nodePath, cliPath, dbPath, driver) {
237
227
  args: [cliPath, "mcp", "--path", dbPath, "--driver", driver],
238
228
  };
239
229
  }
240
- function updateClaudeDesktopConfig(config) {
241
- if (platform() !== "darwin") {
242
- return { skipped: true, reason: "Claude Desktop auto-config is only supported on macOS." };
243
- }
244
- const configPath = join(homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
245
- if (!existsSync(configPath)) {
246
- return {
247
- skipped: true,
248
- reason: `Config file not found at ${configPath}. Is Claude Desktop installed?`,
249
- };
250
- }
251
- try {
252
- const raw = readFileSync(configPath, "utf-8");
253
- const existing = JSON.parse(raw);
254
- const mcpServers = (existing.mcpServers ?? {});
255
- mcpServers.thingd = config;
256
- existing.mcpServers = mcpServers;
257
- writeFileSync(configPath, `${JSON.stringify(existing, null, 2)}\n`, "utf-8");
258
- return { updated: true, path: configPath };
259
- }
260
- catch (error) {
261
- return {
262
- skipped: true,
263
- reason: `Failed to update config: ${error instanceof Error ? error.message : String(error)}`,
264
- };
265
- }
266
- }
267
- function updateAntigravityConfig(config) {
268
- const candidates = [
269
- join(homedir(), ".gemini", "config", "mcp_config.json"),
270
- join(homedir(), ".gemini", "antigravity-ide", "mcp_config.json"),
271
- ];
272
- let updatedAny = false;
273
- const pathsUpdated = [];
274
- let lastError = null;
275
- for (const configPath of candidates) {
276
- const dir = dirname(configPath);
277
- if (existsSync(dir)) {
278
- try {
279
- let existing = {};
280
- if (existsSync(configPath)) {
281
- const raw = readFileSync(configPath, "utf-8").trim();
282
- if (raw) {
283
- existing = JSON.parse(raw);
284
- }
285
- }
286
- const mcpServers = (existing.mcpServers ?? {});
287
- mcpServers.thingd = config;
288
- existing.mcpServers = mcpServers;
289
- writeFileSync(configPath, `${JSON.stringify(existing, null, 2)}\n`, "utf-8");
290
- updatedAny = true;
291
- pathsUpdated.push(configPath);
292
- }
293
- catch (error) {
294
- lastError = error instanceof Error ? error : new Error(String(error));
295
- }
296
- }
297
- }
298
- if (updatedAny) {
299
- return { updated: true, path: pathsUpdated.join(" & ") };
300
- }
301
- if (lastError) {
302
- return {
303
- skipped: true,
304
- reason: `Failed to update config: ${lastError.message}`,
305
- };
306
- }
307
- return {
308
- skipped: true,
309
- reason: `Antigravity directory not found in ${candidates.map((c) => dirname(c)).join(" or ")}.`,
310
- };
311
- }
@@ -0,0 +1,26 @@
1
+ export type McpServerConfig = {
2
+ command: string;
3
+ args: string[];
4
+ } | {
5
+ url: string;
6
+ headers?: Record<string, string>;
7
+ };
8
+ export type McpServersBlock = {
9
+ mcpServers: Record<string, McpServerConfig>;
10
+ };
11
+ export declare function printMcpConfigJson(config: McpServerConfig): string;
12
+ export type ClaudeUpdateResult = {
13
+ updated: true;
14
+ path: string;
15
+ skipped?: undefined;
16
+ reason?: undefined;
17
+ } | {
18
+ updated?: undefined;
19
+ skipped: true;
20
+ reason: string;
21
+ path?: undefined;
22
+ };
23
+ export declare function getClaudeConfigPath(): string;
24
+ export declare function updateClaudeDesktopConfig(config: McpServerConfig): ClaudeUpdateResult;
25
+ export declare function updateAntigravityConfig(config: McpServerConfig): ClaudeUpdateResult;
26
+ //# sourceMappingURL=mcp-config-writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-config-writer.d.ts","sourceRoot":"","sources":["../../src/lib/mcp-config-writer.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,eAAe,GACvB;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,EAAE,CAAA;CAAE,GACnC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAC;AAEtD,MAAM,MAAM,eAAe,GAAG;IAC5B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CAC7C,CAAC;AAEF,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,eAAe,GAAG,MAAM,CAOlE;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,OAAO,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,SAAS,CAAC;IAAC,MAAM,CAAC,EAAE,SAAS,CAAA;CAAE,GACxE;IAAE,OAAO,CAAC,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,SAAS,CAAA;CAAE,CAAC;AAE7E,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,eAAe,GAAG,kBAAkB,CA+BrF;AAED,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,eAAe,GAAG,kBAAkB,CAkDnF"}
@@ -0,0 +1,86 @@
1
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
+ import { homedir, platform } from "node:os";
3
+ import { dirname, join } from "node:path";
4
+ export function printMcpConfigJson(config) {
5
+ const full = {
6
+ mcpServers: {
7
+ thingd: config,
8
+ },
9
+ };
10
+ return JSON.stringify(full, null, 2);
11
+ }
12
+ export function getClaudeConfigPath() {
13
+ return join(homedir(), "Library", "Application Support", "Claude", "claude_desktop_config.json");
14
+ }
15
+ export function updateClaudeDesktopConfig(config) {
16
+ if (platform() !== "darwin") {
17
+ return { skipped: true, reason: "Claude Desktop auto-config is only supported on macOS." };
18
+ }
19
+ const configPath = getClaudeConfigPath();
20
+ if (!existsSync(configPath)) {
21
+ return {
22
+ skipped: true,
23
+ reason: `Config file not found at ${configPath}. Is Claude Desktop installed?`,
24
+ };
25
+ }
26
+ try {
27
+ const raw = readFileSync(configPath, "utf-8");
28
+ const existing = JSON.parse(raw);
29
+ const mcpServers = (existing.mcpServers ?? {});
30
+ mcpServers.thingd = config;
31
+ existing.mcpServers = mcpServers;
32
+ writeFileSync(configPath, `${JSON.stringify(existing, null, 2)}\n`, "utf-8");
33
+ return { updated: true, path: configPath };
34
+ }
35
+ catch (error) {
36
+ return {
37
+ skipped: true,
38
+ reason: `Failed to update config: ${error instanceof Error ? error.message : String(error)}`,
39
+ };
40
+ }
41
+ }
42
+ export function updateAntigravityConfig(config) {
43
+ const candidates = [
44
+ join(homedir(), ".gemini", "config", "mcp_config.json"),
45
+ join(homedir(), ".gemini", "antigravity-ide", "mcp_config.json"),
46
+ ];
47
+ let updatedAny = false;
48
+ const pathsUpdated = [];
49
+ let lastError = null;
50
+ for (const configPath of candidates) {
51
+ const dir = dirname(configPath);
52
+ if (existsSync(dir)) {
53
+ try {
54
+ let existing = {};
55
+ if (existsSync(configPath)) {
56
+ const raw = readFileSync(configPath, "utf-8").trim();
57
+ if (raw) {
58
+ existing = JSON.parse(raw);
59
+ }
60
+ }
61
+ const mcpServers = (existing.mcpServers ?? {});
62
+ mcpServers.thingd = config;
63
+ existing.mcpServers = mcpServers;
64
+ writeFileSync(configPath, `${JSON.stringify(existing, null, 2)}\n`, "utf-8");
65
+ updatedAny = true;
66
+ pathsUpdated.push(configPath);
67
+ }
68
+ catch (error) {
69
+ lastError = error instanceof Error ? error : new Error(String(error));
70
+ }
71
+ }
72
+ }
73
+ if (updatedAny) {
74
+ return { updated: true, path: pathsUpdated.join(" & ") };
75
+ }
76
+ if (lastError) {
77
+ return {
78
+ skipped: true,
79
+ reason: `Failed to update config: ${lastError.message}`,
80
+ };
81
+ }
82
+ return {
83
+ skipped: true,
84
+ reason: `Antigravity directory not found in ${candidates.map((c) => dirname(c)).join(" or ")}.`,
85
+ };
86
+ }
package/dist/mcp.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,UAAU,EAA6B,MAAM,YAAY,CAAC;AAGxE,wBAAsB,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAoB/D"}
1
+ {"version":3,"file":"mcp.d.ts","sourceRoot":"","sources":["../src/mcp.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,UAAU,EAA6B,MAAM,YAAY,CAAC;AAGxE,wBAAsB,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA2B/D"}
package/dist/mcp.js CHANGED
@@ -3,6 +3,12 @@ import { createThingdMcpServer, readMcpHardeningOptionsFromEnv } from "@thingd/s
3
3
  import { resolveConnection, withDb } from "./index.js";
4
4
  import { readMcpAuditOptionsFromEnv } from "./mcp/config.js";
5
5
  export async function runMcp(context) {
6
+ const sub = context.parsed.tokens[1];
7
+ if (sub === "connect") {
8
+ const { runMcpConnect } = await import("./commands/mcp-connect.js");
9
+ await runMcpConnect(context);
10
+ return;
11
+ }
6
12
  const connection = resolveConnection(context);
7
13
  await withDb(context, async (db) => {
8
14
  const server = createThingdMcpServer(db, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thingd/cli",
3
- "version": "0.43.0",
3
+ "version": "0.44.1",
4
4
  "description": "CLI, Interactive TUI Dashboard, and MCP server for thingd — a fast object-first data engine for applications and AI agents.",
5
5
  "type": "module",
6
6
  "homepage": "https://engine.thingd.cloud",
@@ -45,7 +45,7 @@
45
45
  "cli-table3": "^0.6.5",
46
46
  "picocolors": "^1.1.1",
47
47
  "zod": "^4.4.3",
48
- "@thingd/sdk": "0.43.0"
48
+ "@thingd/sdk": "0.44.1"
49
49
  },
50
50
  "engines": {
51
51
  "node": ">=24.0.0"