@ontrails/mcp 1.0.0-beta.15 → 1.0.0-beta.16

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.
Files changed (49) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/README.md +19 -3
  3. package/package.json +11 -3
  4. package/src/build.ts +642 -70
  5. package/src/index.ts +5 -0
  6. package/src/surface.ts +71 -53
  7. package/.turbo/turbo-build.log +0 -1
  8. package/.turbo/turbo-lint.log +0 -3
  9. package/.turbo/turbo-typecheck.log +0 -1
  10. package/dist/annotations.d.ts +0 -19
  11. package/dist/annotations.d.ts.map +0 -1
  12. package/dist/annotations.js +0 -31
  13. package/dist/annotations.js.map +0 -1
  14. package/dist/build.d.ts +0 -49
  15. package/dist/build.d.ts.map +0 -1
  16. package/dist/build.js +0 -220
  17. package/dist/build.js.map +0 -1
  18. package/dist/index.d.ts +0 -7
  19. package/dist/index.d.ts.map +0 -1
  20. package/dist/index.js +0 -13
  21. package/dist/index.js.map +0 -1
  22. package/dist/progress.d.ts +0 -13
  23. package/dist/progress.d.ts.map +0 -1
  24. package/dist/progress.js +0 -51
  25. package/dist/progress.js.map +0 -1
  26. package/dist/stdio.d.ts +0 -12
  27. package/dist/stdio.d.ts.map +0 -1
  28. package/dist/stdio.js +0 -15
  29. package/dist/stdio.js.map +0 -1
  30. package/dist/surface.d.ts +0 -35
  31. package/dist/surface.d.ts.map +0 -1
  32. package/dist/surface.js +0 -123
  33. package/dist/surface.js.map +0 -1
  34. package/dist/tool-name.d.ts +0 -15
  35. package/dist/tool-name.d.ts.map +0 -1
  36. package/dist/tool-name.js +0 -19
  37. package/dist/tool-name.js.map +0 -1
  38. package/dist/trailhead.d.ts +0 -57
  39. package/dist/trailhead.d.ts.map +0 -1
  40. package/dist/trailhead.js +0 -136
  41. package/dist/trailhead.js.map +0 -1
  42. package/src/__tests__/annotations.test.ts +0 -63
  43. package/src/__tests__/build.test.ts +0 -648
  44. package/src/__tests__/progress.test.ts +0 -136
  45. package/src/__tests__/surface.test.ts +0 -191
  46. package/src/__tests__/tool-name.test.ts +0 -46
  47. package/tsconfig.json +0 -9
  48. package/tsconfig.tests.json +0 -10
  49. package/tsconfig.tsbuildinfo +0 -1
@@ -1,136 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
-
3
- import type { McpExtra } from '../build.js';
4
- import { createMcpProgressCallback } from '../progress.js';
5
-
6
- describe('createMcpProgressCallback', () => {
7
- test('returns undefined when no progressToken', () => {
8
- const extra: McpExtra = {};
9
- expect(createMcpProgressCallback(extra)).toBeUndefined();
10
- });
11
-
12
- test('returns undefined when no sendProgress function', () => {
13
- const extra: McpExtra = { progressToken: 'tok-1' };
14
- expect(createMcpProgressCallback(extra)).toBeUndefined();
15
- });
16
-
17
- test('sends 0/1 for start events', () => {
18
- const calls: [number, number][] = [];
19
- const extra: McpExtra = {
20
- progressToken: 'tok-1',
21
- sendProgress: (current, total) => {
22
- calls.push([current, total]);
23
- return Promise.resolve();
24
- },
25
- };
26
-
27
- const cb = createMcpProgressCallback(extra);
28
- expect(cb).toBeDefined();
29
-
30
- const callback = cb as NonNullable<typeof cb>;
31
- // oxlint-disable-next-line prefer-await-to-callbacks -- not a node callback
32
- callback({
33
- ts: new Date().toISOString(),
34
- type: 'start',
35
- });
36
-
37
- expect(calls).toEqual([[0, 1]]);
38
- });
39
-
40
- test('sends progress notification for progress events', () => {
41
- const calls: [number, number][] = [];
42
- const extra: McpExtra = {
43
- progressToken: 'tok-1',
44
- sendProgress: (current, total) => {
45
- calls.push([current, total]);
46
- return Promise.resolve();
47
- },
48
- };
49
-
50
- const cb = createMcpProgressCallback(extra);
51
- expect(cb).toBeDefined();
52
- const callback = cb as NonNullable<typeof cb>;
53
-
54
- // oxlint-disable-next-line prefer-await-to-callbacks -- not a node callback
55
- callback({
56
- current: 5,
57
- total: 10,
58
- ts: new Date().toISOString(),
59
- type: 'progress',
60
- });
61
-
62
- expect(calls).toEqual([[5, 10]]);
63
- });
64
-
65
- test('sends 1/1 for complete events', () => {
66
- const calls: [number, number][] = [];
67
- const extra: McpExtra = {
68
- progressToken: 'tok-1',
69
- sendProgress: (current, total) => {
70
- calls.push([current, total]);
71
- return Promise.resolve();
72
- },
73
- };
74
-
75
- const cb = createMcpProgressCallback(extra);
76
- expect(cb).toBeDefined();
77
- const callback = cb as NonNullable<typeof cb>;
78
-
79
- // oxlint-disable-next-line prefer-await-to-callbacks -- not a node callback
80
- callback({
81
- ts: new Date().toISOString(),
82
- type: 'complete',
83
- });
84
-
85
- expect(calls).toEqual([[1, 1]]);
86
- });
87
-
88
- test('does not send for error events', () => {
89
- const calls: [number, number][] = [];
90
- const extra: McpExtra = {
91
- progressToken: 'tok-1',
92
- sendProgress: (current, total) => {
93
- calls.push([current, total]);
94
- return Promise.resolve();
95
- },
96
- };
97
-
98
- const cb = createMcpProgressCallback(extra);
99
- expect(cb).toBeDefined();
100
- const callback = cb as NonNullable<typeof cb>;
101
-
102
- // oxlint-disable-next-line prefer-await-to-callbacks -- not a node callback
103
- callback({
104
- message: 'something broke',
105
- ts: new Date().toISOString(),
106
- type: 'error',
107
- });
108
-
109
- expect(calls).toEqual([]);
110
- });
111
-
112
- test('handles missing total gracefully', () => {
113
- const calls: [number, number][] = [];
114
- const extra: McpExtra = {
115
- progressToken: 'tok-1',
116
- sendProgress: (current, total) => {
117
- calls.push([current, total]);
118
- return Promise.resolve();
119
- },
120
- };
121
-
122
- const cb = createMcpProgressCallback(extra);
123
- expect(cb).toBeDefined();
124
- const callback = cb as NonNullable<typeof cb>;
125
-
126
- // oxlint-disable-next-line prefer-await-to-callbacks -- not a node callback
127
- callback({
128
- current: 3,
129
- ts: new Date().toISOString(),
130
- type: 'progress',
131
- });
132
-
133
- // Sends current with 0 as indeterminate total
134
- expect(calls).toEqual([[3, 0]]);
135
- });
136
- });
@@ -1,191 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
-
3
- import { Result, trail, topo } from '@ontrails/core';
4
- import { z } from 'zod';
5
-
6
- import { createServer, surface } from '../surface.js';
7
- import { deriveMcpTools } from '../build.js';
8
- import type { McpToolDefinition } from '../build.js';
9
-
10
- // ---------------------------------------------------------------------------
11
- // Tests
12
- // ---------------------------------------------------------------------------
13
-
14
- const unwrapOk = <T>(result: Result<T, Error>): T =>
15
- result.match({
16
- err: (error) => {
17
- throw error;
18
- },
19
- ok: (value) => value,
20
- });
21
-
22
- const requireTool = (tools: McpToolDefinition[], name: string) => {
23
- const tool = tools.find((entry) => entry.name === name);
24
- expect(tool).toBeDefined();
25
- if (!tool) {
26
- throw new Error(`Expected tool: ${name}`);
27
- }
28
- return tool;
29
- };
30
-
31
- /**
32
- * Unwrap deriveMcpTools result, throwing on error so test failures show up clearly.
33
- */
34
- const deriveTools = (
35
- ...args: Parameters<typeof deriveMcpTools>
36
- ): McpToolDefinition[] => {
37
- const result = deriveMcpTools(...args);
38
- if (result.isErr()) {
39
- throw result.error;
40
- }
41
- return result.value;
42
- };
43
-
44
- const createIntegrationFixtures = () => {
45
- const greetTrail = trail('greet', {
46
- blaze: (input) => Result.ok({ greeting: `Hello, ${input.name}!` }),
47
- description: 'Greet someone',
48
- input: z.object({ name: z.string() }),
49
- intent: 'read',
50
- });
51
-
52
- const deleteTrail = trail('item.delete', {
53
- blaze: (_input) => Result.ok({ deleted: true }),
54
- description: 'Delete an item',
55
- input: z.object({ id: z.string() }),
56
- intent: 'destroy',
57
- });
58
-
59
- const app = topo('myapp', { deleteTrail, greetTrail });
60
- return { app, tools: deriveTools(app) };
61
- };
62
-
63
- describe('surface', () => {
64
- test('surface throws on invalid topo', async () => {
65
- const t = trail('broken', {
66
- blaze: () => Result.ok({}),
67
- crosses: ['nonexistent.trail'],
68
- input: z.object({}),
69
- output: z.object({}),
70
- });
71
- const app = topo('test', { t });
72
- await expect(surface(app)).rejects.toThrow(/validation/i);
73
- });
74
-
75
- test('surface skips validation when validate: false', async () => {
76
- const t = trail('broken', {
77
- blaze: () => Result.ok({}),
78
- crosses: ['nonexistent.trail'],
79
- input: z.object({}),
80
- output: z.object({}),
81
- });
82
- const app = topo('test', { t });
83
- const result = await Promise.race([
84
- surface(app, { validate: false }).then(() => 'resolved' as const),
85
- // oxlint-disable-next-line avoid-new -- Promise constructor needed for setTimeout-based timeout
86
- new Promise<'timeout'>((resolve) => {
87
- setTimeout(() => {
88
- resolve('timeout');
89
- }, 50);
90
- }),
91
- ]);
92
- expect(['resolved', 'timeout']).toContain(result);
93
- });
94
-
95
- test('CreateServerOptions accepts flattened identity and resource fields', () => {
96
- const opts: Parameters<typeof surface>[1] = {
97
- description: 'Test MCP server',
98
- name: 'testapp',
99
- resources: {},
100
- validate: false,
101
- version: '1.2.3',
102
- };
103
- expect(opts.description).toBe('Test MCP server');
104
- expect(opts.name).toBe('testapp');
105
- expect(opts.resources).toEqual({});
106
- expect(opts.validate).toBe(false);
107
- expect(opts.version).toBe('1.2.3');
108
- });
109
-
110
- test('createServer registers tools that can be listed', () => {
111
- const echoTrail = trail('echo', {
112
- blaze: (input) => Result.ok({ reply: input.message }),
113
- description: 'Echo',
114
- input: z.object({ message: z.string() }),
115
- intent: 'read',
116
- });
117
-
118
- const app = topo('testapp', { echoTrail });
119
- const server = createServer(app, {
120
- name: 'testapp',
121
- version: '0.1.0',
122
- });
123
-
124
- // Server is created successfully
125
- expect(server).toBeDefined();
126
- });
127
-
128
- test('createServer handles multiple tools', () => {
129
- const echoTrail = trail('echo', {
130
- blaze: (input) => Result.ok({ reply: input.message }),
131
- description: 'Echo',
132
- input: z.object({ message: z.string() }),
133
- });
134
-
135
- const searchTrail = trail('search', {
136
- blaze: (input) => Result.ok({ results: [input.query] }),
137
- description: 'Search',
138
- input: z.object({ query: z.string() }),
139
- intent: 'read',
140
- });
141
-
142
- const app = topo('testapp', { echoTrail, searchTrail });
143
- const tools = deriveTools(app);
144
-
145
- expect(tools).toHaveLength(2);
146
-
147
- const server = createServer(app, {
148
- name: 'testapp',
149
- version: '0.1.0',
150
- });
151
- expect(server).toBeDefined();
152
- });
153
-
154
- test('deriveMcpTools returns tools and createServer materializes the server', () => {
155
- const echoTrail = trail('echo', {
156
- blaze: (input) => Result.ok({ reply: input.message }),
157
- description: 'Echo',
158
- input: z.object({ message: z.string() }),
159
- });
160
- const app = topo('surface-api', { echoTrail });
161
-
162
- const tools = unwrapOk(deriveMcpTools(app));
163
- expect(tools).toHaveLength(1);
164
-
165
- const server = createServer(app, {
166
- description: 'Surface API smoke',
167
- version: '2.0.0',
168
- });
169
- expect(server).toBeDefined();
170
- });
171
-
172
- test('deriveMcpTools + createServer integration', () => {
173
- const { app, tools } = createIntegrationFixtures();
174
- const names = tools.map((t) => t.name);
175
- expect(names).toContain('myapp_greet');
176
- expect(names).toContain('myapp_item_delete');
177
-
178
- expect(requireTool(tools, 'myapp_greet').annotations?.readOnlyHint).toBe(
179
- true
180
- );
181
- expect(
182
- requireTool(tools, 'myapp_item_delete').annotations?.destructiveHint
183
- ).toBe(true);
184
-
185
- const server = createServer(app, {
186
- name: 'myapp',
187
- version: '1.0.0',
188
- });
189
- expect(server).toBeDefined();
190
- });
191
- });
@@ -1,46 +0,0 @@
1
- import { describe, expect, test } from 'bun:test';
2
-
3
- import { deriveToolName } from '../tool-name.js';
4
-
5
- describe('deriveToolName', () => {
6
- test('replaces dots with underscores', () => {
7
- expect(deriveToolName('myapp', 'entity.show')).toBe('myapp_entity_show');
8
- });
9
-
10
- test('prefixes with app name', () => {
11
- expect(deriveToolName('myapp', 'search')).toBe('myapp_search');
12
- });
13
-
14
- test('handles multiple dots', () => {
15
- expect(deriveToolName('myapp', 'entity.onboard')).toBe(
16
- 'myapp_entity_onboard'
17
- );
18
- });
19
-
20
- test('replaces hyphens with underscores', () => {
21
- expect(deriveToolName('my-app', 'some-trail')).toBe('my_app_some_trail');
22
- });
23
-
24
- test('lowercases everything', () => {
25
- expect(deriveToolName('MyApp', 'Entity.Show')).toBe('myapp_entity_show');
26
- });
27
-
28
- test('handles single-segment trail IDs', () => {
29
- expect(deriveToolName('dispatch', 'search')).toBe('dispatch_search');
30
- });
31
-
32
- test('handles dots in app name', () => {
33
- expect(deriveToolName('my.app', 'trail')).toBe('my_app_trail');
34
- });
35
-
36
- test('matches spec examples', () => {
37
- expect(deriveToolName('myapp', 'entity.show')).toBe('myapp_entity_show');
38
- expect(deriveToolName('myapp', 'search')).toBe('myapp_search');
39
- expect(deriveToolName('myapp', 'entity.onboard')).toBe(
40
- 'myapp_entity_onboard'
41
- );
42
- expect(deriveToolName('dispatch', 'patch.search')).toBe(
43
- 'dispatch_patch_search'
44
- );
45
- });
46
- });
package/tsconfig.json DELETED
@@ -1,9 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.json",
3
- "compilerOptions": {
4
- "outDir": "dist",
5
- "rootDir": "src"
6
- },
7
- "include": ["src"],
8
- "exclude": ["**/__tests__/**", "**/*.test.ts", "dist"]
9
- }
@@ -1,10 +0,0 @@
1
- {
2
- "extends": "./tsconfig.json",
3
- "compilerOptions": {
4
- "noEmit": true,
5
- "rootDir": "./src",
6
- "types": ["bun"]
7
- },
8
- "include": ["src/**/*.test.ts", "src/__tests__/**/*.ts"],
9
- "exclude": []
10
- }
@@ -1 +0,0 @@
1
- {"root":["./src/annotations.ts","./src/build.ts","./src/index.ts","./src/progress.ts","./src/stdio.ts","./src/surface.ts","./src/tool-name.ts"],"version":"5.9.3"}