@ontrails/mcp 1.0.0-beta.18 → 1.0.0-beta.19
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/CHANGELOG.md +29 -0
- package/README.md +4 -5
- package/package.json +2 -2
- package/src/annotations.ts +20 -0
- package/src/build.ts +78 -2
- package/src/progress.ts +22 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,34 @@
|
|
|
1
1
|
# @ontrails/mcp
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.19
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e41c382: Document beta-channel install guidance in package and adapter README install snippets so consumers use explicit `@beta` (or pinned `1.0.0-beta.N`) tags instead of accidental `latest` resolution during the prerelease line. Adds the policy doc at `docs/releases/beta-channel-policy.md`, prints both `latest` and `beta` dist-tags in `bun run publish:registry-check`, and aligns plugin/skill install snippets.
|
|
8
|
+
- 1eb5bdc: Rename first-class trail composition from the `cross` API family to the `compose` family across core contracts, testing helpers, topo projections, Warden rules, CLI scaffolds, and docs. `composes`, `ctx.compose`, `composeInput`, and `Compose*` type names are now the public authoring vocabulary; topo persistence migrates legacy composition rows and graph keys forward.
|
|
9
|
+
- 8638dae: Add a public API example for MCP `deriveAnnotations` annotation derivation.
|
|
10
|
+
- 8638dae: Add public API examples for the MCP tool metadata keys.
|
|
11
|
+
- 8638dae: Add a public API example for the MCP progress callback bridge.
|
|
12
|
+
- 84f56a5: Project live trail-version metadata on CLI, HTTP, and MCP surfaces and thread explicit surface version selection into shared trail execution.
|
|
13
|
+
- 5d88104: Polish Trails blaze terminology across package docs and Warden guidance.
|
|
14
|
+
- Updated dependencies [e41c382]
|
|
15
|
+
- Updated dependencies [1eb5bdc]
|
|
16
|
+
- Updated dependencies [f8d80b9]
|
|
17
|
+
- Updated dependencies [846a597]
|
|
18
|
+
- Updated dependencies [223aaad]
|
|
19
|
+
- Updated dependencies [3125f4d]
|
|
20
|
+
- Updated dependencies [2494dc6]
|
|
21
|
+
- Updated dependencies [2d53717]
|
|
22
|
+
- Updated dependencies [16cb740]
|
|
23
|
+
- Updated dependencies [8894ecb]
|
|
24
|
+
- Updated dependencies [fdf7ec9]
|
|
25
|
+
- Updated dependencies [d76be13]
|
|
26
|
+
- Updated dependencies [84f56a5]
|
|
27
|
+
- Updated dependencies [431b04c]
|
|
28
|
+
- Updated dependencies [5d88104]
|
|
29
|
+
- Updated dependencies [f04a9ef]
|
|
30
|
+
- @ontrails/core@1.0.0-beta.19
|
|
31
|
+
|
|
3
32
|
## 1.0.0-beta.18
|
|
4
33
|
|
|
5
34
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -85,11 +85,11 @@ Trail IDs become MCP tool names with the app prefix: `entity.show` in app `myapp
|
|
|
85
85
|
|
|
86
86
|
## Resource resolution
|
|
87
87
|
|
|
88
|
-
Declared resources on each trail are resolved into the context before the
|
|
88
|
+
Declared resources on each trail are resolved into the context before the blaze receives input.
|
|
89
89
|
|
|
90
90
|
## Progress bridge
|
|
91
91
|
|
|
92
|
-
|
|
92
|
+
Blazes report progress through `ctx.progress`. On MCP, these bridge to `notifications/progress` when the client sends a `progressToken`:
|
|
93
93
|
|
|
94
94
|
```typescript
|
|
95
95
|
const importTrail = trail('data.import', {
|
|
@@ -110,11 +110,10 @@ await surface(graph, { include: ['entity.**', 'search'] });
|
|
|
110
110
|
await surface(graph, { exclude: ['internal.debug'] });
|
|
111
111
|
```
|
|
112
112
|
|
|
113
|
-
`*` matches one dotted segment and `**` matches any depth. Trails declared with
|
|
114
|
-
`visibility: 'internal'` stay hidden unless you include their exact trail ID.
|
|
113
|
+
`*` matches one dotted segment and `**` matches any depth. Trails declared with `visibility: 'internal'` stay hidden unless you include their exact trail ID.
|
|
115
114
|
|
|
116
115
|
## Installation
|
|
117
116
|
|
|
118
117
|
```bash
|
|
119
|
-
bun add @ontrails/mcp
|
|
118
|
+
bun add @ontrails/mcp@beta
|
|
120
119
|
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ontrails/mcp",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.19",
|
|
4
4
|
"files": [
|
|
5
5
|
"src/**/*.ts",
|
|
6
6
|
"!src/**/__tests__/**",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"clean": "rm -rf dist *.tsbuildinfo"
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@ontrails/core": "^1.0.0-beta.
|
|
25
|
+
"@ontrails/core": "^1.0.0-beta.19"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"@modelcontextprotocol/sdk": "^1.28.0",
|
package/src/annotations.ts
CHANGED
|
@@ -25,6 +25,26 @@ export interface McpAnnotations {
|
|
|
25
25
|
*
|
|
26
26
|
* Only sets hints that are explicitly declared on the trail.
|
|
27
27
|
* Omitted hints let the MCP SDK use its defaults.
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```ts
|
|
31
|
+
* import { deriveAnnotations } from '@ontrails/mcp';
|
|
32
|
+
*
|
|
33
|
+
* const annotations = deriveAnnotations({
|
|
34
|
+
* intent: 'read',
|
|
35
|
+
* idempotent: true,
|
|
36
|
+
* description: 'Show account',
|
|
37
|
+
* });
|
|
38
|
+
*
|
|
39
|
+
* // read intent -> readOnlyHint, idempotent -> idempotentHint, description -> title.
|
|
40
|
+
* annotations.readOnlyHint === true;
|
|
41
|
+
* annotations.idempotentHint === true;
|
|
42
|
+
* annotations.title === 'Show account';
|
|
43
|
+
*
|
|
44
|
+
* // destroy intent -> destructiveHint.
|
|
45
|
+
* const destroyAnnotations = deriveAnnotations({ intent: 'destroy' });
|
|
46
|
+
* destroyAnnotations.destructiveHint === true;
|
|
47
|
+
* ```
|
|
28
48
|
*/
|
|
29
49
|
export const deriveAnnotations = (
|
|
30
50
|
trail: Pick<
|
package/src/build.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
Result,
|
|
12
12
|
ValidationError,
|
|
13
13
|
collectAttachedTypedLayers,
|
|
14
|
+
deriveSurfaceTrailVersionProjections,
|
|
14
15
|
deriveStructuredTrailExamples,
|
|
15
16
|
executeTrail,
|
|
16
17
|
filterSurfaceTrails,
|
|
@@ -32,9 +33,11 @@ import type {
|
|
|
32
33
|
Layer,
|
|
33
34
|
ResourceOverrideMap,
|
|
34
35
|
SurfaceErrorProjection,
|
|
36
|
+
SurfaceTrailVersionProjection,
|
|
35
37
|
Topo,
|
|
36
38
|
Trail,
|
|
37
39
|
TrailContextInit,
|
|
40
|
+
TrailVersionReference,
|
|
38
41
|
} from '@ontrails/core';
|
|
39
42
|
|
|
40
43
|
import type { McpAnnotations } from './annotations.js';
|
|
@@ -42,8 +45,28 @@ import { deriveAnnotations } from './annotations.js';
|
|
|
42
45
|
import { createMcpProgressCallback } from './progress.js';
|
|
43
46
|
import { deriveToolName } from './tool-name.js';
|
|
44
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Metadata key used for structured trail examples on derived MCP tools.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* import { MCP_TOOL_EXAMPLES_META_KEY } from '@ontrails/mcp';
|
|
54
|
+
*
|
|
55
|
+
* const examples = tool._meta?.[MCP_TOOL_EXAMPLES_META_KEY];
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
45
58
|
export const MCP_TOOL_EXAMPLES_META_KEY = 'ontrails/examples';
|
|
46
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Metadata key used for public Trails error projections on MCP tool errors.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* import { MCP_TOOL_ERROR_META_KEY } from '@ontrails/mcp';
|
|
66
|
+
*
|
|
67
|
+
* const error = result._meta?.[MCP_TOOL_ERROR_META_KEY];
|
|
68
|
+
* ```
|
|
69
|
+
*/
|
|
47
70
|
export const MCP_TOOL_ERROR_META_KEY = 'ontrails/error';
|
|
48
71
|
|
|
49
72
|
// ---------------------------------------------------------------------------
|
|
@@ -84,6 +107,7 @@ export interface McpToolDefinition {
|
|
|
84
107
|
readonly outputSchema?: Record<string, unknown> | undefined;
|
|
85
108
|
/** The trail ID this tool was derived from. */
|
|
86
109
|
readonly trailId: string;
|
|
110
|
+
readonly versions?: readonly SurfaceTrailVersionProjection[] | undefined;
|
|
87
111
|
}
|
|
88
112
|
|
|
89
113
|
export interface McpExtra {
|
|
@@ -602,6 +626,48 @@ const projectMcpInputSchema = (
|
|
|
602
626
|
return { projections, schema: mergedSchema };
|
|
603
627
|
};
|
|
604
628
|
|
|
629
|
+
const TRAIL_VERSION_PARAM = 'trailVersion';
|
|
630
|
+
|
|
631
|
+
const addMcpVersionInputSchema = (
|
|
632
|
+
trail: Trail<unknown, unknown, unknown>,
|
|
633
|
+
schema: Record<string, unknown>
|
|
634
|
+
): Record<string, unknown> => {
|
|
635
|
+
if (trail.version === undefined) {
|
|
636
|
+
return schema;
|
|
637
|
+
}
|
|
638
|
+
const properties =
|
|
639
|
+
isJsonObjectSchema(schema) && schema.properties !== undefined
|
|
640
|
+
? schema.properties
|
|
641
|
+
: undefined;
|
|
642
|
+
return {
|
|
643
|
+
...schema,
|
|
644
|
+
properties: {
|
|
645
|
+
...properties,
|
|
646
|
+
[TRAIL_VERSION_PARAM]: {
|
|
647
|
+
description: 'Live trail version number or marker prefix',
|
|
648
|
+
type: 'string',
|
|
649
|
+
},
|
|
650
|
+
},
|
|
651
|
+
type: 'object',
|
|
652
|
+
};
|
|
653
|
+
};
|
|
654
|
+
|
|
655
|
+
const splitMcpSurfaceVersion = (
|
|
656
|
+
args: Record<string, unknown>
|
|
657
|
+
): {
|
|
658
|
+
readonly args: Record<string, unknown>;
|
|
659
|
+
readonly version: TrailVersionReference | undefined;
|
|
660
|
+
} => {
|
|
661
|
+
const { [TRAIL_VERSION_PARAM]: rawVersion, ...rest } = args;
|
|
662
|
+
return {
|
|
663
|
+
args: rest,
|
|
664
|
+
version:
|
|
665
|
+
typeof rawVersion === 'string' || typeof rawVersion === 'number'
|
|
666
|
+
? rawVersion
|
|
667
|
+
: undefined,
|
|
668
|
+
};
|
|
669
|
+
};
|
|
670
|
+
|
|
605
671
|
/**
|
|
606
672
|
* Partition a parsed MCP `args` record into the trail input plus per-layer
|
|
607
673
|
* inputs, using each layer's routing table.
|
|
@@ -750,8 +816,12 @@ const createHandler =
|
|
|
750
816
|
) => Promise<McpToolResult>) =>
|
|
751
817
|
async (args, extra): Promise<McpToolResult> => {
|
|
752
818
|
const progressCb = createMcpProgressCallback(extra);
|
|
819
|
+
const versionedArgs =
|
|
820
|
+
t.version === undefined
|
|
821
|
+
? { args, version: undefined }
|
|
822
|
+
: splitMcpSurfaceVersion(args);
|
|
753
823
|
const { trailInput, layerInputs } = partitionMcpArgs(
|
|
754
|
-
args,
|
|
824
|
+
versionedArgs.args,
|
|
755
825
|
layerProjections
|
|
756
826
|
);
|
|
757
827
|
const permitResolution = await resolveMcpPermit(options, extra);
|
|
@@ -770,6 +840,9 @@ const createHandler =
|
|
|
770
840
|
surfaceLayers: layers,
|
|
771
841
|
topo: graph,
|
|
772
842
|
topoLayers: graph.layers,
|
|
843
|
+
...(versionedArgs.version === undefined
|
|
844
|
+
? {}
|
|
845
|
+
: { version: versionedArgs.version }),
|
|
773
846
|
});
|
|
774
847
|
if (result.isOk()) {
|
|
775
848
|
return {
|
|
@@ -867,6 +940,8 @@ const buildToolDefinition = (
|
|
|
867
940
|
options.layers
|
|
868
941
|
);
|
|
869
942
|
const inputProjection = projectMcpInputSchema(trail, attachedLayers);
|
|
943
|
+
const inputSchema = addMcpVersionInputSchema(trail, inputProjection.schema);
|
|
944
|
+
const versions = deriveSurfaceTrailVersionProjections(trail);
|
|
870
945
|
return {
|
|
871
946
|
_meta: buildMeta(trail),
|
|
872
947
|
annotations,
|
|
@@ -879,10 +954,11 @@ const buildToolDefinition = (
|
|
|
879
954
|
projection?.wrapAsData ?? false,
|
|
880
955
|
inputProjection.projections
|
|
881
956
|
),
|
|
882
|
-
inputSchema
|
|
957
|
+
inputSchema,
|
|
883
958
|
name: deriveToolName(graph.name, trail.id),
|
|
884
959
|
outputSchema: projection?.schema,
|
|
885
960
|
trailId: trail.id,
|
|
961
|
+
...(versions === undefined ? {} : { versions }),
|
|
886
962
|
};
|
|
887
963
|
};
|
|
888
964
|
|
package/src/progress.ts
CHANGED
|
@@ -54,6 +54,28 @@ const progressHandlers: Record<
|
|
|
54
54
|
*
|
|
55
55
|
* Returns `undefined` if the MCP client did not provide a progressToken
|
|
56
56
|
* (meaning no progress reporting was requested).
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```ts
|
|
60
|
+
* import { createMcpProgressCallback, type McpExtra } from '@ontrails/mcp';
|
|
61
|
+
*
|
|
62
|
+
* const extra: McpExtra = {
|
|
63
|
+
* progressToken: 'token-123',
|
|
64
|
+
* sendProgress: async (current, total) => {
|
|
65
|
+
* console.log(`progress ${current}/${total}`);
|
|
66
|
+
* },
|
|
67
|
+
* };
|
|
68
|
+
*
|
|
69
|
+
* const progress = createMcpProgressCallback(extra);
|
|
70
|
+
* if (progress !== undefined) {
|
|
71
|
+
* progress({
|
|
72
|
+
* current: 0,
|
|
73
|
+
* ts: new Date().toISOString(),
|
|
74
|
+
* total: 1,
|
|
75
|
+
* type: 'start',
|
|
76
|
+
* });
|
|
77
|
+
* }
|
|
78
|
+
* ```
|
|
57
79
|
*/
|
|
58
80
|
export const createMcpProgressCallback = (
|
|
59
81
|
extra: McpExtra
|