@ontrails/mcp 1.0.0-beta.12 → 1.0.0-beta.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-lint.log +1 -1
- package/CHANGELOG.md +71 -32
- package/README.md +10 -10
- package/dist/blaze.js +1 -1
- package/dist/blaze.js.map +1 -1
- package/dist/build.d.ts +8 -6
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +34 -21
- package/dist/build.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/stdio.d.ts +1 -1
- package/dist/stdio.js +1 -1
- package/dist/trailhead.d.ts +41 -0
- package/dist/trailhead.d.ts.map +1 -0
- package/dist/trailhead.js +109 -0
- package/dist/trailhead.js.map +1 -0
- package/package.json +2 -2
- package/src/__tests__/build.test.ts +60 -45
- package/src/__tests__/{blaze.test.ts → trailhead.test.ts} +20 -20
- package/src/build.ts +55 -28
- package/src/index.ts +2 -2
- package/src/stdio.ts +1 -1
- package/src/{blaze.ts → trailhead.ts} +17 -16
- package/tsconfig.tsbuildinfo +1 -1
package/src/build.ts
CHANGED
|
@@ -2,22 +2,23 @@
|
|
|
2
2
|
* Build MCP tool definitions from a Trails App.
|
|
3
3
|
*
|
|
4
4
|
* Iterates the topo, generates McpToolDefinition[] with handlers that
|
|
5
|
-
* validate input, compose
|
|
5
|
+
* validate input, compose gates, execute the implementation, and map
|
|
6
6
|
* Results to MCP responses.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import {
|
|
10
10
|
Result,
|
|
11
|
-
|
|
11
|
+
TRAILHEAD_KEY,
|
|
12
12
|
ValidationError,
|
|
13
13
|
executeTrail,
|
|
14
14
|
isBlobRef,
|
|
15
|
+
validateEstablishedTopo,
|
|
15
16
|
zodToJsonSchema,
|
|
16
17
|
} from '@ontrails/core';
|
|
17
18
|
import type {
|
|
18
19
|
BlobRef,
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
Gate,
|
|
21
|
+
ProvisionOverrideMap,
|
|
21
22
|
Topo,
|
|
22
23
|
Trail,
|
|
23
24
|
TrailContextInit,
|
|
@@ -33,7 +34,7 @@ import { deriveToolName } from './tool-name.js';
|
|
|
33
34
|
// ---------------------------------------------------------------------------
|
|
34
35
|
|
|
35
36
|
export interface BuildMcpToolsOptions {
|
|
36
|
-
/** Config values for
|
|
37
|
+
/** Config values for provisions that declare a `config` schema, keyed by provision ID. */
|
|
37
38
|
readonly configValues?:
|
|
38
39
|
| Readonly<Record<string, Record<string, unknown>>>
|
|
39
40
|
| undefined;
|
|
@@ -42,8 +43,10 @@ export interface BuildMcpToolsOptions {
|
|
|
42
43
|
| undefined;
|
|
43
44
|
readonly excludeTrails?: readonly string[] | undefined;
|
|
44
45
|
readonly includeTrails?: readonly string[] | undefined;
|
|
45
|
-
readonly
|
|
46
|
-
readonly
|
|
46
|
+
readonly gates?: readonly Gate[] | undefined;
|
|
47
|
+
readonly provisions?: ProvisionOverrideMap | undefined;
|
|
48
|
+
/** Set to `false` to skip topo validation while building tools. */
|
|
49
|
+
readonly validate?: boolean | undefined;
|
|
47
50
|
}
|
|
48
51
|
|
|
49
52
|
export interface McpToolDefinition {
|
|
@@ -64,7 +67,7 @@ export interface McpExtra {
|
|
|
64
67
|
readonly sendProgress?:
|
|
65
68
|
| ((current: number, total: number) => Promise<void>)
|
|
66
69
|
| undefined;
|
|
67
|
-
readonly
|
|
70
|
+
readonly abortSignal?: AbortSignal | undefined;
|
|
68
71
|
}
|
|
69
72
|
|
|
70
73
|
export interface McpToolResult {
|
|
@@ -212,20 +215,20 @@ const mcpError = (message: string): McpToolResult => ({
|
|
|
212
215
|
isError: true,
|
|
213
216
|
});
|
|
214
217
|
|
|
215
|
-
/** Add the MCP
|
|
216
|
-
const
|
|
218
|
+
/** Add the MCP trailhead marker while preserving any existing context extras. */
|
|
219
|
+
const withMcpTrailhead = (
|
|
217
220
|
progressCb: TrailContextInit['progress']
|
|
218
221
|
): Partial<TrailContextInit> => ({
|
|
219
222
|
...(progressCb === undefined ? {} : { progress: progressCb }),
|
|
220
223
|
extensions: {
|
|
221
|
-
[
|
|
224
|
+
[TRAILHEAD_KEY]: 'mcp' as const,
|
|
222
225
|
},
|
|
223
226
|
});
|
|
224
227
|
|
|
225
228
|
const createHandler =
|
|
226
229
|
(
|
|
227
230
|
t: Trail<unknown, unknown>,
|
|
228
|
-
|
|
231
|
+
gates: readonly Gate[],
|
|
229
232
|
options: BuildMcpToolsOptions
|
|
230
233
|
): ((
|
|
231
234
|
args: Record<string, unknown>,
|
|
@@ -234,12 +237,12 @@ const createHandler =
|
|
|
234
237
|
async (args, extra): Promise<McpToolResult> => {
|
|
235
238
|
const progressCb = createMcpProgressCallback(extra);
|
|
236
239
|
const result = await executeTrail(t, args, {
|
|
240
|
+
abortSignal: extra.abortSignal,
|
|
237
241
|
configValues: options.configValues,
|
|
238
242
|
createContext: options.createContext,
|
|
239
|
-
ctx:
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
signal: extra.signal,
|
|
243
|
+
ctx: withMcpTrailhead(progressCb),
|
|
244
|
+
gates,
|
|
245
|
+
provisions: options.provisions,
|
|
243
246
|
});
|
|
244
247
|
if (result.isOk()) {
|
|
245
248
|
return { content: await serializeOutput(result.value) };
|
|
@@ -257,15 +260,15 @@ const createHandler =
|
|
|
257
260
|
* Each trail in the topo becomes an McpToolDefinition with:
|
|
258
261
|
* - A derived tool name (app-prefixed, underscore-delimited)
|
|
259
262
|
* - JSON Schema input from zodToJsonSchema
|
|
260
|
-
* - MCP annotations from trail
|
|
261
|
-
* - A handler that validates, composes
|
|
263
|
+
* - MCP annotations from trail meta
|
|
264
|
+
* - A handler that validates, composes gates, executes, and maps results
|
|
262
265
|
*/
|
|
263
|
-
/** Check if a trail should be included based on
|
|
266
|
+
/** Check if a trail should be included based on meta and filters. */
|
|
264
267
|
const shouldInclude = (
|
|
265
268
|
trail: Trail<unknown, unknown>,
|
|
266
269
|
options: BuildMcpToolsOptions
|
|
267
270
|
): boolean => {
|
|
268
|
-
if (trail.
|
|
271
|
+
if (trail.meta?.['internal'] === true) {
|
|
269
272
|
return false;
|
|
270
273
|
}
|
|
271
274
|
if (options.includeTrails !== undefined && options.includeTrails.length > 0) {
|
|
@@ -302,7 +305,7 @@ const buildDescription = (
|
|
|
302
305
|
const buildToolDefinition = (
|
|
303
306
|
app: Topo,
|
|
304
307
|
trail: Trail<unknown, unknown>,
|
|
305
|
-
|
|
308
|
+
gates: readonly Gate[],
|
|
306
309
|
options: BuildMcpToolsOptions
|
|
307
310
|
): McpToolDefinition => {
|
|
308
311
|
const rawAnnotations = deriveAnnotations(trail);
|
|
@@ -311,7 +314,7 @@ const buildToolDefinition = (
|
|
|
311
314
|
return {
|
|
312
315
|
annotations,
|
|
313
316
|
description: buildDescription(trail),
|
|
314
|
-
handler: createHandler(trail,
|
|
317
|
+
handler: createHandler(trail, gates, options),
|
|
315
318
|
inputSchema: zodToJsonSchema(trail.input),
|
|
316
319
|
name: deriveToolName(app.name, trail.id),
|
|
317
320
|
trailId: trail.id,
|
|
@@ -322,7 +325,7 @@ const buildToolDefinition = (
|
|
|
322
325
|
const registerTool = (
|
|
323
326
|
app: Topo,
|
|
324
327
|
trailItem: Trail<unknown, unknown>,
|
|
325
|
-
|
|
328
|
+
gates: readonly Gate[],
|
|
326
329
|
options: BuildMcpToolsOptions,
|
|
327
330
|
nameToTrailId: Map<string, string>,
|
|
328
331
|
tools: McpToolDefinition[]
|
|
@@ -337,7 +340,7 @@ const registerTool = (
|
|
|
337
340
|
);
|
|
338
341
|
}
|
|
339
342
|
nameToTrailId.set(toolName, trailItem.id);
|
|
340
|
-
tools.push(buildToolDefinition(app, trailItem,
|
|
343
|
+
tools.push(buildToolDefinition(app, trailItem, gates, options));
|
|
341
344
|
return Result.ok();
|
|
342
345
|
};
|
|
343
346
|
|
|
@@ -348,11 +351,23 @@ const eligibleTrails = (
|
|
|
348
351
|
): Trail<unknown, unknown>[] =>
|
|
349
352
|
app.list().filter((trail) => shouldInclude(trail, options));
|
|
350
353
|
|
|
351
|
-
|
|
354
|
+
const validateToolBuild = (
|
|
352
355
|
app: Topo,
|
|
353
|
-
options: BuildMcpToolsOptions
|
|
356
|
+
options: BuildMcpToolsOptions
|
|
357
|
+
): Result<void, Error> => {
|
|
358
|
+
if (options.validate === false) {
|
|
359
|
+
return Result.ok();
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const validated = validateEstablishedTopo(app);
|
|
363
|
+
return validated.isErr() ? Result.err(validated.error) : Result.ok();
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
const registerTools = (
|
|
367
|
+
app: Topo,
|
|
368
|
+
options: BuildMcpToolsOptions,
|
|
369
|
+
gates: readonly Gate[]
|
|
354
370
|
): Result<McpToolDefinition[], Error> => {
|
|
355
|
-
const layers = options.layers ?? [];
|
|
356
371
|
const tools: McpToolDefinition[] = [];
|
|
357
372
|
const nameToTrailId = new Map<string, string>();
|
|
358
373
|
|
|
@@ -360,7 +375,7 @@ export const buildMcpTools = (
|
|
|
360
375
|
const registered = registerTool(
|
|
361
376
|
app,
|
|
362
377
|
trailItem,
|
|
363
|
-
|
|
378
|
+
gates,
|
|
364
379
|
options,
|
|
365
380
|
nameToTrailId,
|
|
366
381
|
tools
|
|
@@ -372,3 +387,15 @@ export const buildMcpTools = (
|
|
|
372
387
|
|
|
373
388
|
return Result.ok(tools);
|
|
374
389
|
};
|
|
390
|
+
|
|
391
|
+
export const buildMcpTools = (
|
|
392
|
+
app: Topo,
|
|
393
|
+
options: BuildMcpToolsOptions = {}
|
|
394
|
+
): Result<McpToolDefinition[], Error> => {
|
|
395
|
+
const validation = validateToolBuild(app, options);
|
|
396
|
+
if (validation.isErr()) {
|
|
397
|
+
return validation;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
return registerTools(app, options, options.gates ?? []);
|
|
401
|
+
};
|
package/src/index.ts
CHANGED
|
@@ -17,8 +17,8 @@ export { deriveAnnotations, type McpAnnotations } from './annotations.js';
|
|
|
17
17
|
// Progress
|
|
18
18
|
export { createMcpProgressCallback } from './progress.js';
|
|
19
19
|
|
|
20
|
-
//
|
|
21
|
-
export {
|
|
20
|
+
// Trailhead
|
|
21
|
+
export { trailhead, type TrailheadMcpOptions } from './trailhead.js';
|
|
22
22
|
|
|
23
23
|
// Transport
|
|
24
24
|
export { connectStdio } from './stdio.js';
|
package/src/stdio.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Thin wrapper around MCP SDK's StdioServerTransport.
|
|
3
3
|
*
|
|
4
4
|
* Exists as a separate function so it can be swapped for other transports
|
|
5
|
-
* (SSE, streamable HTTP) without changing
|
|
5
|
+
* (SSE, streamable HTTP) without changing trailhead().
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
import type { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* trailhead() -- the one-liner MCP server launcher.
|
|
3
3
|
*
|
|
4
4
|
* Three lines to expose trails as MCP tools:
|
|
5
5
|
*
|
|
6
6
|
* ```ts
|
|
7
7
|
* const app = topo("myapp", entity);
|
|
8
|
-
* await
|
|
8
|
+
* await trailhead(app);
|
|
9
9
|
* ```
|
|
10
10
|
*/
|
|
11
11
|
|
|
@@ -15,12 +15,12 @@ import {
|
|
|
15
15
|
ListToolsRequestSchema,
|
|
16
16
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
17
17
|
import type {
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
Gate,
|
|
19
|
+
ProvisionOverrideMap,
|
|
20
20
|
Topo,
|
|
21
21
|
TrailContextInit,
|
|
22
22
|
} from '@ontrails/core';
|
|
23
|
-
import {
|
|
23
|
+
import { validateEstablishedTopo } from '@ontrails/core';
|
|
24
24
|
|
|
25
25
|
import type { McpToolDefinition } from './build.js';
|
|
26
26
|
import { buildMcpTools } from './build.js';
|
|
@@ -30,8 +30,8 @@ import { connectStdio } from './stdio.js';
|
|
|
30
30
|
// Options
|
|
31
31
|
// ---------------------------------------------------------------------------
|
|
32
32
|
|
|
33
|
-
export interface
|
|
34
|
-
/** Config values for
|
|
33
|
+
export interface TrailheadMcpOptions {
|
|
34
|
+
/** Config values for provisions that declare a `config` schema, keyed by provision ID. */
|
|
35
35
|
readonly configValues?:
|
|
36
36
|
| Readonly<Record<string, Record<string, unknown>>>
|
|
37
37
|
| undefined;
|
|
@@ -40,7 +40,8 @@ export interface BlazeMcpOptions {
|
|
|
40
40
|
| undefined;
|
|
41
41
|
readonly excludeTrails?: readonly string[] | undefined;
|
|
42
42
|
readonly includeTrails?: readonly string[] | undefined;
|
|
43
|
-
readonly
|
|
43
|
+
readonly gates?: readonly Gate[] | undefined;
|
|
44
|
+
readonly provisions?: ProvisionOverrideMap | undefined;
|
|
44
45
|
readonly serverInfo?:
|
|
45
46
|
| {
|
|
46
47
|
readonly name?: string | undefined;
|
|
@@ -48,7 +49,6 @@ export interface BlazeMcpOptions {
|
|
|
48
49
|
}
|
|
49
50
|
| undefined;
|
|
50
51
|
readonly transport?: 'stdio' | undefined;
|
|
51
|
-
readonly services?: ServiceOverrideMap | undefined;
|
|
52
52
|
/** Set to `false` to skip topo validation at startup. Defaults to `true`. */
|
|
53
53
|
readonly validate?: boolean | undefined;
|
|
54
54
|
}
|
|
@@ -119,9 +119,9 @@ export const createMcpServer = (
|
|
|
119
119
|
};
|
|
120
120
|
|
|
121
121
|
const extra = {
|
|
122
|
+
abortSignal: undefined as AbortSignal | undefined,
|
|
122
123
|
progressToken,
|
|
123
124
|
sendProgress,
|
|
124
|
-
signal: undefined as AbortSignal | undefined,
|
|
125
125
|
};
|
|
126
126
|
|
|
127
127
|
const result = await tool.handler(args, extra);
|
|
@@ -133,18 +133,18 @@ export const createMcpServer = (
|
|
|
133
133
|
};
|
|
134
134
|
|
|
135
135
|
// ---------------------------------------------------------------------------
|
|
136
|
-
//
|
|
136
|
+
// trailhead
|
|
137
137
|
// ---------------------------------------------------------------------------
|
|
138
138
|
|
|
139
139
|
/**
|
|
140
140
|
* Build MCP tools from an App, create a server, and connect via stdio.
|
|
141
141
|
*/
|
|
142
|
-
export const
|
|
142
|
+
export const trailhead = async (
|
|
143
143
|
app: Topo,
|
|
144
|
-
options:
|
|
144
|
+
options: TrailheadMcpOptions = {}
|
|
145
145
|
): Promise<void> => {
|
|
146
146
|
if (options.validate !== false) {
|
|
147
|
-
const validated =
|
|
147
|
+
const validated = validateEstablishedTopo(app);
|
|
148
148
|
if (validated.isErr()) {
|
|
149
149
|
throw validated.error;
|
|
150
150
|
}
|
|
@@ -154,9 +154,10 @@ export const blaze = async (
|
|
|
154
154
|
configValues: options.configValues,
|
|
155
155
|
createContext: options.createContext,
|
|
156
156
|
excludeTrails: options.excludeTrails,
|
|
157
|
+
gates: options.gates,
|
|
157
158
|
includeTrails: options.includeTrails,
|
|
158
|
-
|
|
159
|
-
|
|
159
|
+
provisions: options.provisions,
|
|
160
|
+
validate: options.validate,
|
|
160
161
|
});
|
|
161
162
|
|
|
162
163
|
if (toolsResult.isErr()) {
|
package/tsconfig.tsbuildinfo
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/annotations.ts","./src/
|
|
1
|
+
{"root":["./src/annotations.ts","./src/build.ts","./src/index.ts","./src/progress.ts","./src/stdio.ts","./src/tool-name.ts","./src/trailhead.ts"],"version":"5.9.3"}
|