@ontrails/mcp 1.0.0-beta.23 → 1.0.0-beta.29
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 +46 -0
- package/README.md +4 -1
- package/package.json +2 -2
- package/src/build.ts +5 -0
- package/src/index.ts +1 -0
- package/src/resources.ts +108 -0
- package/src/surface.ts +9 -7
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
# @ontrails/mcp
|
|
2
2
|
|
|
3
|
+
## 1.0.0-beta.29
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- @ontrails/core@1.0.0-beta.29
|
|
8
|
+
|
|
9
|
+
## 1.0.0-beta.28
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- @ontrails/core@1.0.0-beta.28
|
|
14
|
+
|
|
15
|
+
## 1.0.0-beta.27
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- @ontrails/core@1.0.0-beta.27
|
|
20
|
+
|
|
21
|
+
## 1.0.0-beta.26
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- Updated dependencies [1307568]
|
|
26
|
+
- Updated dependencies [371d19e]
|
|
27
|
+
- @ontrails/core@1.0.0-beta.26
|
|
28
|
+
|
|
29
|
+
## 1.0.0-beta.25
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- a9fdbc7: Clarify surface accommodation doctrine in MCP surface facet metadata and Warden trail-fork coaching guidance.
|
|
34
|
+
- 2c08afe: Expose MCP trail graph fact resources and enable them for the Trails operator MCP surface.
|
|
35
|
+
- f1e6efa: Document the Wayfinder MCP resource surface and polish Wayfinder filter dogfood coverage for unified navigation.
|
|
36
|
+
- df13faf: Tighten Wayfinder navigation review findings: carry adapter filters into included adapter facts, keep live-source outline off the operator MCP surface until host-root binding exists, make unknown MCP resources protocol errors, route secondary Wayfinder graph populations through unified flags, and keep undeclared string `ctx.compose()` calls as Warden errors.
|
|
37
|
+
- Updated dependencies [c36aca9]
|
|
38
|
+
- Updated dependencies [3befcf1]
|
|
39
|
+
- Updated dependencies [a4f9cf6]
|
|
40
|
+
- Updated dependencies [9bcf34e]
|
|
41
|
+
- @ontrails/core@1.0.0-beta.25
|
|
42
|
+
|
|
43
|
+
## 1.0.0-beta.24
|
|
44
|
+
|
|
45
|
+
### Patch Changes
|
|
46
|
+
|
|
47
|
+
- @ontrails/core@1.0.0-beta.24
|
|
48
|
+
|
|
3
49
|
## 1.0.0-beta.23
|
|
4
50
|
|
|
5
51
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -86,6 +86,7 @@ Cold context is projected through MCP resources, not extra Trails resources. `su
|
|
|
86
86
|
|
|
87
87
|
- `trails://surface-map` lists the resolved MCP tool projection, including ordinary tools, facet tools, schemas, versions, deferred hints, and member trail IDs.
|
|
88
88
|
- `trails://examples/<trailId>` exposes structured examples for exposed trails that define examples.
|
|
89
|
+
- `trails://trail/<trailId>` exposes MCP-visible graph facts for an exposed trail when graph resources are enabled.
|
|
89
90
|
|
|
90
91
|
Disable resource projection only when the host needs a minimal MCP capability surface:
|
|
91
92
|
|
|
@@ -97,10 +98,12 @@ Or choose a narrower resource set:
|
|
|
97
98
|
|
|
98
99
|
```typescript
|
|
99
100
|
await surface(graph, {
|
|
100
|
-
mcpResources: { examples: false, surfaceMap: true },
|
|
101
|
+
mcpResources: { examples: false, graph: true, surfaceMap: true },
|
|
101
102
|
});
|
|
102
103
|
```
|
|
103
104
|
|
|
105
|
+
Graph resources are opt-in for general MCP hosts because they widen cold context for every exposed trail. The Trails operator enables them so agents can inspect high-signal graph facts without invoking another tool.
|
|
106
|
+
|
|
104
107
|
Facet definitions may set `mcp: { loading: 'deferred' }`. In this release, deferred loading is a compatibility hint under `_meta["ontrails/deferred"]`; the MCP tool schema remains present so clients that do not understand deferred loading continue to work.
|
|
105
108
|
|
|
106
109
|
## Tool naming
|
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.29",
|
|
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.29"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"@modelcontextprotocol/sdk": "^1.28.0",
|
package/src/build.ts
CHANGED
|
@@ -73,6 +73,10 @@ export const MCP_TOOL_ERROR_META_KEY = 'ontrails/error';
|
|
|
73
73
|
/**
|
|
74
74
|
* Metadata key used to identify MCP tools derived from surface facets.
|
|
75
75
|
*
|
|
76
|
+
* Surface facets preserve member trail identity rather than merging member
|
|
77
|
+
* contracts. The metadata names the facet and its member trail IDs so clients
|
|
78
|
+
* can inspect the grouped entry before choosing a selected trail.
|
|
79
|
+
*
|
|
76
80
|
* @example
|
|
77
81
|
* ```ts
|
|
78
82
|
* import { MCP_TOOL_FACET_META_KEY } from '@ontrails/mcp';
|
|
@@ -111,6 +115,7 @@ export interface DeriveMcpToolsOptions extends BaseSurfaceOptions {
|
|
|
111
115
|
|
|
112
116
|
export type McpSurfaceFacetTrailSelector = string | readonly string[];
|
|
113
117
|
|
|
118
|
+
/** Surface-side grouped entry over existing trails. */
|
|
114
119
|
export interface McpSurfaceFacetDefinition {
|
|
115
120
|
readonly trails: McpSurfaceFacetTrailSelector;
|
|
116
121
|
readonly description: string;
|
package/src/index.ts
CHANGED
package/src/resources.ts
CHANGED
|
@@ -35,6 +35,18 @@ export const MCP_SURFACE_MAP_RESOURCE_URI = 'trails://surface-map';
|
|
|
35
35
|
*/
|
|
36
36
|
export const MCP_EXAMPLES_RESOURCE_PREFIX = 'trails://examples/';
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Prefix used for trail graph fact resources exposed through MCP.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```ts
|
|
43
|
+
* import { MCP_TRAIL_RESOURCE_PREFIX } from '@ontrails/mcp';
|
|
44
|
+
*
|
|
45
|
+
* const uri = `${MCP_TRAIL_RESOURCE_PREFIX}${encodeURIComponent('tasks.create')}`;
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export const MCP_TRAIL_RESOURCE_PREFIX = 'trails://trail/';
|
|
49
|
+
|
|
38
50
|
export interface McpResourceDefinition {
|
|
39
51
|
readonly uri: string;
|
|
40
52
|
readonly mimeType: string;
|
|
@@ -51,6 +63,7 @@ export interface McpResourceContent {
|
|
|
51
63
|
export interface McpResourcesConfig {
|
|
52
64
|
readonly surfaceMap?: boolean | undefined;
|
|
53
65
|
readonly examples?: boolean | undefined;
|
|
66
|
+
readonly graph?: boolean | undefined;
|
|
54
67
|
}
|
|
55
68
|
|
|
56
69
|
export interface BuiltMcpResources {
|
|
@@ -76,6 +89,21 @@ interface McpSurfaceMap {
|
|
|
76
89
|
readonly tools: readonly McpSurfaceMapTool[];
|
|
77
90
|
}
|
|
78
91
|
|
|
92
|
+
interface McpTrailResource {
|
|
93
|
+
readonly trailId: string;
|
|
94
|
+
readonly description?: string | undefined;
|
|
95
|
+
readonly intent: Trail<unknown, unknown, unknown>['intent'];
|
|
96
|
+
readonly visibility: Trail<unknown, unknown, unknown>['visibility'];
|
|
97
|
+
readonly composes: readonly string[];
|
|
98
|
+
readonly resources: readonly string[];
|
|
99
|
+
readonly signals: {
|
|
100
|
+
readonly fires: readonly string[];
|
|
101
|
+
readonly on: readonly string[];
|
|
102
|
+
};
|
|
103
|
+
readonly surface: 'mcp';
|
|
104
|
+
readonly tools: readonly McpSurfaceMapTool[];
|
|
105
|
+
}
|
|
106
|
+
|
|
79
107
|
const asJson = (value: unknown): string =>
|
|
80
108
|
`${JSON.stringify(value, null, 2)}\n`;
|
|
81
109
|
|
|
@@ -118,6 +146,9 @@ const exposedTrailIds = (
|
|
|
118
146
|
const examplesUriForTrail = (trailId: string): string =>
|
|
119
147
|
`${MCP_EXAMPLES_RESOURCE_PREFIX}${encodeURIComponent(trailId)}`;
|
|
120
148
|
|
|
149
|
+
const trailUriForTrail = (trailId: string): string =>
|
|
150
|
+
`${MCP_TRAIL_RESOURCE_PREFIX}${encodeURIComponent(trailId)}`;
|
|
151
|
+
|
|
121
152
|
const buildExampleResource = (
|
|
122
153
|
trailItem: Trail<unknown, unknown, unknown>
|
|
123
154
|
):
|
|
@@ -167,6 +198,76 @@ const buildExampleResources = (
|
|
|
167
198
|
.filter((resource) => resource !== undefined);
|
|
168
199
|
};
|
|
169
200
|
|
|
201
|
+
const resourceId = (
|
|
202
|
+
resource: Trail<unknown, unknown, unknown>['resources'][number]
|
|
203
|
+
) => resource.id;
|
|
204
|
+
|
|
205
|
+
const buildTrailGraphResource = (
|
|
206
|
+
trailItem: Trail<unknown, unknown, unknown>,
|
|
207
|
+
tools: readonly McpToolDefinition[]
|
|
208
|
+
): {
|
|
209
|
+
readonly content: McpResourceContent;
|
|
210
|
+
readonly listing: McpResourceDefinition;
|
|
211
|
+
} => {
|
|
212
|
+
const uri = trailUriForTrail(trailItem.id);
|
|
213
|
+
const surfaceTools = tools
|
|
214
|
+
.filter(
|
|
215
|
+
(tool) =>
|
|
216
|
+
tool.trailId === trailItem.id ||
|
|
217
|
+
tool.memberTrailIds?.includes(trailItem.id) === true
|
|
218
|
+
)
|
|
219
|
+
.map(projectSurfaceMapTool);
|
|
220
|
+
const payload: McpTrailResource = {
|
|
221
|
+
composes: trailItem.composes,
|
|
222
|
+
...(trailItem.description === undefined
|
|
223
|
+
? {}
|
|
224
|
+
: { description: trailItem.description }),
|
|
225
|
+
intent: trailItem.intent,
|
|
226
|
+
resources: trailItem.resources.map(resourceId),
|
|
227
|
+
signals: {
|
|
228
|
+
fires: trailItem.fires,
|
|
229
|
+
on: trailItem.on,
|
|
230
|
+
},
|
|
231
|
+
surface: 'mcp',
|
|
232
|
+
tools: surfaceTools,
|
|
233
|
+
trailId: trailItem.id,
|
|
234
|
+
visibility: trailItem.visibility,
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
return {
|
|
238
|
+
content: {
|
|
239
|
+
mimeType: 'application/json',
|
|
240
|
+
text: asJson(payload),
|
|
241
|
+
uri,
|
|
242
|
+
},
|
|
243
|
+
listing: {
|
|
244
|
+
description: `MCP-visible graph facts for trail "${trailItem.id}".`,
|
|
245
|
+
mimeType: 'application/json',
|
|
246
|
+
name: `Trail graph fact: ${trailItem.id}`,
|
|
247
|
+
uri,
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
const buildTrailGraphResources = (
|
|
253
|
+
graph: Topo,
|
|
254
|
+
tools: readonly McpToolDefinition[]
|
|
255
|
+
): readonly {
|
|
256
|
+
readonly content: McpResourceContent;
|
|
257
|
+
readonly listing: McpResourceDefinition;
|
|
258
|
+
}[] => {
|
|
259
|
+
const visibleTrailIds = exposedTrailIds(tools);
|
|
260
|
+
return graph
|
|
261
|
+
.list()
|
|
262
|
+
.filter((trailItem) => visibleTrailIds.has(trailItem.id))
|
|
263
|
+
.map((trailItem) =>
|
|
264
|
+
buildTrailGraphResource(
|
|
265
|
+
trailItem as Trail<unknown, unknown, unknown>,
|
|
266
|
+
tools
|
|
267
|
+
)
|
|
268
|
+
);
|
|
269
|
+
};
|
|
270
|
+
|
|
170
271
|
/**
|
|
171
272
|
* Build the cold-context MCP resources for a Trails graph and tool set.
|
|
172
273
|
*
|
|
@@ -208,6 +309,13 @@ export const buildMcpResources = (
|
|
|
208
309
|
}
|
|
209
310
|
}
|
|
210
311
|
|
|
312
|
+
if (config.graph === true) {
|
|
313
|
+
for (const resource of buildTrailGraphResources(graph, tools)) {
|
|
314
|
+
listings.push(resource.listing);
|
|
315
|
+
contents.set(resource.content.uri, resource.content);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
211
319
|
return {
|
|
212
320
|
list: listings,
|
|
213
321
|
read: (uri) => contents.get(uri),
|
package/src/surface.ts
CHANGED
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
6
6
|
import {
|
|
7
7
|
CallToolRequestSchema,
|
|
8
|
+
ErrorCode,
|
|
8
9
|
ListResourcesRequestSchema,
|
|
9
10
|
ListToolsRequestSchema,
|
|
11
|
+
McpError,
|
|
10
12
|
ReadResourceRequestSchema,
|
|
11
13
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
12
14
|
import type {
|
|
@@ -176,14 +178,14 @@ const createMcpServer = (
|
|
|
176
178
|
|
|
177
179
|
server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
|
|
178
180
|
const content = mcpResources.read(request.params.uri);
|
|
181
|
+
if (content === undefined) {
|
|
182
|
+
throw new McpError(
|
|
183
|
+
ErrorCode.InvalidParams,
|
|
184
|
+
`Resource ${request.params.uri} not found`
|
|
185
|
+
);
|
|
186
|
+
}
|
|
179
187
|
return {
|
|
180
|
-
contents: [
|
|
181
|
-
content ?? {
|
|
182
|
-
mimeType: 'text/plain',
|
|
183
|
-
text: `Unknown MCP resource: ${request.params.uri}`,
|
|
184
|
-
uri: request.params.uri,
|
|
185
|
-
},
|
|
186
|
-
],
|
|
188
|
+
contents: [content],
|
|
187
189
|
};
|
|
188
190
|
});
|
|
189
191
|
}
|