@tool-bridge/server 0.22.1 → 0.24.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/dist/admin.js +2 -2
- package/dist/{airtable-ML2GIGCH.js → airtable-Z6KEL3MA.js} +6 -6
- package/dist/{alt_text_generator_ai-FGYQAF2A.js → alt_text_generator_ai-RM2GHSNM.js} +5 -5
- package/dist/{amap-G7V65NGK.js → amap-YEJLGIKY.js} +5 -5
- package/dist/{anthropic-6ZK24TBB.js → anthropic-62M4MUVQ.js} +6 -6
- package/dist/{apify-VDGYHP6W.js → apify-AHRNDBCB.js} +6 -6
- package/dist/{brave_search-TAATLZOS.js → brave_search-JAHWOMQC.js} +6 -6
- package/dist/{chunk-HA4BGL6C.js → chunk-7MUNQNXG.js} +486 -450
- package/dist/{chunk-RTW5VRTK.js → chunk-FZV7CF7L.js} +3 -3
- package/dist/{chunk-7ISGFRC6.js → chunk-GQ4O7NK5.js} +1 -1
- package/dist/{chunk-RMAWSG7E.js → chunk-LD7KQRQ3.js} +372 -554
- package/dist/{chunk-BNMLA2RC.js → chunk-NG4C7YB3.js} +3 -3
- package/dist/{chunk-X7ZUTKHR.js → chunk-SU6Q4RAY.js} +2 -2
- package/dist/{chunk-UY6ANCOY.js → chunk-TH3H5YAG.js} +1 -1
- package/dist/{chunk-2IAI3XQM.js → chunk-U2UGFSOX.js} +2 -2
- package/dist/{circleci-BQ2UWXL2.js → circleci-UJUYBIAO.js} +6 -6
- package/dist/{clerk-2JYWQNOI.js → clerk-FCFM3WJK.js} +6 -6
- package/dist/{cohere-6MI7AQM4.js → cohere-OTSYSMPC.js} +6 -6
- package/dist/{confluence-6Y6GDETF.js → confluence-LPANSCGT.js} +6 -6
- package/dist/{convertapi-HBZCSWOX.js → convertapi-AJZOVUHT.js} +4 -4
- package/dist/{currencyapi-337U5TGI.js → currencyapi-HGK5FSGO.js} +6 -6
- package/dist/{deepseek-OSPASO7O.js → deepseek-7HMTFJRV.js} +6 -6
- package/dist/{docker_hub-3ATQOY5L.js → docker_hub-FCNVKJZW.js} +5 -5
- package/dist/{dropbox-LSA4GM2Y.js → dropbox-2XVKCQZE.js} +6 -6
- package/dist/{dub-VZPJSPI6.js → dub-CTUKPX2A.js} +6 -6
- package/dist/{e2b-6SDYQZL2.js → e2b-ULEWTRKI.js} +6 -6
- package/dist/{exa-B6EUYDVP.js → exa-QENFV3AU.js} +6 -6
- package/dist/{fal_ai-K4Q27IME.js → fal_ai-TQYUBBAF.js} +6 -6
- package/dist/{feishu-4TKXG4SU.js → feishu-OYCWDSHD.js} +3 -3
- package/dist/{feishu_custom_bot-7CTEAKRB.js → feishu_custom_bot-VYQ7A3PU.js} +4 -4
- package/dist/{figma-OUKSZLD5.js → figma-5DLOKAQQ.js} +6 -6
- package/dist/{firehydrant-7MOYL7QH.js → firehydrant-X4MGP2OI.js} +6 -6
- package/dist/{fixer-H2BV2NO4.js → fixer-LMIWM3ZX.js} +5 -5
- package/dist/{fly-PXKY6PNH.js → fly-J5HN5L2I.js} +6 -6
- package/dist/{front-UZYIV5DW.js → front-E3SMBQW3.js} +6 -6
- package/dist/{geocodio-NSYO7TFP.js → geocodio-AOINRPLA.js} +5 -5
- package/dist/{ghost-QBKKQQMF.js → ghost-E4CBGZWJ.js} +5 -5
- package/dist/{github-ENLSJ4CL.js → github-PGR6U3FC.js} +6 -6
- package/dist/{gmail-KQSDEB47.js → gmail-XNQHMQ6F.js} +6 -6
- package/dist/{googlecalendar-5YCX4SZF.js → googlecalendar-RE6DGG7L.js} +6 -6
- package/dist/{googledocs-SSWIVFKA.js → googledocs-CX2BZDQH.js} +4 -4
- package/dist/{grafana-TF2LXDQA.js → grafana-GX75ZA5X.js} +6 -6
- package/dist/{graphhopper-CURBVHYK.js → graphhopper-XMUYLWHS.js} +5 -5
- package/dist/index.js +5 -5
- package/dist/{ip2proxy-YNVMTZEM.js → ip2proxy-ZGIRBAG5.js} +5 -5
- package/dist/{ipgeolocation_io-NAU7VJ4J.js → ipgeolocation_io-MAP27QMO.js} +5 -5
- package/dist/{ipqualityscore-OT63L4TI.js → ipqualityscore-6IIUUAQ2.js} +5 -5
- package/dist/{jina_ai-6WBMBGWM.js → jina_ai-GGH77RQH.js} +6 -6
- package/dist/{jira-DVDVTHNO.js → jira-7GPZW6HZ.js} +6 -6
- package/dist/{langsmith-IM5N4YAU.js → langsmith-CJXYE7WM.js} +6 -6
- package/dist/{lemlist-277SHUQF.js → lemlist-OYPOX6GN.js} +6 -6
- package/dist/{linear-AEPH7B5V.js → linear-TPQ6X4XZ.js} +4 -4
- package/dist/{logsnag-VEWRAGBG.js → logsnag-HT2PRLIV.js} +6 -6
- package/dist/main.js +5 -5
- package/dist/{mattermost-Q3A2BIZA.js → mattermost-6IYTWTM5.js} +6 -6
- package/dist/{mem0-AXS7GZGI.js → mem0-7AVGBGOX.js} +6 -6
- package/dist/{memos-7TXG4ZTU.js → memos-CTOXWZ6X.js} +6 -6
- package/dist/{metabase-NSVACWQM.js → metabase-AFJXQ5SQ.js} +6 -6
- package/dist/{mistral_ai-YZ52RGD4.js → mistral_ai-QDKM4N3R.js} +6 -6
- package/dist/{mother_duck-XLLL6FVL.js → mother_duck-XSKR4GVL.js} +6 -6
- package/dist/{ngrok-4O4W3WZW.js → ngrok-NQMLM24P.js} +6 -6
- package/dist/{notes-YTB3TJOO.js → notes-ZWMVZQWJ.js} +2 -2
- package/dist/{notion-4W4O7J7V.js → notion-6544KSMM.js} +6 -6
- package/dist/{open_exchange_rates-23QJXVO5.js → open_exchange_rates-4CLN7O2N.js} +5 -5
- package/dist/{openai-ZS7GLSLH.js → openai-HLFGPVI5.js} +6 -6
- package/dist/{opengraph_io-PMVH7OYI.js → opengraph_io-57JDHT3M.js} +5 -5
- package/dist/{openrouter-ONRGFNB6.js → openrouter-WDAVB2OP.js} +6 -6
- package/dist/{outline-UCUYZZ7J.js → outline-A6MDLZVH.js} +6 -6
- package/dist/{paddle-35HTKTUL.js → paddle-WX5ULOPP.js} +6 -6
- package/dist/{perplexity-NVOBYN24.js → perplexity-LYTWWWCZ.js} +6 -6
- package/dist/{pinecone-55CJY73C.js → pinecone-7KAF3S7U.js} +6 -6
- package/dist/{pipedrive-WMCAKS72.js → pipedrive-YQY243G7.js} +6 -6
- package/dist/{polar-SM4ZM53B.js → polar-A5HKXSQY.js} +6 -6
- package/dist/{posthog-NWCXVXNJ.js → posthog-CF2LHLS4.js} +6 -6
- package/dist/{postmark-QJV5PHUQ.js → postmark-W756TMJM.js} +6 -6
- package/dist/{prerender-2W7UT4SC.js → prerender-ZYM4UQ5R.js} +5 -5
- package/dist/{pubmed-VVV7XYLU.js → pubmed-QXTUQCTQ.js} +4 -4
- package/dist/{railway-KGI57S3O.js → railway-F4MOZ3LQ.js} +4 -4
- package/dist/{readwise-AGHTQB42.js → readwise-S7MF5SR5.js} +6 -6
- package/dist/{render-O4HBROCK.js → render-D7EIVDUA.js} +6 -6
- package/dist/{replicate-KWBOMX7D.js → replicate-ABNKPZR7.js} +6 -6
- package/dist/{resend-DRH6Y6I4.js → resend-7VJEY4KC.js} +6 -6
- package/dist/{rootly-XGCUDW6X.js → rootly-UMFJOKXC.js} +6 -6
- package/dist/{scrapfly-OIQ3OY6L.js → scrapfly-UDT4KNFL.js} +5 -5
- package/dist/{scrapingbee-OCZO4FHX.js → scrapingbee-XTFD54NB.js} +5 -5
- package/dist/{screenshot_fyi-CUNGFZOC.js → screenshot_fyi-5GTW3SFY.js} +5 -5
- package/dist/{semantic_scholar-3UJRLKES.js → semantic_scholar-Y6WK2MST.js} +6 -6
- package/dist/{sentry-5BWVZFJV.js → sentry-ZFPGDA6C.js} +6 -6
- package/dist/{shodan-HI37CTEW.js → shodan-3SCDBOQ3.js} +5 -5
- package/dist/{shopify-LJ2EV2HH.js → shopify-LMTBS2I2.js} +6 -6
- package/dist/{stripe-3LHMV55K.js → stripe-4JQJ2CUG.js} +4 -4
- package/dist/{supabase-H2KPX3Q2.js → supabase-7HA3BEFK.js} +6 -6
- package/dist/{tavily-FBEWGH3Z.js → tavily-H34ZBPGC.js} +6 -6
- package/dist/{telegram-MYYO3JND.js → telegram-CRX4YWQ3.js} +5 -5
- package/dist/{telnyx-H4ALEGAX.js → telnyx-TIKGEU34.js} +6 -6
- package/dist/{todoist-OBWICA5Q.js → todoist-LU563DGZ.js} +6 -6
- package/dist/{trello-GUFUJRWO.js → trello-NTRGEROX.js} +5 -5
- package/dist/{turso-NIAK4UMS.js → turso-EY3CNVPZ.js} +6 -6
- package/dist/{twilio-K6SLK2CX.js → twilio-ICX3WRQH.js} +4 -4
- package/dist/{umami-42RS2EPS.js → umami-NPMRVI3M.js} +6 -6
- package/dist/{unsplash-V7TOTETT.js → unsplash-TIHBZFIM.js} +6 -6
- package/dist/{upstash_redis-AWQMB6Y3.js → upstash_redis-2DO6EHCN.js} +6 -6
- package/dist/{uptimerobot-AZC2DHOT.js → uptimerobot-BGYOCKGI.js} +4 -4
- package/dist/{v2ex-4TVRNMLS.js → v2ex-GOWDPGGA.js} +6 -6
- package/dist/{vercel-DPHTJ3XR.js → vercel-G33RXVBI.js} +6 -6
- package/dist/{wolfram_alpha_api-XAG7IXBW.js → wolfram_alpha_api-IRZSMD3P.js} +5 -5
- package/dist/{wordpress-KMPKVGUX.js → wordpress-ATWGGUC3.js} +6 -6
- package/dist/{workos-PKB2YR7S.js → workos-LHJDETBX.js} +6 -6
- package/dist/{zhihu-Y4H4XYPB.js → zhihu-IAH53YPP.js} +6 -6
- package/package.json +3 -3
|
@@ -10,15 +10,14 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
BootstrapStateStore,
|
|
12
12
|
package_default
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-U2UGFSOX.js";
|
|
14
14
|
import {
|
|
15
15
|
createGuardedFetch
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-GQ4O7NK5.js";
|
|
17
17
|
import {
|
|
18
18
|
AnnotationStore,
|
|
19
19
|
CONTEXT_CAPABILITIES,
|
|
20
20
|
CONTEXT_DIRECT_UPLOAD_CAPABILITY,
|
|
21
|
-
DEFAULT_MAX_NODES,
|
|
22
21
|
DEVICE_CALL_TIMEOUT_MS,
|
|
23
22
|
DeviceGatewaySession,
|
|
24
23
|
DeviceMailboxService,
|
|
@@ -35,6 +34,7 @@ import {
|
|
|
35
34
|
MAX_TREE_DEPTH,
|
|
36
35
|
NodeRegistryStore,
|
|
37
36
|
OAUTH_CLIENT_FIELDS,
|
|
37
|
+
OperationRegistry,
|
|
38
38
|
PG_SEARCH_INSERT_ROWS_MAX,
|
|
39
39
|
PG_SEARCH_SCHEMA_STATEMENTS,
|
|
40
40
|
PG_SEARCH_SNAPSHOTS_COLUMNS,
|
|
@@ -72,6 +72,7 @@ import {
|
|
|
72
72
|
buildHttpRequest,
|
|
73
73
|
buildTokenRequest,
|
|
74
74
|
buildTree,
|
|
75
|
+
canonicalizePath,
|
|
75
76
|
catalogSetDigest,
|
|
76
77
|
check,
|
|
77
78
|
checkAllowlist,
|
|
@@ -99,6 +100,7 @@ import {
|
|
|
99
100
|
deploymentSettingsSchema,
|
|
100
101
|
derivePresence,
|
|
101
102
|
deviceDirectoryHelpModel,
|
|
103
|
+
deviceEnvironmentSchema,
|
|
102
104
|
deviceFsHelpModel,
|
|
103
105
|
deviceOperationClaimRequestSchema,
|
|
104
106
|
deviceOperationClaimResponseSchema,
|
|
@@ -109,6 +111,7 @@ import {
|
|
|
109
111
|
deviceOperationListResponseSchema,
|
|
110
112
|
deviceOperationRenewRequestSchema,
|
|
111
113
|
deviceOperationRenewResponseSchema,
|
|
114
|
+
deviceOperationStateSchema,
|
|
112
115
|
deviceOperationSummarySchema,
|
|
113
116
|
deviceShellHelpModel,
|
|
114
117
|
dispatchContextCmd,
|
|
@@ -176,6 +179,7 @@ import {
|
|
|
176
179
|
storeUri,
|
|
177
180
|
tbErrorBodySchema,
|
|
178
181
|
toolHelpModel,
|
|
182
|
+
toolSearchOptionsSchema,
|
|
179
183
|
toolSearchPageSchema,
|
|
180
184
|
toolSearchRelevanceSchema,
|
|
181
185
|
toolSearchRequestSchema,
|
|
@@ -188,7 +192,7 @@ import {
|
|
|
188
192
|
validatePath,
|
|
189
193
|
validateStoreTokenKeyring,
|
|
190
194
|
virtualizeTools
|
|
191
|
-
} from "./chunk-
|
|
195
|
+
} from "./chunk-7MUNQNXG.js";
|
|
192
196
|
|
|
193
197
|
// src/config.ts
|
|
194
198
|
function runtimeAppSettings(settings, instanceId) {
|
|
@@ -216,7 +220,7 @@ function runtimeAppSettings(settings, instanceId) {
|
|
|
216
220
|
// ../app/package.json
|
|
217
221
|
var package_default2 = {
|
|
218
222
|
name: "@tool-bridge/app",
|
|
219
|
-
version: "0.
|
|
223
|
+
version: "0.23.0",
|
|
220
224
|
description: "Host-neutral HTBP application: assemble the tool-bridge tree on any runtime by injecting state, object, secret, device-channel and search adapters",
|
|
221
225
|
type: "module",
|
|
222
226
|
license: "MIT",
|
|
@@ -254,7 +258,8 @@ var package_default2 = {
|
|
|
254
258
|
"@modelcontextprotocol/client": "catalog:",
|
|
255
259
|
"@modelcontextprotocol/core": "catalog:",
|
|
256
260
|
"@modelcontextprotocol/server": "catalog:",
|
|
257
|
-
hono: "catalog:"
|
|
261
|
+
hono: "catalog:",
|
|
262
|
+
zod: "catalog:"
|
|
258
263
|
},
|
|
259
264
|
devDependencies: {
|
|
260
265
|
"@modelcontextprotocol/sdk": "catalog:",
|
|
@@ -262,8 +267,7 @@ var package_default2 = {
|
|
|
262
267
|
"@tool-bridge/plugins": "workspace:*",
|
|
263
268
|
tsup: "catalog:",
|
|
264
269
|
typescript: "catalog:",
|
|
265
|
-
vitest: "catalog:"
|
|
266
|
-
zod: "catalog:"
|
|
270
|
+
vitest: "catalog:"
|
|
267
271
|
},
|
|
268
272
|
repository: {
|
|
269
273
|
type: "git",
|
|
@@ -13607,8 +13611,8 @@ var require_utils = /* @__PURE__ */ __commonJSMin2(((exports, module) => {
|
|
|
13607
13611
|
}
|
|
13608
13612
|
function consumeHextets(buffer, address, output) {
|
|
13609
13613
|
if (buffer.length) {
|
|
13610
|
-
const
|
|
13611
|
-
if (
|
|
13614
|
+
const hex = stringArrayToHexStripped(buffer);
|
|
13615
|
+
if (hex !== "") address.push(hex);
|
|
13612
13616
|
else {
|
|
13613
13617
|
output.error = true;
|
|
13614
13618
|
return false;
|
|
@@ -19302,6 +19306,10 @@ async function processDeviceHello(opts) {
|
|
|
19302
19306
|
throw new TBError("permission_denied", `no scope grants 'register' on '${mountPath}'`);
|
|
19303
19307
|
}
|
|
19304
19308
|
if (hello.expose.fs !== void 0) assertFsRoots(hello.expose.fs.roots);
|
|
19309
|
+
const environment = hello.expose.environment === void 0 ? void 0 : deviceEnvironmentSchema.safeParse(hello.expose.environment);
|
|
19310
|
+
if (environment !== void 0 && !environment.success) {
|
|
19311
|
+
throw new TBError("invalid_argument", "device environment contains invalid or unsupported fields");
|
|
19312
|
+
}
|
|
19305
19313
|
const inputs = nodesForHello(mountPath, hello.deviceId, hello.expose);
|
|
19306
19314
|
const registry = new NodeRegistryStore(store);
|
|
19307
19315
|
for (const input of inputs) {
|
|
@@ -19320,7 +19328,12 @@ async function processDeviceHello(opts) {
|
|
|
19320
19328
|
input,
|
|
19321
19329
|
authCtx.keyId,
|
|
19322
19330
|
now,
|
|
19323
|
-
input.path === mountPath ? {
|
|
19331
|
+
input.path === mountPath ? {
|
|
19332
|
+
deviceId: hello.deviceId,
|
|
19333
|
+
online: true,
|
|
19334
|
+
lastSeenAt: now,
|
|
19335
|
+
...environment === void 0 ? {} : { deviceEnvironment: environment.data, deviceReportedAt: now }
|
|
19336
|
+
} : {}
|
|
19324
19337
|
);
|
|
19325
19338
|
} catch (error) {
|
|
19326
19339
|
await searchSync?.abort(marker);
|
|
@@ -24524,8 +24537,8 @@ function syntheticElicitationId() {
|
|
|
24524
24537
|
webCrypto.getRandomValues(bytes);
|
|
24525
24538
|
bytes[6] = bytes[6] & 15 | 64;
|
|
24526
24539
|
bytes[8] = bytes[8] & 63 | 128;
|
|
24527
|
-
const
|
|
24528
|
-
return `${
|
|
24540
|
+
const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
24541
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
24529
24542
|
}
|
|
24530
24543
|
function legacyShimFailure(method, message) {
|
|
24531
24544
|
if (method === "tools/call") return {
|
|
@@ -27003,24 +27016,6 @@ function createMcpHandler(factory, options = {}) {
|
|
|
27003
27016
|
}
|
|
27004
27017
|
|
|
27005
27018
|
// ../app/src/mcpServer.ts
|
|
27006
|
-
function hex(bytes) {
|
|
27007
|
-
return [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
27008
|
-
}
|
|
27009
|
-
function mcpToolIdentity(invokePath, toolName) {
|
|
27010
|
-
return JSON.stringify([invokePath, toolName]);
|
|
27011
|
-
}
|
|
27012
|
-
async function mcpToolName(identity2) {
|
|
27013
|
-
const encoded = [...new TextEncoder().encode(identity2)].map((byte) => {
|
|
27014
|
-
const char = String.fromCharCode(byte);
|
|
27015
|
-
if (/[A-Za-z0-9.-]/.test(char)) return char;
|
|
27016
|
-
if (char === "_") return "__";
|
|
27017
|
-
return `_${byte.toString(16).padStart(2, "0")}`;
|
|
27018
|
-
}).join("");
|
|
27019
|
-
const prefixed = `tb_${encoded}`;
|
|
27020
|
-
if (prefixed.length <= 128) return prefixed;
|
|
27021
|
-
const digest = new Uint8Array(await crypto.subtle.digest("SHA-256", new TextEncoder().encode(identity2)));
|
|
27022
|
-
return `tb_${encoded.slice(0, 60)}_${hex(digest)}`;
|
|
27023
|
-
}
|
|
27024
27019
|
var SUBSCHEMA_KEYS = [
|
|
27025
27020
|
"additionalProperties",
|
|
27026
27021
|
"contains",
|
|
@@ -27050,7 +27045,10 @@ function assertSchemaShape(value, path, depth = 0) {
|
|
|
27050
27045
|
if (depth >= MAX_SCHEMA_DEPTH) throw new Error(`JSON Schema nested too deeply at '${path}'`);
|
|
27051
27046
|
const schema = value;
|
|
27052
27047
|
for (const key of SUBSCHEMA_KEYS) {
|
|
27053
|
-
|
|
27048
|
+
const sub = schema[key];
|
|
27049
|
+
if (key === "items" && Array.isArray(sub)) {
|
|
27050
|
+
sub.forEach((item, i) => assertSchemaShape(item, `${path}/items/${i}`, depth + 1));
|
|
27051
|
+
} else if (sub !== void 0) assertSchemaShape(sub, `${path}/${key}`, depth + 1);
|
|
27054
27052
|
}
|
|
27055
27053
|
for (const key of SUBSCHEMA_MAP_KEYS) {
|
|
27056
27054
|
const map = schema[key];
|
|
@@ -27069,9 +27067,9 @@ function assertSchemaShape(value, path, depth = 0) {
|
|
|
27069
27067
|
list.forEach((sub, i) => assertSchemaShape(sub, `${path}/${key}/${i}`, depth + 1));
|
|
27070
27068
|
}
|
|
27071
27069
|
}
|
|
27072
|
-
function inputSchemaOf(raw
|
|
27073
|
-
if (raw === void 0
|
|
27074
|
-
const source = raw
|
|
27070
|
+
function inputSchemaOf(raw) {
|
|
27071
|
+
if (raw === void 0) return { type: "object", properties: {} };
|
|
27072
|
+
const source = raw;
|
|
27075
27073
|
if (source === null || typeof source !== "object" || Array.isArray(source)) {
|
|
27076
27074
|
throw new Error("MCP tool inputSchema must be a JSON Schema object");
|
|
27077
27075
|
}
|
|
@@ -27080,23 +27078,21 @@ function inputSchemaOf(raw, delivery) {
|
|
|
27080
27078
|
throw new Error("MCP tool inputSchema root type must be object");
|
|
27081
27079
|
}
|
|
27082
27080
|
assertSchemaShape(schema, "inputSchema");
|
|
27083
|
-
|
|
27084
|
-
|
|
27081
|
+
return { ...schema, type: "object" };
|
|
27082
|
+
}
|
|
27083
|
+
function inputValidator(raw, path) {
|
|
27084
|
+
try {
|
|
27085
|
+
return new ToolJsonSchemaValidator().getValidator(
|
|
27086
|
+
inputSchemaOf(raw)
|
|
27087
|
+
);
|
|
27088
|
+
} catch {
|
|
27089
|
+
throw new ProtocolError3(ProtocolErrorCode2.InternalError, `invalid input schema for '${path}'`);
|
|
27085
27090
|
}
|
|
27086
|
-
|
|
27087
|
-
|
|
27088
|
-
|
|
27089
|
-
|
|
27090
|
-
|
|
27091
|
-
properties: {
|
|
27092
|
-
...properties ?? {},
|
|
27093
|
-
"~delivery": {
|
|
27094
|
-
type: "string",
|
|
27095
|
-
enum: delivery === "both" ? ["realtime", "mailbox", "fallback"] : ["mailbox", "fallback"],
|
|
27096
|
-
description: "Tool Bridge delivery policy; fallback prefers realtime and queues only when dispatch definitely did not occur."
|
|
27097
|
-
}
|
|
27098
|
-
}
|
|
27099
|
-
};
|
|
27091
|
+
}
|
|
27092
|
+
function validateMcpArguments(raw, args, path) {
|
|
27093
|
+
const validate = inputValidator(raw, path);
|
|
27094
|
+
const result = validate(args);
|
|
27095
|
+
if (!result.valid) throw new ProtocolError3(ProtocolErrorCode2.InvalidParams, result.errorMessage);
|
|
27100
27096
|
}
|
|
27101
27097
|
function annotationsOf(tool) {
|
|
27102
27098
|
const annotations = {};
|
|
@@ -27105,69 +27101,26 @@ function annotationsOf(tool) {
|
|
|
27105
27101
|
if (tool.effect === "destructive" || tool.confirm === true) annotations.destructiveHint = true;
|
|
27106
27102
|
return Object.keys(annotations).length > 0 ? annotations : void 0;
|
|
27107
27103
|
}
|
|
27108
|
-
|
|
27109
|
-
const unique = /* @__PURE__ */ new Map();
|
|
27110
|
-
for (const tool of source) {
|
|
27111
|
-
if (unique.has(tool.identity)) {
|
|
27112
|
-
throw new ProtocolError3(ProtocolErrorCode2.InternalError, "duplicate HTBP tool identity");
|
|
27113
|
-
}
|
|
27114
|
-
unique.set(tool.identity, tool);
|
|
27115
|
-
}
|
|
27116
|
-
const projected = await Promise.all(
|
|
27117
|
-
[...unique.values()].map(async (bridge) => {
|
|
27118
|
-
const name = bridge.mcpName ?? await mcpToolName(bridge.identity);
|
|
27119
|
-
const annotations = annotationsOf(bridge);
|
|
27120
|
-
const description = bridge.description === void 0 ? `HTBP ${bridge.invokePath}` : `${bridge.description}
|
|
27121
|
-
|
|
27122
|
-
HTBP ${bridge.invokePath}`;
|
|
27123
|
-
let inputSchema;
|
|
27124
|
-
try {
|
|
27125
|
-
inputSchema = inputSchemaOf(bridge.inputSchema, bridge.delivery);
|
|
27126
|
-
} catch {
|
|
27127
|
-
throw new ProtocolError3(
|
|
27128
|
-
ProtocolErrorCode2.InternalError,
|
|
27129
|
-
`invalid input schema for '${bridge.sourcePath}/${bridge.toolName}'`
|
|
27130
|
-
);
|
|
27131
|
-
}
|
|
27132
|
-
const candidate = {
|
|
27133
|
-
name,
|
|
27134
|
-
description,
|
|
27135
|
-
inputSchema,
|
|
27136
|
-
_meta: {
|
|
27137
|
-
"io.tool-bridge/path": bridge.sourcePath,
|
|
27138
|
-
"io.tool-bridge/command": bridge.toolName
|
|
27139
|
-
},
|
|
27140
|
-
...annotations !== void 0 ? { annotations } : {}
|
|
27141
|
-
};
|
|
27142
|
-
const parsed = ToolSchema.safeParse(candidate);
|
|
27143
|
-
if (!parsed.success) {
|
|
27144
|
-
throw new ProtocolError3(
|
|
27145
|
-
ProtocolErrorCode2.InternalError,
|
|
27146
|
-
`invalid tool metadata for '${bridge.sourcePath}/${bridge.toolName}'`
|
|
27147
|
-
);
|
|
27148
|
-
}
|
|
27149
|
-
let validateInput;
|
|
27150
|
-
try {
|
|
27151
|
-
validateInput = validator.getValidator(
|
|
27152
|
-
parsed.data.inputSchema
|
|
27153
|
-
);
|
|
27154
|
-
} catch {
|
|
27155
|
-
throw new ProtocolError3(
|
|
27156
|
-
ProtocolErrorCode2.InternalError,
|
|
27157
|
-
`invalid input schema for '${bridge.sourcePath}/${bridge.toolName}'`
|
|
27158
|
-
);
|
|
27159
|
-
}
|
|
27160
|
-
return { bridge, tool: parsed.data, validateInput };
|
|
27161
|
-
})
|
|
27162
|
-
);
|
|
27104
|
+
function projectTools(source) {
|
|
27163
27105
|
const names = /* @__PURE__ */ new Set();
|
|
27164
|
-
|
|
27165
|
-
if (names.has(
|
|
27106
|
+
return source.map((bridge) => {
|
|
27107
|
+
if (names.has(bridge.name)) {
|
|
27166
27108
|
throw new ProtocolError3(ProtocolErrorCode2.InternalError, "MCP tool name collision");
|
|
27167
27109
|
}
|
|
27168
|
-
names.add(
|
|
27169
|
-
|
|
27170
|
-
|
|
27110
|
+
names.add(bridge.name);
|
|
27111
|
+
const annotations = annotationsOf(bridge);
|
|
27112
|
+
const validateInput = inputValidator(bridge.inputSchema, bridge.name);
|
|
27113
|
+
const parsed = ToolSchema.safeParse({
|
|
27114
|
+
name: bridge.name,
|
|
27115
|
+
description: bridge.description,
|
|
27116
|
+
inputSchema: inputSchemaOf(bridge.inputSchema),
|
|
27117
|
+
...annotations === void 0 ? {} : { annotations }
|
|
27118
|
+
});
|
|
27119
|
+
if (!parsed.success) {
|
|
27120
|
+
throw new ProtocolError3(ProtocolErrorCode2.InternalError, `invalid tool metadata for '${bridge.name}'`);
|
|
27121
|
+
}
|
|
27122
|
+
return { bridge, tool: parsed.data, validateInput };
|
|
27123
|
+
}).sort((a, b) => a.tool.name.localeCompare(b.tool.name));
|
|
27171
27124
|
}
|
|
27172
27125
|
function contentOf(value) {
|
|
27173
27126
|
if (Array.isArray(value)) {
|
|
@@ -27188,12 +27141,13 @@ function buildMcpServer(version, bridge, listTtlMs) {
|
|
|
27188
27141
|
cacheHints: { "tools/list": { ttlMs: listTtlMs, cacheScope: "private" } }
|
|
27189
27142
|
}
|
|
27190
27143
|
);
|
|
27144
|
+
let projected;
|
|
27145
|
+
const tools = () => projected ??= bridge.list().then(projectTools);
|
|
27191
27146
|
server.setRequestHandler("tools/list", async () => ({
|
|
27192
|
-
tools: (await
|
|
27147
|
+
tools: (await tools()).map((item) => item.tool)
|
|
27193
27148
|
}));
|
|
27194
27149
|
server.setRequestHandler("tools/call", async (rpc) => {
|
|
27195
|
-
const
|
|
27196
|
-
const selected = projected.find((item) => item.tool.name === rpc.params.name);
|
|
27150
|
+
const selected = (await tools()).find((item) => item.tool.name === rpc.params.name);
|
|
27197
27151
|
if (selected === void 0) {
|
|
27198
27152
|
throw new ProtocolError3(ProtocolErrorCode2.InvalidParams, "tool not found");
|
|
27199
27153
|
}
|
|
@@ -27202,9 +27156,15 @@ function buildMcpServer(version, bridge, listTtlMs) {
|
|
|
27202
27156
|
if (!validation.valid) {
|
|
27203
27157
|
throw new ProtocolError3(ProtocolErrorCode2.InvalidParams, validation.errorMessage);
|
|
27204
27158
|
}
|
|
27205
|
-
|
|
27159
|
+
let result;
|
|
27160
|
+
try {
|
|
27161
|
+
result = await bridge.call(selected.bridge, args);
|
|
27162
|
+
} catch (error) {
|
|
27163
|
+
if (!isTBError(error)) throw error;
|
|
27164
|
+
result = { content: error.toJSON(), isError: true };
|
|
27165
|
+
}
|
|
27206
27166
|
const candidate = {
|
|
27207
|
-
content: contentOf(result.content),
|
|
27167
|
+
content: contentOf(result.contentBlocks ?? result.content),
|
|
27208
27168
|
...result.isError === true ? { isError: true } : {},
|
|
27209
27169
|
...result.structuredContent !== void 0 ? { structuredContent: result.structuredContent } : result.content !== null && typeof result.content === "object" && !Array.isArray(result.content) ? { structuredContent: result.content } : {}
|
|
27210
27170
|
};
|
|
@@ -28444,6 +28404,7 @@ var RemotePathProjector = class {
|
|
|
28444
28404
|
node: { ...help.node, path: nodePath },
|
|
28445
28405
|
cmds,
|
|
28446
28406
|
...children === void 0 ? {} : { children },
|
|
28407
|
+
...help.deviceContext === void 0 ? {} : { deviceContext: help.deviceContext },
|
|
28447
28408
|
...help.feedback === void 0 ? {} : { feedback: help.feedback },
|
|
28448
28409
|
...help.hint === void 0 ? {} : { hint: help.hint },
|
|
28449
28410
|
...help.note === void 0 ? {} : { note: help.note }
|
|
@@ -30676,6 +30637,9 @@ function registerSearchRoute(app, env) {
|
|
|
30676
30637
|
);
|
|
30677
30638
|
}
|
|
30678
30639
|
|
|
30640
|
+
// ../app/src/routes/mcp.ts
|
|
30641
|
+
import { z as z5 } from "zod/v4";
|
|
30642
|
+
|
|
30679
30643
|
// ../app/src/helpModel.ts
|
|
30680
30644
|
async function helpModelFor(node, registry, ctx, builtins, deps, opts) {
|
|
30681
30645
|
const index = opts.schemas !== true;
|
|
@@ -30696,7 +30660,13 @@ async function helpModelFor(node, registry, ctx, builtins, deps, opts) {
|
|
|
30696
30660
|
now: opts.now
|
|
30697
30661
|
});
|
|
30698
30662
|
return deviceDirectoryHelpModel(
|
|
30699
|
-
{
|
|
30663
|
+
{
|
|
30664
|
+
path: node.path,
|
|
30665
|
+
description: node.description,
|
|
30666
|
+
presence,
|
|
30667
|
+
...node.deviceEnvironment === void 0 ? {} : { environment: node.deviceEnvironment },
|
|
30668
|
+
...node.deviceReportedAt === void 0 ? {} : { reportedAt: node.deviceReportedAt }
|
|
30669
|
+
},
|
|
30700
30670
|
children.map((n) => ({ path: n.path, kind: n.kind, description: n.description }))
|
|
30701
30671
|
);
|
|
30702
30672
|
}
|
|
@@ -30799,362 +30769,210 @@ async function commandHelpModelFor(registry, ctx, builtins, deps, path, opts) {
|
|
|
30799
30769
|
};
|
|
30800
30770
|
}
|
|
30801
30771
|
|
|
30802
|
-
// ../app/src/
|
|
30803
|
-
|
|
30804
|
-
|
|
30805
|
-
|
|
30806
|
-
|
|
30807
|
-
|
|
30808
|
-
|
|
30809
|
-
|
|
30810
|
-
|
|
30811
|
-
|
|
30812
|
-
|
|
30813
|
-
|
|
30814
|
-
|
|
30815
|
-
|
|
30816
|
-
|
|
30817
|
-
...
|
|
30818
|
-
|
|
30819
|
-
|
|
30820
|
-
|
|
30821
|
-
|
|
30822
|
-
|
|
30823
|
-
|
|
30824
|
-
|
|
30825
|
-
|
|
30826
|
-
|
|
30827
|
-
|
|
30828
|
-
|
|
30829
|
-
|
|
30830
|
-
|
|
30831
|
-
|
|
30832
|
-
|
|
30833
|
-
|
|
30834
|
-
|
|
30835
|
-
|
|
30836
|
-
}
|
|
30837
|
-
|
|
30838
|
-
|
|
30839
|
-
|
|
30772
|
+
// ../app/src/mcpInvoke.ts
|
|
30773
|
+
function mcpPath(path, allowRoot = false) {
|
|
30774
|
+
const error = validatePath(path, { allowRoot });
|
|
30775
|
+
if (error !== null) throw error;
|
|
30776
|
+
return canonicalizePath(path).split("/").map(encodeURIComponent).join("/");
|
|
30777
|
+
}
|
|
30778
|
+
function mcpRequest(c, app, path, body, extraHeaders) {
|
|
30779
|
+
return Promise.resolve(app.request(new Request(new URL(path, c.req.url), {
|
|
30780
|
+
method: body === void 0 ? "GET" : "POST",
|
|
30781
|
+
headers: {
|
|
30782
|
+
"authorization": c.req.header("authorization") ?? "",
|
|
30783
|
+
"accept": "application/json",
|
|
30784
|
+
"content-type": "application/json",
|
|
30785
|
+
...extraHeaders
|
|
30786
|
+
},
|
|
30787
|
+
...body === void 0 ? {} : { body: JSON.stringify(body) },
|
|
30788
|
+
signal: c.req.raw.signal
|
|
30789
|
+
})));
|
|
30790
|
+
}
|
|
30791
|
+
async function mcpResponse(response) {
|
|
30792
|
+
const text = await response.text();
|
|
30793
|
+
let content = text;
|
|
30794
|
+
try {
|
|
30795
|
+
content = JSON.parse(text);
|
|
30796
|
+
} catch {
|
|
30797
|
+
}
|
|
30798
|
+
return { content, ...response.ok ? {} : { isError: true } };
|
|
30799
|
+
}
|
|
30800
|
+
async function invokeMcpTarget(c, env, app, input) {
|
|
30801
|
+
const encoded = mcpPath(input.path);
|
|
30802
|
+
const path = canonicalizePath(input.path);
|
|
30803
|
+
const args = { ...input.args };
|
|
30804
|
+
if (input.delivery !== void 0 && Object.hasOwn(args, "~delivery")) {
|
|
30805
|
+
throw new TBError("invalid_argument", "delivery and args.~delivery cannot both be provided");
|
|
30806
|
+
}
|
|
30807
|
+
const delivery = input.delivery ?? args["~delivery"];
|
|
30808
|
+
delete args["~delivery"];
|
|
30809
|
+
if (Object.keys(args).some((key) => key.startsWith("~"))) {
|
|
30810
|
+
throw new TBError("invalid_argument", "unknown invocation control in args");
|
|
30811
|
+
}
|
|
30812
|
+
if (delivery !== void 0 && delivery !== "realtime" && delivery !== "mailbox" && delivery !== "fallback") {
|
|
30813
|
+
throw new TBError("invalid_argument", "delivery must be realtime, mailbox or fallback");
|
|
30814
|
+
}
|
|
30815
|
+
if ((input.ttlSeconds !== void 0 || input.idempotencyKey !== void 0) && input.delivery !== "mailbox" && input.delivery !== "fallback") {
|
|
30816
|
+
throw new TBError("invalid_argument", "ttlSeconds and idempotencyKey require mailbox or fallback delivery");
|
|
30817
|
+
}
|
|
30818
|
+
const { deps, searchSync } = env;
|
|
30840
30819
|
const ctx = c.get("ctx");
|
|
30841
30820
|
const registry = new NodeRegistryStore(c.get("store"));
|
|
30842
|
-
|
|
30843
|
-
|
|
30844
|
-
|
|
30845
|
-
|
|
30846
|
-
|
|
30847
|
-
|
|
30848
|
-
|
|
30849
|
-
|
|
30850
|
-
|
|
30851
|
-
|
|
30852
|
-
|
|
30853
|
-
|
|
30854
|
-
|
|
30855
|
-
|
|
30856
|
-
|
|
30857
|
-
|
|
30858
|
-
|
|
30859
|
-
|
|
30860
|
-
cursor: { type: "string", minLength: 1 },
|
|
30861
|
-
detail: { type: "string", enum: ["compact", "full"], default: "compact" },
|
|
30862
|
-
effects: {
|
|
30863
|
-
type: "array",
|
|
30864
|
-
minItems: 1,
|
|
30865
|
-
items: {
|
|
30866
|
-
type: "string",
|
|
30867
|
-
enum: ["read", "write", "destructive", "unknown"]
|
|
30868
|
-
}
|
|
30869
|
-
},
|
|
30870
|
-
federation: { type: "string", enum: ["local", "recursive"] },
|
|
30871
|
-
matching: { type: "string", enum: ["best", "all"] },
|
|
30872
|
-
minCoverage: { type: "number", exclusiveMinimum: 0, maximum: 1 },
|
|
30873
|
-
pathPrefix: { type: "string", minLength: 1 }
|
|
30874
|
-
},
|
|
30875
|
-
required: ["query"]
|
|
30876
|
-
}
|
|
30877
|
-
}] : [],
|
|
30878
|
-
{
|
|
30879
|
-
identity: JSON.stringify(["control", "help"]),
|
|
30880
|
-
sourcePath: "",
|
|
30881
|
-
toolName: "Help",
|
|
30882
|
-
invokePath: "/~help",
|
|
30883
|
-
mcpName: "tb_help",
|
|
30884
|
-
operation: "help",
|
|
30885
|
-
description: "Describe a visible Tool Bridge node or one of its tools.",
|
|
30886
|
-
effect: "read",
|
|
30887
|
-
inputSchema: {
|
|
30888
|
-
type: "object",
|
|
30889
|
-
additionalProperties: false,
|
|
30890
|
-
properties: {
|
|
30891
|
-
path: { type: "string" },
|
|
30892
|
-
tool: { type: "string", minLength: 1, pattern: "^[^/]+$" },
|
|
30893
|
-
format: { type: "string", enum: ["json", "markdown", "dsl"] }
|
|
30894
|
-
}
|
|
30895
|
-
}
|
|
30896
|
-
},
|
|
30897
|
-
{
|
|
30898
|
-
identity: JSON.stringify(["control", "list-nodes"]),
|
|
30899
|
-
sourcePath: "",
|
|
30900
|
-
toolName: "List",
|
|
30901
|
-
invokePath: "/~tree",
|
|
30902
|
-
mcpName: "tb_list_nodes",
|
|
30903
|
-
operation: "listNodes",
|
|
30904
|
-
description: "List the visible Tool Bridge node tree from a path.",
|
|
30905
|
-
effect: "read",
|
|
30906
|
-
inputSchema: {
|
|
30907
|
-
type: "object",
|
|
30908
|
-
additionalProperties: false,
|
|
30909
|
-
properties: {
|
|
30910
|
-
path: { type: "string" },
|
|
30911
|
-
depth: { type: "integer", minimum: 0, maximum: MAX_TREE_DEPTH }
|
|
30912
|
-
}
|
|
30913
|
-
}
|
|
30914
|
-
}
|
|
30915
|
-
];
|
|
30916
|
-
const takeRemoteRequest = () => {
|
|
30917
|
-
remoteRequests += 1;
|
|
30918
|
-
if (remoteRequests > MCP_REMOTE_MAX_REQUESTS) {
|
|
30919
|
-
throw new TBError("unavailable", "remote MCP discovery request budget exceeded", {
|
|
30920
|
-
retryable: false
|
|
30921
|
-
});
|
|
30922
|
-
}
|
|
30923
|
-
};
|
|
30924
|
-
const remoteHelp = async (path) => {
|
|
30925
|
-
takeRemoteRequest();
|
|
30926
|
-
const projector = await remotePathProjectorIfMatch(registry, path);
|
|
30927
|
-
if (projector === null) {
|
|
30928
|
-
throw remoteProtocolError(`remote ~help path '${path}' lost its mount owner`);
|
|
30929
|
-
}
|
|
30930
|
-
const headers = new Headers(c.req.raw.headers);
|
|
30931
|
-
headers.set("accept", "application/json");
|
|
30932
|
-
const response = await remotePassthroughIfMatch(
|
|
30933
|
-
c,
|
|
30934
|
-
ctx,
|
|
30935
|
-
registry,
|
|
30936
|
-
path,
|
|
30937
|
-
"~help",
|
|
30938
|
-
deps,
|
|
30939
|
-
headers
|
|
30940
|
-
);
|
|
30941
|
-
if (response === null || !response.ok) {
|
|
30942
|
-
throw new TBError("unavailable", `remote ~help failed for '${path}'`, { retryable: true });
|
|
30943
|
-
}
|
|
30944
|
-
const parsed = helpJsonSchema.safeParse(await response.json().catch(() => null));
|
|
30945
|
-
if (!parsed.success) {
|
|
30946
|
-
throw new TBError("unavailable", `remote ~help returned invalid JSON for '${path}'`);
|
|
30821
|
+
const resolved = await registry.resolve(path).catch(() => null);
|
|
30822
|
+
if (resolved === null) throw TBError.notFound("not found");
|
|
30823
|
+
const { node, rest: command } = resolved;
|
|
30824
|
+
if (node.kind === "remote") {
|
|
30825
|
+
if (!check(ctx, path, "read").allow) throw TBError.notFound("not found");
|
|
30826
|
+
if (!check(ctx, path, "call").allow) {
|
|
30827
|
+
throw new TBError("permission_denied", `no scope grants 'call' on '${path}'`);
|
|
30828
|
+
}
|
|
30829
|
+
const response2 = await mcpRequest(c, app, `/${encoded}/~help`);
|
|
30830
|
+
if (!response2.ok) return mcpResponse(response2);
|
|
30831
|
+
const model = helpJsonSchema.safeParse(await response2.json().catch(() => null));
|
|
30832
|
+
if (!model.success) throw new TBError("unavailable", "remote command help returned invalid JSON");
|
|
30833
|
+
const selected = model.data.cmds.find((cmd) => canonicalizePath(cmd.path) === path);
|
|
30834
|
+
if (selected === void 0) throw TBError.notFound("not found");
|
|
30835
|
+
validateMcpArguments(selected.inputSchema, args, path);
|
|
30836
|
+
} else {
|
|
30837
|
+
if (command === "" || command.includes("/") || !check(ctx, node.path, "read").allow) {
|
|
30838
|
+
throw TBError.notFound("not found");
|
|
30947
30839
|
}
|
|
30948
|
-
|
|
30949
|
-
|
|
30950
|
-
|
|
30951
|
-
|
|
30952
|
-
const seen = /* @__PURE__ */ new Set();
|
|
30953
|
-
const pending = [{ depth: 0, path: root }];
|
|
30954
|
-
while (pending.length > 0) {
|
|
30955
|
-
const current = pending.shift();
|
|
30956
|
-
if (current === void 0 || seen.has(current.path)) continue;
|
|
30957
|
-
const { depth, path } = current;
|
|
30958
|
-
seen.add(path);
|
|
30959
|
-
if (!check(ctx, path, "read").allow || !check(ctx, path, "call").allow) continue;
|
|
30960
|
-
const owner = await registry.resolve(path).catch(() => null);
|
|
30961
|
-
if (owner?.node.path !== root || owner.node.kind !== "remote") continue;
|
|
30962
|
-
if (found.length >= DEFAULT_MAX_NODES) {
|
|
30963
|
-
throw new TBError("unavailable", "remote MCP discovery node budget exceeded", {
|
|
30964
|
-
retryable: false
|
|
30965
|
-
});
|
|
30840
|
+
const marker = deviceToolMarker(node);
|
|
30841
|
+
if (marker === null && (node.kind === "mcp" || node.kind === "http" || node.kind === "tool")) {
|
|
30842
|
+
if (!check(ctx, node.path, "call").allow) {
|
|
30843
|
+
throw new TBError("permission_denied", `no scope grants 'call' on '${node.path}'`);
|
|
30966
30844
|
}
|
|
30967
|
-
|
|
30968
|
-
|
|
30969
|
-
const children = await remoteTreeChildren(c, ctx, registry, path, deps);
|
|
30970
|
-
if (children.length > 0 && depth >= MAX_TREE_DEPTH) {
|
|
30971
|
-
throw new TBError("unavailable", "remote MCP discovery depth exceeded", {
|
|
30972
|
-
retryable: false
|
|
30973
|
-
});
|
|
30974
|
-
}
|
|
30975
|
-
for (const child of children) {
|
|
30976
|
-
if (child.path.startsWith(`${root}/`) && !seen.has(child.path)) {
|
|
30977
|
-
pending.push({ path: child.path, depth: depth + 1 });
|
|
30978
|
-
}
|
|
30845
|
+
if (delivery !== void 0) {
|
|
30846
|
+
throw new TBError("invalid_argument", "delivery is only supported by device-backed tool commands");
|
|
30979
30847
|
}
|
|
30848
|
+
const provider = await providerFor(node, ctx, deps);
|
|
30849
|
+
const raw = await upstreamTools(node, provider, deps, false, (/* @__PURE__ */ new Date()).toISOString(), searchSync);
|
|
30850
|
+
const selected = virtualizeTools(node.virtualize, raw).exposed.find((tool) => tool.name === command);
|
|
30851
|
+
if (selected === void 0) throw TBError.notFound("not found");
|
|
30852
|
+
validateMcpArguments(selected.inputSchema, args, path);
|
|
30853
|
+
return provider.call(resolveUpstreamTool(node.virtualize, raw, command), args);
|
|
30980
30854
|
}
|
|
30981
|
-
|
|
30982
|
-
|
|
30983
|
-
|
|
30984
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
30985
|
-
const nodes = await pruneExpiredContext(await registry.subtree(""), registry);
|
|
30986
|
-
const result = controlTools();
|
|
30987
|
-
for (const node of nodes) {
|
|
30988
|
-
if (node.kind === "directory") continue;
|
|
30989
|
-
if (!check(ctx, node.path, "read").allow) continue;
|
|
30990
|
-
if (node.kind === "remote") {
|
|
30991
|
-
for (const path of await remotePaths(node.path)) {
|
|
30992
|
-
const model2 = await remoteHelp(path);
|
|
30993
|
-
for (const command of model2.cmds) {
|
|
30994
|
-
if (check(ctx, path, command.scope).allow) {
|
|
30995
|
-
let detailed = command;
|
|
30996
|
-
if (command.inputSchema === void 0 && command.path !== `/${model2.node.path}`) {
|
|
30997
|
-
const detail = await remoteHelp(command.path.replace(/^\/+/, ""));
|
|
30998
|
-
detailed = detail.cmds.find((item) => item.name === command.name) ?? command;
|
|
30999
|
-
}
|
|
31000
|
-
result.push(mcpCommand(path, model2.node.description, detailed));
|
|
31001
|
-
}
|
|
31002
|
-
}
|
|
31003
|
-
}
|
|
31004
|
-
continue;
|
|
31005
|
-
}
|
|
31006
|
-
const marker = deviceToolMarker(node);
|
|
31007
|
-
if (marker !== null) {
|
|
31008
|
-
if (check(ctx, node.path, "call").allow) {
|
|
31009
|
-
result.push(...(marker.cmds ?? []).map((tool) => toolSpecCommand(node, tool)));
|
|
31010
|
-
}
|
|
31011
|
-
continue;
|
|
31012
|
-
}
|
|
31013
|
-
if ((node.kind === "mcp" || node.kind === "http" || node.kind === "tool") && node.config !== void 0) {
|
|
31014
|
-
if (!check(ctx, node.path, "call").allow) continue;
|
|
31015
|
-
const provider = await providerFor(node, ctx, deps);
|
|
31016
|
-
const raw = await upstreamTools(node, provider, deps, false, now, searchSync);
|
|
31017
|
-
const { exposed } = virtualizeTools(node.virtualize, raw);
|
|
31018
|
-
result.push(...exposed.map((tool) => toolSpecCommand(node, tool, true)));
|
|
31019
|
-
continue;
|
|
30855
|
+
if (marker !== null && marker.cmds === void 0) {
|
|
30856
|
+
if (!check(ctx, node.path, "call").allow) {
|
|
30857
|
+
throw new TBError("permission_denied", `no scope grants 'call' on '${node.path}'`);
|
|
31020
30858
|
}
|
|
31021
|
-
|
|
30859
|
+
} else {
|
|
30860
|
+
const model = await helpModelFor(node, registry, ctx, env.builtinsOf(c.get("store")), deps, {
|
|
31022
30861
|
includeDirectUpload: check(ctx, node.path, "write").allow,
|
|
30862
|
+
now: (/* @__PURE__ */ new Date()).toISOString(),
|
|
31023
30863
|
refresh: false,
|
|
31024
|
-
|
|
30864
|
+
schemas: true,
|
|
31025
30865
|
searchSync
|
|
31026
30866
|
});
|
|
31027
|
-
|
|
31028
|
-
|
|
31029
|
-
|
|
31030
|
-
}
|
|
30867
|
+
const selected = model.cmds.find((cmd) => canonicalizePath(cmd.path) === path);
|
|
30868
|
+
if (selected === void 0) throw TBError.notFound("not found");
|
|
30869
|
+
if (!check(ctx, node.path, selected.scope).allow) {
|
|
30870
|
+
throw new TBError("permission_denied", `no scope grants '${selected.scope}' on '${node.path}'`);
|
|
31031
30871
|
}
|
|
30872
|
+
validateMcpArguments(selected.inputSchema, args, path);
|
|
31032
30873
|
}
|
|
31033
|
-
|
|
31034
|
-
}
|
|
30874
|
+
}
|
|
30875
|
+
const query = input.ttlSeconds === void 0 ? "" : `?ttlSeconds=${input.ttlSeconds}`;
|
|
30876
|
+
const response = await mcpRequest(c, app, `/${encoded}${query}`, {
|
|
30877
|
+
...args,
|
|
30878
|
+
...delivery === void 0 ? {} : { "~delivery": delivery }
|
|
30879
|
+
}, input.idempotencyKey === void 0 ? void 0 : { "x-tb-idempotency-key": input.idempotencyKey });
|
|
30880
|
+
const result = await mcpResponse(response);
|
|
30881
|
+
if (delivery !== void 0 && response.ok) {
|
|
30882
|
+
return {
|
|
30883
|
+
content: response.status === 202 ? { delivery: "mailbox", operation: result.content } : { delivery: "realtime", result: result.content }
|
|
30884
|
+
};
|
|
30885
|
+
}
|
|
30886
|
+
return result;
|
|
30887
|
+
}
|
|
30888
|
+
|
|
30889
|
+
// ../app/src/routes/mcp.ts
|
|
30890
|
+
var callInput = z5.strictObject({
|
|
30891
|
+
path: z5.string().min(1).describe("Complete command path returned by tb_help or tb_search; the same path as tb call."),
|
|
30892
|
+
args: z5.record(z5.string(), z5.unknown()).optional().describe("The command arguments object. Defaults to {}."),
|
|
30893
|
+
delivery: z5.enum(["realtime", "mailbox", "fallback"]).optional(),
|
|
30894
|
+
ttlSeconds: z5.number().int().positive().optional(),
|
|
30895
|
+
idempotencyKey: z5.string().min(1).optional()
|
|
30896
|
+
});
|
|
30897
|
+
var operationIdentity = {
|
|
30898
|
+
deviceId: z5.string().min(1),
|
|
30899
|
+
operationId: z5.string().min(1)
|
|
30900
|
+
};
|
|
30901
|
+
var deviceOperationInput = z5.discriminatedUnion("action", [
|
|
30902
|
+
z5.strictObject({
|
|
30903
|
+
action: z5.literal("list"),
|
|
30904
|
+
deviceId: z5.string().min(1),
|
|
30905
|
+
cursor: z5.string().min(1).optional(),
|
|
30906
|
+
limit: z5.number().int().positive().optional(),
|
|
30907
|
+
states: z5.array(deviceOperationStateSchema).min(1).optional()
|
|
30908
|
+
}),
|
|
30909
|
+
z5.strictObject({ action: z5.literal("get"), ...operationIdentity }),
|
|
30910
|
+
z5.strictObject({ action: z5.literal("cancel"), ...operationIdentity })
|
|
30911
|
+
]);
|
|
30912
|
+
function mcpBridgeFor(c, env, app) {
|
|
30913
|
+
const operations = new OperationRegistry();
|
|
30914
|
+
const request = async (path, body) => mcpResponse(await mcpRequest(c, app, path, body));
|
|
30915
|
+
if (env.globalSearchCapabilities().includes("search")) {
|
|
30916
|
+
operations.register("tb_search", {
|
|
30917
|
+
description: 'Search visible Tool Bridge tools, compact by default. Use tb_help on a selected command path for its full schema, then tb_call. Use detail="full" to include schemas in this response.',
|
|
30918
|
+
effect: "read",
|
|
30919
|
+
inputSchema: toolSearchOptionsSchema.extend({ query: z5.string().trim().min(1) })
|
|
30920
|
+
}, async ({ query, ...opts }) => request("/~search", { query, opts }));
|
|
30921
|
+
}
|
|
30922
|
+
operations.register("tb_help", {
|
|
30923
|
+
description: "Describe a visible node or complete command path, including input schema, permissions, effects and device delivery. Root help browses available nodes. Equivalent to tb help.",
|
|
30924
|
+
effect: "read",
|
|
30925
|
+
inputSchema: z5.strictObject({
|
|
30926
|
+
path: z5.string().optional(),
|
|
30927
|
+
tool: z5.string().min(1).regex(/^[^/]+$/).optional(),
|
|
30928
|
+
format: z5.enum(["json", "markdown", "dsl"]).optional(),
|
|
30929
|
+
schemas: z5.boolean().optional()
|
|
30930
|
+
})
|
|
30931
|
+
}, async ({ path = "", tool, format = "json", schemas: schemas2 }) => {
|
|
30932
|
+
const prefix = mcpPath(path, true);
|
|
30933
|
+
if (tool !== void 0 && prefix === "") {
|
|
30934
|
+
throw new TBError("invalid_argument", "tool detail requires a node path");
|
|
30935
|
+
}
|
|
30936
|
+
const command = tool === void 0 ? prefix : `${prefix}/${mcpPath(tool)}`;
|
|
30937
|
+
const response = await mcpRequest(c, app, `/${command ? `${command}/` : ""}~help${schemas2 ? "?schemas=1" : ""}`, void 0, {
|
|
30938
|
+
accept: format === "json" ? "application/json" : format === "dsl" ? "text/plain" : "text/markdown"
|
|
30939
|
+
});
|
|
30940
|
+
return mcpResponse(response);
|
|
30941
|
+
});
|
|
30942
|
+
operations.register("tb_list_nodes", {
|
|
30943
|
+
description: "Browse visible Tool Bridge nodes at a bounded depth. Use tb_help to inspect one node or command. Equivalent to tb ls / tb tree; works without search.",
|
|
30944
|
+
effect: "read",
|
|
30945
|
+
inputSchema: z5.strictObject({
|
|
30946
|
+
path: z5.string().optional(),
|
|
30947
|
+
depth: z5.number().int().min(0).max(MAX_TREE_DEPTH).optional()
|
|
30948
|
+
})
|
|
30949
|
+
}, async ({ path = "", depth = 1 }) => {
|
|
30950
|
+
const prefix = mcpPath(path, true);
|
|
30951
|
+
return request(`/${prefix ? `${prefix}/` : ""}~tree?depth=${depth}`);
|
|
30952
|
+
});
|
|
30953
|
+
operations.register("tb_call", {
|
|
30954
|
+
description: "Invoke one Tool Bridge command by its complete path and arguments, equivalent to tb call. Discover unknown commands with tb_search / tb_help; check the target effect and confirm before writes. Supports tools, Context, Skill and system commands. Device delivery may return a mailbox operation; inspect it with tb_device_operations. Never retry a write merely because the result is unknown.",
|
|
30955
|
+
effect: "destructive",
|
|
30956
|
+
confirm: true,
|
|
30957
|
+
inputSchema: callInput
|
|
30958
|
+
}, async (input) => invokeMcpTarget(c, env, app, input));
|
|
30959
|
+
operations.register("tb_device_operations", {
|
|
30960
|
+
description: "List, inspect or cancel device mailbox operations, equivalent to tb device op. Use the original deviceId and operationId. Cancellation of a claimed operation is cooperative; result_unknown and expired with executionMayHaveOccurred do not establish that a retry is safe.",
|
|
30961
|
+
effect: "destructive",
|
|
30962
|
+
confirm: true,
|
|
30963
|
+
inputSchema: deviceOperationInput
|
|
30964
|
+
}, async (input) => {
|
|
30965
|
+
const { action, deviceId } = input;
|
|
30966
|
+
const body = action === "list" ? { deviceId, opts: { cursor: input.cursor, limit: input.limit, states: input.states } } : { deviceId, operationId: input.operationId };
|
|
30967
|
+
return request(`/~device/operations/${action}`, body);
|
|
30968
|
+
});
|
|
31035
30969
|
return {
|
|
31036
|
-
list,
|
|
31037
|
-
call: async (tool, args) =>
|
|
31038
|
-
const resultFromResponse = async (response2) => {
|
|
31039
|
-
const text = await response2.text();
|
|
31040
|
-
let value = text;
|
|
31041
|
-
try {
|
|
31042
|
-
value = JSON.parse(text);
|
|
31043
|
-
} catch {
|
|
31044
|
-
}
|
|
31045
|
-
return { content: value, ...response2.ok ? {} : { isError: true } };
|
|
31046
|
-
};
|
|
31047
|
-
if (tool.operation !== void 0) {
|
|
31048
|
-
const rawPath = args.path ?? "";
|
|
31049
|
-
if (typeof rawPath !== "string") {
|
|
31050
|
-
throw new TBError("invalid_argument", "path must be a string");
|
|
31051
|
-
}
|
|
31052
|
-
const path = rawPath.replace(/^\/+|\/+$/g, "");
|
|
31053
|
-
const pathError = validatePath(path, { allowRoot: true });
|
|
31054
|
-
if (pathError !== null) throw pathError;
|
|
31055
|
-
const segments = path === "" ? [] : path.split("/");
|
|
31056
|
-
if (segments.some((segment) => segment === "." || segment === "..")) {
|
|
31057
|
-
throw new TBError("invalid_argument", "path contains a dot segment");
|
|
31058
|
-
}
|
|
31059
|
-
const encoded = segments.map((segment) => encodeURIComponent(segment));
|
|
31060
|
-
const headers2 = new Headers({
|
|
31061
|
-
authorization: c.req.header("authorization") ?? ""
|
|
31062
|
-
});
|
|
31063
|
-
if (tool.operation === "search") {
|
|
31064
|
-
headers2.set("accept", "application/json");
|
|
31065
|
-
headers2.set("content-type", "application/json");
|
|
31066
|
-
const opts = {
|
|
31067
|
-
detail: args.detail ?? "compact",
|
|
31068
|
-
...Object.fromEntries(
|
|
31069
|
-
[
|
|
31070
|
-
"mode",
|
|
31071
|
-
"limit",
|
|
31072
|
-
"cursor",
|
|
31073
|
-
"effects",
|
|
31074
|
-
"federation",
|
|
31075
|
-
"matching",
|
|
31076
|
-
"minCoverage",
|
|
31077
|
-
"pathPrefix"
|
|
31078
|
-
].filter((key) => args[key] !== void 0).map((key) => [key, args[key]])
|
|
31079
|
-
)
|
|
31080
|
-
};
|
|
31081
|
-
const response2 = await app.request(new Request(new URL("/~search", c.req.url), {
|
|
31082
|
-
method: "POST",
|
|
31083
|
-
headers: headers2,
|
|
31084
|
-
body: JSON.stringify({
|
|
31085
|
-
query: args.query,
|
|
31086
|
-
opts
|
|
31087
|
-
})
|
|
31088
|
-
}));
|
|
31089
|
-
return await resultFromResponse(response2);
|
|
31090
|
-
}
|
|
31091
|
-
if (tool.operation === "help") {
|
|
31092
|
-
const detail = args.tool;
|
|
31093
|
-
if (detail !== void 0) {
|
|
31094
|
-
if (path === "" || typeof detail !== "string" || detail.includes("/")) {
|
|
31095
|
-
throw new TBError("invalid_argument", "tool detail requires a node path and one segment");
|
|
31096
|
-
}
|
|
31097
|
-
encoded.push(encodeURIComponent(detail));
|
|
31098
|
-
}
|
|
31099
|
-
const format = args.format ?? "json";
|
|
31100
|
-
headers2.set("accept", format === "json" ? "application/json" : format === "dsl" ? "text/plain" : "text/markdown");
|
|
31101
|
-
const prefix2 = encoded.length === 0 ? "" : `/${encoded.join("/")}`;
|
|
31102
|
-
return await resultFromResponse(await app.request(new Request(
|
|
31103
|
-
new URL(`${prefix2}/~help`, c.req.url),
|
|
31104
|
-
{ headers: headers2 }
|
|
31105
|
-
)));
|
|
31106
|
-
}
|
|
31107
|
-
headers2.set("accept", "application/json");
|
|
31108
|
-
const prefix = encoded.length === 0 ? "" : `/${encoded.join("/")}`;
|
|
31109
|
-
const url5 = new URL(`${prefix}/~tree`, c.req.url);
|
|
31110
|
-
if (args.depth !== void 0) url5.searchParams.set("depth", String(args.depth));
|
|
31111
|
-
return await resultFromResponse(await app.request(new Request(url5, { headers: headers2 })));
|
|
31112
|
-
}
|
|
31113
|
-
if (tool.providerBacked === true) {
|
|
31114
|
-
let node;
|
|
31115
|
-
try {
|
|
31116
|
-
node = await registry.get(tool.sourcePath);
|
|
31117
|
-
} catch {
|
|
31118
|
-
throw TBError.notFound("not found");
|
|
31119
|
-
}
|
|
31120
|
-
if (!check(ctx, node.path, "read").allow) throw TBError.notFound("not found");
|
|
31121
|
-
if (!check(ctx, node.path, "call").allow) {
|
|
31122
|
-
throw new TBError("permission_denied", `no scope grants 'call' on '${node.path}'`);
|
|
31123
|
-
}
|
|
31124
|
-
if (node.kind !== "mcp" && node.kind !== "http" && node.kind !== "tool" || node.config === void 0) {
|
|
31125
|
-
throw TBError.notFound("not found");
|
|
31126
|
-
}
|
|
31127
|
-
const provider = await providerFor(node, ctx, deps);
|
|
31128
|
-
const raw = await upstreamTools(node, provider, deps, false, (/* @__PURE__ */ new Date()).toISOString(), searchSync);
|
|
31129
|
-
const upstreamName = resolveUpstreamTool(node.virtualize, raw, tool.toolName);
|
|
31130
|
-
const result2 = await provider.call(upstreamName, args);
|
|
31131
|
-
return {
|
|
31132
|
-
content: result2.contentBlocks ?? result2.content,
|
|
31133
|
-
...result2.isError === true ? { isError: true } : {},
|
|
31134
|
-
...result2.structuredContent !== void 0 ? { structuredContent: result2.structuredContent } : {}
|
|
31135
|
-
};
|
|
31136
|
-
}
|
|
31137
|
-
const url4 = new URL(tool.invokePath, c.req.url);
|
|
31138
|
-
const headers = new Headers({
|
|
31139
|
-
"accept": "application/json",
|
|
31140
|
-
"authorization": c.req.header("authorization") ?? "",
|
|
31141
|
-
"content-type": "application/json"
|
|
31142
|
-
});
|
|
31143
|
-
const response = await app.request(
|
|
31144
|
-
new Request(url4, { method: "POST", headers, body: JSON.stringify(args) })
|
|
31145
|
-
);
|
|
31146
|
-
const result = await resultFromResponse(response);
|
|
31147
|
-
if (args["~delivery"] !== void 0 && response.ok) {
|
|
31148
|
-
return {
|
|
31149
|
-
content: response.status === 202 ? { delivery: "mailbox", operation: result.content } : { delivery: "realtime", result: result.content }
|
|
31150
|
-
};
|
|
31151
|
-
}
|
|
31152
|
-
return result;
|
|
31153
|
-
}
|
|
30970
|
+
list: async () => operations.list(),
|
|
30971
|
+
call: async (tool, args) => operations.call(tool.name, args, void 0)
|
|
31154
30972
|
};
|
|
31155
30973
|
}
|
|
31156
30974
|
function registerMcpRoute(app, env) {
|
|
31157
|
-
app.all("/~mcp", (c) => runHandler(async () =>
|
|
30975
|
+
app.all("/~mcp", (c) => runHandler(async () => handleMcpRequest(
|
|
31158
30976
|
c.req.raw,
|
|
31159
30977
|
env.deps.version,
|
|
31160
30978
|
mcpBridgeFor(c, env, app),
|
|
@@ -35371,104 +35189,104 @@ function createTbServer(config) {
|
|
|
35371
35189
|
|
|
35372
35190
|
// ../plugins/src/registry.generated.ts
|
|
35373
35191
|
var BUILTIN_PLUGIN_LOADERS = {
|
|
35374
|
-
airtable: () => import("./airtable-
|
|
35375
|
-
alt_text_generator_ai: () => import("./alt_text_generator_ai-
|
|
35376
|
-
amap: () => import("./amap-
|
|
35377
|
-
anthropic: () => import("./anthropic-
|
|
35378
|
-
apify: () => import("./apify-
|
|
35379
|
-
brave_search: () => import("./brave_search-
|
|
35380
|
-
circleci: () => import("./circleci-
|
|
35381
|
-
clerk: () => import("./clerk-
|
|
35382
|
-
cohere: () => import("./cohere-
|
|
35383
|
-
confluence: () => import("./confluence-
|
|
35384
|
-
convertapi: () => import("./convertapi-
|
|
35385
|
-
currencyapi: () => import("./currencyapi-
|
|
35386
|
-
deepseek: () => import("./deepseek-
|
|
35387
|
-
docker_hub: () => import("./docker_hub-
|
|
35388
|
-
dropbox: () => import("./dropbox-
|
|
35389
|
-
dub: () => import("./dub-
|
|
35390
|
-
e2b: () => import("./e2b-
|
|
35391
|
-
exa: () => import("./exa-
|
|
35392
|
-
fal_ai: () => import("./fal_ai-
|
|
35393
|
-
feishu: () => import("./feishu-
|
|
35394
|
-
feishu_custom_bot: () => import("./feishu_custom_bot-
|
|
35395
|
-
figma: () => import("./figma-
|
|
35396
|
-
firehydrant: () => import("./firehydrant-
|
|
35397
|
-
fixer: () => import("./fixer-
|
|
35398
|
-
fly: () => import("./fly-
|
|
35399
|
-
front: () => import("./front-
|
|
35400
|
-
geocodio: () => import("./geocodio-
|
|
35401
|
-
ghost: () => import("./ghost-
|
|
35402
|
-
github: () => import("./github-
|
|
35403
|
-
gmail: () => import("./gmail-
|
|
35404
|
-
googlecalendar: () => import("./googlecalendar-
|
|
35405
|
-
googledocs: () => import("./googledocs-
|
|
35406
|
-
grafana: () => import("./grafana-
|
|
35407
|
-
graphhopper: () => import("./graphhopper-
|
|
35408
|
-
ip2proxy: () => import("./ip2proxy-
|
|
35409
|
-
ipgeolocation_io: () => import("./ipgeolocation_io-
|
|
35410
|
-
ipqualityscore: () => import("./ipqualityscore-
|
|
35411
|
-
jina_ai: () => import("./jina_ai-
|
|
35412
|
-
jira: () => import("./jira-
|
|
35413
|
-
langsmith: () => import("./langsmith-
|
|
35414
|
-
lemlist: () => import("./lemlist-
|
|
35415
|
-
linear: () => import("./linear-
|
|
35416
|
-
logsnag: () => import("./logsnag-
|
|
35417
|
-
mattermost: () => import("./mattermost-
|
|
35418
|
-
mem0: () => import("./mem0-
|
|
35419
|
-
memos: () => import("./memos-
|
|
35420
|
-
metabase: () => import("./metabase-
|
|
35421
|
-
mistral_ai: () => import("./mistral_ai-
|
|
35422
|
-
mother_duck: () => import("./mother_duck-
|
|
35423
|
-
ngrok: () => import("./ngrok-
|
|
35424
|
-
notes: () => import("./notes-
|
|
35425
|
-
notion: () => import("./notion-
|
|
35426
|
-
open_exchange_rates: () => import("./open_exchange_rates-
|
|
35427
|
-
openai: () => import("./openai-
|
|
35428
|
-
opengraph_io: () => import("./opengraph_io-
|
|
35429
|
-
openrouter: () => import("./openrouter-
|
|
35430
|
-
outline: () => import("./outline-
|
|
35431
|
-
paddle: () => import("./paddle-
|
|
35432
|
-
perplexity: () => import("./perplexity-
|
|
35433
|
-
pinecone: () => import("./pinecone-
|
|
35434
|
-
pipedrive: () => import("./pipedrive-
|
|
35435
|
-
polar: () => import("./polar-
|
|
35436
|
-
posthog: () => import("./posthog-
|
|
35437
|
-
postmark: () => import("./postmark-
|
|
35438
|
-
prerender: () => import("./prerender-
|
|
35439
|
-
pubmed: () => import("./pubmed-
|
|
35440
|
-
railway: () => import("./railway-
|
|
35441
|
-
readwise: () => import("./readwise-
|
|
35442
|
-
render: () => import("./render-
|
|
35443
|
-
replicate: () => import("./replicate-
|
|
35444
|
-
resend: () => import("./resend-
|
|
35445
|
-
rootly: () => import("./rootly-
|
|
35446
|
-
scrapfly: () => import("./scrapfly-
|
|
35447
|
-
scrapingbee: () => import("./scrapingbee-
|
|
35448
|
-
screenshot_fyi: () => import("./screenshot_fyi-
|
|
35449
|
-
semantic_scholar: () => import("./semantic_scholar-
|
|
35450
|
-
sentry: () => import("./sentry-
|
|
35451
|
-
shodan: () => import("./shodan-
|
|
35452
|
-
shopify: () => import("./shopify-
|
|
35453
|
-
stripe: () => import("./stripe-
|
|
35454
|
-
supabase: () => import("./supabase-
|
|
35455
|
-
tavily: () => import("./tavily-
|
|
35456
|
-
telegram: () => import("./telegram-
|
|
35457
|
-
telnyx: () => import("./telnyx-
|
|
35458
|
-
todoist: () => import("./todoist-
|
|
35459
|
-
trello: () => import("./trello-
|
|
35460
|
-
turso: () => import("./turso-
|
|
35461
|
-
twilio: () => import("./twilio-
|
|
35462
|
-
umami: () => import("./umami-
|
|
35463
|
-
unsplash: () => import("./unsplash-
|
|
35464
|
-
upstash_redis: () => import("./upstash_redis-
|
|
35465
|
-
uptimerobot: () => import("./uptimerobot-
|
|
35466
|
-
v2ex: () => import("./v2ex-
|
|
35467
|
-
vercel: () => import("./vercel-
|
|
35468
|
-
wolfram_alpha_api: () => import("./wolfram_alpha_api-
|
|
35469
|
-
wordpress: () => import("./wordpress-
|
|
35470
|
-
workos: () => import("./workos-
|
|
35471
|
-
zhihu: () => import("./zhihu-
|
|
35192
|
+
airtable: () => import("./airtable-Z6KEL3MA.js"),
|
|
35193
|
+
alt_text_generator_ai: () => import("./alt_text_generator_ai-RM2GHSNM.js"),
|
|
35194
|
+
amap: () => import("./amap-YEJLGIKY.js"),
|
|
35195
|
+
anthropic: () => import("./anthropic-62M4MUVQ.js"),
|
|
35196
|
+
apify: () => import("./apify-AHRNDBCB.js"),
|
|
35197
|
+
brave_search: () => import("./brave_search-JAHWOMQC.js"),
|
|
35198
|
+
circleci: () => import("./circleci-UJUYBIAO.js"),
|
|
35199
|
+
clerk: () => import("./clerk-FCFM3WJK.js"),
|
|
35200
|
+
cohere: () => import("./cohere-OTSYSMPC.js"),
|
|
35201
|
+
confluence: () => import("./confluence-LPANSCGT.js"),
|
|
35202
|
+
convertapi: () => import("./convertapi-AJZOVUHT.js"),
|
|
35203
|
+
currencyapi: () => import("./currencyapi-HGK5FSGO.js"),
|
|
35204
|
+
deepseek: () => import("./deepseek-7HMTFJRV.js"),
|
|
35205
|
+
docker_hub: () => import("./docker_hub-FCNVKJZW.js"),
|
|
35206
|
+
dropbox: () => import("./dropbox-2XVKCQZE.js"),
|
|
35207
|
+
dub: () => import("./dub-CTUKPX2A.js"),
|
|
35208
|
+
e2b: () => import("./e2b-ULEWTRKI.js"),
|
|
35209
|
+
exa: () => import("./exa-QENFV3AU.js"),
|
|
35210
|
+
fal_ai: () => import("./fal_ai-TQYUBBAF.js"),
|
|
35211
|
+
feishu: () => import("./feishu-OYCWDSHD.js"),
|
|
35212
|
+
feishu_custom_bot: () => import("./feishu_custom_bot-VYQ7A3PU.js"),
|
|
35213
|
+
figma: () => import("./figma-5DLOKAQQ.js"),
|
|
35214
|
+
firehydrant: () => import("./firehydrant-X4MGP2OI.js"),
|
|
35215
|
+
fixer: () => import("./fixer-LMIWM3ZX.js"),
|
|
35216
|
+
fly: () => import("./fly-J5HN5L2I.js"),
|
|
35217
|
+
front: () => import("./front-E3SMBQW3.js"),
|
|
35218
|
+
geocodio: () => import("./geocodio-AOINRPLA.js"),
|
|
35219
|
+
ghost: () => import("./ghost-E4CBGZWJ.js"),
|
|
35220
|
+
github: () => import("./github-PGR6U3FC.js"),
|
|
35221
|
+
gmail: () => import("./gmail-XNQHMQ6F.js"),
|
|
35222
|
+
googlecalendar: () => import("./googlecalendar-RE6DGG7L.js"),
|
|
35223
|
+
googledocs: () => import("./googledocs-CX2BZDQH.js"),
|
|
35224
|
+
grafana: () => import("./grafana-GX75ZA5X.js"),
|
|
35225
|
+
graphhopper: () => import("./graphhopper-XMUYLWHS.js"),
|
|
35226
|
+
ip2proxy: () => import("./ip2proxy-ZGIRBAG5.js"),
|
|
35227
|
+
ipgeolocation_io: () => import("./ipgeolocation_io-MAP27QMO.js"),
|
|
35228
|
+
ipqualityscore: () => import("./ipqualityscore-6IIUUAQ2.js"),
|
|
35229
|
+
jina_ai: () => import("./jina_ai-GGH77RQH.js"),
|
|
35230
|
+
jira: () => import("./jira-7GPZW6HZ.js"),
|
|
35231
|
+
langsmith: () => import("./langsmith-CJXYE7WM.js"),
|
|
35232
|
+
lemlist: () => import("./lemlist-OYPOX6GN.js"),
|
|
35233
|
+
linear: () => import("./linear-TPQ6X4XZ.js"),
|
|
35234
|
+
logsnag: () => import("./logsnag-HT2PRLIV.js"),
|
|
35235
|
+
mattermost: () => import("./mattermost-6IYTWTM5.js"),
|
|
35236
|
+
mem0: () => import("./mem0-7AVGBGOX.js"),
|
|
35237
|
+
memos: () => import("./memos-CTOXWZ6X.js"),
|
|
35238
|
+
metabase: () => import("./metabase-AFJXQ5SQ.js"),
|
|
35239
|
+
mistral_ai: () => import("./mistral_ai-QDKM4N3R.js"),
|
|
35240
|
+
mother_duck: () => import("./mother_duck-XSKR4GVL.js"),
|
|
35241
|
+
ngrok: () => import("./ngrok-NQMLM24P.js"),
|
|
35242
|
+
notes: () => import("./notes-ZWMVZQWJ.js"),
|
|
35243
|
+
notion: () => import("./notion-6544KSMM.js"),
|
|
35244
|
+
open_exchange_rates: () => import("./open_exchange_rates-4CLN7O2N.js"),
|
|
35245
|
+
openai: () => import("./openai-HLFGPVI5.js"),
|
|
35246
|
+
opengraph_io: () => import("./opengraph_io-57JDHT3M.js"),
|
|
35247
|
+
openrouter: () => import("./openrouter-WDAVB2OP.js"),
|
|
35248
|
+
outline: () => import("./outline-A6MDLZVH.js"),
|
|
35249
|
+
paddle: () => import("./paddle-WX5ULOPP.js"),
|
|
35250
|
+
perplexity: () => import("./perplexity-LYTWWWCZ.js"),
|
|
35251
|
+
pinecone: () => import("./pinecone-7KAF3S7U.js"),
|
|
35252
|
+
pipedrive: () => import("./pipedrive-YQY243G7.js"),
|
|
35253
|
+
polar: () => import("./polar-A5HKXSQY.js"),
|
|
35254
|
+
posthog: () => import("./posthog-CF2LHLS4.js"),
|
|
35255
|
+
postmark: () => import("./postmark-W756TMJM.js"),
|
|
35256
|
+
prerender: () => import("./prerender-ZYM4UQ5R.js"),
|
|
35257
|
+
pubmed: () => import("./pubmed-QXTUQCTQ.js"),
|
|
35258
|
+
railway: () => import("./railway-F4MOZ3LQ.js"),
|
|
35259
|
+
readwise: () => import("./readwise-S7MF5SR5.js"),
|
|
35260
|
+
render: () => import("./render-D7EIVDUA.js"),
|
|
35261
|
+
replicate: () => import("./replicate-ABNKPZR7.js"),
|
|
35262
|
+
resend: () => import("./resend-7VJEY4KC.js"),
|
|
35263
|
+
rootly: () => import("./rootly-UMFJOKXC.js"),
|
|
35264
|
+
scrapfly: () => import("./scrapfly-UDT4KNFL.js"),
|
|
35265
|
+
scrapingbee: () => import("./scrapingbee-XTFD54NB.js"),
|
|
35266
|
+
screenshot_fyi: () => import("./screenshot_fyi-5GTW3SFY.js"),
|
|
35267
|
+
semantic_scholar: () => import("./semantic_scholar-Y6WK2MST.js"),
|
|
35268
|
+
sentry: () => import("./sentry-ZFPGDA6C.js"),
|
|
35269
|
+
shodan: () => import("./shodan-3SCDBOQ3.js"),
|
|
35270
|
+
shopify: () => import("./shopify-LMTBS2I2.js"),
|
|
35271
|
+
stripe: () => import("./stripe-4JQJ2CUG.js"),
|
|
35272
|
+
supabase: () => import("./supabase-7HA3BEFK.js"),
|
|
35273
|
+
tavily: () => import("./tavily-H34ZBPGC.js"),
|
|
35274
|
+
telegram: () => import("./telegram-CRX4YWQ3.js"),
|
|
35275
|
+
telnyx: () => import("./telnyx-TIKGEU34.js"),
|
|
35276
|
+
todoist: () => import("./todoist-LU563DGZ.js"),
|
|
35277
|
+
trello: () => import("./trello-NTRGEROX.js"),
|
|
35278
|
+
turso: () => import("./turso-EY3CNVPZ.js"),
|
|
35279
|
+
twilio: () => import("./twilio-ICX3WRQH.js"),
|
|
35280
|
+
umami: () => import("./umami-NPMRVI3M.js"),
|
|
35281
|
+
unsplash: () => import("./unsplash-TIHBZFIM.js"),
|
|
35282
|
+
upstash_redis: () => import("./upstash_redis-2DO6EHCN.js"),
|
|
35283
|
+
uptimerobot: () => import("./uptimerobot-BGYOCKGI.js"),
|
|
35284
|
+
v2ex: () => import("./v2ex-GOWDPGGA.js"),
|
|
35285
|
+
vercel: () => import("./vercel-G33RXVBI.js"),
|
|
35286
|
+
wolfram_alpha_api: () => import("./wolfram_alpha_api-IRZSMD3P.js"),
|
|
35287
|
+
wordpress: () => import("./wordpress-ATWGGUC3.js"),
|
|
35288
|
+
workos: () => import("./workos-LHJDETBX.js"),
|
|
35289
|
+
zhihu: () => import("./zhihu-IAH53YPP.js")
|
|
35472
35290
|
};
|
|
35473
35291
|
|
|
35474
35292
|
// ../plugins/src/catalog.generated.ts
|