@ontrails/mcp 1.0.0-beta.11 → 1.0.0-beta.13
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 -27
- package/README.md +10 -10
- package/dist/blaze.d.ts +2 -0
- package/dist/blaze.d.ts.map +1 -1
- package/dist/blaze.js +2 -1
- package/dist/blaze.js.map +1 -1
- package/dist/build.d.ts +7 -5
- package/dist/build.d.ts.map +1 -1
- package/dist/build.js +25 -17
- 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 +108 -0
- package/dist/trailhead.js.map +1 -0
- package/package.json +2 -2
- package/src/__tests__/build.test.ts +51 -41
- package/src/__tests__/{blaze.test.ts → trailhead.test.ts} +20 -20
- package/src/build.ts +37 -21
- package/src/index.ts +2 -2
- package/src/stdio.ts +1 -1
- package/src/{blaze.ts → trailhead.ts} +18 -13
- package/tsconfig.tsbuildinfo +1 -1
package/src/build.ts
CHANGED
|
@@ -2,12 +2,13 @@
|
|
|
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
|
+
TRAILHEAD_KEY,
|
|
11
12
|
ValidationError,
|
|
12
13
|
executeTrail,
|
|
13
14
|
isBlobRef,
|
|
@@ -15,8 +16,8 @@ import {
|
|
|
15
16
|
} from '@ontrails/core';
|
|
16
17
|
import type {
|
|
17
18
|
BlobRef,
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
Gate,
|
|
20
|
+
ProvisionOverrideMap,
|
|
20
21
|
Topo,
|
|
21
22
|
Trail,
|
|
22
23
|
TrailContextInit,
|
|
@@ -32,13 +33,17 @@ import { deriveToolName } from './tool-name.js';
|
|
|
32
33
|
// ---------------------------------------------------------------------------
|
|
33
34
|
|
|
34
35
|
export interface BuildMcpToolsOptions {
|
|
36
|
+
/** Config values for provisions that declare a `config` schema, keyed by provision ID. */
|
|
37
|
+
readonly configValues?:
|
|
38
|
+
| Readonly<Record<string, Record<string, unknown>>>
|
|
39
|
+
| undefined;
|
|
35
40
|
readonly createContext?:
|
|
36
41
|
| (() => TrailContextInit | Promise<TrailContextInit>)
|
|
37
42
|
| undefined;
|
|
38
43
|
readonly excludeTrails?: readonly string[] | undefined;
|
|
39
44
|
readonly includeTrails?: readonly string[] | undefined;
|
|
40
|
-
readonly
|
|
41
|
-
readonly
|
|
45
|
+
readonly gates?: readonly Gate[] | undefined;
|
|
46
|
+
readonly provisions?: ProvisionOverrideMap | undefined;
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
export interface McpToolDefinition {
|
|
@@ -59,7 +64,7 @@ export interface McpExtra {
|
|
|
59
64
|
readonly sendProgress?:
|
|
60
65
|
| ((current: number, total: number) => Promise<void>)
|
|
61
66
|
| undefined;
|
|
62
|
-
readonly
|
|
67
|
+
readonly abortSignal?: AbortSignal | undefined;
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
export interface McpToolResult {
|
|
@@ -207,10 +212,20 @@ const mcpError = (message: string): McpToolResult => ({
|
|
|
207
212
|
isError: true,
|
|
208
213
|
});
|
|
209
214
|
|
|
215
|
+
/** Add the MCP trailhead marker while preserving any existing context extras. */
|
|
216
|
+
const withMcpTrailhead = (
|
|
217
|
+
progressCb: TrailContextInit['progress']
|
|
218
|
+
): Partial<TrailContextInit> => ({
|
|
219
|
+
...(progressCb === undefined ? {} : { progress: progressCb }),
|
|
220
|
+
extensions: {
|
|
221
|
+
[TRAILHEAD_KEY]: 'mcp' as const,
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
|
|
210
225
|
const createHandler =
|
|
211
226
|
(
|
|
212
227
|
t: Trail<unknown, unknown>,
|
|
213
|
-
|
|
228
|
+
gates: readonly Gate[],
|
|
214
229
|
options: BuildMcpToolsOptions
|
|
215
230
|
): ((
|
|
216
231
|
args: Record<string, unknown>,
|
|
@@ -219,11 +234,12 @@ const createHandler =
|
|
|
219
234
|
async (args, extra): Promise<McpToolResult> => {
|
|
220
235
|
const progressCb = createMcpProgressCallback(extra);
|
|
221
236
|
const result = await executeTrail(t, args, {
|
|
237
|
+
abortSignal: extra.abortSignal,
|
|
238
|
+
configValues: options.configValues,
|
|
222
239
|
createContext: options.createContext,
|
|
223
|
-
ctx: progressCb
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
signal: extra.signal,
|
|
240
|
+
ctx: withMcpTrailhead(progressCb),
|
|
241
|
+
gates,
|
|
242
|
+
provisions: options.provisions,
|
|
227
243
|
});
|
|
228
244
|
if (result.isOk()) {
|
|
229
245
|
return { content: await serializeOutput(result.value) };
|
|
@@ -241,15 +257,15 @@ const createHandler =
|
|
|
241
257
|
* Each trail in the topo becomes an McpToolDefinition with:
|
|
242
258
|
* - A derived tool name (app-prefixed, underscore-delimited)
|
|
243
259
|
* - JSON Schema input from zodToJsonSchema
|
|
244
|
-
* - MCP annotations from trail
|
|
245
|
-
* - A handler that validates, composes
|
|
260
|
+
* - MCP annotations from trail meta
|
|
261
|
+
* - A handler that validates, composes gates, executes, and maps results
|
|
246
262
|
*/
|
|
247
|
-
/** Check if a trail should be included based on
|
|
263
|
+
/** Check if a trail should be included based on meta and filters. */
|
|
248
264
|
const shouldInclude = (
|
|
249
265
|
trail: Trail<unknown, unknown>,
|
|
250
266
|
options: BuildMcpToolsOptions
|
|
251
267
|
): boolean => {
|
|
252
|
-
if (trail.
|
|
268
|
+
if (trail.meta?.['internal'] === true) {
|
|
253
269
|
return false;
|
|
254
270
|
}
|
|
255
271
|
if (options.includeTrails !== undefined && options.includeTrails.length > 0) {
|
|
@@ -286,7 +302,7 @@ const buildDescription = (
|
|
|
286
302
|
const buildToolDefinition = (
|
|
287
303
|
app: Topo,
|
|
288
304
|
trail: Trail<unknown, unknown>,
|
|
289
|
-
|
|
305
|
+
gates: readonly Gate[],
|
|
290
306
|
options: BuildMcpToolsOptions
|
|
291
307
|
): McpToolDefinition => {
|
|
292
308
|
const rawAnnotations = deriveAnnotations(trail);
|
|
@@ -295,7 +311,7 @@ const buildToolDefinition = (
|
|
|
295
311
|
return {
|
|
296
312
|
annotations,
|
|
297
313
|
description: buildDescription(trail),
|
|
298
|
-
handler: createHandler(trail,
|
|
314
|
+
handler: createHandler(trail, gates, options),
|
|
299
315
|
inputSchema: zodToJsonSchema(trail.input),
|
|
300
316
|
name: deriveToolName(app.name, trail.id),
|
|
301
317
|
trailId: trail.id,
|
|
@@ -306,7 +322,7 @@ const buildToolDefinition = (
|
|
|
306
322
|
const registerTool = (
|
|
307
323
|
app: Topo,
|
|
308
324
|
trailItem: Trail<unknown, unknown>,
|
|
309
|
-
|
|
325
|
+
gates: readonly Gate[],
|
|
310
326
|
options: BuildMcpToolsOptions,
|
|
311
327
|
nameToTrailId: Map<string, string>,
|
|
312
328
|
tools: McpToolDefinition[]
|
|
@@ -321,7 +337,7 @@ const registerTool = (
|
|
|
321
337
|
);
|
|
322
338
|
}
|
|
323
339
|
nameToTrailId.set(toolName, trailItem.id);
|
|
324
|
-
tools.push(buildToolDefinition(app, trailItem,
|
|
340
|
+
tools.push(buildToolDefinition(app, trailItem, gates, options));
|
|
325
341
|
return Result.ok();
|
|
326
342
|
};
|
|
327
343
|
|
|
@@ -336,7 +352,7 @@ export const buildMcpTools = (
|
|
|
336
352
|
app: Topo,
|
|
337
353
|
options: BuildMcpToolsOptions = {}
|
|
338
354
|
): Result<McpToolDefinition[], Error> => {
|
|
339
|
-
const
|
|
355
|
+
const gates = options.gates ?? [];
|
|
340
356
|
const tools: McpToolDefinition[] = [];
|
|
341
357
|
const nameToTrailId = new Map<string, string>();
|
|
342
358
|
|
|
@@ -344,7 +360,7 @@ export const buildMcpTools = (
|
|
|
344
360
|
const registered = registerTool(
|
|
345
361
|
app,
|
|
346
362
|
trailItem,
|
|
347
|
-
|
|
363
|
+
gates,
|
|
348
364
|
options,
|
|
349
365
|
nameToTrailId,
|
|
350
366
|
tools
|
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,8 +15,8 @@ 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';
|
|
@@ -30,13 +30,18 @@ import { connectStdio } from './stdio.js';
|
|
|
30
30
|
// Options
|
|
31
31
|
// ---------------------------------------------------------------------------
|
|
32
32
|
|
|
33
|
-
export interface
|
|
33
|
+
export interface TrailheadMcpOptions {
|
|
34
|
+
/** Config values for provisions that declare a `config` schema, keyed by provision ID. */
|
|
35
|
+
readonly configValues?:
|
|
36
|
+
| Readonly<Record<string, Record<string, unknown>>>
|
|
37
|
+
| undefined;
|
|
34
38
|
readonly createContext?:
|
|
35
39
|
| (() => TrailContextInit | Promise<TrailContextInit>)
|
|
36
40
|
| undefined;
|
|
37
41
|
readonly excludeTrails?: readonly string[] | undefined;
|
|
38
42
|
readonly includeTrails?: readonly string[] | undefined;
|
|
39
|
-
readonly
|
|
43
|
+
readonly gates?: readonly Gate[] | undefined;
|
|
44
|
+
readonly provisions?: ProvisionOverrideMap | undefined;
|
|
40
45
|
readonly serverInfo?:
|
|
41
46
|
| {
|
|
42
47
|
readonly name?: string | undefined;
|
|
@@ -44,7 +49,6 @@ export interface BlazeMcpOptions {
|
|
|
44
49
|
}
|
|
45
50
|
| undefined;
|
|
46
51
|
readonly transport?: 'stdio' | undefined;
|
|
47
|
-
readonly services?: ServiceOverrideMap | undefined;
|
|
48
52
|
/** Set to `false` to skip topo validation at startup. Defaults to `true`. */
|
|
49
53
|
readonly validate?: boolean | undefined;
|
|
50
54
|
}
|
|
@@ -115,9 +119,9 @@ export const createMcpServer = (
|
|
|
115
119
|
};
|
|
116
120
|
|
|
117
121
|
const extra = {
|
|
122
|
+
abortSignal: undefined as AbortSignal | undefined,
|
|
118
123
|
progressToken,
|
|
119
124
|
sendProgress,
|
|
120
|
-
signal: undefined as AbortSignal | undefined,
|
|
121
125
|
};
|
|
122
126
|
|
|
123
127
|
const result = await tool.handler(args, extra);
|
|
@@ -129,15 +133,15 @@ export const createMcpServer = (
|
|
|
129
133
|
};
|
|
130
134
|
|
|
131
135
|
// ---------------------------------------------------------------------------
|
|
132
|
-
//
|
|
136
|
+
// trailhead
|
|
133
137
|
// ---------------------------------------------------------------------------
|
|
134
138
|
|
|
135
139
|
/**
|
|
136
140
|
* Build MCP tools from an App, create a server, and connect via stdio.
|
|
137
141
|
*/
|
|
138
|
-
export const
|
|
142
|
+
export const trailhead = async (
|
|
139
143
|
app: Topo,
|
|
140
|
-
options:
|
|
144
|
+
options: TrailheadMcpOptions = {}
|
|
141
145
|
): Promise<void> => {
|
|
142
146
|
if (options.validate !== false) {
|
|
143
147
|
const validated = validateTopo(app);
|
|
@@ -147,11 +151,12 @@ export const blaze = async (
|
|
|
147
151
|
}
|
|
148
152
|
|
|
149
153
|
const toolsResult = buildMcpTools(app, {
|
|
154
|
+
configValues: options.configValues,
|
|
150
155
|
createContext: options.createContext,
|
|
151
156
|
excludeTrails: options.excludeTrails,
|
|
157
|
+
gates: options.gates,
|
|
152
158
|
includeTrails: options.includeTrails,
|
|
153
|
-
|
|
154
|
-
services: options.services,
|
|
159
|
+
provisions: options.provisions,
|
|
155
160
|
});
|
|
156
161
|
|
|
157
162
|
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"}
|