mcpose 2.1.1 → 3.1.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 +461 -62
- package/dist/backendClient.d.ts +1 -1
- package/dist/backendClient.d.ts.map +1 -1
- package/dist/backendClient.js +6 -1
- package/dist/backendClient.js.map +1 -1
- package/dist/core.d.ts +309 -35
- package/dist/core.d.ts.map +1 -1
- package/dist/core.js +1023 -186
- package/dist/core.js.map +1 -1
- package/dist/delegation.d.ts +89 -0
- package/dist/delegation.d.ts.map +1 -0
- package/dist/delegation.js +175 -0
- package/dist/delegation.js.map +1 -0
- package/dist/eventStore.d.ts +12 -0
- package/dist/eventStore.d.ts.map +1 -1
- package/dist/eventStore.js +43 -5
- package/dist/eventStore.js.map +1 -1
- package/dist/hiddenTools.d.ts +42 -0
- package/dist/hiddenTools.d.ts.map +1 -0
- package/dist/hiddenTools.js +53 -0
- package/dist/hiddenTools.js.map +1 -0
- package/dist/index.d.ts +15 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -3
- package/dist/index.js.map +1 -1
- package/dist/mesh.d.ts +82 -0
- package/dist/mesh.d.ts.map +1 -0
- package/dist/mesh.js +141 -0
- package/dist/mesh.js.map +1 -0
- package/dist/middleware.d.ts +13 -0
- package/dist/middleware.d.ts.map +1 -1
- package/dist/middleware.js +27 -3
- package/dist/middleware.js.map +1 -1
- package/dist/proxyContext.d.ts +65 -5
- package/dist/proxyContext.d.ts.map +1 -1
- package/dist/proxyContext.js +39 -4
- package/dist/proxyContext.js.map +1 -1
- package/dist/rejection.d.ts +7 -1
- package/dist/rejection.d.ts.map +1 -1
- package/dist/rejection.js +24 -1
- package/dist/rejection.js.map +1 -1
- package/dist/sanitizeCatalog.d.ts +37 -0
- package/dist/sanitizeCatalog.d.ts.map +1 -0
- package/dist/sanitizeCatalog.js +92 -0
- package/dist/sanitizeCatalog.js.map +1 -0
- package/dist/sessionRegistry.d.ts +79 -0
- package/dist/sessionRegistry.d.ts.map +1 -0
- package/dist/sessionRegistry.js +83 -0
- package/dist/sessionRegistry.js.map +1 -0
- package/dist/telemetry.d.ts +29 -1
- package/dist/telemetry.d.ts.map +1 -1
- package/dist/testing.d.ts +18 -2
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +30 -8
- package/dist/testing.js.map +1 -1
- package/dist/version.d.ts +7 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +7 -0
- package/dist/version.js.map +1 -0
- package/package.json +22 -8
- package/src/__tests__/_helpers.ts +64 -0
- package/src/__tests__/backendClient.test.ts +198 -0
- package/src/__tests__/core.delegation.test.ts +964 -0
- package/src/__tests__/core.edge.test.ts +314 -0
- package/src/__tests__/core.hiddenTools.predicate.test.ts +236 -0
- package/src/__tests__/core.localTools.test.ts +314 -0
- package/src/__tests__/core.mesh.test.ts +1182 -0
- package/src/__tests__/core.stripRequestMeta.test.ts +226 -0
- package/src/__tests__/core.stripResultMeta.test.ts +217 -0
- package/src/__tests__/core.test.ts +1105 -0
- package/src/__tests__/core.toolCallTelemetry.test.ts +157 -0
- package/src/__tests__/eventStore.test.ts +141 -0
- package/src/__tests__/hasToolContent.test.ts +63 -0
- package/src/__tests__/mapToolResult.test.ts +101 -0
- package/src/__tests__/middleware.edge.test.ts +126 -0
- package/src/__tests__/middleware.test.ts +233 -0
- package/src/__tests__/proxyContext.test.ts +140 -0
- package/src/__tests__/sanitizeCatalog.test.ts +380 -0
- package/src/__tests__/startHttpProxy.lifecycle.test.ts +675 -0
- package/src/__tests__/startHttpProxy.registry.test.ts +409 -0
- package/src/__tests__/startHttpProxy.replay.test.ts +116 -0
- package/src/__tests__/startHttpProxy.security.test.ts +288 -0
- package/src/__tests__/startHttpProxy.test.ts +1065 -0
- package/src/__tests__/testing.test.ts +250 -0
- package/src/__tests__/version.test.ts +12 -0
- package/src/backendClient.ts +83 -0
- package/src/core.ts +2129 -0
- package/src/delegation.ts +224 -0
- package/src/eventStore.ts +106 -0
- package/src/hiddenTools.ts +84 -0
- package/src/identity.ts +15 -0
- package/src/index.ts +63 -0
- package/src/mesh.ts +204 -0
- package/src/middleware.ts +101 -0
- package/src/proxyContext.ts +108 -0
- package/src/rejection.ts +62 -0
- package/src/sanitizeCatalog.ts +126 -0
- package/src/sessionRegistry.ts +142 -0
- package/src/telemetry.ts +46 -0
- package/src/testing.ts +174 -0
- package/src/version.ts +6 -0
package/src/testing.ts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Test helpers for mcpose middleware. No test framework imports — works in any env.
|
|
3
|
+
* @module mcpose/testing
|
|
4
|
+
*/
|
|
5
|
+
import type {
|
|
6
|
+
CallToolRequest,
|
|
7
|
+
CallToolResult,
|
|
8
|
+
ListToolsRequest,
|
|
9
|
+
ListToolsResult,
|
|
10
|
+
ListResourcesResult,
|
|
11
|
+
ListPromptsResult,
|
|
12
|
+
ReadResourceRequest,
|
|
13
|
+
ReadResourceResult,
|
|
14
|
+
Tool,
|
|
15
|
+
Resource,
|
|
16
|
+
Prompt,
|
|
17
|
+
CallToolRequestParams,
|
|
18
|
+
ReadResourceRequestParams,
|
|
19
|
+
GetPromptRequestParams,
|
|
20
|
+
GetPromptResult,
|
|
21
|
+
ServerCapabilities,
|
|
22
|
+
} from '@modelcontextprotocol/sdk/types.js';
|
|
23
|
+
import { hasToolContent } from './core.js';
|
|
24
|
+
import type {
|
|
25
|
+
ListToolsMiddleware,
|
|
26
|
+
ResourceMiddleware,
|
|
27
|
+
ToolMiddleware,
|
|
28
|
+
} from './core.js';
|
|
29
|
+
import type { BackendClient } from './backendClient.js';
|
|
30
|
+
import { createProxyContext, type ProxyContext } from './proxyContext.js';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Runs a `ToolMiddleware` and narrows result to `CallToolResult`.
|
|
34
|
+
* Throws if upstream returns legacy `{ toolResult }` shape.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* const result = await runToolMiddleware(mw, req, async () => mockResult);
|
|
38
|
+
* expect(result.content[0]).toMatchObject({ type: 'text' });
|
|
39
|
+
*/
|
|
40
|
+
export async function runToolMiddleware(
|
|
41
|
+
mw: ToolMiddleware,
|
|
42
|
+
req: CallToolRequest,
|
|
43
|
+
next: (req: CallToolRequest) => Promise<CallToolResult>,
|
|
44
|
+
context: ProxyContext = createProxyContext(),
|
|
45
|
+
): Promise<CallToolResult> {
|
|
46
|
+
const result = await mw(req, next, context);
|
|
47
|
+
if (!hasToolContent(result)) {
|
|
48
|
+
throw new Error(
|
|
49
|
+
'runToolMiddleware: middleware returned legacy toolResult shape — expected { content: [...] }',
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
return result;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Runs a `ListToolsMiddleware` with a defaulted `ProxyContext`, so tests
|
|
57
|
+
* do not pass `undefined as never` for the context argument.
|
|
58
|
+
*
|
|
59
|
+
* `ListToolsResult` has no legacy variant, so unlike `runToolMiddleware`
|
|
60
|
+
* there is nothing to narrow and this never throws on shape.
|
|
61
|
+
*/
|
|
62
|
+
export async function runListToolsMiddleware(
|
|
63
|
+
mw: ListToolsMiddleware,
|
|
64
|
+
req: ListToolsRequest,
|
|
65
|
+
next: (req: ListToolsRequest) => Promise<ListToolsResult>,
|
|
66
|
+
context: ProxyContext = createProxyContext(),
|
|
67
|
+
): Promise<ListToolsResult> {
|
|
68
|
+
return mw(req, next, context);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Runs a `ResourceMiddleware` with a defaulted `ProxyContext`.
|
|
73
|
+
*
|
|
74
|
+
* `ReadResourceResult` has no legacy variant, so unlike
|
|
75
|
+
* `runToolMiddleware` there is nothing to narrow and this never throws on
|
|
76
|
+
* shape.
|
|
77
|
+
*/
|
|
78
|
+
export async function runResourceMiddleware(
|
|
79
|
+
mw: ResourceMiddleware,
|
|
80
|
+
req: ReadResourceRequest,
|
|
81
|
+
next: (req: ReadResourceRequest) => Promise<ReadResourceResult>,
|
|
82
|
+
context: ProxyContext = createProxyContext(),
|
|
83
|
+
): Promise<ReadResourceResult> {
|
|
84
|
+
return mw(req, next, context);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Config for mock backend client. */
|
|
88
|
+
export interface MockBackendClientOptions {
|
|
89
|
+
/** Default: tools/resources/prompts enabled */
|
|
90
|
+
capabilities?: ServerCapabilities;
|
|
91
|
+
/** Default: `[]` */
|
|
92
|
+
tools?: Tool[];
|
|
93
|
+
/**
|
|
94
|
+
* Static result or factory `(params) => result` for `callTool`.
|
|
95
|
+
* Default: `{ content: [{ type: 'text', text: 'mock response' }] }`
|
|
96
|
+
*/
|
|
97
|
+
callToolResponse?:
|
|
98
|
+
CallToolResult | ((params: CallToolRequestParams) => CallToolResult);
|
|
99
|
+
/** Default: `[]` */
|
|
100
|
+
resources?: Resource[];
|
|
101
|
+
/** Default: `{ contents: [{ uri: '', text: 'mock resource' }] }` */
|
|
102
|
+
readResourceResponse?: ReadResourceResult;
|
|
103
|
+
/** Default: `[]` */
|
|
104
|
+
prompts?: Prompt[];
|
|
105
|
+
/** Default: `{ messages: [] }` */
|
|
106
|
+
getPromptResponse?: GetPromptResult;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Creates an in-memory `BackendClient` for unit tests. No process/network.
|
|
111
|
+
*
|
|
112
|
+
* @example
|
|
113
|
+
* const backend = createMockBackendClient({
|
|
114
|
+
* callToolResponse: { content: [{ type: 'text', text: 'John Doe: 123-45-6789' }] },
|
|
115
|
+
* });
|
|
116
|
+
* const pipeline = compose([auditMW, piiToolMW]);
|
|
117
|
+
* const result = await pipeline(req, (r) => backend.callTool(r.params, undefined));
|
|
118
|
+
*/
|
|
119
|
+
export function createMockBackendClient(
|
|
120
|
+
options: MockBackendClientOptions = {},
|
|
121
|
+
): BackendClient {
|
|
122
|
+
const capabilities = options.capabilities ?? {
|
|
123
|
+
tools: {},
|
|
124
|
+
resources: {},
|
|
125
|
+
prompts: {},
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// Fixtures are cloned per call so a mutating middleware cannot corrupt
|
|
129
|
+
// them across calls.
|
|
130
|
+
return {
|
|
131
|
+
getServerCapabilities: (): ServerCapabilities =>
|
|
132
|
+
structuredClone(capabilities),
|
|
133
|
+
|
|
134
|
+
listTools: async (): Promise<ListToolsResult> => ({
|
|
135
|
+
tools: structuredClone(options.tools ?? []),
|
|
136
|
+
}),
|
|
137
|
+
|
|
138
|
+
callTool: async (
|
|
139
|
+
params: CallToolRequestParams,
|
|
140
|
+
): Promise<CallToolResult> => {
|
|
141
|
+
const resp = options.callToolResponse;
|
|
142
|
+
if (typeof resp === 'function') return resp(params);
|
|
143
|
+
return structuredClone(
|
|
144
|
+
resp ?? { content: [{ type: 'text', text: 'mock response' }] },
|
|
145
|
+
);
|
|
146
|
+
},
|
|
147
|
+
|
|
148
|
+
listResources: async (): Promise<ListResourcesResult> => ({
|
|
149
|
+
resources: structuredClone(options.resources ?? []),
|
|
150
|
+
}),
|
|
151
|
+
|
|
152
|
+
readResource: async (
|
|
153
|
+
_params: ReadResourceRequestParams,
|
|
154
|
+
): Promise<ReadResourceResult> =>
|
|
155
|
+
structuredClone(
|
|
156
|
+
options.readResourceResponse ?? {
|
|
157
|
+
contents: [{ uri: '', text: 'mock resource' }],
|
|
158
|
+
},
|
|
159
|
+
),
|
|
160
|
+
|
|
161
|
+
listPrompts: async (): Promise<ListPromptsResult> => ({
|
|
162
|
+
prompts: structuredClone(options.prompts ?? []),
|
|
163
|
+
}),
|
|
164
|
+
|
|
165
|
+
getPrompt: async (
|
|
166
|
+
_params: GetPromptRequestParams,
|
|
167
|
+
): Promise<GetPromptResult> =>
|
|
168
|
+
structuredClone(options.getPromptResponse ?? { messages: [] }),
|
|
169
|
+
|
|
170
|
+
setNotificationHandler: () => undefined,
|
|
171
|
+
removeNotificationHandler: () => undefined,
|
|
172
|
+
close: async () => undefined,
|
|
173
|
+
} as unknown as BackendClient;
|
|
174
|
+
}
|
package/src/version.ts
ADDED