@chrischall/mcp-utils 0.14.1 → 0.15.0
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/README.md +17 -2
- package/dist/server/index.d.ts +27 -0
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +55 -0
- package/dist/server/index.js.map +1 -1
- package/dist/test/index.d.ts +3 -0
- package/dist/test/index.d.ts.map +1 -1
- package/dist/test/index.js +5 -0
- package/dist/test/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](LICENSE)
|
|
6
6
|
|
|
7
7
|
Shared scaffolding for the **chrischall MCP fleet** — the generic MCP glue
|
|
8
|
-
hoisted out of ~
|
|
8
|
+
hoisted out of ~50 sibling servers so each one no longer reimplements server
|
|
9
9
|
bootstrap, tool-result formatting, helpful errors, hardened env/config, a bearer
|
|
10
10
|
API-client kit, zod atoms, session registries, a fetchproxy transport adapter,
|
|
11
11
|
auth resolver skeletons, an in-memory test harness, and opt-in HTML helpers.
|
|
@@ -48,7 +48,7 @@ import { createFetchproxyTransport } from '@chrischall/mcp-utils/fetchproxy';
|
|
|
48
48
|
|
|
49
49
|
### `server` — bootstrap & lifecycle
|
|
50
50
|
|
|
51
|
-
`createMcpServer`, `runMcp`, `withGracefulShutdown`.
|
|
51
|
+
`createMcpServer`, `runMcp`, `withGracefulShutdown`, `surfaceToolHints`.
|
|
52
52
|
|
|
53
53
|
```ts
|
|
54
54
|
import { runMcp, textResult } from '@chrischall/mcp-utils';
|
|
@@ -67,6 +67,21 @@ await runMcp({
|
|
|
67
67
|
handlers via `withGracefulShutdown`. Use `createMcpServer` directly if you need
|
|
68
68
|
the server instance without connecting a transport.
|
|
69
69
|
|
|
70
|
+
Both render a thrown `McpToolError`'s `hint` into the failing tool's text:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
no such option 999
|
|
74
|
+
|
|
75
|
+
Hint: Available: 1 (Bus), 2 (Walker)
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
The MCP tool boundary itself surfaces only `message`, so a `hint` — the
|
|
79
|
+
actionable half — used to be dropped even though `wrapToolError` preserved it.
|
|
80
|
+
Anything that is not an `McpToolError`, or has no `hint`, propagates untouched,
|
|
81
|
+
so a genuine bug still reads as one. Opt out with `surfaceHints: false`.
|
|
82
|
+
`createTestHarness` applies the same wrapper, so a tool's failure text under
|
|
83
|
+
test is the text production returns.
|
|
84
|
+
|
|
70
85
|
### `response` — tool-result formatting
|
|
71
86
|
|
|
72
87
|
`textResult` / `jsonResult` (alias), `rawTextResult`, `imageResult`,
|
package/dist/server/index.d.ts
CHANGED
|
@@ -54,7 +54,34 @@ export interface CreateMcpServerOptions<TDeps = unknown> {
|
|
|
54
54
|
* `'stdio'`.
|
|
55
55
|
*/
|
|
56
56
|
transport?: TransportSpec;
|
|
57
|
+
/**
|
|
58
|
+
* Append an {@link McpToolError}'s `hint` to the text a failing tool returns.
|
|
59
|
+
* Default `true`. Set `false` only for a server that deliberately wants the
|
|
60
|
+
* bare message.
|
|
61
|
+
*/
|
|
62
|
+
surfaceHints?: boolean;
|
|
57
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Wrap `server.registerTool` so every tool handler surfaces its error `hint`.
|
|
66
|
+
*
|
|
67
|
+
* Why this lives here rather than in each repo: the MCP tool boundary renders
|
|
68
|
+
* only a thrown error's `message`. `McpToolError` has carried a `hint` — the
|
|
69
|
+
* actionable half ("the available options are …", "set FOO_API_KEY") — since
|
|
70
|
+
* the beginning, and {@link wrapToolError} is careful to preserve it, but
|
|
71
|
+
* nothing ever rendered it, so every hint thrown from a tool handler was
|
|
72
|
+
* invisible to the caller. Two repos had independently grown the same
|
|
73
|
+
* hand-rolled wrapper before this landed.
|
|
74
|
+
*
|
|
75
|
+
* Handlers are invoked variadically because the SDK passes `(args, extra)` for
|
|
76
|
+
* a tool with an `inputSchema` and `(extra)` for one without; forwarding
|
|
77
|
+
* whatever arrived keeps both shapes intact. Both a synchronous throw and a
|
|
78
|
+
* rejected promise are handled, since a handler may fail either way.
|
|
79
|
+
*
|
|
80
|
+
* Exported so `createTestHarness` can apply the same wrapper: a harness that
|
|
81
|
+
* built a bare `McpServer` would show tests a different error surface than
|
|
82
|
+
* production, which is the one thing a harness must never do.
|
|
83
|
+
*/
|
|
84
|
+
export declare function surfaceToolHints(server: McpServer): void;
|
|
58
85
|
/**
|
|
59
86
|
* Build an {@link McpServer}, print the optional stderr banner, and apply every
|
|
60
87
|
* tool registrar (awaiting async ones) — but do **not** connect a transport.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+CAA+C,CAAC;AAK/E;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,CAAC,KAAK,GAAG,OAAO,IAAI,CAC3C,MAAM,EAAE,SAAS,EACjB,IAAI,EAAE,KAAK,KACR,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1B,+EAA+E;AAC/E,MAAM,MAAM,aAAa,GAAG,OAAO,GAAG,SAAS,CAAC;AAEhD,2CAA2C;AAC3C,MAAM,WAAW,sBAAsB,CAAC,KAAK,GAAG,OAAO;IACrD,mEAAmE;IACnE,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;IAC9B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,KAAK,CAAC;IACb,mGAAmG;IACnG,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;;;OAIG;IACH,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAiBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,CAsBxD;AAED;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,KAAK,GAAG,OAAO,EACnD,IAAI,EAAE,sBAAsB,CAAC,KAAK,CAAC,GAClC,OAAO,CAAC,SAAS,CAAC,CAmBpB;AAED,wDAAwD;AACxD,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,SAAS,CAAC;AAElD,gDAAgD;AAChD,MAAM,WAAW,uBAAuB;IACtC;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D;;;OAGG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,IAAI,CAAC,SAAS,EAAE,OAAO,CAAC,EAChC,IAAI,GAAE,uBAA4B,GACjC,IAAI,CAyBN;AAED,oFAAoF;AACpF,MAAM,WAAW,aAAa,CAAC,KAAK,GAAG,OAAO,CAAE,SAAQ,sBAAsB,CAAC,KAAK,CAAC;IACnF;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,GAAG,uBAAuB,CAAC;CAC9C;AAED;;;;;;;;GAQG;AACH,wBAAsB,MAAM,CAAC,KAAK,GAAG,OAAO,EAC1C,IAAI,EAAE,aAAa,CAAC,KAAK,CAAC,GACzB,OAAO,CAAC,SAAS,CAAC,CAapB"}
|
package/dist/server/index.js
CHANGED
|
@@ -20,6 +20,58 @@
|
|
|
20
20
|
*/
|
|
21
21
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
22
22
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
23
|
+
import { McpToolError } from '../errors/index.js';
|
|
24
|
+
import { errorResult } from '../response/index.js';
|
|
25
|
+
/**
|
|
26
|
+
* Turn a thrown value into a tool result carrying its remediation `hint`, or
|
|
27
|
+
* rethrow it untouched.
|
|
28
|
+
*
|
|
29
|
+
* Only {@link McpToolError} with a `hint` is converted. Anything else keeps
|
|
30
|
+
* propagating so a genuine bug still reads as one instead of being flattened
|
|
31
|
+
* into advice.
|
|
32
|
+
*/
|
|
33
|
+
function hintResultOrRethrow(err) {
|
|
34
|
+
if (err instanceof McpToolError && err.hint) {
|
|
35
|
+
return errorResult(`${err.message}\n\nHint: ${err.hint}`);
|
|
36
|
+
}
|
|
37
|
+
throw err;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Wrap `server.registerTool` so every tool handler surfaces its error `hint`.
|
|
41
|
+
*
|
|
42
|
+
* Why this lives here rather than in each repo: the MCP tool boundary renders
|
|
43
|
+
* only a thrown error's `message`. `McpToolError` has carried a `hint` — the
|
|
44
|
+
* actionable half ("the available options are …", "set FOO_API_KEY") — since
|
|
45
|
+
* the beginning, and {@link wrapToolError} is careful to preserve it, but
|
|
46
|
+
* nothing ever rendered it, so every hint thrown from a tool handler was
|
|
47
|
+
* invisible to the caller. Two repos had independently grown the same
|
|
48
|
+
* hand-rolled wrapper before this landed.
|
|
49
|
+
*
|
|
50
|
+
* Handlers are invoked variadically because the SDK passes `(args, extra)` for
|
|
51
|
+
* a tool with an `inputSchema` and `(extra)` for one without; forwarding
|
|
52
|
+
* whatever arrived keeps both shapes intact. Both a synchronous throw and a
|
|
53
|
+
* rejected promise are handled, since a handler may fail either way.
|
|
54
|
+
*
|
|
55
|
+
* Exported so `createTestHarness` can apply the same wrapper: a harness that
|
|
56
|
+
* built a bare `McpServer` would show tests a different error surface than
|
|
57
|
+
* production, which is the one thing a harness must never do.
|
|
58
|
+
*/
|
|
59
|
+
export function surfaceToolHints(server) {
|
|
60
|
+
const register = server.registerTool.bind(server);
|
|
61
|
+
// The SDK's `registerTool` is heavily generic over the input/output schemas.
|
|
62
|
+
// Re-expressing those generics here would buy nothing — the wrapper is
|
|
63
|
+
// transparent — so the seam is cast once, here, and nowhere else.
|
|
64
|
+
server.registerTool = (name, config, cb) => register(name, config, (...args) => {
|
|
65
|
+
let result;
|
|
66
|
+
try {
|
|
67
|
+
result = cb(...args);
|
|
68
|
+
}
|
|
69
|
+
catch (err) {
|
|
70
|
+
return hintResultOrRethrow(err);
|
|
71
|
+
}
|
|
72
|
+
return result instanceof Promise ? result.catch(hintResultOrRethrow) : result;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
23
75
|
/**
|
|
24
76
|
* Build an {@link McpServer}, print the optional stderr banner, and apply every
|
|
25
77
|
* tool registrar (awaiting async ones) — but do **not** connect a transport.
|
|
@@ -28,6 +80,9 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
|
28
80
|
*/
|
|
29
81
|
export async function createMcpServer(opts) {
|
|
30
82
|
const server = new McpServer({ name: opts.name, version: opts.version });
|
|
83
|
+
// Before the registrars run, so every tool they register is wrapped.
|
|
84
|
+
if (opts.surfaceHints !== false)
|
|
85
|
+
surfaceToolHints(server);
|
|
31
86
|
if (opts.banner !== undefined) {
|
|
32
87
|
// stderr only: stdout carries the JSON-RPC frames over stdio transport.
|
|
33
88
|
console.error(opts.banner);
|
package/dist/server/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
package/dist/test/index.d.ts
CHANGED
|
@@ -24,6 +24,9 @@ export interface TestHarness {
|
|
|
24
24
|
* `InMemoryTransport`. The byte-identical helper every MCP's `tests/helpers.ts`
|
|
25
25
|
* defines — register your tools, then drive them through the real client RPC
|
|
26
26
|
* path (schema validation, content envelopes, isError, and all).
|
|
27
|
+
*
|
|
28
|
+
* Applies the same error-hint surfacing `createMcpServer` does, so a tool's
|
|
29
|
+
* failure text under test is the text production returns.
|
|
27
30
|
*/
|
|
28
31
|
export declare function createTestHarness(registerFn: RegisterFn): Promise<TestHarness>;
|
|
29
32
|
/**
|
package/dist/test/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAEnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"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"}
|
package/dist/test/index.js
CHANGED
|
@@ -17,14 +17,19 @@ import { vi } from 'vitest';
|
|
|
17
17
|
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
18
18
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
19
19
|
import { InMemoryTransport } from '@modelcontextprotocol/sdk/inMemory.js';
|
|
20
|
+
import { surfaceToolHints } from '../server/index.js';
|
|
20
21
|
/**
|
|
21
22
|
* Create a connected `McpServer` + `Client` pair wired over
|
|
22
23
|
* `InMemoryTransport`. The byte-identical helper every MCP's `tests/helpers.ts`
|
|
23
24
|
* defines — register your tools, then drive them through the real client RPC
|
|
24
25
|
* path (schema validation, content envelopes, isError, and all).
|
|
26
|
+
*
|
|
27
|
+
* Applies the same error-hint surfacing `createMcpServer` does, so a tool's
|
|
28
|
+
* failure text under test is the text production returns.
|
|
25
29
|
*/
|
|
26
30
|
export async function createTestHarness(registerFn) {
|
|
27
31
|
const server = new McpServer({ name: 'test', version: '0.0.0' });
|
|
32
|
+
surfaceToolHints(server);
|
|
28
33
|
await registerFn(server);
|
|
29
34
|
const client = new Client({ name: 'test-client', version: '0.0.0' });
|
|
30
35
|
const [clientTransport, serverTransport] = InMemoryTransport.createLinkedPair();
|
package/dist/test/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,iBAAiB,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chrischall/mcp-utils",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "Shared scaffolding for the chrischall MCP fleet — server bootstrap, tool-result formatting, helpful errors, hardened env/config, a bearer API-client kit, zod atoms, session registries, a fetchproxy transport adapter, auth resolver skeletons, an in-memory test harness, and opt-in HTML helpers. The generic MCP glue hoisted out of ~19 sibling servers.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|