@tangle-network/tcloud 0.4.13 → 0.4.14
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/dist/{chunk-THOMQXU5.js → chunk-26M4HGWE.js} +1 -1
- package/dist/chunk-GHMW4RWJ.js +16 -0
- package/dist/{chunk-U4VOGRVW.js → chunk-LUJXMUH5.js} +20 -0
- package/dist/{chunk-UBUCUSCF.js → chunk-ZJCWJGPM.js} +2 -2
- package/dist/cli.cjs +275 -21
- package/dist/cli.js +11 -13
- package/dist/{client-CaD5Oal0.d.ts → client-CaPP4njg.d.cts} +54 -1
- package/dist/{client-CaD5Oal0.d.cts → client-CaPP4njg.d.ts} +54 -1
- package/dist/index.cjs +20 -0
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/instance.cjs +20 -0
- package/dist/instance.d.cts +1 -1
- package/dist/instance.d.ts +1 -1
- package/dist/instance.js +1 -1
- package/dist/mcp.cjs +254 -0
- package/dist/mcp.d.cts +27 -0
- package/dist/mcp.d.ts +27 -0
- package/dist/mcp.js +207 -0
- package/dist/shielded.cjs +20 -0
- package/dist/shielded.d.cts +1 -1
- package/dist/shielded.d.ts +1 -1
- package/dist/shielded.js +2 -2
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1057,6 +1057,26 @@ var TCloudClient = class _TCloudClient {
|
|
|
1057
1057
|
})
|
|
1058
1058
|
});
|
|
1059
1059
|
}
|
|
1060
|
+
/** Run a multi-step deep-research task through Tangle Router billing and
|
|
1061
|
+
* provider routing (POST /v1/research). Slower and costlier than `search` —
|
|
1062
|
+
* the provider synthesizes an answer over many fetches. Pick depth with
|
|
1063
|
+
* `effort` (provider-specific vocabulary; see {@link ResearchOptions.effort}). */
|
|
1064
|
+
async research(options) {
|
|
1065
|
+
return this._request(`${this.baseURL}/research`, {
|
|
1066
|
+
method: "POST",
|
|
1067
|
+
body: JSON.stringify({
|
|
1068
|
+
query: options.query,
|
|
1069
|
+
provider: options.provider,
|
|
1070
|
+
model: options.model,
|
|
1071
|
+
effort: options.effort,
|
|
1072
|
+
maxResults: options.maxResults,
|
|
1073
|
+
searchRecency: options.searchRecency,
|
|
1074
|
+
includeDomains: options.includeDomains,
|
|
1075
|
+
excludeDomains: options.excludeDomains,
|
|
1076
|
+
outputSchema: options.outputSchema
|
|
1077
|
+
})
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
1060
1080
|
/** Text-to-speech */
|
|
1061
1081
|
async speech(options) {
|
|
1062
1082
|
const res = await this._requestRaw(`${this.baseURL}/audio/speech`, {
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ShieldedWallet, generateWallet } from './shielded.cjs';
|
|
2
2
|
export { createShieldedClient, estimateCost, signSpendAuth } from './shielded.cjs';
|
|
3
|
-
import {
|
|
4
|
-
export { A as ApiKeyInfo, b as AvatarGenerateRequest, c as AvatarGenerateResponse, d as AvatarJobStatus, e as AvatarResult, B as BatchJobResponse, f as BatchRequest, g as BridgeOptions, h as BridgeSession, C as ChatCompletion, i as ChatCompletionChunk, j as ChatMessage, k as ChatOptions, l as ChatPlugin, m as CompletionOptions, n as CompletionResponse, o as CreateKeyOptions, p as CreatedKey, q as CreditBalance, E as EmbeddingOptions, r as EmbeddingResponse, F as FineTuningJob, s as FineTuningJobOptions, G as GatewayOptions, I as ImageEditAttachment, t as ImageEditOptions, u as ImageGenerateOptions, v as ImageResponse, J as JobEvent, M as Model, O as Operator, w as OperatorInfo, P as PricingTier, x as PrivacyConfig, y as PrivateRouter, z as PrivateRouterConfig, D as RerankOptions, H as RerankResponse, K as
|
|
3
|
+
import { a as TCloudClient, T as TCloudConfig, R as RotatingClientConfig } from './client-CaPP4njg.cjs';
|
|
4
|
+
export { A as ApiKeyInfo, b as AvatarGenerateRequest, c as AvatarGenerateResponse, d as AvatarJobStatus, e as AvatarResult, B as BatchJobResponse, f as BatchRequest, g as BridgeOptions, h as BridgeSession, C as ChatCompletion, i as ChatCompletionChunk, j as ChatMessage, k as ChatOptions, l as ChatPlugin, m as CompletionOptions, n as CompletionResponse, o as CreateKeyOptions, p as CreatedKey, q as CreditBalance, E as EmbeddingOptions, r as EmbeddingResponse, F as FineTuningJob, s as FineTuningJobOptions, G as GatewayOptions, I as ImageEditAttachment, t as ImageEditOptions, u as ImageGenerateOptions, v as ImageResponse, J as JobEvent, M as Model, O as Operator, w as OperatorInfo, P as PricingTier, x as PrivacyConfig, y as PrivateRouter, z as PrivateRouterConfig, D as RerankOptions, H as RerankResponse, K as ResearchHit, L as ResearchOptions, N as ResearchProvider, Q as ResearchResponse, S as RetryConfig, U as RotatingRoutingConfig, V as RotationStats, W as RoutingConfig, X as RoutingStrategy, Y as SandboxChatOptions, Z as SearchHit, _ as SearchOptions, $ as SearchProvider, a0 as SearchRecency, a1 as SearchResponse, a2 as ShieldedConfig, a3 as SpendAuth, a4 as SpendingLimits, a5 as TCloudError, a6 as TierConfig, a7 as TranscriptionResponse, a8 as UpdateKeyOptions, a9 as VideoGenerateOptions, aa as VideoResponse, ab as WatchJobOptions, ac as WebSearchPlugin } from './client-CaPP4njg.cjs';
|
|
5
5
|
import { TCloudSandboxConfig, TCloudSandbox } from './sandbox.cjs';
|
|
6
6
|
export { TCloudSandboxAttestationStatus, TCloudSandboxCreateOptions, TCloudSandboxCreateResult, TCloudSandboxTee, TCloudTeeAttestationChallenge, TCloudTeeAttestationHeartbeat, TCloudTeeAttestationHeartbeatOptions, TCloudTeeAttestationHeartbeatSample, createTeeAttestationChallenge, generateAttestationNonce, startTeeAttestationHeartbeat } from './sandbox.cjs';
|
|
7
7
|
export { AsyncAttestationPolicy, AsyncHardwareVerifier, AttestationPolicy, AttestationVerificationResult, HardwareVerifier, HardwareVerifierResult, NitroAttestationDocument, NitroVerifierOptions, ParsedAttestation, SevSnpReport, SevSnpVerifierOptions, TeeType, assertAttestation, createNitroHardwareVerifier, createSevSnpHardwareVerifier, createTdxHardwareVerifier, normalizeTeeType, parseAttestation, parseNitroAttestationDocument, parseSevSnpReport, toHex, verifyAttestation, verifyAttestationAsync } from '@tangle-network/tcloud-attestation';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ShieldedWallet, generateWallet } from './shielded.js';
|
|
2
2
|
export { createShieldedClient, estimateCost, signSpendAuth } from './shielded.js';
|
|
3
|
-
import {
|
|
4
|
-
export { A as ApiKeyInfo, b as AvatarGenerateRequest, c as AvatarGenerateResponse, d as AvatarJobStatus, e as AvatarResult, B as BatchJobResponse, f as BatchRequest, g as BridgeOptions, h as BridgeSession, C as ChatCompletion, i as ChatCompletionChunk, j as ChatMessage, k as ChatOptions, l as ChatPlugin, m as CompletionOptions, n as CompletionResponse, o as CreateKeyOptions, p as CreatedKey, q as CreditBalance, E as EmbeddingOptions, r as EmbeddingResponse, F as FineTuningJob, s as FineTuningJobOptions, G as GatewayOptions, I as ImageEditAttachment, t as ImageEditOptions, u as ImageGenerateOptions, v as ImageResponse, J as JobEvent, M as Model, O as Operator, w as OperatorInfo, P as PricingTier, x as PrivacyConfig, y as PrivateRouter, z as PrivateRouterConfig, D as RerankOptions, H as RerankResponse, K as
|
|
3
|
+
import { a as TCloudClient, T as TCloudConfig, R as RotatingClientConfig } from './client-CaPP4njg.js';
|
|
4
|
+
export { A as ApiKeyInfo, b as AvatarGenerateRequest, c as AvatarGenerateResponse, d as AvatarJobStatus, e as AvatarResult, B as BatchJobResponse, f as BatchRequest, g as BridgeOptions, h as BridgeSession, C as ChatCompletion, i as ChatCompletionChunk, j as ChatMessage, k as ChatOptions, l as ChatPlugin, m as CompletionOptions, n as CompletionResponse, o as CreateKeyOptions, p as CreatedKey, q as CreditBalance, E as EmbeddingOptions, r as EmbeddingResponse, F as FineTuningJob, s as FineTuningJobOptions, G as GatewayOptions, I as ImageEditAttachment, t as ImageEditOptions, u as ImageGenerateOptions, v as ImageResponse, J as JobEvent, M as Model, O as Operator, w as OperatorInfo, P as PricingTier, x as PrivacyConfig, y as PrivateRouter, z as PrivateRouterConfig, D as RerankOptions, H as RerankResponse, K as ResearchHit, L as ResearchOptions, N as ResearchProvider, Q as ResearchResponse, S as RetryConfig, U as RotatingRoutingConfig, V as RotationStats, W as RoutingConfig, X as RoutingStrategy, Y as SandboxChatOptions, Z as SearchHit, _ as SearchOptions, $ as SearchProvider, a0 as SearchRecency, a1 as SearchResponse, a2 as ShieldedConfig, a3 as SpendAuth, a4 as SpendingLimits, a5 as TCloudError, a6 as TierConfig, a7 as TranscriptionResponse, a8 as UpdateKeyOptions, a9 as VideoGenerateOptions, aa as VideoResponse, ab as WatchJobOptions, ac as WebSearchPlugin } from './client-CaPP4njg.js';
|
|
5
5
|
import { TCloudSandboxConfig, TCloudSandbox } from './sandbox.js';
|
|
6
6
|
export { TCloudSandboxAttestationStatus, TCloudSandboxCreateOptions, TCloudSandboxCreateResult, TCloudSandboxTee, TCloudTeeAttestationChallenge, TCloudTeeAttestationHeartbeat, TCloudTeeAttestationHeartbeatOptions, TCloudTeeAttestationHeartbeatSample, createTeeAttestationChallenge, generateAttestationNonce, startTeeAttestationHeartbeat } from './sandbox.js';
|
|
7
7
|
export { AsyncAttestationPolicy, AsyncHardwareVerifier, AttestationPolicy, AttestationVerificationResult, HardwareVerifier, HardwareVerifierResult, NitroAttestationDocument, NitroVerifierOptions, ParsedAttestation, SevSnpReport, SevSnpVerifierOptions, TeeType, assertAttestation, createNitroHardwareVerifier, createSevSnpHardwareVerifier, createTdxHardwareVerifier, normalizeTeeType, parseAttestation, parseNitroAttestationDocument, parseSevSnpReport, toHex, verifyAttestation, verifyAttestationAsync } from '@tangle-network/tcloud-attestation';
|
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
toHex,
|
|
12
12
|
verifyAttestation,
|
|
13
13
|
verifyAttestationAsync
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-ZJCWJGPM.js";
|
|
15
15
|
import {
|
|
16
16
|
TCloudSandbox,
|
|
17
17
|
createTeeAttestationChallenge,
|
|
@@ -23,13 +23,13 @@ import {
|
|
|
23
23
|
estimateCost,
|
|
24
24
|
generateWallet,
|
|
25
25
|
signSpendAuth
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-26M4HGWE.js";
|
|
27
27
|
import {
|
|
28
28
|
BridgeSession,
|
|
29
29
|
PrivateRouter,
|
|
30
30
|
TCloudClient,
|
|
31
31
|
TCloudError
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-LUJXMUH5.js";
|
|
33
33
|
export {
|
|
34
34
|
BridgeSession,
|
|
35
35
|
PrivateRouter,
|
package/dist/instance.cjs
CHANGED
|
@@ -1041,6 +1041,26 @@ var TCloudClient = class _TCloudClient {
|
|
|
1041
1041
|
})
|
|
1042
1042
|
});
|
|
1043
1043
|
}
|
|
1044
|
+
/** Run a multi-step deep-research task through Tangle Router billing and
|
|
1045
|
+
* provider routing (POST /v1/research). Slower and costlier than `search` —
|
|
1046
|
+
* the provider synthesizes an answer over many fetches. Pick depth with
|
|
1047
|
+
* `effort` (provider-specific vocabulary; see {@link ResearchOptions.effort}). */
|
|
1048
|
+
async research(options) {
|
|
1049
|
+
return this._request(`${this.baseURL}/research`, {
|
|
1050
|
+
method: "POST",
|
|
1051
|
+
body: JSON.stringify({
|
|
1052
|
+
query: options.query,
|
|
1053
|
+
provider: options.provider,
|
|
1054
|
+
model: options.model,
|
|
1055
|
+
effort: options.effort,
|
|
1056
|
+
maxResults: options.maxResults,
|
|
1057
|
+
searchRecency: options.searchRecency,
|
|
1058
|
+
includeDomains: options.includeDomains,
|
|
1059
|
+
excludeDomains: options.excludeDomains,
|
|
1060
|
+
outputSchema: options.outputSchema
|
|
1061
|
+
})
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1044
1064
|
/** Text-to-speech */
|
|
1045
1065
|
async speech(options) {
|
|
1046
1066
|
const res = await this._requestRaw(`${this.baseURL}/audio/speech`, {
|
package/dist/instance.d.cts
CHANGED
package/dist/instance.d.ts
CHANGED
package/dist/instance.js
CHANGED
package/dist/mcp.cjs
ADDED
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/mcp.ts
|
|
31
|
+
var mcp_exports = {};
|
|
32
|
+
__export(mcp_exports, {
|
|
33
|
+
runMcpServer: () => runMcpServer
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(mcp_exports);
|
|
36
|
+
var readline = __toESM(require("readline"), 1);
|
|
37
|
+
|
|
38
|
+
// src/version.ts
|
|
39
|
+
var fs = __toESM(require("fs"), 1);
|
|
40
|
+
var import_meta = {};
|
|
41
|
+
function packageVersion() {
|
|
42
|
+
try {
|
|
43
|
+
const packageJson = JSON.parse(
|
|
44
|
+
fs.readFileSync(new URL("../package.json", import_meta.url), "utf-8")
|
|
45
|
+
);
|
|
46
|
+
if (typeof packageJson.version === "string") return packageJson.version;
|
|
47
|
+
} catch {
|
|
48
|
+
}
|
|
49
|
+
return "0.0.0";
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// src/mcp.ts
|
|
53
|
+
var SEARCH_PROVIDERS = /* @__PURE__ */ new Set(["perplexity", "exa", "you", "parallel", "tavily", "brave"]);
|
|
54
|
+
var RESEARCH_PROVIDERS = /* @__PURE__ */ new Set(["perplexity", "exa", "you", "parallel", "tavily"]);
|
|
55
|
+
var RECENCY_WINDOWS = /* @__PURE__ */ new Set(["day", "week", "month", "year"]);
|
|
56
|
+
var SUPPORTED_PROTOCOL_VERSIONS = /* @__PURE__ */ new Set(["2025-06-18", "2025-03-26"]);
|
|
57
|
+
var DEFAULT_PROTOCOL_VERSION = "2025-06-18";
|
|
58
|
+
var DOMAIN_FILTER_SCHEMA = {
|
|
59
|
+
type: "array",
|
|
60
|
+
items: { type: "string" }
|
|
61
|
+
};
|
|
62
|
+
var TOOLS = [
|
|
63
|
+
{
|
|
64
|
+
name: "web_search",
|
|
65
|
+
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.",
|
|
66
|
+
inputSchema: {
|
|
67
|
+
type: "object",
|
|
68
|
+
properties: {
|
|
69
|
+
query: { type: "string", description: "The search query." },
|
|
70
|
+
provider: {
|
|
71
|
+
type: "string",
|
|
72
|
+
description: "Optional provider: exa | parallel | perplexity | tavily | brave | you."
|
|
73
|
+
},
|
|
74
|
+
maxResults: { type: "number", description: "Optional max number of results." },
|
|
75
|
+
recency: { type: "string", description: "Optional recency window: day | week | month | year." },
|
|
76
|
+
includeDomains: { ...DOMAIN_FILTER_SCHEMA, description: "Optional: restrict results to these domains." },
|
|
77
|
+
excludeDomains: { ...DOMAIN_FILTER_SCHEMA, description: "Optional: drop results from these domains." }
|
|
78
|
+
},
|
|
79
|
+
required: ["query"]
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
name: "deep_research",
|
|
84
|
+
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.',
|
|
85
|
+
inputSchema: {
|
|
86
|
+
type: "object",
|
|
87
|
+
properties: {
|
|
88
|
+
query: { type: "string", description: "The research question." },
|
|
89
|
+
provider: {
|
|
90
|
+
type: "string",
|
|
91
|
+
description: "Optional provider: you | exa | perplexity | tavily | parallel."
|
|
92
|
+
},
|
|
93
|
+
effort: {
|
|
94
|
+
type: "string",
|
|
95
|
+
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."
|
|
96
|
+
},
|
|
97
|
+
maxResults: { type: "number", description: "Optional max number of supporting sources." },
|
|
98
|
+
searchRecency: { type: "string", description: "Optional recency window: day | week | month | year." },
|
|
99
|
+
includeDomains: { ...DOMAIN_FILTER_SCHEMA, description: "Optional: restrict sources to these domains." },
|
|
100
|
+
excludeDomains: { ...DOMAIN_FILTER_SCHEMA, description: "Optional: drop sources from these domains." },
|
|
101
|
+
outputSchema: {
|
|
102
|
+
type: "object",
|
|
103
|
+
description: "Optional JSON schema requesting structured output from the provider."
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
required: ["query"]
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
];
|
|
110
|
+
var InvalidParams = class extends Error {
|
|
111
|
+
};
|
|
112
|
+
function optionalMaxResults(value) {
|
|
113
|
+
if (value == null) return void 0;
|
|
114
|
+
const n = Number(value);
|
|
115
|
+
return Number.isFinite(n) && n >= 0 ? n : void 0;
|
|
116
|
+
}
|
|
117
|
+
function requireEnum(value, allowed, label) {
|
|
118
|
+
if (value == null) return void 0;
|
|
119
|
+
if (typeof value !== "string" || !allowed.has(value)) {
|
|
120
|
+
throw new InvalidParams(`invalid ${label}: ${String(value)}`);
|
|
121
|
+
}
|
|
122
|
+
return value;
|
|
123
|
+
}
|
|
124
|
+
function optionalDomains(value) {
|
|
125
|
+
if (!Array.isArray(value)) return void 0;
|
|
126
|
+
const domains = value.filter((d) => typeof d === "string");
|
|
127
|
+
return domains.length ? domains : void 0;
|
|
128
|
+
}
|
|
129
|
+
async function runMcpServer(client, opts = {}) {
|
|
130
|
+
const input = opts.input ?? process.stdin;
|
|
131
|
+
const output = opts.output ?? process.stdout;
|
|
132
|
+
const rl = readline.createInterface({ input });
|
|
133
|
+
const send = (msg) => {
|
|
134
|
+
output.write(`${JSON.stringify(msg)}
|
|
135
|
+
`);
|
|
136
|
+
};
|
|
137
|
+
const ok = (id, result) => send({ jsonrpc: "2.0", id, result });
|
|
138
|
+
const fail = (id, code, message) => send({ jsonrpc: "2.0", id, error: { code, message } });
|
|
139
|
+
const toolError = (id, message) => ok(id, { content: [{ type: "text", text: message }], isError: true });
|
|
140
|
+
process.stderr.write("tcloud mcp: web_search + deep_research server ready (stdio)\n");
|
|
141
|
+
async function handleRequest(req) {
|
|
142
|
+
const { id, method, params } = req;
|
|
143
|
+
try {
|
|
144
|
+
if (method === "initialize") {
|
|
145
|
+
const requested = params?.protocolVersion ?? DEFAULT_PROTOCOL_VERSION;
|
|
146
|
+
const protocolVersion = SUPPORTED_PROTOCOL_VERSIONS.has(requested) ? requested : DEFAULT_PROTOCOL_VERSION;
|
|
147
|
+
ok(id, {
|
|
148
|
+
protocolVersion,
|
|
149
|
+
capabilities: { tools: {} },
|
|
150
|
+
serverInfo: { name: "tangle-tcloud", version: packageVersion() }
|
|
151
|
+
});
|
|
152
|
+
} else if (method === "tools/list") {
|
|
153
|
+
ok(id, { tools: TOOLS });
|
|
154
|
+
} else if (method === "tools/call") {
|
|
155
|
+
const name = params?.name;
|
|
156
|
+
if (name === "web_search") {
|
|
157
|
+
await handleWebSearch(id, params?.arguments ?? {});
|
|
158
|
+
} else if (name === "deep_research") {
|
|
159
|
+
await handleDeepResearch(id, params?.arguments ?? {});
|
|
160
|
+
} else {
|
|
161
|
+
fail(id, -32602, `unknown tool: ${String(name)}`);
|
|
162
|
+
}
|
|
163
|
+
} else {
|
|
164
|
+
fail(id, -32601, `method not found: ${String(method)}`);
|
|
165
|
+
}
|
|
166
|
+
} catch (e) {
|
|
167
|
+
if (e instanceof InvalidParams) {
|
|
168
|
+
fail(id, -32602, e.message);
|
|
169
|
+
} else {
|
|
170
|
+
fail(id, -32603, e instanceof Error ? e.message : String(e));
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
async function handleWebSearch(id, args) {
|
|
175
|
+
const query = String(args.query ?? "").trim();
|
|
176
|
+
if (!query) {
|
|
177
|
+
fail(id, -32602, 'web_search requires a non-empty "query"');
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const provider = requireEnum(args.provider, SEARCH_PROVIDERS, "provider");
|
|
181
|
+
const searchRecency = requireEnum(args.recency, RECENCY_WINDOWS, "recency");
|
|
182
|
+
const maxResults = optionalMaxResults(args.maxResults);
|
|
183
|
+
const includeDomains = optionalDomains(args.includeDomains);
|
|
184
|
+
const excludeDomains = optionalDomains(args.excludeDomains);
|
|
185
|
+
try {
|
|
186
|
+
const resp = await client.search({
|
|
187
|
+
query,
|
|
188
|
+
...provider ? { provider } : {},
|
|
189
|
+
...maxResults != null ? { maxResults } : {},
|
|
190
|
+
...searchRecency ? { searchRecency } : {},
|
|
191
|
+
...includeDomains ? { includeDomains } : {},
|
|
192
|
+
...excludeDomains ? { excludeDomains } : {}
|
|
193
|
+
});
|
|
194
|
+
const hits = resp.data ?? [];
|
|
195
|
+
const text = hits.length ? hits.map((h, i) => `${i + 1}. ${h.title}
|
|
196
|
+
${h.url}${h.snippet ? `
|
|
197
|
+
${h.snippet}` : ""}`).join("\n\n") : `No results for "${resp.query ?? query}".`;
|
|
198
|
+
ok(id, { content: [{ type: "text", text }] });
|
|
199
|
+
} catch (e) {
|
|
200
|
+
toolError(id, e instanceof Error ? e.message : String(e));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
async function handleDeepResearch(id, args) {
|
|
204
|
+
const query = String(args.query ?? "").trim();
|
|
205
|
+
if (!query) {
|
|
206
|
+
fail(id, -32602, 'deep_research requires a non-empty "query"');
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
const provider = requireEnum(args.provider, RESEARCH_PROVIDERS, "provider");
|
|
210
|
+
const searchRecency = requireEnum(args.searchRecency, RECENCY_WINDOWS, "searchRecency");
|
|
211
|
+
const maxResults = optionalMaxResults(args.maxResults);
|
|
212
|
+
const includeDomains = optionalDomains(args.includeDomains);
|
|
213
|
+
const excludeDomains = optionalDomains(args.excludeDomains);
|
|
214
|
+
try {
|
|
215
|
+
const resp = await client.research({
|
|
216
|
+
query,
|
|
217
|
+
...provider ? { provider } : {},
|
|
218
|
+
...typeof args.effort === "string" ? { effort: args.effort } : {},
|
|
219
|
+
...maxResults != null ? { maxResults } : {},
|
|
220
|
+
...searchRecency ? { searchRecency } : {},
|
|
221
|
+
...includeDomains ? { includeDomains } : {},
|
|
222
|
+
...excludeDomains ? { excludeDomains } : {},
|
|
223
|
+
...args.outputSchema !== void 0 ? { outputSchema: args.outputSchema } : {}
|
|
224
|
+
});
|
|
225
|
+
const sources = resp.results ?? [];
|
|
226
|
+
const sourceList = sources.length ? `
|
|
227
|
+
|
|
228
|
+
Sources:
|
|
229
|
+
${sources.map((h, i) => `${i + 1}. ${h.title}
|
|
230
|
+
${h.url}`).join("\n")}` : "";
|
|
231
|
+
const text = `${resp.answer ?? ""}${sourceList}`.trim() || `No research result for "${resp.query ?? query}".`;
|
|
232
|
+
ok(id, { content: [{ type: "text", text }] });
|
|
233
|
+
} catch (e) {
|
|
234
|
+
toolError(id, e instanceof Error ? e.message : String(e));
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
for await (const line of rl) {
|
|
238
|
+
const trimmed = line.trim();
|
|
239
|
+
if (!trimmed) continue;
|
|
240
|
+
let req;
|
|
241
|
+
try {
|
|
242
|
+
req = JSON.parse(trimmed);
|
|
243
|
+
} catch {
|
|
244
|
+
send({ jsonrpc: "2.0", id: null, error: { code: -32700, message: "Parse error" } });
|
|
245
|
+
continue;
|
|
246
|
+
}
|
|
247
|
+
if (req.id === void 0 || req.id === null) continue;
|
|
248
|
+
void handleRequest(req);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
252
|
+
0 && (module.exports = {
|
|
253
|
+
runMcpServer
|
|
254
|
+
});
|
package/dist/mcp.d.cts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Readable, Writable } from 'node:stream';
|
|
2
|
+
import { TCloud } from './index.cjs';
|
|
3
|
+
import './shielded.cjs';
|
|
4
|
+
import 'viem';
|
|
5
|
+
import './client-CaPP4njg.cjs';
|
|
6
|
+
import '@tangle-network/sandbox';
|
|
7
|
+
import './sandbox.cjs';
|
|
8
|
+
import '@tangle-network/tcloud-attestation';
|
|
9
|
+
|
|
10
|
+
/** Transport streams the server reads/writes. Defaults bind to the process
|
|
11
|
+
* stdio; tests inject in-memory streams. */
|
|
12
|
+
interface McpServerOptions {
|
|
13
|
+
input?: Readable;
|
|
14
|
+
output?: Writable;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Run the MCP stdio server against an authenticated TCloud client. Resolves when input closes.
|
|
18
|
+
* Handles `initialize`, `tools/list`, `tools/call` (+ ignores notifications, which carry no id).
|
|
19
|
+
*
|
|
20
|
+
* Requests are dispatched without blocking the read loop, so a slow `deep_research`
|
|
21
|
+
* call cannot stall concurrent `web_search` requests — each response carries its
|
|
22
|
+
* own id. Pass `{ input, output }` to drive the transport over arbitrary streams
|
|
23
|
+
* (tests inject in-memory streams); both default to the process stdio.
|
|
24
|
+
*/
|
|
25
|
+
declare function runMcpServer(client: TCloud, opts?: McpServerOptions): Promise<void>;
|
|
26
|
+
|
|
27
|
+
export { type McpServerOptions, runMcpServer };
|
package/dist/mcp.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Readable, Writable } from 'node:stream';
|
|
2
|
+
import { TCloud } from './index.js';
|
|
3
|
+
import './shielded.js';
|
|
4
|
+
import 'viem';
|
|
5
|
+
import './client-CaPP4njg.js';
|
|
6
|
+
import '@tangle-network/sandbox';
|
|
7
|
+
import './sandbox.js';
|
|
8
|
+
import '@tangle-network/tcloud-attestation';
|
|
9
|
+
|
|
10
|
+
/** Transport streams the server reads/writes. Defaults bind to the process
|
|
11
|
+
* stdio; tests inject in-memory streams. */
|
|
12
|
+
interface McpServerOptions {
|
|
13
|
+
input?: Readable;
|
|
14
|
+
output?: Writable;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Run the MCP stdio server against an authenticated TCloud client. Resolves when input closes.
|
|
18
|
+
* Handles `initialize`, `tools/list`, `tools/call` (+ ignores notifications, which carry no id).
|
|
19
|
+
*
|
|
20
|
+
* Requests are dispatched without blocking the read loop, so a slow `deep_research`
|
|
21
|
+
* call cannot stall concurrent `web_search` requests — each response carries its
|
|
22
|
+
* own id. Pass `{ input, output }` to drive the transport over arbitrary streams
|
|
23
|
+
* (tests inject in-memory streams); both default to the process stdio.
|
|
24
|
+
*/
|
|
25
|
+
declare function runMcpServer(client: TCloud, opts?: McpServerOptions): Promise<void>;
|
|
26
|
+
|
|
27
|
+
export { type McpServerOptions, runMcpServer };
|
package/dist/mcp.js
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import {
|
|
2
|
+
packageVersion
|
|
3
|
+
} from "./chunk-GHMW4RWJ.js";
|
|
4
|
+
|
|
5
|
+
// src/mcp.ts
|
|
6
|
+
import * as readline from "readline";
|
|
7
|
+
var SEARCH_PROVIDERS = /* @__PURE__ */ new Set(["perplexity", "exa", "you", "parallel", "tavily", "brave"]);
|
|
8
|
+
var RESEARCH_PROVIDERS = /* @__PURE__ */ new Set(["perplexity", "exa", "you", "parallel", "tavily"]);
|
|
9
|
+
var RECENCY_WINDOWS = /* @__PURE__ */ new Set(["day", "week", "month", "year"]);
|
|
10
|
+
var SUPPORTED_PROTOCOL_VERSIONS = /* @__PURE__ */ new Set(["2025-06-18", "2025-03-26"]);
|
|
11
|
+
var DEFAULT_PROTOCOL_VERSION = "2025-06-18";
|
|
12
|
+
var DOMAIN_FILTER_SCHEMA = {
|
|
13
|
+
type: "array",
|
|
14
|
+
items: { type: "string" }
|
|
15
|
+
};
|
|
16
|
+
var TOOLS = [
|
|
17
|
+
{
|
|
18
|
+
name: "web_search",
|
|
19
|
+
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.",
|
|
20
|
+
inputSchema: {
|
|
21
|
+
type: "object",
|
|
22
|
+
properties: {
|
|
23
|
+
query: { type: "string", description: "The search query." },
|
|
24
|
+
provider: {
|
|
25
|
+
type: "string",
|
|
26
|
+
description: "Optional provider: exa | parallel | perplexity | tavily | brave | you."
|
|
27
|
+
},
|
|
28
|
+
maxResults: { type: "number", description: "Optional max number of results." },
|
|
29
|
+
recency: { type: "string", description: "Optional recency window: day | week | month | year." },
|
|
30
|
+
includeDomains: { ...DOMAIN_FILTER_SCHEMA, description: "Optional: restrict results to these domains." },
|
|
31
|
+
excludeDomains: { ...DOMAIN_FILTER_SCHEMA, description: "Optional: drop results from these domains." }
|
|
32
|
+
},
|
|
33
|
+
required: ["query"]
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
name: "deep_research",
|
|
38
|
+
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.',
|
|
39
|
+
inputSchema: {
|
|
40
|
+
type: "object",
|
|
41
|
+
properties: {
|
|
42
|
+
query: { type: "string", description: "The research question." },
|
|
43
|
+
provider: {
|
|
44
|
+
type: "string",
|
|
45
|
+
description: "Optional provider: you | exa | perplexity | tavily | parallel."
|
|
46
|
+
},
|
|
47
|
+
effort: {
|
|
48
|
+
type: "string",
|
|
49
|
+
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."
|
|
50
|
+
},
|
|
51
|
+
maxResults: { type: "number", description: "Optional max number of supporting sources." },
|
|
52
|
+
searchRecency: { type: "string", description: "Optional recency window: day | week | month | year." },
|
|
53
|
+
includeDomains: { ...DOMAIN_FILTER_SCHEMA, description: "Optional: restrict sources to these domains." },
|
|
54
|
+
excludeDomains: { ...DOMAIN_FILTER_SCHEMA, description: "Optional: drop sources from these domains." },
|
|
55
|
+
outputSchema: {
|
|
56
|
+
type: "object",
|
|
57
|
+
description: "Optional JSON schema requesting structured output from the provider."
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
required: ["query"]
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
];
|
|
64
|
+
var InvalidParams = class extends Error {
|
|
65
|
+
};
|
|
66
|
+
function optionalMaxResults(value) {
|
|
67
|
+
if (value == null) return void 0;
|
|
68
|
+
const n = Number(value);
|
|
69
|
+
return Number.isFinite(n) && n >= 0 ? n : void 0;
|
|
70
|
+
}
|
|
71
|
+
function requireEnum(value, allowed, label) {
|
|
72
|
+
if (value == null) return void 0;
|
|
73
|
+
if (typeof value !== "string" || !allowed.has(value)) {
|
|
74
|
+
throw new InvalidParams(`invalid ${label}: ${String(value)}`);
|
|
75
|
+
}
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
function optionalDomains(value) {
|
|
79
|
+
if (!Array.isArray(value)) return void 0;
|
|
80
|
+
const domains = value.filter((d) => typeof d === "string");
|
|
81
|
+
return domains.length ? domains : void 0;
|
|
82
|
+
}
|
|
83
|
+
async function runMcpServer(client, opts = {}) {
|
|
84
|
+
const input = opts.input ?? process.stdin;
|
|
85
|
+
const output = opts.output ?? process.stdout;
|
|
86
|
+
const rl = readline.createInterface({ input });
|
|
87
|
+
const send = (msg) => {
|
|
88
|
+
output.write(`${JSON.stringify(msg)}
|
|
89
|
+
`);
|
|
90
|
+
};
|
|
91
|
+
const ok = (id, result) => send({ jsonrpc: "2.0", id, result });
|
|
92
|
+
const fail = (id, code, message) => send({ jsonrpc: "2.0", id, error: { code, message } });
|
|
93
|
+
const toolError = (id, message) => ok(id, { content: [{ type: "text", text: message }], isError: true });
|
|
94
|
+
process.stderr.write("tcloud mcp: web_search + deep_research server ready (stdio)\n");
|
|
95
|
+
async function handleRequest(req) {
|
|
96
|
+
const { id, method, params } = req;
|
|
97
|
+
try {
|
|
98
|
+
if (method === "initialize") {
|
|
99
|
+
const requested = params?.protocolVersion ?? DEFAULT_PROTOCOL_VERSION;
|
|
100
|
+
const protocolVersion = SUPPORTED_PROTOCOL_VERSIONS.has(requested) ? requested : DEFAULT_PROTOCOL_VERSION;
|
|
101
|
+
ok(id, {
|
|
102
|
+
protocolVersion,
|
|
103
|
+
capabilities: { tools: {} },
|
|
104
|
+
serverInfo: { name: "tangle-tcloud", version: packageVersion() }
|
|
105
|
+
});
|
|
106
|
+
} else if (method === "tools/list") {
|
|
107
|
+
ok(id, { tools: TOOLS });
|
|
108
|
+
} else if (method === "tools/call") {
|
|
109
|
+
const name = params?.name;
|
|
110
|
+
if (name === "web_search") {
|
|
111
|
+
await handleWebSearch(id, params?.arguments ?? {});
|
|
112
|
+
} else if (name === "deep_research") {
|
|
113
|
+
await handleDeepResearch(id, params?.arguments ?? {});
|
|
114
|
+
} else {
|
|
115
|
+
fail(id, -32602, `unknown tool: ${String(name)}`);
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
fail(id, -32601, `method not found: ${String(method)}`);
|
|
119
|
+
}
|
|
120
|
+
} catch (e) {
|
|
121
|
+
if (e instanceof InvalidParams) {
|
|
122
|
+
fail(id, -32602, e.message);
|
|
123
|
+
} else {
|
|
124
|
+
fail(id, -32603, e instanceof Error ? e.message : String(e));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async function handleWebSearch(id, args) {
|
|
129
|
+
const query = String(args.query ?? "").trim();
|
|
130
|
+
if (!query) {
|
|
131
|
+
fail(id, -32602, 'web_search requires a non-empty "query"');
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
const provider = requireEnum(args.provider, SEARCH_PROVIDERS, "provider");
|
|
135
|
+
const searchRecency = requireEnum(args.recency, RECENCY_WINDOWS, "recency");
|
|
136
|
+
const maxResults = optionalMaxResults(args.maxResults);
|
|
137
|
+
const includeDomains = optionalDomains(args.includeDomains);
|
|
138
|
+
const excludeDomains = optionalDomains(args.excludeDomains);
|
|
139
|
+
try {
|
|
140
|
+
const resp = await client.search({
|
|
141
|
+
query,
|
|
142
|
+
...provider ? { provider } : {},
|
|
143
|
+
...maxResults != null ? { maxResults } : {},
|
|
144
|
+
...searchRecency ? { searchRecency } : {},
|
|
145
|
+
...includeDomains ? { includeDomains } : {},
|
|
146
|
+
...excludeDomains ? { excludeDomains } : {}
|
|
147
|
+
});
|
|
148
|
+
const hits = resp.data ?? [];
|
|
149
|
+
const text = hits.length ? hits.map((h, i) => `${i + 1}. ${h.title}
|
|
150
|
+
${h.url}${h.snippet ? `
|
|
151
|
+
${h.snippet}` : ""}`).join("\n\n") : `No results for "${resp.query ?? query}".`;
|
|
152
|
+
ok(id, { content: [{ type: "text", text }] });
|
|
153
|
+
} catch (e) {
|
|
154
|
+
toolError(id, e instanceof Error ? e.message : String(e));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
async function handleDeepResearch(id, args) {
|
|
158
|
+
const query = String(args.query ?? "").trim();
|
|
159
|
+
if (!query) {
|
|
160
|
+
fail(id, -32602, 'deep_research requires a non-empty "query"');
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const provider = requireEnum(args.provider, RESEARCH_PROVIDERS, "provider");
|
|
164
|
+
const searchRecency = requireEnum(args.searchRecency, RECENCY_WINDOWS, "searchRecency");
|
|
165
|
+
const maxResults = optionalMaxResults(args.maxResults);
|
|
166
|
+
const includeDomains = optionalDomains(args.includeDomains);
|
|
167
|
+
const excludeDomains = optionalDomains(args.excludeDomains);
|
|
168
|
+
try {
|
|
169
|
+
const resp = await client.research({
|
|
170
|
+
query,
|
|
171
|
+
...provider ? { provider } : {},
|
|
172
|
+
...typeof args.effort === "string" ? { effort: args.effort } : {},
|
|
173
|
+
...maxResults != null ? { maxResults } : {},
|
|
174
|
+
...searchRecency ? { searchRecency } : {},
|
|
175
|
+
...includeDomains ? { includeDomains } : {},
|
|
176
|
+
...excludeDomains ? { excludeDomains } : {},
|
|
177
|
+
...args.outputSchema !== void 0 ? { outputSchema: args.outputSchema } : {}
|
|
178
|
+
});
|
|
179
|
+
const sources = resp.results ?? [];
|
|
180
|
+
const sourceList = sources.length ? `
|
|
181
|
+
|
|
182
|
+
Sources:
|
|
183
|
+
${sources.map((h, i) => `${i + 1}. ${h.title}
|
|
184
|
+
${h.url}`).join("\n")}` : "";
|
|
185
|
+
const text = `${resp.answer ?? ""}${sourceList}`.trim() || `No research result for "${resp.query ?? query}".`;
|
|
186
|
+
ok(id, { content: [{ type: "text", text }] });
|
|
187
|
+
} catch (e) {
|
|
188
|
+
toolError(id, e instanceof Error ? e.message : String(e));
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
for await (const line of rl) {
|
|
192
|
+
const trimmed = line.trim();
|
|
193
|
+
if (!trimmed) continue;
|
|
194
|
+
let req;
|
|
195
|
+
try {
|
|
196
|
+
req = JSON.parse(trimmed);
|
|
197
|
+
} catch {
|
|
198
|
+
send({ jsonrpc: "2.0", id: null, error: { code: -32700, message: "Parse error" } });
|
|
199
|
+
continue;
|
|
200
|
+
}
|
|
201
|
+
if (req.id === void 0 || req.id === null) continue;
|
|
202
|
+
void handleRequest(req);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
export {
|
|
206
|
+
runMcpServer
|
|
207
|
+
};
|