@tool-bridge/server 0.22.1 → 0.23.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-VMQVXLHK.js} +6 -6
- package/dist/{alt_text_generator_ai-FGYQAF2A.js → alt_text_generator_ai-FTWY4RU4.js} +5 -5
- package/dist/{amap-G7V65NGK.js → amap-OK5VBHYC.js} +5 -5
- package/dist/{anthropic-6ZK24TBB.js → anthropic-S67AZFZ3.js} +6 -6
- package/dist/{apify-VDGYHP6W.js → apify-ZE6MYQI3.js} +6 -6
- package/dist/{brave_search-TAATLZOS.js → brave_search-TG2M2KOD.js} +6 -6
- package/dist/{chunk-7ISGFRC6.js → chunk-2JNAI4OC.js} +1 -1
- package/dist/{chunk-RMAWSG7E.js → chunk-4XJPN3DY.js} +353 -552
- package/dist/{chunk-HA4BGL6C.js → chunk-5ICRY3VU.js} +15 -12
- package/dist/{chunk-2IAI3XQM.js → chunk-7CTWGTDU.js} +2 -2
- package/dist/{chunk-UY6ANCOY.js → chunk-BADVCN6K.js} +1 -1
- package/dist/{chunk-RTW5VRTK.js → chunk-TDAWLMDE.js} +3 -3
- package/dist/{chunk-BNMLA2RC.js → chunk-VWRUGUSU.js} +3 -3
- package/dist/{chunk-X7ZUTKHR.js → chunk-WJHG6OK7.js} +2 -2
- package/dist/{circleci-BQ2UWXL2.js → circleci-3L3WJVSK.js} +6 -6
- package/dist/{clerk-2JYWQNOI.js → clerk-EZPF2V7T.js} +6 -6
- package/dist/{cohere-6MI7AQM4.js → cohere-U27DPO64.js} +6 -6
- package/dist/{confluence-6Y6GDETF.js → confluence-G2KL6ERH.js} +6 -6
- package/dist/{convertapi-HBZCSWOX.js → convertapi-L4CLJ2M3.js} +4 -4
- package/dist/{currencyapi-337U5TGI.js → currencyapi-YPYXG7YY.js} +6 -6
- package/dist/{deepseek-OSPASO7O.js → deepseek-6HT6WF3M.js} +6 -6
- package/dist/{docker_hub-3ATQOY5L.js → docker_hub-LPE3PCVB.js} +5 -5
- package/dist/{dropbox-LSA4GM2Y.js → dropbox-V56ABHTA.js} +6 -6
- package/dist/{dub-VZPJSPI6.js → dub-6OKQ7MHT.js} +6 -6
- package/dist/{e2b-6SDYQZL2.js → e2b-JS2U2QFU.js} +6 -6
- package/dist/{exa-B6EUYDVP.js → exa-DPWVYXSP.js} +6 -6
- package/dist/{fal_ai-K4Q27IME.js → fal_ai-DK6Y27ZF.js} +6 -6
- package/dist/{feishu-4TKXG4SU.js → feishu-K7EGSRF3.js} +3 -3
- package/dist/{feishu_custom_bot-7CTEAKRB.js → feishu_custom_bot-2JUGFYNG.js} +4 -4
- package/dist/{figma-OUKSZLD5.js → figma-FT5I7ITD.js} +6 -6
- package/dist/{firehydrant-7MOYL7QH.js → firehydrant-EIKLKHX2.js} +6 -6
- package/dist/{fixer-H2BV2NO4.js → fixer-U5QXIAKD.js} +5 -5
- package/dist/{fly-PXKY6PNH.js → fly-T3JYFZ2M.js} +6 -6
- package/dist/{front-UZYIV5DW.js → front-D72MGVOR.js} +6 -6
- package/dist/{geocodio-NSYO7TFP.js → geocodio-BOTD5TI5.js} +5 -5
- package/dist/{ghost-QBKKQQMF.js → ghost-KYP7SZGB.js} +5 -5
- package/dist/{github-ENLSJ4CL.js → github-AGMZT3VY.js} +6 -6
- package/dist/{gmail-KQSDEB47.js → gmail-BLJNJOBG.js} +6 -6
- package/dist/{googlecalendar-5YCX4SZF.js → googlecalendar-GTHWNCF6.js} +6 -6
- package/dist/{googledocs-SSWIVFKA.js → googledocs-6EEDMEBQ.js} +4 -4
- package/dist/{grafana-TF2LXDQA.js → grafana-GMW6EKSQ.js} +6 -6
- package/dist/{graphhopper-CURBVHYK.js → graphhopper-6OLGBDGB.js} +5 -5
- package/dist/index.js +5 -5
- package/dist/{ip2proxy-YNVMTZEM.js → ip2proxy-4QN42E6T.js} +5 -5
- package/dist/{ipgeolocation_io-NAU7VJ4J.js → ipgeolocation_io-SK4XKDA2.js} +5 -5
- package/dist/{ipqualityscore-OT63L4TI.js → ipqualityscore-6ANBPXKT.js} +5 -5
- package/dist/{jina_ai-6WBMBGWM.js → jina_ai-IHPSVRM5.js} +6 -6
- package/dist/{jira-DVDVTHNO.js → jira-46KKM4LC.js} +6 -6
- package/dist/{langsmith-IM5N4YAU.js → langsmith-JZA345I5.js} +6 -6
- package/dist/{lemlist-277SHUQF.js → lemlist-43IV7DK6.js} +6 -6
- package/dist/{linear-AEPH7B5V.js → linear-5LFH7XNL.js} +4 -4
- package/dist/{logsnag-VEWRAGBG.js → logsnag-5RMYAHIL.js} +6 -6
- package/dist/main.js +5 -5
- package/dist/{mattermost-Q3A2BIZA.js → mattermost-XFL6SHGG.js} +6 -6
- package/dist/{mem0-AXS7GZGI.js → mem0-NYO4DTP6.js} +6 -6
- package/dist/{memos-7TXG4ZTU.js → memos-37MPQOLV.js} +6 -6
- package/dist/{metabase-NSVACWQM.js → metabase-KYBKZFMG.js} +6 -6
- package/dist/{mistral_ai-YZ52RGD4.js → mistral_ai-6PL3K4PM.js} +6 -6
- package/dist/{mother_duck-XLLL6FVL.js → mother_duck-2NH7W5M5.js} +6 -6
- package/dist/{ngrok-4O4W3WZW.js → ngrok-UO6CDYCA.js} +6 -6
- package/dist/{notes-YTB3TJOO.js → notes-I3P32WP4.js} +2 -2
- package/dist/{notion-4W4O7J7V.js → notion-BEAJFUOE.js} +6 -6
- package/dist/{open_exchange_rates-23QJXVO5.js → open_exchange_rates-CMF62JB4.js} +5 -5
- package/dist/{openai-ZS7GLSLH.js → openai-IHOMKVND.js} +6 -6
- package/dist/{opengraph_io-PMVH7OYI.js → opengraph_io-ZQ2FGLHX.js} +5 -5
- package/dist/{openrouter-ONRGFNB6.js → openrouter-HXLW3NR5.js} +6 -6
- package/dist/{outline-UCUYZZ7J.js → outline-ELCP4NEU.js} +6 -6
- package/dist/{paddle-35HTKTUL.js → paddle-O77LALVN.js} +6 -6
- package/dist/{perplexity-NVOBYN24.js → perplexity-JCU654QV.js} +6 -6
- package/dist/{pinecone-55CJY73C.js → pinecone-W5W4LRKL.js} +6 -6
- package/dist/{pipedrive-WMCAKS72.js → pipedrive-ITMJLLPZ.js} +6 -6
- package/dist/{polar-SM4ZM53B.js → polar-R33XU4L3.js} +6 -6
- package/dist/{posthog-NWCXVXNJ.js → posthog-JVNTOLTV.js} +6 -6
- package/dist/{postmark-QJV5PHUQ.js → postmark-6SBG7HWV.js} +6 -6
- package/dist/{prerender-2W7UT4SC.js → prerender-GPNKTNFC.js} +5 -5
- package/dist/{pubmed-VVV7XYLU.js → pubmed-UP6ZEEIH.js} +4 -4
- package/dist/{railway-KGI57S3O.js → railway-KWEWXHTY.js} +4 -4
- package/dist/{readwise-AGHTQB42.js → readwise-BLATSMC3.js} +6 -6
- package/dist/{render-O4HBROCK.js → render-QYRVIXII.js} +6 -6
- package/dist/{replicate-KWBOMX7D.js → replicate-JYTWH4NF.js} +6 -6
- package/dist/{resend-DRH6Y6I4.js → resend-L5N75SZM.js} +6 -6
- package/dist/{rootly-XGCUDW6X.js → rootly-MHCPEQ26.js} +6 -6
- package/dist/{scrapfly-OIQ3OY6L.js → scrapfly-PTPGYSJM.js} +5 -5
- package/dist/{scrapingbee-OCZO4FHX.js → scrapingbee-JN6UH5PY.js} +5 -5
- package/dist/{screenshot_fyi-CUNGFZOC.js → screenshot_fyi-4QRVSV55.js} +5 -5
- package/dist/{semantic_scholar-3UJRLKES.js → semantic_scholar-LRSWA2GE.js} +6 -6
- package/dist/{sentry-5BWVZFJV.js → sentry-2G6PF5W6.js} +6 -6
- package/dist/{shodan-HI37CTEW.js → shodan-WKKPP5C6.js} +5 -5
- package/dist/{shopify-LJ2EV2HH.js → shopify-64YDK5T2.js} +6 -6
- package/dist/{stripe-3LHMV55K.js → stripe-QAIGGOTF.js} +4 -4
- package/dist/{supabase-H2KPX3Q2.js → supabase-WHTGR6ND.js} +6 -6
- package/dist/{tavily-FBEWGH3Z.js → tavily-QIXCDDWO.js} +6 -6
- package/dist/{telegram-MYYO3JND.js → telegram-E6G7CWI6.js} +5 -5
- package/dist/{telnyx-H4ALEGAX.js → telnyx-ZDVVS7PK.js} +6 -6
- package/dist/{todoist-OBWICA5Q.js → todoist-DMYF3G7J.js} +6 -6
- package/dist/{trello-GUFUJRWO.js → trello-HY2RYIRP.js} +5 -5
- package/dist/{turso-NIAK4UMS.js → turso-HAQWMGRP.js} +6 -6
- package/dist/{twilio-K6SLK2CX.js → twilio-MLXYPHJE.js} +4 -4
- package/dist/{umami-42RS2EPS.js → umami-DZHBLPVG.js} +6 -6
- package/dist/{unsplash-V7TOTETT.js → unsplash-GS2OPXKE.js} +6 -6
- package/dist/{upstash_redis-AWQMB6Y3.js → upstash_redis-XMXWTNAJ.js} +6 -6
- package/dist/{uptimerobot-AZC2DHOT.js → uptimerobot-TF5WRZ4G.js} +4 -4
- package/dist/{v2ex-4TVRNMLS.js → v2ex-2BVXAPDF.js} +6 -6
- package/dist/{vercel-DPHTJ3XR.js → vercel-YMJGQYJE.js} +6 -6
- package/dist/{wolfram_alpha_api-XAG7IXBW.js → wolfram_alpha_api-I56SXWFZ.js} +5 -5
- package/dist/{wordpress-KMPKVGUX.js → wordpress-R7TDFZ2P.js} +6 -6
- package/dist/{workos-PKB2YR7S.js → workos-HDNHWVMS.js} +6 -6
- package/dist/{zhihu-Y4H4XYPB.js → zhihu-LX6AGGDS.js} +6 -6
- package/package.json +2 -2
|
@@ -10,15 +10,14 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
BootstrapStateStore,
|
|
12
12
|
package_default
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-7CTWGTDU.js";
|
|
14
14
|
import {
|
|
15
15
|
createGuardedFetch
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-2JNAI4OC.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,
|
|
@@ -109,6 +110,7 @@ import {
|
|
|
109
110
|
deviceOperationListResponseSchema,
|
|
110
111
|
deviceOperationRenewRequestSchema,
|
|
111
112
|
deviceOperationRenewResponseSchema,
|
|
113
|
+
deviceOperationStateSchema,
|
|
112
114
|
deviceOperationSummarySchema,
|
|
113
115
|
deviceShellHelpModel,
|
|
114
116
|
dispatchContextCmd,
|
|
@@ -176,6 +178,7 @@ import {
|
|
|
176
178
|
storeUri,
|
|
177
179
|
tbErrorBodySchema,
|
|
178
180
|
toolHelpModel,
|
|
181
|
+
toolSearchOptionsSchema,
|
|
179
182
|
toolSearchPageSchema,
|
|
180
183
|
toolSearchRelevanceSchema,
|
|
181
184
|
toolSearchRequestSchema,
|
|
@@ -188,7 +191,7 @@ import {
|
|
|
188
191
|
validatePath,
|
|
189
192
|
validateStoreTokenKeyring,
|
|
190
193
|
virtualizeTools
|
|
191
|
-
} from "./chunk-
|
|
194
|
+
} from "./chunk-5ICRY3VU.js";
|
|
192
195
|
|
|
193
196
|
// src/config.ts
|
|
194
197
|
function runtimeAppSettings(settings, instanceId) {
|
|
@@ -216,7 +219,7 @@ function runtimeAppSettings(settings, instanceId) {
|
|
|
216
219
|
// ../app/package.json
|
|
217
220
|
var package_default2 = {
|
|
218
221
|
name: "@tool-bridge/app",
|
|
219
|
-
version: "0.
|
|
222
|
+
version: "0.22.0",
|
|
220
223
|
description: "Host-neutral HTBP application: assemble the tool-bridge tree on any runtime by injecting state, object, secret, device-channel and search adapters",
|
|
221
224
|
type: "module",
|
|
222
225
|
license: "MIT",
|
|
@@ -254,7 +257,8 @@ var package_default2 = {
|
|
|
254
257
|
"@modelcontextprotocol/client": "catalog:",
|
|
255
258
|
"@modelcontextprotocol/core": "catalog:",
|
|
256
259
|
"@modelcontextprotocol/server": "catalog:",
|
|
257
|
-
hono: "catalog:"
|
|
260
|
+
hono: "catalog:",
|
|
261
|
+
zod: "catalog:"
|
|
258
262
|
},
|
|
259
263
|
devDependencies: {
|
|
260
264
|
"@modelcontextprotocol/sdk": "catalog:",
|
|
@@ -262,8 +266,7 @@ var package_default2 = {
|
|
|
262
266
|
"@tool-bridge/plugins": "workspace:*",
|
|
263
267
|
tsup: "catalog:",
|
|
264
268
|
typescript: "catalog:",
|
|
265
|
-
vitest: "catalog:"
|
|
266
|
-
zod: "catalog:"
|
|
269
|
+
vitest: "catalog:"
|
|
267
270
|
},
|
|
268
271
|
repository: {
|
|
269
272
|
type: "git",
|
|
@@ -13607,8 +13610,8 @@ var require_utils = /* @__PURE__ */ __commonJSMin2(((exports, module) => {
|
|
|
13607
13610
|
}
|
|
13608
13611
|
function consumeHextets(buffer, address, output) {
|
|
13609
13612
|
if (buffer.length) {
|
|
13610
|
-
const
|
|
13611
|
-
if (
|
|
13613
|
+
const hex = stringArrayToHexStripped(buffer);
|
|
13614
|
+
if (hex !== "") address.push(hex);
|
|
13612
13615
|
else {
|
|
13613
13616
|
output.error = true;
|
|
13614
13617
|
return false;
|
|
@@ -24524,8 +24527,8 @@ function syntheticElicitationId() {
|
|
|
24524
24527
|
webCrypto.getRandomValues(bytes);
|
|
24525
24528
|
bytes[6] = bytes[6] & 15 | 64;
|
|
24526
24529
|
bytes[8] = bytes[8] & 63 | 128;
|
|
24527
|
-
const
|
|
24528
|
-
return `${
|
|
24530
|
+
const hex = [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
24531
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
24529
24532
|
}
|
|
24530
24533
|
function legacyShimFailure(method, message) {
|
|
24531
24534
|
if (method === "tools/call") return {
|
|
@@ -27003,24 +27006,6 @@ function createMcpHandler(factory, options = {}) {
|
|
|
27003
27006
|
}
|
|
27004
27007
|
|
|
27005
27008
|
// ../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
27009
|
var SUBSCHEMA_KEYS = [
|
|
27025
27010
|
"additionalProperties",
|
|
27026
27011
|
"contains",
|
|
@@ -27050,7 +27035,10 @@ function assertSchemaShape(value, path, depth = 0) {
|
|
|
27050
27035
|
if (depth >= MAX_SCHEMA_DEPTH) throw new Error(`JSON Schema nested too deeply at '${path}'`);
|
|
27051
27036
|
const schema = value;
|
|
27052
27037
|
for (const key of SUBSCHEMA_KEYS) {
|
|
27053
|
-
|
|
27038
|
+
const sub = schema[key];
|
|
27039
|
+
if (key === "items" && Array.isArray(sub)) {
|
|
27040
|
+
sub.forEach((item, i) => assertSchemaShape(item, `${path}/items/${i}`, depth + 1));
|
|
27041
|
+
} else if (sub !== void 0) assertSchemaShape(sub, `${path}/${key}`, depth + 1);
|
|
27054
27042
|
}
|
|
27055
27043
|
for (const key of SUBSCHEMA_MAP_KEYS) {
|
|
27056
27044
|
const map = schema[key];
|
|
@@ -27069,9 +27057,9 @@ function assertSchemaShape(value, path, depth = 0) {
|
|
|
27069
27057
|
list.forEach((sub, i) => assertSchemaShape(sub, `${path}/${key}/${i}`, depth + 1));
|
|
27070
27058
|
}
|
|
27071
27059
|
}
|
|
27072
|
-
function inputSchemaOf(raw
|
|
27073
|
-
if (raw === void 0
|
|
27074
|
-
const source = raw
|
|
27060
|
+
function inputSchemaOf(raw) {
|
|
27061
|
+
if (raw === void 0) return { type: "object", properties: {} };
|
|
27062
|
+
const source = raw;
|
|
27075
27063
|
if (source === null || typeof source !== "object" || Array.isArray(source)) {
|
|
27076
27064
|
throw new Error("MCP tool inputSchema must be a JSON Schema object");
|
|
27077
27065
|
}
|
|
@@ -27080,23 +27068,21 @@ function inputSchemaOf(raw, delivery) {
|
|
|
27080
27068
|
throw new Error("MCP tool inputSchema root type must be object");
|
|
27081
27069
|
}
|
|
27082
27070
|
assertSchemaShape(schema, "inputSchema");
|
|
27083
|
-
|
|
27084
|
-
|
|
27071
|
+
return { ...schema, type: "object" };
|
|
27072
|
+
}
|
|
27073
|
+
function inputValidator(raw, path) {
|
|
27074
|
+
try {
|
|
27075
|
+
return new ToolJsonSchemaValidator().getValidator(
|
|
27076
|
+
inputSchemaOf(raw)
|
|
27077
|
+
);
|
|
27078
|
+
} catch {
|
|
27079
|
+
throw new ProtocolError3(ProtocolErrorCode2.InternalError, `invalid input schema for '${path}'`);
|
|
27085
27080
|
}
|
|
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
|
-
};
|
|
27081
|
+
}
|
|
27082
|
+
function validateMcpArguments(raw, args, path) {
|
|
27083
|
+
const validate = inputValidator(raw, path);
|
|
27084
|
+
const result = validate(args);
|
|
27085
|
+
if (!result.valid) throw new ProtocolError3(ProtocolErrorCode2.InvalidParams, result.errorMessage);
|
|
27100
27086
|
}
|
|
27101
27087
|
function annotationsOf(tool) {
|
|
27102
27088
|
const annotations = {};
|
|
@@ -27105,69 +27091,26 @@ function annotationsOf(tool) {
|
|
|
27105
27091
|
if (tool.effect === "destructive" || tool.confirm === true) annotations.destructiveHint = true;
|
|
27106
27092
|
return Object.keys(annotations).length > 0 ? annotations : void 0;
|
|
27107
27093
|
}
|
|
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
|
-
);
|
|
27094
|
+
function projectTools(source) {
|
|
27163
27095
|
const names = /* @__PURE__ */ new Set();
|
|
27164
|
-
|
|
27165
|
-
if (names.has(
|
|
27096
|
+
return source.map((bridge) => {
|
|
27097
|
+
if (names.has(bridge.name)) {
|
|
27166
27098
|
throw new ProtocolError3(ProtocolErrorCode2.InternalError, "MCP tool name collision");
|
|
27167
27099
|
}
|
|
27168
|
-
names.add(
|
|
27169
|
-
|
|
27170
|
-
|
|
27100
|
+
names.add(bridge.name);
|
|
27101
|
+
const annotations = annotationsOf(bridge);
|
|
27102
|
+
const validateInput = inputValidator(bridge.inputSchema, bridge.name);
|
|
27103
|
+
const parsed = ToolSchema.safeParse({
|
|
27104
|
+
name: bridge.name,
|
|
27105
|
+
description: bridge.description,
|
|
27106
|
+
inputSchema: inputSchemaOf(bridge.inputSchema),
|
|
27107
|
+
...annotations === void 0 ? {} : { annotations }
|
|
27108
|
+
});
|
|
27109
|
+
if (!parsed.success) {
|
|
27110
|
+
throw new ProtocolError3(ProtocolErrorCode2.InternalError, `invalid tool metadata for '${bridge.name}'`);
|
|
27111
|
+
}
|
|
27112
|
+
return { bridge, tool: parsed.data, validateInput };
|
|
27113
|
+
}).sort((a, b) => a.tool.name.localeCompare(b.tool.name));
|
|
27171
27114
|
}
|
|
27172
27115
|
function contentOf(value) {
|
|
27173
27116
|
if (Array.isArray(value)) {
|
|
@@ -27188,12 +27131,13 @@ function buildMcpServer(version, bridge, listTtlMs) {
|
|
|
27188
27131
|
cacheHints: { "tools/list": { ttlMs: listTtlMs, cacheScope: "private" } }
|
|
27189
27132
|
}
|
|
27190
27133
|
);
|
|
27134
|
+
let projected;
|
|
27135
|
+
const tools = () => projected ??= bridge.list().then(projectTools);
|
|
27191
27136
|
server.setRequestHandler("tools/list", async () => ({
|
|
27192
|
-
tools: (await
|
|
27137
|
+
tools: (await tools()).map((item) => item.tool)
|
|
27193
27138
|
}));
|
|
27194
27139
|
server.setRequestHandler("tools/call", async (rpc) => {
|
|
27195
|
-
const
|
|
27196
|
-
const selected = projected.find((item) => item.tool.name === rpc.params.name);
|
|
27140
|
+
const selected = (await tools()).find((item) => item.tool.name === rpc.params.name);
|
|
27197
27141
|
if (selected === void 0) {
|
|
27198
27142
|
throw new ProtocolError3(ProtocolErrorCode2.InvalidParams, "tool not found");
|
|
27199
27143
|
}
|
|
@@ -27202,9 +27146,15 @@ function buildMcpServer(version, bridge, listTtlMs) {
|
|
|
27202
27146
|
if (!validation.valid) {
|
|
27203
27147
|
throw new ProtocolError3(ProtocolErrorCode2.InvalidParams, validation.errorMessage);
|
|
27204
27148
|
}
|
|
27205
|
-
|
|
27149
|
+
let result;
|
|
27150
|
+
try {
|
|
27151
|
+
result = await bridge.call(selected.bridge, args);
|
|
27152
|
+
} catch (error) {
|
|
27153
|
+
if (!isTBError(error)) throw error;
|
|
27154
|
+
result = { content: error.toJSON(), isError: true };
|
|
27155
|
+
}
|
|
27206
27156
|
const candidate = {
|
|
27207
|
-
content: contentOf(result.content),
|
|
27157
|
+
content: contentOf(result.contentBlocks ?? result.content),
|
|
27208
27158
|
...result.isError === true ? { isError: true } : {},
|
|
27209
27159
|
...result.structuredContent !== void 0 ? { structuredContent: result.structuredContent } : result.content !== null && typeof result.content === "object" && !Array.isArray(result.content) ? { structuredContent: result.content } : {}
|
|
27210
27160
|
};
|
|
@@ -30676,6 +30626,9 @@ function registerSearchRoute(app, env) {
|
|
|
30676
30626
|
);
|
|
30677
30627
|
}
|
|
30678
30628
|
|
|
30629
|
+
// ../app/src/routes/mcp.ts
|
|
30630
|
+
import { z as z5 } from "zod/v4";
|
|
30631
|
+
|
|
30679
30632
|
// ../app/src/helpModel.ts
|
|
30680
30633
|
async function helpModelFor(node, registry, ctx, builtins, deps, opts) {
|
|
30681
30634
|
const index = opts.schemas !== true;
|
|
@@ -30799,362 +30752,210 @@ async function commandHelpModelFor(registry, ctx, builtins, deps, path, opts) {
|
|
|
30799
30752
|
};
|
|
30800
30753
|
}
|
|
30801
30754
|
|
|
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
|
-
|
|
30755
|
+
// ../app/src/mcpInvoke.ts
|
|
30756
|
+
function mcpPath(path, allowRoot = false) {
|
|
30757
|
+
const error = validatePath(path, { allowRoot });
|
|
30758
|
+
if (error !== null) throw error;
|
|
30759
|
+
return canonicalizePath(path).split("/").map(encodeURIComponent).join("/");
|
|
30760
|
+
}
|
|
30761
|
+
function mcpRequest(c, app, path, body, extraHeaders) {
|
|
30762
|
+
return Promise.resolve(app.request(new Request(new URL(path, c.req.url), {
|
|
30763
|
+
method: body === void 0 ? "GET" : "POST",
|
|
30764
|
+
headers: {
|
|
30765
|
+
"authorization": c.req.header("authorization") ?? "",
|
|
30766
|
+
"accept": "application/json",
|
|
30767
|
+
"content-type": "application/json",
|
|
30768
|
+
...extraHeaders
|
|
30769
|
+
},
|
|
30770
|
+
...body === void 0 ? {} : { body: JSON.stringify(body) },
|
|
30771
|
+
signal: c.req.raw.signal
|
|
30772
|
+
})));
|
|
30773
|
+
}
|
|
30774
|
+
async function mcpResponse(response) {
|
|
30775
|
+
const text = await response.text();
|
|
30776
|
+
let content = text;
|
|
30777
|
+
try {
|
|
30778
|
+
content = JSON.parse(text);
|
|
30779
|
+
} catch {
|
|
30780
|
+
}
|
|
30781
|
+
return { content, ...response.ok ? {} : { isError: true } };
|
|
30782
|
+
}
|
|
30783
|
+
async function invokeMcpTarget(c, env, app, input) {
|
|
30784
|
+
const encoded = mcpPath(input.path);
|
|
30785
|
+
const path = canonicalizePath(input.path);
|
|
30786
|
+
const args = { ...input.args };
|
|
30787
|
+
if (input.delivery !== void 0 && Object.hasOwn(args, "~delivery")) {
|
|
30788
|
+
throw new TBError("invalid_argument", "delivery and args.~delivery cannot both be provided");
|
|
30789
|
+
}
|
|
30790
|
+
const delivery = input.delivery ?? args["~delivery"];
|
|
30791
|
+
delete args["~delivery"];
|
|
30792
|
+
if (Object.keys(args).some((key) => key.startsWith("~"))) {
|
|
30793
|
+
throw new TBError("invalid_argument", "unknown invocation control in args");
|
|
30794
|
+
}
|
|
30795
|
+
if (delivery !== void 0 && delivery !== "realtime" && delivery !== "mailbox" && delivery !== "fallback") {
|
|
30796
|
+
throw new TBError("invalid_argument", "delivery must be realtime, mailbox or fallback");
|
|
30797
|
+
}
|
|
30798
|
+
if ((input.ttlSeconds !== void 0 || input.idempotencyKey !== void 0) && input.delivery !== "mailbox" && input.delivery !== "fallback") {
|
|
30799
|
+
throw new TBError("invalid_argument", "ttlSeconds and idempotencyKey require mailbox or fallback delivery");
|
|
30800
|
+
}
|
|
30801
|
+
const { deps, searchSync } = env;
|
|
30840
30802
|
const ctx = c.get("ctx");
|
|
30841
30803
|
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}'`);
|
|
30804
|
+
const resolved = await registry.resolve(path).catch(() => null);
|
|
30805
|
+
if (resolved === null) throw TBError.notFound("not found");
|
|
30806
|
+
const { node, rest: command } = resolved;
|
|
30807
|
+
if (node.kind === "remote") {
|
|
30808
|
+
if (!check(ctx, path, "read").allow) throw TBError.notFound("not found");
|
|
30809
|
+
if (!check(ctx, path, "call").allow) {
|
|
30810
|
+
throw new TBError("permission_denied", `no scope grants 'call' on '${path}'`);
|
|
30811
|
+
}
|
|
30812
|
+
const response2 = await mcpRequest(c, app, `/${encoded}/~help`);
|
|
30813
|
+
if (!response2.ok) return mcpResponse(response2);
|
|
30814
|
+
const model = helpJsonSchema.safeParse(await response2.json().catch(() => null));
|
|
30815
|
+
if (!model.success) throw new TBError("unavailable", "remote command help returned invalid JSON");
|
|
30816
|
+
const selected = model.data.cmds.find((cmd) => canonicalizePath(cmd.path) === path);
|
|
30817
|
+
if (selected === void 0) throw TBError.notFound("not found");
|
|
30818
|
+
validateMcpArguments(selected.inputSchema, args, path);
|
|
30819
|
+
} else {
|
|
30820
|
+
if (command === "" || command.includes("/") || !check(ctx, node.path, "read").allow) {
|
|
30821
|
+
throw TBError.notFound("not found");
|
|
30947
30822
|
}
|
|
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
|
-
});
|
|
30966
|
-
}
|
|
30967
|
-
found.push(path);
|
|
30968
|
-
takeRemoteRequest();
|
|
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
|
-
});
|
|
30823
|
+
const marker = deviceToolMarker(node);
|
|
30824
|
+
if (marker === null && (node.kind === "mcp" || node.kind === "http" || node.kind === "tool")) {
|
|
30825
|
+
if (!check(ctx, node.path, "call").allow) {
|
|
30826
|
+
throw new TBError("permission_denied", `no scope grants 'call' on '${node.path}'`);
|
|
30974
30827
|
}
|
|
30975
|
-
|
|
30976
|
-
|
|
30977
|
-
pending.push({ path: child.path, depth: depth + 1 });
|
|
30978
|
-
}
|
|
30828
|
+
if (delivery !== void 0) {
|
|
30829
|
+
throw new TBError("invalid_argument", "delivery is only supported by device-backed tool commands");
|
|
30979
30830
|
}
|
|
30831
|
+
const provider = await providerFor(node, ctx, deps);
|
|
30832
|
+
const raw = await upstreamTools(node, provider, deps, false, (/* @__PURE__ */ new Date()).toISOString(), searchSync);
|
|
30833
|
+
const selected = virtualizeTools(node.virtualize, raw).exposed.find((tool) => tool.name === command);
|
|
30834
|
+
if (selected === void 0) throw TBError.notFound("not found");
|
|
30835
|
+
validateMcpArguments(selected.inputSchema, args, path);
|
|
30836
|
+
return provider.call(resolveUpstreamTool(node.virtualize, raw, command), args);
|
|
30980
30837
|
}
|
|
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;
|
|
30838
|
+
if (marker !== null && marker.cmds === void 0) {
|
|
30839
|
+
if (!check(ctx, node.path, "call").allow) {
|
|
30840
|
+
throw new TBError("permission_denied", `no scope grants 'call' on '${node.path}'`);
|
|
31005
30841
|
}
|
|
31006
|
-
|
|
31007
|
-
|
|
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;
|
|
31020
|
-
}
|
|
31021
|
-
const model = await helpModelFor(node, registry, ctx, builtinsOf(c.get("store")), deps, {
|
|
30842
|
+
} else {
|
|
30843
|
+
const model = await helpModelFor(node, registry, ctx, env.builtinsOf(c.get("store")), deps, {
|
|
31022
30844
|
includeDirectUpload: check(ctx, node.path, "write").allow,
|
|
30845
|
+
now: (/* @__PURE__ */ new Date()).toISOString(),
|
|
31023
30846
|
refresh: false,
|
|
31024
|
-
|
|
30847
|
+
schemas: true,
|
|
31025
30848
|
searchSync
|
|
31026
30849
|
});
|
|
31027
|
-
|
|
31028
|
-
|
|
31029
|
-
|
|
31030
|
-
}
|
|
30850
|
+
const selected = model.cmds.find((cmd) => canonicalizePath(cmd.path) === path);
|
|
30851
|
+
if (selected === void 0) throw TBError.notFound("not found");
|
|
30852
|
+
if (!check(ctx, node.path, selected.scope).allow) {
|
|
30853
|
+
throw new TBError("permission_denied", `no scope grants '${selected.scope}' on '${node.path}'`);
|
|
31031
30854
|
}
|
|
30855
|
+
validateMcpArguments(selected.inputSchema, args, path);
|
|
31032
30856
|
}
|
|
31033
|
-
|
|
31034
|
-
}
|
|
30857
|
+
}
|
|
30858
|
+
const query = input.ttlSeconds === void 0 ? "" : `?ttlSeconds=${input.ttlSeconds}`;
|
|
30859
|
+
const response = await mcpRequest(c, app, `/${encoded}${query}`, {
|
|
30860
|
+
...args,
|
|
30861
|
+
...delivery === void 0 ? {} : { "~delivery": delivery }
|
|
30862
|
+
}, input.idempotencyKey === void 0 ? void 0 : { "x-tb-idempotency-key": input.idempotencyKey });
|
|
30863
|
+
const result = await mcpResponse(response);
|
|
30864
|
+
if (delivery !== void 0 && response.ok) {
|
|
30865
|
+
return {
|
|
30866
|
+
content: response.status === 202 ? { delivery: "mailbox", operation: result.content } : { delivery: "realtime", result: result.content }
|
|
30867
|
+
};
|
|
30868
|
+
}
|
|
30869
|
+
return result;
|
|
30870
|
+
}
|
|
30871
|
+
|
|
30872
|
+
// ../app/src/routes/mcp.ts
|
|
30873
|
+
var callInput = z5.strictObject({
|
|
30874
|
+
path: z5.string().min(1).describe("Complete command path returned by tb_help or tb_search; the same path as tb call."),
|
|
30875
|
+
args: z5.record(z5.string(), z5.unknown()).optional().describe("The command arguments object. Defaults to {}."),
|
|
30876
|
+
delivery: z5.enum(["realtime", "mailbox", "fallback"]).optional(),
|
|
30877
|
+
ttlSeconds: z5.number().int().positive().optional(),
|
|
30878
|
+
idempotencyKey: z5.string().min(1).optional()
|
|
30879
|
+
});
|
|
30880
|
+
var operationIdentity = {
|
|
30881
|
+
deviceId: z5.string().min(1),
|
|
30882
|
+
operationId: z5.string().min(1)
|
|
30883
|
+
};
|
|
30884
|
+
var deviceOperationInput = z5.discriminatedUnion("action", [
|
|
30885
|
+
z5.strictObject({
|
|
30886
|
+
action: z5.literal("list"),
|
|
30887
|
+
deviceId: z5.string().min(1),
|
|
30888
|
+
cursor: z5.string().min(1).optional(),
|
|
30889
|
+
limit: z5.number().int().positive().optional(),
|
|
30890
|
+
states: z5.array(deviceOperationStateSchema).min(1).optional()
|
|
30891
|
+
}),
|
|
30892
|
+
z5.strictObject({ action: z5.literal("get"), ...operationIdentity }),
|
|
30893
|
+
z5.strictObject({ action: z5.literal("cancel"), ...operationIdentity })
|
|
30894
|
+
]);
|
|
30895
|
+
function mcpBridgeFor(c, env, app) {
|
|
30896
|
+
const operations = new OperationRegistry();
|
|
30897
|
+
const request = async (path, body) => mcpResponse(await mcpRequest(c, app, path, body));
|
|
30898
|
+
if (env.globalSearchCapabilities().includes("search")) {
|
|
30899
|
+
operations.register("tb_search", {
|
|
30900
|
+
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.',
|
|
30901
|
+
effect: "read",
|
|
30902
|
+
inputSchema: toolSearchOptionsSchema.extend({ query: z5.string().trim().min(1) })
|
|
30903
|
+
}, async ({ query, ...opts }) => request("/~search", { query, opts }));
|
|
30904
|
+
}
|
|
30905
|
+
operations.register("tb_help", {
|
|
30906
|
+
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.",
|
|
30907
|
+
effect: "read",
|
|
30908
|
+
inputSchema: z5.strictObject({
|
|
30909
|
+
path: z5.string().optional(),
|
|
30910
|
+
tool: z5.string().min(1).regex(/^[^/]+$/).optional(),
|
|
30911
|
+
format: z5.enum(["json", "markdown", "dsl"]).optional(),
|
|
30912
|
+
schemas: z5.boolean().optional()
|
|
30913
|
+
})
|
|
30914
|
+
}, async ({ path = "", tool, format = "json", schemas: schemas2 }) => {
|
|
30915
|
+
const prefix = mcpPath(path, true);
|
|
30916
|
+
if (tool !== void 0 && prefix === "") {
|
|
30917
|
+
throw new TBError("invalid_argument", "tool detail requires a node path");
|
|
30918
|
+
}
|
|
30919
|
+
const command = tool === void 0 ? prefix : `${prefix}/${mcpPath(tool)}`;
|
|
30920
|
+
const response = await mcpRequest(c, app, `/${command ? `${command}/` : ""}~help${schemas2 ? "?schemas=1" : ""}`, void 0, {
|
|
30921
|
+
accept: format === "json" ? "application/json" : format === "dsl" ? "text/plain" : "text/markdown"
|
|
30922
|
+
});
|
|
30923
|
+
return mcpResponse(response);
|
|
30924
|
+
});
|
|
30925
|
+
operations.register("tb_list_nodes", {
|
|
30926
|
+
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.",
|
|
30927
|
+
effect: "read",
|
|
30928
|
+
inputSchema: z5.strictObject({
|
|
30929
|
+
path: z5.string().optional(),
|
|
30930
|
+
depth: z5.number().int().min(0).max(MAX_TREE_DEPTH).optional()
|
|
30931
|
+
})
|
|
30932
|
+
}, async ({ path = "", depth = 1 }) => {
|
|
30933
|
+
const prefix = mcpPath(path, true);
|
|
30934
|
+
return request(`/${prefix ? `${prefix}/` : ""}~tree?depth=${depth}`);
|
|
30935
|
+
});
|
|
30936
|
+
operations.register("tb_call", {
|
|
30937
|
+
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.",
|
|
30938
|
+
effect: "destructive",
|
|
30939
|
+
confirm: true,
|
|
30940
|
+
inputSchema: callInput
|
|
30941
|
+
}, async (input) => invokeMcpTarget(c, env, app, input));
|
|
30942
|
+
operations.register("tb_device_operations", {
|
|
30943
|
+
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.",
|
|
30944
|
+
effect: "destructive",
|
|
30945
|
+
confirm: true,
|
|
30946
|
+
inputSchema: deviceOperationInput
|
|
30947
|
+
}, async (input) => {
|
|
30948
|
+
const { action, deviceId } = input;
|
|
30949
|
+
const body = action === "list" ? { deviceId, opts: { cursor: input.cursor, limit: input.limit, states: input.states } } : { deviceId, operationId: input.operationId };
|
|
30950
|
+
return request(`/~device/operations/${action}`, body);
|
|
30951
|
+
});
|
|
31035
30952
|
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
|
-
}
|
|
30953
|
+
list: async () => operations.list(),
|
|
30954
|
+
call: async (tool, args) => operations.call(tool.name, args, void 0)
|
|
31154
30955
|
};
|
|
31155
30956
|
}
|
|
31156
30957
|
function registerMcpRoute(app, env) {
|
|
31157
|
-
app.all("/~mcp", (c) => runHandler(async () =>
|
|
30958
|
+
app.all("/~mcp", (c) => runHandler(async () => handleMcpRequest(
|
|
31158
30959
|
c.req.raw,
|
|
31159
30960
|
env.deps.version,
|
|
31160
30961
|
mcpBridgeFor(c, env, app),
|
|
@@ -35371,104 +35172,104 @@ function createTbServer(config) {
|
|
|
35371
35172
|
|
|
35372
35173
|
// ../plugins/src/registry.generated.ts
|
|
35373
35174
|
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-
|
|
35175
|
+
airtable: () => import("./airtable-VMQVXLHK.js"),
|
|
35176
|
+
alt_text_generator_ai: () => import("./alt_text_generator_ai-FTWY4RU4.js"),
|
|
35177
|
+
amap: () => import("./amap-OK5VBHYC.js"),
|
|
35178
|
+
anthropic: () => import("./anthropic-S67AZFZ3.js"),
|
|
35179
|
+
apify: () => import("./apify-ZE6MYQI3.js"),
|
|
35180
|
+
brave_search: () => import("./brave_search-TG2M2KOD.js"),
|
|
35181
|
+
circleci: () => import("./circleci-3L3WJVSK.js"),
|
|
35182
|
+
clerk: () => import("./clerk-EZPF2V7T.js"),
|
|
35183
|
+
cohere: () => import("./cohere-U27DPO64.js"),
|
|
35184
|
+
confluence: () => import("./confluence-G2KL6ERH.js"),
|
|
35185
|
+
convertapi: () => import("./convertapi-L4CLJ2M3.js"),
|
|
35186
|
+
currencyapi: () => import("./currencyapi-YPYXG7YY.js"),
|
|
35187
|
+
deepseek: () => import("./deepseek-6HT6WF3M.js"),
|
|
35188
|
+
docker_hub: () => import("./docker_hub-LPE3PCVB.js"),
|
|
35189
|
+
dropbox: () => import("./dropbox-V56ABHTA.js"),
|
|
35190
|
+
dub: () => import("./dub-6OKQ7MHT.js"),
|
|
35191
|
+
e2b: () => import("./e2b-JS2U2QFU.js"),
|
|
35192
|
+
exa: () => import("./exa-DPWVYXSP.js"),
|
|
35193
|
+
fal_ai: () => import("./fal_ai-DK6Y27ZF.js"),
|
|
35194
|
+
feishu: () => import("./feishu-K7EGSRF3.js"),
|
|
35195
|
+
feishu_custom_bot: () => import("./feishu_custom_bot-2JUGFYNG.js"),
|
|
35196
|
+
figma: () => import("./figma-FT5I7ITD.js"),
|
|
35197
|
+
firehydrant: () => import("./firehydrant-EIKLKHX2.js"),
|
|
35198
|
+
fixer: () => import("./fixer-U5QXIAKD.js"),
|
|
35199
|
+
fly: () => import("./fly-T3JYFZ2M.js"),
|
|
35200
|
+
front: () => import("./front-D72MGVOR.js"),
|
|
35201
|
+
geocodio: () => import("./geocodio-BOTD5TI5.js"),
|
|
35202
|
+
ghost: () => import("./ghost-KYP7SZGB.js"),
|
|
35203
|
+
github: () => import("./github-AGMZT3VY.js"),
|
|
35204
|
+
gmail: () => import("./gmail-BLJNJOBG.js"),
|
|
35205
|
+
googlecalendar: () => import("./googlecalendar-GTHWNCF6.js"),
|
|
35206
|
+
googledocs: () => import("./googledocs-6EEDMEBQ.js"),
|
|
35207
|
+
grafana: () => import("./grafana-GMW6EKSQ.js"),
|
|
35208
|
+
graphhopper: () => import("./graphhopper-6OLGBDGB.js"),
|
|
35209
|
+
ip2proxy: () => import("./ip2proxy-4QN42E6T.js"),
|
|
35210
|
+
ipgeolocation_io: () => import("./ipgeolocation_io-SK4XKDA2.js"),
|
|
35211
|
+
ipqualityscore: () => import("./ipqualityscore-6ANBPXKT.js"),
|
|
35212
|
+
jina_ai: () => import("./jina_ai-IHPSVRM5.js"),
|
|
35213
|
+
jira: () => import("./jira-46KKM4LC.js"),
|
|
35214
|
+
langsmith: () => import("./langsmith-JZA345I5.js"),
|
|
35215
|
+
lemlist: () => import("./lemlist-43IV7DK6.js"),
|
|
35216
|
+
linear: () => import("./linear-5LFH7XNL.js"),
|
|
35217
|
+
logsnag: () => import("./logsnag-5RMYAHIL.js"),
|
|
35218
|
+
mattermost: () => import("./mattermost-XFL6SHGG.js"),
|
|
35219
|
+
mem0: () => import("./mem0-NYO4DTP6.js"),
|
|
35220
|
+
memos: () => import("./memos-37MPQOLV.js"),
|
|
35221
|
+
metabase: () => import("./metabase-KYBKZFMG.js"),
|
|
35222
|
+
mistral_ai: () => import("./mistral_ai-6PL3K4PM.js"),
|
|
35223
|
+
mother_duck: () => import("./mother_duck-2NH7W5M5.js"),
|
|
35224
|
+
ngrok: () => import("./ngrok-UO6CDYCA.js"),
|
|
35225
|
+
notes: () => import("./notes-I3P32WP4.js"),
|
|
35226
|
+
notion: () => import("./notion-BEAJFUOE.js"),
|
|
35227
|
+
open_exchange_rates: () => import("./open_exchange_rates-CMF62JB4.js"),
|
|
35228
|
+
openai: () => import("./openai-IHOMKVND.js"),
|
|
35229
|
+
opengraph_io: () => import("./opengraph_io-ZQ2FGLHX.js"),
|
|
35230
|
+
openrouter: () => import("./openrouter-HXLW3NR5.js"),
|
|
35231
|
+
outline: () => import("./outline-ELCP4NEU.js"),
|
|
35232
|
+
paddle: () => import("./paddle-O77LALVN.js"),
|
|
35233
|
+
perplexity: () => import("./perplexity-JCU654QV.js"),
|
|
35234
|
+
pinecone: () => import("./pinecone-W5W4LRKL.js"),
|
|
35235
|
+
pipedrive: () => import("./pipedrive-ITMJLLPZ.js"),
|
|
35236
|
+
polar: () => import("./polar-R33XU4L3.js"),
|
|
35237
|
+
posthog: () => import("./posthog-JVNTOLTV.js"),
|
|
35238
|
+
postmark: () => import("./postmark-6SBG7HWV.js"),
|
|
35239
|
+
prerender: () => import("./prerender-GPNKTNFC.js"),
|
|
35240
|
+
pubmed: () => import("./pubmed-UP6ZEEIH.js"),
|
|
35241
|
+
railway: () => import("./railway-KWEWXHTY.js"),
|
|
35242
|
+
readwise: () => import("./readwise-BLATSMC3.js"),
|
|
35243
|
+
render: () => import("./render-QYRVIXII.js"),
|
|
35244
|
+
replicate: () => import("./replicate-JYTWH4NF.js"),
|
|
35245
|
+
resend: () => import("./resend-L5N75SZM.js"),
|
|
35246
|
+
rootly: () => import("./rootly-MHCPEQ26.js"),
|
|
35247
|
+
scrapfly: () => import("./scrapfly-PTPGYSJM.js"),
|
|
35248
|
+
scrapingbee: () => import("./scrapingbee-JN6UH5PY.js"),
|
|
35249
|
+
screenshot_fyi: () => import("./screenshot_fyi-4QRVSV55.js"),
|
|
35250
|
+
semantic_scholar: () => import("./semantic_scholar-LRSWA2GE.js"),
|
|
35251
|
+
sentry: () => import("./sentry-2G6PF5W6.js"),
|
|
35252
|
+
shodan: () => import("./shodan-WKKPP5C6.js"),
|
|
35253
|
+
shopify: () => import("./shopify-64YDK5T2.js"),
|
|
35254
|
+
stripe: () => import("./stripe-QAIGGOTF.js"),
|
|
35255
|
+
supabase: () => import("./supabase-WHTGR6ND.js"),
|
|
35256
|
+
tavily: () => import("./tavily-QIXCDDWO.js"),
|
|
35257
|
+
telegram: () => import("./telegram-E6G7CWI6.js"),
|
|
35258
|
+
telnyx: () => import("./telnyx-ZDVVS7PK.js"),
|
|
35259
|
+
todoist: () => import("./todoist-DMYF3G7J.js"),
|
|
35260
|
+
trello: () => import("./trello-HY2RYIRP.js"),
|
|
35261
|
+
turso: () => import("./turso-HAQWMGRP.js"),
|
|
35262
|
+
twilio: () => import("./twilio-MLXYPHJE.js"),
|
|
35263
|
+
umami: () => import("./umami-DZHBLPVG.js"),
|
|
35264
|
+
unsplash: () => import("./unsplash-GS2OPXKE.js"),
|
|
35265
|
+
upstash_redis: () => import("./upstash_redis-XMXWTNAJ.js"),
|
|
35266
|
+
uptimerobot: () => import("./uptimerobot-TF5WRZ4G.js"),
|
|
35267
|
+
v2ex: () => import("./v2ex-2BVXAPDF.js"),
|
|
35268
|
+
vercel: () => import("./vercel-YMJGQYJE.js"),
|
|
35269
|
+
wolfram_alpha_api: () => import("./wolfram_alpha_api-I56SXWFZ.js"),
|
|
35270
|
+
wordpress: () => import("./wordpress-R7TDFZ2P.js"),
|
|
35271
|
+
workos: () => import("./workos-HDNHWVMS.js"),
|
|
35272
|
+
zhihu: () => import("./zhihu-LX6AGGDS.js")
|
|
35472
35273
|
};
|
|
35473
35274
|
|
|
35474
35275
|
// ../plugins/src/catalog.generated.ts
|