@tangle-network/tcloud 0.4.13 → 0.5.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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  TCloudClient
3
- } from "./chunk-U4VOGRVW.js";
3
+ } from "./chunk-H3K3A3EI.js";
4
4
 
5
5
  // src/shielded.ts
6
6
  import { privateKeyToAccount } from "viem/accounts";
@@ -1,3 +1,7 @@
1
+ import {
2
+ packageVersion
3
+ } from "./chunk-YK2SGW76.js";
4
+
1
5
  // src/private-router.ts
2
6
  function secureRandom() {
3
7
  const arr = new Uint32Array(1);
@@ -222,44 +226,31 @@ var PrivateRouter = class {
222
226
  var ROTATING_MARKER = "__tcloudRotating";
223
227
  var DIRECT_CLI_BRIDGE_MARKER = "__tcloudDirectCliBridge";
224
228
  var DEFAULT_BASE_URL = "https://router.tangle.tools/v1";
225
- var SDK_VERSION = "0.4.0";
226
229
  async function proxiedFetch(privacy, url, init, streaming) {
227
230
  if (!privacy || privacy.mode === "direct") {
228
231
  return fetch(url, init);
229
232
  }
230
- if (privacy.mode === "relayer") {
231
- if (!privacy.relayerUrl) {
232
- throw new Error('relayerUrl is required when privacy mode is "relayer"');
233
- }
234
- const proxyPath = streaming ? "/relay/proxy-stream" : "/relay/proxy";
235
- const hdrs = {};
236
- if (init.headers) {
237
- const entries = init.headers instanceof Headers ? Array.from(init.headers.entries()) : Object.entries(init.headers);
238
- for (const [k, v] of entries) hdrs[k] = v;
239
- }
240
- return fetch(`${privacy.relayerUrl}${proxyPath}`, {
241
- method: "POST",
242
- headers: { "Content-Type": "application/json" },
243
- body: JSON.stringify({
244
- target: url,
245
- body: typeof init.body === "string" ? JSON.parse(init.body) : init.body,
246
- headers: hdrs
247
- })
248
- });
249
- }
250
- if (privacy.mode === "socks5") {
251
- if (!privacy.socksProxy) {
252
- throw new Error('socksProxy is required when privacy mode is "socks5"');
253
- }
254
- const { SocksProxyAgent } = await import("socks-proxy-agent");
255
- const agent = new SocksProxyAgent(privacy.socksProxy);
256
- return fetch(url, {
257
- ...init,
258
- // @ts-expect-error agent is supported by Node's undici but not in the standard RequestInit type
259
- agent
260
- });
261
- }
262
- return fetch(url, init);
233
+ if (privacy.mode !== "relayer") {
234
+ throw new Error(`Unsupported privacy mode: ${String(privacy.mode)}`);
235
+ }
236
+ if (!privacy.relayerUrl) {
237
+ throw new Error('relayerUrl is required when privacy mode is "relayer"');
238
+ }
239
+ const proxyPath = streaming ? "/relay/proxy-stream" : "/relay/proxy";
240
+ const headers = {};
241
+ if (init.headers) {
242
+ const entries = init.headers instanceof Headers ? Array.from(init.headers.entries()) : Object.entries(init.headers);
243
+ for (const [key, value] of entries) headers[key] = value;
244
+ }
245
+ return fetch(`${privacy.relayerUrl}${proxyPath}`, {
246
+ method: "POST",
247
+ headers: { "Content-Type": "application/json" },
248
+ body: JSON.stringify({
249
+ target: url,
250
+ body: typeof init.body === "string" ? JSON.parse(init.body) : init.body,
251
+ headers
252
+ })
253
+ });
263
254
  }
264
255
  var DEFAULT_RETRY = {
265
256
  maxRetries: 3,
@@ -424,7 +415,7 @@ var TCloudClient = class _TCloudClient {
424
415
  this.timeoutMs = config.timeout ?? DEFAULT_TIMEOUT_MS;
425
416
  this.headers = {
426
417
  "Content-Type": "application/json",
427
- "X-Tangle-Client": `tcloud-sdk/${SDK_VERSION}`
418
+ "X-Tangle-Client": `tcloud-sdk/${packageVersion()}`
428
419
  };
429
420
  if (this.apiKey) {
430
421
  this.headers["Authorization"] = `Bearer ${this.apiKey}`;
@@ -998,6 +989,26 @@ var TCloudClient = class _TCloudClient {
998
989
  })
999
990
  });
1000
991
  }
992
+ /** Run a multi-step deep-research task through Tangle Router billing and
993
+ * provider routing (POST /v1/research). Slower and costlier than `search` —
994
+ * the provider synthesizes an answer over many fetches. Pick depth with
995
+ * `effort` (provider-specific vocabulary; see {@link ResearchOptions.effort}). */
996
+ async research(options) {
997
+ return this._request(`${this.baseURL}/research`, {
998
+ method: "POST",
999
+ body: JSON.stringify({
1000
+ query: options.query,
1001
+ provider: options.provider,
1002
+ model: options.model,
1003
+ effort: options.effort,
1004
+ maxResults: options.maxResults,
1005
+ searchRecency: options.searchRecency,
1006
+ includeDomains: options.includeDomains,
1007
+ excludeDomains: options.excludeDomains,
1008
+ outputSchema: options.outputSchema
1009
+ })
1010
+ });
1011
+ }
1001
1012
  /** Text-to-speech */
1002
1013
  async speech(options) {
1003
1014
  const res = await this._requestRaw(`${this.baseURL}/audio/speech`, {
@@ -4,10 +4,10 @@ import {
4
4
  import {
5
5
  createShieldedClient,
6
6
  generateWallet
7
- } from "./chunk-THOMQXU5.js";
7
+ } from "./chunk-GDGQQRE3.js";
8
8
  import {
9
9
  TCloudClient
10
- } from "./chunk-U4VOGRVW.js";
10
+ } from "./chunk-H3K3A3EI.js";
11
11
 
12
12
  // src/index.ts
13
13
  import {
@@ -0,0 +1,11 @@
1
+ // package.json
2
+ var version = "0.5.0";
3
+
4
+ // src/version.ts
5
+ function packageVersion() {
6
+ return version;
7
+ }
8
+
9
+ export {
10
+ packageVersion
11
+ };
package/dist/cli.cjs CHANGED
@@ -6,6 +6,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
12
+ var __export = (target, all) => {
13
+ for (var name in all)
14
+ __defProp(target, name, { get: all[name], enumerable: true });
15
+ };
9
16
  var __copyProps = (to, from, except, desc) => {
10
17
  if (from && typeof from === "object" || typeof from === "function") {
11
18
  for (let key of __getOwnPropNames(from))
@@ -23,6 +30,237 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
23
30
  mod
24
31
  ));
25
32
 
33
+ // package.json
34
+ var version;
35
+ var init_package = __esm({
36
+ "package.json"() {
37
+ version = "0.5.0";
38
+ }
39
+ });
40
+
41
+ // src/version.ts
42
+ function packageVersion() {
43
+ return version;
44
+ }
45
+ var init_version = __esm({
46
+ "src/version.ts"() {
47
+ "use strict";
48
+ init_package();
49
+ }
50
+ });
51
+
52
+ // src/mcp.ts
53
+ var mcp_exports = {};
54
+ __export(mcp_exports, {
55
+ runMcpServer: () => runMcpServer
56
+ });
57
+ function optionalMaxResults(value) {
58
+ if (value == null) return void 0;
59
+ const n = Number(value);
60
+ return Number.isFinite(n) && n >= 0 ? n : void 0;
61
+ }
62
+ function requireEnum(value, allowed, label) {
63
+ if (value == null) return void 0;
64
+ if (typeof value !== "string" || !allowed.has(value)) {
65
+ throw new InvalidParams(`invalid ${label}: ${String(value)}`);
66
+ }
67
+ return value;
68
+ }
69
+ function optionalDomains(value) {
70
+ if (!Array.isArray(value)) return void 0;
71
+ const domains = value.filter((d) => typeof d === "string");
72
+ return domains.length ? domains : void 0;
73
+ }
74
+ async function runMcpServer(client, opts = {}) {
75
+ const input = opts.input ?? process.stdin;
76
+ const output = opts.output ?? process.stdout;
77
+ const rl = readline.createInterface({ input });
78
+ const send = (msg) => {
79
+ output.write(`${JSON.stringify(msg)}
80
+ `);
81
+ };
82
+ const ok = (id, result) => send({ jsonrpc: "2.0", id, result });
83
+ const fail = (id, code, message) => send({ jsonrpc: "2.0", id, error: { code, message } });
84
+ const toolError = (id, message) => ok(id, { content: [{ type: "text", text: message }], isError: true });
85
+ process.stderr.write("tcloud mcp: web_search + deep_research server ready (stdio)\n");
86
+ async function handleRequest(req) {
87
+ const { id, method, params } = req;
88
+ try {
89
+ if (method === "initialize") {
90
+ const requested = params?.protocolVersion ?? DEFAULT_PROTOCOL_VERSION;
91
+ const protocolVersion = SUPPORTED_PROTOCOL_VERSIONS.has(requested) ? requested : DEFAULT_PROTOCOL_VERSION;
92
+ ok(id, {
93
+ protocolVersion,
94
+ capabilities: { tools: {} },
95
+ serverInfo: { name: "tangle-tcloud", version: packageVersion() }
96
+ });
97
+ } else if (method === "tools/list") {
98
+ ok(id, { tools: TOOLS });
99
+ } else if (method === "tools/call") {
100
+ const name = params?.name;
101
+ if (name === "web_search") {
102
+ await handleWebSearch(id, params?.arguments ?? {});
103
+ } else if (name === "deep_research") {
104
+ await handleDeepResearch(id, params?.arguments ?? {});
105
+ } else {
106
+ fail(id, -32602, `unknown tool: ${String(name)}`);
107
+ }
108
+ } else {
109
+ fail(id, -32601, `method not found: ${String(method)}`);
110
+ }
111
+ } catch (e) {
112
+ if (e instanceof InvalidParams) {
113
+ fail(id, -32602, e.message);
114
+ } else {
115
+ fail(id, -32603, e instanceof Error ? e.message : String(e));
116
+ }
117
+ }
118
+ }
119
+ async function handleWebSearch(id, args) {
120
+ const query = String(args.query ?? "").trim();
121
+ if (!query) {
122
+ fail(id, -32602, 'web_search requires a non-empty "query"');
123
+ return;
124
+ }
125
+ const provider = requireEnum(args.provider, SEARCH_PROVIDERS, "provider");
126
+ const searchRecency = requireEnum(args.recency, RECENCY_WINDOWS, "recency");
127
+ const maxResults = optionalMaxResults(args.maxResults);
128
+ const includeDomains = optionalDomains(args.includeDomains);
129
+ const excludeDomains = optionalDomains(args.excludeDomains);
130
+ try {
131
+ const resp = await client.search({
132
+ query,
133
+ ...provider ? { provider } : {},
134
+ ...maxResults != null ? { maxResults } : {},
135
+ ...searchRecency ? { searchRecency } : {},
136
+ ...includeDomains ? { includeDomains } : {},
137
+ ...excludeDomains ? { excludeDomains } : {}
138
+ });
139
+ const hits = resp.data ?? [];
140
+ const text = hits.length ? hits.map((h, i) => `${i + 1}. ${h.title}
141
+ ${h.url}${h.snippet ? `
142
+ ${h.snippet}` : ""}`).join("\n\n") : `No results for "${resp.query ?? query}".`;
143
+ ok(id, { content: [{ type: "text", text }] });
144
+ } catch (e) {
145
+ toolError(id, e instanceof Error ? e.message : String(e));
146
+ }
147
+ }
148
+ async function handleDeepResearch(id, args) {
149
+ const query = String(args.query ?? "").trim();
150
+ if (!query) {
151
+ fail(id, -32602, 'deep_research requires a non-empty "query"');
152
+ return;
153
+ }
154
+ const provider = requireEnum(args.provider, RESEARCH_PROVIDERS, "provider");
155
+ const searchRecency = requireEnum(args.searchRecency, RECENCY_WINDOWS, "searchRecency");
156
+ const maxResults = optionalMaxResults(args.maxResults);
157
+ const includeDomains = optionalDomains(args.includeDomains);
158
+ const excludeDomains = optionalDomains(args.excludeDomains);
159
+ try {
160
+ const resp = await client.research({
161
+ query,
162
+ ...provider ? { provider } : {},
163
+ ...typeof args.effort === "string" ? { effort: args.effort } : {},
164
+ ...maxResults != null ? { maxResults } : {},
165
+ ...searchRecency ? { searchRecency } : {},
166
+ ...includeDomains ? { includeDomains } : {},
167
+ ...excludeDomains ? { excludeDomains } : {},
168
+ ...args.outputSchema !== void 0 ? { outputSchema: args.outputSchema } : {}
169
+ });
170
+ const sources = resp.results ?? [];
171
+ const sourceList = sources.length ? `
172
+
173
+ Sources:
174
+ ${sources.map((h, i) => `${i + 1}. ${h.title}
175
+ ${h.url}`).join("\n")}` : "";
176
+ const text = `${resp.answer ?? ""}${sourceList}`.trim() || `No research result for "${resp.query ?? query}".`;
177
+ ok(id, { content: [{ type: "text", text }] });
178
+ } catch (e) {
179
+ toolError(id, e instanceof Error ? e.message : String(e));
180
+ }
181
+ }
182
+ for await (const line of rl) {
183
+ const trimmed = line.trim();
184
+ if (!trimmed) continue;
185
+ let req;
186
+ try {
187
+ req = JSON.parse(trimmed);
188
+ } catch {
189
+ send({ jsonrpc: "2.0", id: null, error: { code: -32700, message: "Parse error" } });
190
+ continue;
191
+ }
192
+ if (req.id === void 0 || req.id === null) continue;
193
+ void handleRequest(req);
194
+ }
195
+ }
196
+ var readline, SEARCH_PROVIDERS, RESEARCH_PROVIDERS, RECENCY_WINDOWS, SUPPORTED_PROTOCOL_VERSIONS, DEFAULT_PROTOCOL_VERSION, DOMAIN_FILTER_SCHEMA, TOOLS, InvalidParams;
197
+ var init_mcp = __esm({
198
+ "src/mcp.ts"() {
199
+ "use strict";
200
+ readline = __toESM(require("readline"), 1);
201
+ init_version();
202
+ SEARCH_PROVIDERS = /* @__PURE__ */ new Set(["perplexity", "exa", "you", "parallel", "tavily", "brave"]);
203
+ RESEARCH_PROVIDERS = /* @__PURE__ */ new Set(["perplexity", "exa", "you", "parallel", "tavily"]);
204
+ RECENCY_WINDOWS = /* @__PURE__ */ new Set(["day", "week", "month", "year"]);
205
+ SUPPORTED_PROTOCOL_VERSIONS = /* @__PURE__ */ new Set(["2025-06-18", "2025-03-26"]);
206
+ DEFAULT_PROTOCOL_VERSION = "2025-06-18";
207
+ DOMAIN_FILTER_SCHEMA = {
208
+ type: "array",
209
+ items: { type: "string" }
210
+ };
211
+ TOOLS = [
212
+ {
213
+ name: "web_search",
214
+ description: "Search the web via the Tangle router and return live results (title, url, snippet). Use it to find primary sources and to VERIFY that a citation (paper, PMID/DOI, patent, fact) actually exists before relying on it.",
215
+ inputSchema: {
216
+ type: "object",
217
+ properties: {
218
+ query: { type: "string", description: "The search query." },
219
+ provider: {
220
+ type: "string",
221
+ description: "Optional provider: exa | parallel | perplexity | tavily | brave | you."
222
+ },
223
+ maxResults: { type: "number", description: "Optional max number of results." },
224
+ recency: { type: "string", description: "Optional recency window: day | week | month | year." },
225
+ includeDomains: { ...DOMAIN_FILTER_SCHEMA, description: "Optional: restrict results to these domains." },
226
+ excludeDomains: { ...DOMAIN_FILTER_SCHEMA, description: "Optional: drop results from these domains." }
227
+ },
228
+ required: ["query"]
229
+ }
230
+ },
231
+ {
232
+ name: "deep_research",
233
+ description: 'Run a multi-step DEEP RESEARCH task via the Tangle router: the provider reads many sources and returns one synthesized answer with citations. Slower and costlier than web_search \u2014 use it for questions that need cross-source synthesis (current API/version landscapes, comparisons, "state of X"), not single-fact lookups.',
234
+ inputSchema: {
235
+ type: "object",
236
+ properties: {
237
+ query: { type: "string", description: "The research question." },
238
+ provider: {
239
+ type: "string",
240
+ description: "Optional provider: you | exa | perplexity | tavily | parallel."
241
+ },
242
+ effort: {
243
+ type: "string",
244
+ description: "Optional depth/cost dial (provider-specific): you lite|standard|deep|exhaustive \xB7 perplexity minimal|low|medium|high \xB7 exa deep-lite|deep|deep-reasoning \xB7 tavily mini|pro|auto \xB7 parallel lite|base|core|pro|ultra."
245
+ },
246
+ maxResults: { type: "number", description: "Optional max number of supporting sources." },
247
+ searchRecency: { type: "string", description: "Optional recency window: day | week | month | year." },
248
+ includeDomains: { ...DOMAIN_FILTER_SCHEMA, description: "Optional: restrict sources to these domains." },
249
+ excludeDomains: { ...DOMAIN_FILTER_SCHEMA, description: "Optional: drop sources from these domains." },
250
+ outputSchema: {
251
+ type: "object",
252
+ description: "Optional JSON schema requesting structured output from the provider."
253
+ }
254
+ },
255
+ required: ["query"]
256
+ }
257
+ }
258
+ ];
259
+ InvalidParams = class extends Error {
260
+ };
261
+ }
262
+ });
263
+
26
264
  // src/cli.ts
27
265
  var import_commander = require("commander");
28
266
 
@@ -247,47 +485,35 @@ var PrivateRouter = class {
247
485
  };
248
486
 
249
487
  // src/client.ts
488
+ init_version();
250
489
  var ROTATING_MARKER = "__tcloudRotating";
251
490
  var DIRECT_CLI_BRIDGE_MARKER = "__tcloudDirectCliBridge";
252
491
  var DEFAULT_BASE_URL = "https://router.tangle.tools/v1";
253
- var SDK_VERSION = "0.4.0";
254
492
  async function proxiedFetch(privacy, url, init, streaming) {
255
493
  if (!privacy || privacy.mode === "direct") {
256
494
  return fetch(url, init);
257
495
  }
258
- if (privacy.mode === "relayer") {
259
- if (!privacy.relayerUrl) {
260
- throw new Error('relayerUrl is required when privacy mode is "relayer"');
261
- }
262
- const proxyPath = streaming ? "/relay/proxy-stream" : "/relay/proxy";
263
- const hdrs = {};
264
- if (init.headers) {
265
- const entries = init.headers instanceof Headers ? Array.from(init.headers.entries()) : Object.entries(init.headers);
266
- for (const [k, v] of entries) hdrs[k] = v;
267
- }
268
- return fetch(`${privacy.relayerUrl}${proxyPath}`, {
269
- method: "POST",
270
- headers: { "Content-Type": "application/json" },
271
- body: JSON.stringify({
272
- target: url,
273
- body: typeof init.body === "string" ? JSON.parse(init.body) : init.body,
274
- headers: hdrs
275
- })
276
- });
496
+ if (privacy.mode !== "relayer") {
497
+ throw new Error(`Unsupported privacy mode: ${String(privacy.mode)}`);
277
498
  }
278
- if (privacy.mode === "socks5") {
279
- if (!privacy.socksProxy) {
280
- throw new Error('socksProxy is required when privacy mode is "socks5"');
281
- }
282
- const { SocksProxyAgent } = await import("socks-proxy-agent");
283
- const agent = new SocksProxyAgent(privacy.socksProxy);
284
- return fetch(url, {
285
- ...init,
286
- // @ts-expect-error agent is supported by Node's undici but not in the standard RequestInit type
287
- agent
288
- });
499
+ if (!privacy.relayerUrl) {
500
+ throw new Error('relayerUrl is required when privacy mode is "relayer"');
501
+ }
502
+ const proxyPath = streaming ? "/relay/proxy-stream" : "/relay/proxy";
503
+ const headers = {};
504
+ if (init.headers) {
505
+ const entries = init.headers instanceof Headers ? Array.from(init.headers.entries()) : Object.entries(init.headers);
506
+ for (const [key, value] of entries) headers[key] = value;
289
507
  }
290
- return fetch(url, init);
508
+ return fetch(`${privacy.relayerUrl}${proxyPath}`, {
509
+ method: "POST",
510
+ headers: { "Content-Type": "application/json" },
511
+ body: JSON.stringify({
512
+ target: url,
513
+ body: typeof init.body === "string" ? JSON.parse(init.body) : init.body,
514
+ headers
515
+ })
516
+ });
291
517
  }
292
518
  var DEFAULT_RETRY = {
293
519
  maxRetries: 3,
@@ -452,7 +678,7 @@ var TCloudClient = class _TCloudClient {
452
678
  this.timeoutMs = config.timeout ?? DEFAULT_TIMEOUT_MS;
453
679
  this.headers = {
454
680
  "Content-Type": "application/json",
455
- "X-Tangle-Client": `tcloud-sdk/${SDK_VERSION}`
681
+ "X-Tangle-Client": `tcloud-sdk/${packageVersion()}`
456
682
  };
457
683
  if (this.apiKey) {
458
684
  this.headers["Authorization"] = `Bearer ${this.apiKey}`;
@@ -1026,6 +1252,26 @@ var TCloudClient = class _TCloudClient {
1026
1252
  })
1027
1253
  });
1028
1254
  }
1255
+ /** Run a multi-step deep-research task through Tangle Router billing and
1256
+ * provider routing (POST /v1/research). Slower and costlier than `search` —
1257
+ * the provider synthesizes an answer over many fetches. Pick depth with
1258
+ * `effort` (provider-specific vocabulary; see {@link ResearchOptions.effort}). */
1259
+ async research(options) {
1260
+ return this._request(`${this.baseURL}/research`, {
1261
+ method: "POST",
1262
+ body: JSON.stringify({
1263
+ query: options.query,
1264
+ provider: options.provider,
1265
+ model: options.model,
1266
+ effort: options.effort,
1267
+ maxResults: options.maxResults,
1268
+ searchRecency: options.searchRecency,
1269
+ includeDomains: options.includeDomains,
1270
+ excludeDomains: options.excludeDomains,
1271
+ outputSchema: options.outputSchema
1272
+ })
1273
+ });
1274
+ }
1029
1275
  /** Text-to-speech */
1030
1276
  async speech(options) {
1031
1277
  const res = await this._requestRaw(`${this.baseURL}/audio/speech`, {
@@ -2007,11 +2253,11 @@ var TCloud = class _TCloud extends TCloudClient {
2007
2253
  };
2008
2254
 
2009
2255
  // src/cli.ts
2256
+ init_version();
2010
2257
  var fs = __toESM(require("fs"), 1);
2011
2258
  var path = __toESM(require("path"), 1);
2012
- var readline = __toESM(require("readline"), 1);
2259
+ var readline2 = __toESM(require("readline"), 1);
2013
2260
  var import_child_process = require("child_process");
2014
- var import_meta = {};
2015
2261
  var CONFIG_DIR = path.join(process.env.HOME || "~", ".tcloud");
2016
2262
  var CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
2017
2263
  var WALLETS_FILE = path.join(CONFIG_DIR, "wallets.json");
@@ -2073,16 +2319,6 @@ function teeType(value) {
2073
2319
  if (!value) return void 0;
2074
2320
  return value.toLowerCase();
2075
2321
  }
2076
- function packageVersion() {
2077
- try {
2078
- const packageJson = JSON.parse(
2079
- fs.readFileSync(new URL("../package.json", import_meta.url), "utf-8")
2080
- );
2081
- if (typeof packageJson.version === "string") return packageJson.version;
2082
- } catch {
2083
- }
2084
- return "0.0.0";
2085
- }
2086
2322
  function printJson(value) {
2087
2323
  console.log(JSON.stringify(value, null, 2));
2088
2324
  }
@@ -2292,7 +2528,7 @@ program.command("chat").description("Chat with a model").argument("[message]", "
2292
2528
  const client = getClient({ private: opts.private });
2293
2529
  const model = opts.model || loadConfig().defaultModel;
2294
2530
  if (!message) {
2295
- const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
2531
+ const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
2296
2532
  console.log(`tcloud chat \u2014 ${model}${opts.private ? " (private)" : ""}
2297
2533
  Ctrl+C to exit.
2298
2534
  `);
@@ -2382,6 +2618,11 @@ program.command("search").description("Search the web").argument("<query>", "Sea
2382
2618
  process.exit(1);
2383
2619
  }
2384
2620
  });
2621
+ program.command("mcp").description('Run a Model Context Protocol (stdio) server exposing Tangle tools (web_search, deep_research). Mount with: { "command": ["tcloud", "mcp"] }').action(async () => {
2622
+ const { runMcpServer: runMcpServer2 } = await Promise.resolve().then(() => (init_mcp(), mcp_exports));
2623
+ const client = getClient();
2624
+ await runMcpServer2(client);
2625
+ });
2385
2626
  program.command("image-generate").description("Generate an image").requiredOption("-p, --prompt <prompt>", "Prompt").option("-m, --model <model>", "Image model").option("--size <size>", "Output size").option("--quality <quality>", "Output quality").option("-n, --count <n>", "Number of images").option("--response-format <format>", "url or b64_json").option("--json", "Print raw JSON response").action(async (opts) => {
2386
2627
  const client = getClient();
2387
2628
  try {
package/dist/cli.js CHANGED
@@ -1,14 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  TCloud
4
- } from "./chunk-UBUCUSCF.js";
4
+ } from "./chunk-O33Y34UQ.js";
5
5
  import {
6
6
  TCloudSandbox
7
7
  } from "./chunk-GNACB23W.js";
8
8
  import {
9
9
  generateWallet
10
- } from "./chunk-THOMQXU5.js";
11
- import "./chunk-U4VOGRVW.js";
10
+ } from "./chunk-GDGQQRE3.js";
11
+ import "./chunk-H3K3A3EI.js";
12
+ import {
13
+ packageVersion
14
+ } from "./chunk-YK2SGW76.js";
12
15
 
13
16
  // src/cli.ts
14
17
  import { Command } from "commander";
@@ -77,16 +80,6 @@ function teeType(value) {
77
80
  if (!value) return void 0;
78
81
  return value.toLowerCase();
79
82
  }
80
- function packageVersion() {
81
- try {
82
- const packageJson = JSON.parse(
83
- fs.readFileSync(new URL("../package.json", import.meta.url), "utf-8")
84
- );
85
- if (typeof packageJson.version === "string") return packageJson.version;
86
- } catch {
87
- }
88
- return "0.0.0";
89
- }
90
83
  function printJson(value) {
91
84
  console.log(JSON.stringify(value, null, 2));
92
85
  }
@@ -386,6 +379,11 @@ program.command("search").description("Search the web").argument("<query>", "Sea
386
379
  process.exit(1);
387
380
  }
388
381
  });
382
+ program.command("mcp").description('Run a Model Context Protocol (stdio) server exposing Tangle tools (web_search, deep_research). Mount with: { "command": ["tcloud", "mcp"] }').action(async () => {
383
+ const { runMcpServer } = await import("./mcp.js");
384
+ const client = getClient();
385
+ await runMcpServer(client);
386
+ });
389
387
  program.command("image-generate").description("Generate an image").requiredOption("-p, --prompt <prompt>", "Prompt").option("-m, --model <model>", "Image model").option("--size <size>", "Output size").option("--quality <quality>", "Output quality").option("-n, --count <n>", "Number of images").option("--response-format <format>", "url or b64_json").option("--json", "Print raw JSON response").action(async (opts) => {
390
388
  const client = getClient();
391
389
  try {