@jini-ai/mcp 0.1.2 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -0
- package/dist/bin/serve.d.ts +25 -0
- package/dist/bin/serve.d.ts.map +1 -1
- package/dist/bin/serve.js +51 -5
- package/dist/bin/serve.js.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -2
- package/dist/index.js.map +1 -1
- package/dist/server/index.d.ts +5 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +5 -1
- package/dist/server/index.js.map +1 -1
- package/dist/server/resources/active-resource.d.ts.map +1 -1
- package/dist/server/resources/active-resource.js +3 -2
- package/dist/server/resources/active-resource.js.map +1 -1
- package/dist/server/tool-protocol.d.ts +48 -9
- package/dist/server/tool-protocol.d.ts.map +1 -1
- package/dist/server/tool-protocol.js +142 -10
- package/dist/server/tool-protocol.js.map +1 -1
- package/dist/server/tool-server.d.ts +6 -0
- package/dist/server/tool-server.d.ts.map +1 -1
- package/dist/server/tool-server.js +1 -0
- package/dist/server/tool-server.js.map +1 -1
- package/dist/server/tools/component-catalog-tools.d.ts +8 -0
- package/dist/server/tools/component-catalog-tools.d.ts.map +1 -0
- package/dist/server/tools/component-catalog-tools.js +71 -0
- package/dist/server/tools/component-catalog-tools.js.map +1 -0
- package/dist/server/tools/delegated-tool.d.ts +72 -0
- package/dist/server/tools/delegated-tool.d.ts.map +1 -1
- package/dist/server/tools/delegated-tool.js +148 -14
- package/dist/server/tools/delegated-tool.js.map +1 -1
- package/dist/server/tools/run-tools.d.ts.map +1 -1
- package/dist/server/tools/run-tools.js +8 -8
- package/dist/server/tools/run-tools.js.map +1 -1
- package/dist/server/tools/tool-catalog-tools.d.ts.map +1 -1
- package/dist/server/tools/tool-catalog-tools.js +43 -9
- package/dist/server/tools/tool-catalog-tools.js.map +1 -1
- package/package.json +10 -5
|
@@ -10,10 +10,96 @@
|
|
|
10
10
|
* JSON-serializable payload (wrapped as a successful MCP result) or throws
|
|
11
11
|
* (wrapped as an `{isError:true}` MCP result). `./tool-server.js` is the thin
|
|
12
12
|
* layer that wires this to a real `Server` + `StdioServerTransport`.
|
|
13
|
+
*
|
|
14
|
+
* ## The one exception to "wrapped as a successful MCP result"
|
|
15
|
+
*
|
|
16
|
+
* {@link okResult} used to JSON.stringify every non-string payload unconditionally, which is exactly
|
|
17
|
+
* right for the overwhelming majority of handlers (plain JSON — an id, a list, a count) but wrong
|
|
18
|
+
* for a handler whose payload IS already a well-formed MCP content envelope (`{content: [...]}` of
|
|
19
|
+
* recognized block types). Stringifying that flattens a typed `image` block into an inert
|
|
20
|
+
* base64-in-quotes string the client can no longer render or hand to a vision model — the exact bug
|
|
21
|
+
* `execute_delegated_tool` (`../tools/delegated-tool.js`) hit: `@jini-ai/daemon`'s
|
|
22
|
+
* `delegated-tool-bridge.ts` already keeps an image block in its returned `ToolExecutionResult.output`
|
|
23
|
+
* (it is model-safe per that package's `tool-result-surfaces.ts`), but this module still turned it
|
|
24
|
+
* back into text on the way out. {@link okResult} now recognizes that one shape — a `content` array
|
|
25
|
+
* whose every entry is a known, well-formed block (`text` or `image`) — and passes it through
|
|
26
|
+
* verbatim instead. Whitelist, not blacklist, mirroring `tool-result-surfaces.ts`'s own posture: a
|
|
27
|
+
* `content` array holding even one entry this module cannot verify falls back to the stringify path,
|
|
28
|
+
* so an unrecognized or malformed block is never silently forwarded as if it were valid protocol
|
|
29
|
+
* output.
|
|
13
30
|
*/
|
|
14
31
|
import { sanitizeUntrustedText } from '@jini-ai/cli';
|
|
15
|
-
|
|
32
|
+
import { CfWorkerJsonSchemaValidator } from '@modelcontextprotocol/sdk/validation/cfworker';
|
|
33
|
+
/**
|
|
34
|
+
* Maps a tool context onto the `DaemonRequestOptions` every daemon call needs.
|
|
35
|
+
*
|
|
36
|
+
* **Use this instead of writing `{ fetchImpl: ctx.fetchImpl }` inline.** Both fields have to travel
|
|
37
|
+
* together on every call, and the failure mode when one is forgotten is not a compile error but a
|
|
38
|
+
* silent 401 from that one tool while every other tool keeps working — the kind of bug that reaches
|
|
39
|
+
* a user as "some of these tools just don't do anything". Routing every call site through one
|
|
40
|
+
* mapping means a newly added tool is authenticated by construction.
|
|
41
|
+
*
|
|
42
|
+
* @param ctx - The context handed to a tool or resource handler.
|
|
43
|
+
* @returns Options carrying the injected `fetch` and, when present, the auth headers.
|
|
44
|
+
* @complexity O(1).
|
|
45
|
+
* @overallScore 100/100
|
|
46
|
+
*/
|
|
47
|
+
export function daemonCallOptions(ctx) {
|
|
48
|
+
return {
|
|
49
|
+
fetchImpl: ctx.fetchImpl,
|
|
50
|
+
...(ctx.authHeaders !== undefined ? { headers: { ...ctx.authHeaders } } : {}),
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
function isRecord(value) {
|
|
54
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* One MCP content-block `type` this module will pass through verbatim rather than JSON-stringify.
|
|
58
|
+
* Deliberately narrow — see this module's own doc for why widening it is a considered whitelist
|
|
59
|
+
* addition, not a default. Each entry is checked structurally (not just by `type`), so a block that
|
|
60
|
+
* merely claims a recognized `type` but is missing/mistyping its required field(s) still falls back
|
|
61
|
+
* to the stringify path rather than being forwarded malformed.
|
|
62
|
+
*/
|
|
63
|
+
function isPassthroughContentBlock(block) {
|
|
64
|
+
if (!isRecord(block))
|
|
65
|
+
return false;
|
|
66
|
+
if (block['type'] === 'text')
|
|
67
|
+
return typeof block['text'] === 'string';
|
|
68
|
+
if (block['type'] === 'image')
|
|
69
|
+
return typeof block['data'] === 'string' && typeof block['mimeType'] === 'string';
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* True when `payload` is already a well-formed MCP content envelope safe to hand back to the client
|
|
74
|
+
* unchanged: a record whose `content` field is an array, and every entry in it is a recognized,
|
|
75
|
+
* well-formed block (see {@link isPassthroughContentBlock}). A payload that merely has an array
|
|
76
|
+
* FIELD named `content` for unrelated reasons (an ordinary JSON object happening to use that name)
|
|
77
|
+
* will not match unless every entry also happens to look like a content block — the same duck-typed
|
|
78
|
+
* convention `@jini-ai/daemon`'s `tool-result-media.ts`/`tool-result-surfaces.ts` already apply to
|
|
79
|
+
* this identical envelope shape one layer up, kept consistent here rather than reinvented.
|
|
80
|
+
*/
|
|
81
|
+
function isMcpContentEnvelope(payload) {
|
|
82
|
+
if (!isRecord(payload))
|
|
83
|
+
return false;
|
|
84
|
+
const content = payload['content'];
|
|
85
|
+
return Array.isArray(content) && content.every(isPassthroughContentBlock);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Wraps a successful tool result as an MCP `CallToolResult`.
|
|
89
|
+
*
|
|
90
|
+
* A payload that is already a well-formed MCP content envelope (see {@link isMcpContentEnvelope}) is
|
|
91
|
+
* returned with its `content` array verbatim, so a typed block inside it — an `image`, today — reaches
|
|
92
|
+
* the client as a real content block rather than flattened text (see this module's own doc for the
|
|
93
|
+
* bug this closes). Every other payload keeps the original behavior: a string passes through as one
|
|
94
|
+
* text block; anything else is JSON-stringified into one.
|
|
95
|
+
*
|
|
96
|
+
* @complexity O(n) in the number of content-array entries, only when `payload` already looks like an
|
|
97
|
+
* envelope; O(1) otherwise.
|
|
98
|
+
*/
|
|
16
99
|
export function okResult(payload) {
|
|
100
|
+
if (isMcpContentEnvelope(payload)) {
|
|
101
|
+
return { content: payload.content };
|
|
102
|
+
}
|
|
17
103
|
const text = typeof payload === 'string' ? payload : JSON.stringify(payload, null, 2);
|
|
18
104
|
return { content: [{ type: 'text', text }] };
|
|
19
105
|
}
|
|
@@ -48,22 +134,68 @@ export function buildToolIndex(tools) {
|
|
|
48
134
|
return index;
|
|
49
135
|
}
|
|
50
136
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
|
|
58
|
-
|
|
137
|
+
* The SDK's own edge-runtime-compatible (no `eval`/codegen) JSON Schema validator — the same
|
|
138
|
+
* mechanism `McpServer.registerTool()`'s high-level helper uses internally, borrowed here because
|
|
139
|
+
* `createMcpToolServer` is built on the SDK's low-level `Server.setRequestHandler` instead (see
|
|
140
|
+
* `tool-server.ts`'s module doc), which does not validate a tool's declared `inputSchema` against
|
|
141
|
+
* arguments before its handler runs. One provider instance is reused across every tool: it holds no
|
|
142
|
+
* per-schema state itself (see {@link compiledValidators} for the actual compiled-validator cache).
|
|
143
|
+
*/
|
|
144
|
+
const schemaValidatorProvider = new CfWorkerJsonSchemaValidator();
|
|
145
|
+
/**
|
|
146
|
+
* Compiling a validator from a schema is real work `CfWorkerJsonSchemaValidator` does not cache
|
|
147
|
+
* internally (per its own doc), so it is cached here per `McpToolDef` instance — stable for a
|
|
148
|
+
* server's whole lifetime, since tool defs are created once at module load and never rebuilt.
|
|
149
|
+
*/
|
|
150
|
+
const compiledValidators = new WeakMap();
|
|
151
|
+
function validatorForTool(tool) {
|
|
152
|
+
const cached = compiledValidators.get(tool);
|
|
153
|
+
if (cached)
|
|
154
|
+
return cached;
|
|
155
|
+
const validator = schemaValidatorProvider.getValidator(tool.inputSchema);
|
|
156
|
+
compiledValidators.set(tool, validator);
|
|
157
|
+
return validator;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* `tools/call` dispatch: looks up `name` in `tools`, validates `rawArgs` against the tool's
|
|
161
|
+
* declared `inputSchema`, runs its handler, and converts the outcome to a `CallToolResult` — an
|
|
162
|
+
* unknown tool name, a schema violation, or a thrown error all produce an `{isError:true}` result
|
|
163
|
+
* rather than rejecting, matching MCP's convention that tool failures are protocol-level results,
|
|
164
|
+
* not JSON-RPC errors. Schema validation runs before every handler unconditionally: a caller (an
|
|
165
|
+
* agent, not this repo's own code) supplies `rawArgs`, so a handler must never be trusted to check
|
|
166
|
+
* its own declared contract on the untrusted-input path. Both a validation failure's message and a
|
|
167
|
+
* thrown error's message are passed through {@link sanitizeUntrustedText} before reaching the
|
|
168
|
+
* result: either can end up echoing caller- or daemon-supplied text, and it is cheaper to sanitize
|
|
169
|
+
* unconditionally than to prove which call site needs it.
|
|
59
170
|
*/
|
|
60
171
|
export async function handleToolCall(name, rawArgs, tools, ctx) {
|
|
61
172
|
const tool = tools.get(name);
|
|
62
173
|
if (tool === undefined) {
|
|
63
174
|
return errorResult(`unknown tool: ${name}`);
|
|
64
175
|
}
|
|
176
|
+
const args = rawArgs ?? {};
|
|
177
|
+
// Validation gets its own error boundary, separate from the handler's below. The
|
|
178
|
+
// validator does not only return `{valid:false}` for a bad argument — `@cfworker/json-schema`
|
|
179
|
+
// *throws* for JavaScript values JSON cannot encode (an explicitly-`undefined` optional
|
|
180
|
+
// property yields `Instances of "undefined" type are not supported.`). Compiling the
|
|
181
|
+
// validator can throw too, on a malformed `inputSchema`. Either escaping would break this
|
|
182
|
+
// function's whole contract, that a schema violation is an `{isError:true}` result and never
|
|
183
|
+
// a rejection — and `handleToolCall` is exported, typed `Record<string, unknown>`, and
|
|
184
|
+
// callable directly by a host, so this is reachable and not merely theoretical.
|
|
185
|
+
let validatedArgs;
|
|
186
|
+
try {
|
|
187
|
+
const validation = validatorForTool(tool)(args);
|
|
188
|
+
if (!validation.valid) {
|
|
189
|
+
return errorResult(sanitizeUntrustedText(`invalid arguments for ${name}: ${validation.errorMessage}`));
|
|
190
|
+
}
|
|
191
|
+
validatedArgs = validation.data;
|
|
192
|
+
}
|
|
193
|
+
catch (err) {
|
|
194
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
195
|
+
return errorResult(sanitizeUntrustedText(`invalid arguments for ${name}: ${message}`));
|
|
196
|
+
}
|
|
65
197
|
try {
|
|
66
|
-
const result = await tool.handler(
|
|
198
|
+
const result = await tool.handler(validatedArgs, ctx);
|
|
67
199
|
return okResult(result);
|
|
68
200
|
}
|
|
69
201
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-protocol.js","sourceRoot":"","sources":["../../src/server/tool-protocol.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"tool-protocol.js","sourceRoot":"","sources":["../../src/server/tool-protocol.ts"],"names":[],"mappings":"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"}
|
|
@@ -77,6 +77,12 @@ export interface McpToolServerOptions {
|
|
|
77
77
|
readonly idleMs?: number;
|
|
78
78
|
/** Defaults to the global `fetch`; threaded into every tool call's {@link McpToolContext}. */
|
|
79
79
|
readonly fetchImpl?: typeof fetch;
|
|
80
|
+
/**
|
|
81
|
+
* Headers attached to every daemon call this server's tools and resources make — in practice the
|
|
82
|
+
* bearer credential the spawning daemon issued for this run. Omit for a daemon whose `/api` surface
|
|
83
|
+
* does not require one; omitting is the pre-existing behavior.
|
|
84
|
+
*/
|
|
85
|
+
readonly authHeaders?: Readonly<Record<string, string>>;
|
|
80
86
|
/** Defaults to `process.stdin`; inject for tests (or an alternate stdio pair). */
|
|
81
87
|
readonly stdin?: Readable;
|
|
82
88
|
/** Defaults to `process.stdout`; inject for tests. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-server.d.ts","sourceRoot":"","sources":["../../src/server/tool-server.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"tool-server.d.ts","sourceRoot":"","sources":["../../src/server/tool-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -31,6 +31,7 @@ export function createMcpToolServer(options) {
|
|
|
31
31
|
const ctx = {
|
|
32
32
|
baseUrl: String(resolvedBaseUrl).replace(/\/$/, ''),
|
|
33
33
|
fetchImpl: options.fetchImpl ?? fetch,
|
|
34
|
+
...(options.authHeaders !== undefined ? { authHeaders: options.authHeaders } : {}),
|
|
34
35
|
};
|
|
35
36
|
let closeTransportForIdle = null;
|
|
36
37
|
const idleExit = createMcpIdleExitController({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-server.js","sourceRoot":"","sources":["../../src/server/tool-server.ts"],"names":[],"mappings":"AA2BA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAEnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,oCAAoC,CAAC;AAQ5C,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,eAAe,EAAuB,MAAM,wBAAwB,CAAC;AACtH,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,WAAW,EAAwC,MAAM,oBAAoB,CAAC;AAEvH,qIAAqI;AACrI,MAAM,eAAe,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"tool-server.js","sourceRoot":"","sources":["../../src/server/tool-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type McpToolDef } from '../tool-protocol.js';
|
|
2
|
+
/** `search_components` -> `GET /api/components/search` (`packages/http-kit/src/component-catalog.ts`'s `componentCatalogSearchRoute`). */
|
|
3
|
+
export declare const searchComponentsTool: McpToolDef;
|
|
4
|
+
/** `describe_component` -> `GET /api/components/:id` (`packages/http-kit/src/component-catalog.ts`'s `componentCatalogDescribeRoute`). */
|
|
5
|
+
export declare const describeComponentTool: McpToolDef;
|
|
6
|
+
/** Both component-catalog discovery tools, ready to pass as `createMcpToolServer`'s `tools` option. */
|
|
7
|
+
export declare const COMPONENT_CATALOG_TOOLS: readonly McpToolDef[];
|
|
8
|
+
//# sourceMappingURL=component-catalog-tools.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-catalog-tools.d.ts","sourceRoot":"","sources":["../../../src/server/tools/component-catalog-tools.ts"],"names":[],"mappings":"AAaA,OAAO,EAAoC,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAkBxF,0IAA0I;AAC1I,eAAO,MAAM,oBAAoB,EAAE,UAkClC,CAAC;AAEF,0IAA0I;AAC1I,eAAO,MAAM,qBAAqB,EAAE,UAiBnC,CAAC;AAEF,uGAAuG;AACvG,eAAO,MAAM,uBAAuB,EAAE,SAAS,UAAU,EAAkD,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module @jini-ai/mcp/server/tools/component-catalog-tools
|
|
3
|
+
*
|
|
4
|
+
* `search_components` / `describe_component` — the agent-facing discovery half of the
|
|
5
|
+
* interactive-UI loop, proxying `@jini-ai/http-kit`'s `GET /api/components/search` /
|
|
6
|
+
* `GET /api/components/:id` exactly as `tool-catalog-tools.ts` proxies `tool-catalog.ts`.
|
|
7
|
+
*
|
|
8
|
+
* This does not tell the agent how to render anything, only what's registered and its
|
|
9
|
+
* `propsSchema` — an agent still composes an A2UI or MCP-UI message naming the id and props; the
|
|
10
|
+
* host resolves and mounts it. Finding a component id here grants nothing, same posture as the
|
|
11
|
+
* tool catalog's discovery-is-not-permission stance.
|
|
12
|
+
*/
|
|
13
|
+
import { getDaemonJson } from '../daemon-client.js';
|
|
14
|
+
import { daemonCallOptions, requireString } from '../tool-protocol.js';
|
|
15
|
+
const READ_ANNOTATIONS = {
|
|
16
|
+
readOnlyHint: true,
|
|
17
|
+
idempotentHint: true,
|
|
18
|
+
openWorldHint: false,
|
|
19
|
+
};
|
|
20
|
+
/** `search_components` -> `GET /api/components/search` (`packages/http-kit/src/component-catalog.ts`'s `componentCatalogSearchRoute`). */
|
|
21
|
+
export const searchComponentsTool = {
|
|
22
|
+
name: 'search_components',
|
|
23
|
+
description: 'Search the registered interactive-UI component catalog. Returns ranked {id, provider, capabilities, description, score} candidates only — no propsSchema, so this stays cheap to call broadly. Call describe_component on the 1-3 candidates that look right before composing an A2UI or MCP-UI message that names one. Describe what interaction or data shape you need, not a component class name — e.g. "tabular list of records the user can click into" rather than "table".',
|
|
24
|
+
inputSchema: {
|
|
25
|
+
type: 'object',
|
|
26
|
+
properties: {
|
|
27
|
+
query: {
|
|
28
|
+
type: 'string',
|
|
29
|
+
description: 'Describe the interaction or data shape you need, in plain language — what the user should see and do, not a component name. Example: "let the user pick one date from a range" rather than "DatePicker". Required.',
|
|
30
|
+
},
|
|
31
|
+
limit: {
|
|
32
|
+
type: 'integer',
|
|
33
|
+
minimum: 1,
|
|
34
|
+
maximum: 25,
|
|
35
|
+
description: 'Max hits to return (1-25). Optional, defaults to 10.',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
required: ['query'],
|
|
39
|
+
additionalProperties: false,
|
|
40
|
+
},
|
|
41
|
+
annotations: { ...READ_ANNOTATIONS, title: 'Search the interactive-UI component catalog' },
|
|
42
|
+
handler: async (args, ctx) => {
|
|
43
|
+
requireString(args.query, 'query');
|
|
44
|
+
const params = new URLSearchParams({ q: args.query });
|
|
45
|
+
if (typeof args.limit === 'number')
|
|
46
|
+
params.set('limit', String(args.limit));
|
|
47
|
+
const data = await getDaemonJson(ctx.baseUrl, `/api/components/search?${params.toString()}`, daemonCallOptions(ctx));
|
|
48
|
+
return data.hits;
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
/** `describe_component` -> `GET /api/components/:id` (`packages/http-kit/src/component-catalog.ts`'s `componentCatalogDescribeRoute`). */
|
|
52
|
+
export const describeComponentTool = {
|
|
53
|
+
name: 'describe_component',
|
|
54
|
+
description: 'Get the full descriptor for one component id found via search_components — provider, capabilities, and propsSchema. Paid for only on the candidates that survive search.',
|
|
55
|
+
inputSchema: {
|
|
56
|
+
type: 'object',
|
|
57
|
+
properties: {
|
|
58
|
+
id: { type: 'string', description: 'Component id returned by search_components. Required.' },
|
|
59
|
+
},
|
|
60
|
+
required: ['id'],
|
|
61
|
+
additionalProperties: false,
|
|
62
|
+
},
|
|
63
|
+
annotations: { ...READ_ANNOTATIONS, title: 'Describe an interactive-UI component' },
|
|
64
|
+
handler: async (args, ctx) => {
|
|
65
|
+
requireString(args.id, 'id');
|
|
66
|
+
return getDaemonJson(ctx.baseUrl, `/api/components/${encodeURIComponent(args.id)}`, daemonCallOptions(ctx));
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
/** Both component-catalog discovery tools, ready to pass as `createMcpToolServer`'s `tools` option. */
|
|
70
|
+
export const COMPONENT_CATALOG_TOOLS = [searchComponentsTool, describeComponentTool];
|
|
71
|
+
//# sourceMappingURL=component-catalog-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-catalog-tools.js","sourceRoot":"","sources":["../../../src/server/tools/component-catalog-tools.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAmB,MAAM,qBAAqB,CAAC;AAExF,MAAM,gBAAgB,GAAG;IACvB,YAAY,EAAE,IAAI;IAClB,cAAc,EAAE,IAAI;IACpB,aAAa,EAAE,KAAK;CACZ,CAAC;AAYX,0IAA0I;AAC1I,MAAM,CAAC,MAAM,oBAAoB,GAAe;IAC9C,IAAI,EAAE,mBAAmB;IACzB,WAAW,EACT,odAAod;IACtd,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,WAAW,EACT,oNAAoN;aACvN;YACD,KAAK,EAAE;gBACL,IAAI,EAAE,SAAS;gBACf,OAAO,EAAE,CAAC;gBACV,OAAO,EAAE,EAAE;gBACX,WAAW,EAAE,sDAAsD;aACpE;SACF;QACD,QAAQ,EAAE,CAAC,OAAO,CAAC;QACnB,oBAAoB,EAAE,KAAK;KAC5B;IACD,WAAW,EAAE,EAAE,GAAG,gBAAgB,EAAE,KAAK,EAAE,6CAA6C,EAAE;IAC1F,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QAC3B,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QACtD,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ;YAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC5E,MAAM,IAAI,GAAG,MAAM,aAAa,CAC9B,GAAG,CAAC,OAAO,EACX,0BAA0B,MAAM,CAAC,QAAQ,EAAE,EAAE,EAC7C,iBAAiB,CAAC,GAAG,CAAC,CACvB,CAAC;QACF,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;CACF,CAAC;AAEF,0IAA0I;AAC1I,MAAM,CAAC,MAAM,qBAAqB,GAAe;IAC/C,IAAI,EAAE,oBAAoB;IAC1B,WAAW,EACT,0KAA0K;IAC5K,WAAW,EAAE;QACX,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,uDAAuD,EAAE;SAC7F;QACD,QAAQ,EAAE,CAAC,IAAI,CAAC;QAChB,oBAAoB,EAAE,KAAK;KAC5B;IACD,WAAW,EAAE,EAAE,GAAG,gBAAgB,EAAE,KAAK,EAAE,sCAAsC,EAAE;IACnF,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QAC3B,aAAa,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAC7B,OAAO,aAAa,CAAC,GAAG,CAAC,OAAO,EAAE,mBAAmB,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9G,CAAC;CACF,CAAC;AAEF,uGAAuG;AACvG,MAAM,CAAC,MAAM,uBAAuB,GAA0B,CAAC,oBAAoB,EAAE,qBAAqB,CAAC,CAAC"}
|
|
@@ -1,15 +1,87 @@
|
|
|
1
1
|
import { type McpToolDef } from '../tool-protocol.js';
|
|
2
|
+
/**
|
|
3
|
+
* Request deadline for one delegated tool call, overriding `daemon-client.ts`'s 15 s default.
|
|
4
|
+
*
|
|
5
|
+
* That default is sized for "a slow tool call" — a tool doing work. It is the wrong shape for this
|
|
6
|
+
* route, which is the one path in the system where a registered handler may legitimately be waiting
|
|
7
|
+
* on a *person*: a tool that raises an MCP-UI surface parks until the human answers it, and a human
|
|
8
|
+
* reading a dialog does not answer in fifteen seconds. Left at the default, every human-in-the-loop
|
|
9
|
+
* tool call fails at 15 s regardless of what the human eventually clicks.
|
|
10
|
+
*
|
|
11
|
+
* Six minutes is a *backstop*, not a budget. It assumes the host runs a tighter total-lifetime
|
|
12
|
+
* ceiling on the exchange itself, which ends the call with an explicit "no answer" outcome first;
|
|
13
|
+
* the extra headroom here just guarantees the exchange is always what gives up. Six minutes also
|
|
14
|
+
* stays inside every measured agent-CLI ceiling (Claude Code 30 min idle, Gemini CLI 10 min),
|
|
15
|
+
* which is what keeps this hop from becoming the binding constraint.
|
|
16
|
+
*
|
|
17
|
+
* A host whose exchange ceiling differs should override it via `delegatedToolTimeoutMs` rather
|
|
18
|
+
* than have its number encoded here — the engine has no way to know a given host's exchange
|
|
19
|
+
* policy, and hard-coding one host's value in generic engine source is what this default replaced.
|
|
20
|
+
*
|
|
21
|
+
* This is also, transitively, the hard cap on a multi-turn human conversation driven from one tool
|
|
22
|
+
* call: however many turns an exchange takes, they all happen inside this one request. Raising that
|
|
23
|
+
* ceiling starts here, not in the exchange store.
|
|
24
|
+
*
|
|
25
|
+
* The cost is real and accepted: a genuinely hung daemon now hangs this call for six minutes rather
|
|
26
|
+
* than fifteen seconds. The daemon-side alternative does not exist to lean on — `ToolDescriptor.timeoutMs`
|
|
27
|
+
* is unset on every registration today, so `ToolExecutor` arms no timer of its own.
|
|
28
|
+
*/
|
|
29
|
+
export declare const DEFAULT_DELEGATED_TOOL_TIMEOUT_MS: number;
|
|
2
30
|
export interface CreateExecuteDelegatedToolToolOptions {
|
|
3
31
|
/** The one run this MCP server process — and therefore this tool instance — is scoped to. */
|
|
4
32
|
readonly runId: string;
|
|
5
33
|
/** Generates each call's `toolUseId`. @default node:crypto randomUUID */
|
|
6
34
|
readonly generateToolUseId?: () => string;
|
|
35
|
+
/**
|
|
36
|
+
* Request deadline for one delegated tool call, in milliseconds. Set this to match the host's
|
|
37
|
+
* own exchange total-lifetime ceiling plus headroom, so the exchange — not this request — is
|
|
38
|
+
* what ends a call the human never answers.
|
|
39
|
+
*
|
|
40
|
+
* Must be a finite number greater than zero; anything else falls back to the default rather
|
|
41
|
+
* than arming a nonsensical (or immediately-firing) timer.
|
|
42
|
+
*
|
|
43
|
+
* @default DEFAULT_DELEGATED_TOOL_TIMEOUT_MS (6 min)
|
|
44
|
+
*/
|
|
45
|
+
readonly delegatedToolTimeoutMs?: number;
|
|
7
46
|
}
|
|
8
47
|
/**
|
|
9
48
|
* Builds the `execute_delegated_tool` tool def for one specific `runId`. A fresh MCP server
|
|
10
49
|
* process (one per spawned `claude` run, see `../../bin/serve.js`) calls this once at startup;
|
|
11
50
|
* every `tools/call` for the returned def's `name` during that process's lifetime executes
|
|
12
51
|
* against the same run.
|
|
52
|
+
*
|
|
53
|
+
* Declares `readOnlyHint: false`, which is the truth about a gateway that reaches the entire
|
|
54
|
+
* registry — reads and writes alike. See {@link createExecuteReadonlyDelegatedToolTool} for what
|
|
55
|
+
* that costs under a host that gates on the annotation, and for the companion that answers it.
|
|
13
56
|
*/
|
|
14
57
|
export declare function createExecuteDelegatedToolTool(options: CreateExecuteDelegatedToolToolOptions): McpToolDef;
|
|
58
|
+
/**
|
|
59
|
+
* Builds the `execute_readonly_delegated_tool` companion for one specific `runId` — the same
|
|
60
|
+
* gateway, narrowed to tools whose registration declares them read-only, and annotated
|
|
61
|
+
* `readOnlyHint: true`.
|
|
62
|
+
*
|
|
63
|
+
* WHY IT EXISTS. `execute_delegated_tool` is the sole route from an externally-injected MCP client
|
|
64
|
+
* into this host's entire native tool catalog, and it correctly annotates itself
|
|
65
|
+
* `readOnlyHint: false`. A runtime that auto-denies any MCP tool lacking `readOnlyHint: true`
|
|
66
|
+
* (headless `codex exec`, observed) therefore kills 100% of delegated calls — reads included —
|
|
67
|
+
* before they leave the client process. Nothing reaches the daemon, so no execution row is written
|
|
68
|
+
* and no error surfaces; the model, given no grounding signal at all, narrates a tool call that
|
|
69
|
+
* never happened. Meanwhile `search_tools`/`describe_tool` work, so discovery succeeds and only
|
|
70
|
+
* execution silently dies, which is the worst possible shape for the failure.
|
|
71
|
+
*
|
|
72
|
+
* WHY IT ENFORCES RATHER THAN ASSERTS. MCP annotations are static per tool declaration — the
|
|
73
|
+
* protocol has no way to vary one per call — so a read-only surface can only be a SECOND
|
|
74
|
+
* declaration, never a mode of the first. And a tool that declared `readOnlyHint: true` while
|
|
75
|
+
* still reaching writes would be worse than the bug it fixes: it would launder a write past a
|
|
76
|
+
* caller's own safety gate, and that caller has no way to audit the claim. The check is therefore
|
|
77
|
+
* made where it can be a fact rather than a claim — the daemon, via
|
|
78
|
+
* `@jini-ai/http-kit`'s `requireReadOnly`, resolving the id against the live `ToolRegistry` and
|
|
79
|
+
* `@jini-ai/core`'s `isReadOnlyTool`. Refusal is deny-by-default: an id that is unregistered, or
|
|
80
|
+
* registered without a read-only classification, is refused with a message naming the tool and
|
|
81
|
+
* pointing at `execute_delegated_tool`.
|
|
82
|
+
*
|
|
83
|
+
* Flipping the existing tool's annotation instead was rejected for the same reason: it would lie to
|
|
84
|
+
* every caller, including the ones the annotation exists to protect.
|
|
85
|
+
*/
|
|
86
|
+
export declare function createExecuteReadonlyDelegatedToolTool(options: CreateExecuteDelegatedToolToolOptions): McpToolDef;
|
|
15
87
|
//# sourceMappingURL=delegated-tool.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"delegated-tool.d.ts","sourceRoot":"","sources":["../../../src/server/tools/delegated-tool.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"delegated-tool.d.ts","sourceRoot":"","sources":["../../../src/server/tools/delegated-tool.ts"],"names":[],"mappings":"AAqCA,OAAO,EAAoC,KAAK,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAmCxF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,iCAAiC,QAAgB,CAAC;AAE/D,MAAM,WAAW,qCAAqC;IACpD,6FAA6F;IAC7F,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,yEAAyE;IACzE,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,MAAM,CAAC;IAC1C;;;;;;;;;OASG;IACH,QAAQ,CAAC,sBAAsB,CAAC,EAAE,MAAM,CAAC;CAC1C;AA6FD;;;;;;;;;GASG;AACH,wBAAgB,8BAA8B,CAAC,OAAO,EAAE,qCAAqC,GAAG,UAAU,CAYzG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,sCAAsC,CAAC,OAAO,EAAE,qCAAqC,GAAG,UAAU,CAgBjH"}
|