mcpose 1.0.0 → 1.1.1

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 CHANGED
@@ -2,6 +2,15 @@
2
2
 
3
3
  Composable middleware proxy for MCP servers.
4
4
 
5
+ ## New in 1.1.1
6
+
7
+ - mirrors only upstream-advertised MCP capabilities
8
+ - forwards abort signals and progress updates through the proxy
9
+ - advertises and fans out list-changed notifications correctly
10
+ - closes active HTTP proxy sessions on shutdown
11
+ - ships a stronger `mcpose/testing` mock backend
12
+
13
+ ---
5
14
  ---
6
15
 
7
16
  ## Background
@@ -12,7 +21,7 @@ mcpose was extracted from [`financial-elastic-mcp-server`](https://github.com/am
12
21
 
13
22
  ## Concept
14
23
 
15
- mcpose is a **transparent proxy**: it sits between an LLM client and an upstream MCP server, mirroring the upstream's tool, resource, and prompt lists while routing all calls through a configurable middleware pipeline. The client sees a normal MCP server; the upstream sees a normal MCP client. mcpose is the layer in between — controlling visibility and applying transformations without either side knowing.
24
+ mcpose is a **transparent proxy** between an LLM client and an upstream MCP server. It mirrors the upstream MCP surface and routes supported calls through middleware. The client sees a normal MCP server; the upstream sees a normal MCP client.
16
25
 
17
26
  ---
18
27
 
@@ -68,7 +77,7 @@ await startProxy(backend, {
68
77
  └──────────────┘ └────────────────────────────────┘ └────────────────────┘
69
78
  ```
70
79
 
71
- For each tool or resource, mcpose picks one of three routing paths:
80
+ For each supported tool or resource, mcpose picks one of three routing paths:
72
81
 
73
82
  | Path | Option | Behavior |
74
83
  |---|---|---|
@@ -76,7 +85,14 @@ For each tool or resource, mcpose picks one of three routing paths:
76
85
  | **Pass-through** | `passThroughTools` / `passThroughResources` | Forwarded raw to upstream — all middleware skipped |
77
86
  | **Middleware** | everything else | Routed through the full `toolMiddleware` / `resourceMiddleware` pipeline |
78
87
 
79
- Prompts are always forwarded as-is no filtering or middleware.
88
+ Prompts are forwarded as-is when the upstream supports prompts.
89
+
90
+ The proxy preserves core request semantics end to end:
91
+
92
+ - advertised capabilities are mirrored from the upstream server
93
+ - abort signals are forwarded to upstream tool, resource, and prompt calls
94
+ - upstream progress updates are relayed back to the downstream client
95
+ - list-changed notifications are advertised and fanned out when the upstream supports them
80
96
 
81
97
  ---
82
98
 
@@ -157,7 +173,7 @@ interface BackendConfig {
157
173
  async function createBackendClient(config: BackendConfig): Promise<BackendClient>;
158
174
  ```
159
175
 
160
- `BackendClient` is an alias for the SDK `Client`. Throws if neither `command` nor `url` is provided, or if the connection fails.
176
+ `BackendClient` is an alias for the SDK `Client`. It throws if neither `command` nor `url` is provided, or if the connection fails.
161
177
 
162
178
  ---
163
179
 
@@ -186,10 +202,56 @@ function createProxyServer(backend: BackendClient, options?: ProxyOptions): Serv
186
202
  | `hiddenTools` | Tool names removed from `list_tools` **and** rejected at call time with `MethodNotFound`. |
187
203
  | `hiddenResources` | Resource URIs removed from `list_resources` **and** rejected at call time with `InvalidRequest`. |
188
204
 
205
+ `createProxyServer` mirrors only the upstream capabilities exposed by `backend.getServerCapabilities()`. Unsupported prompt, resource, and tool endpoints are not advertised or registered.
206
+
189
207
  `startProxy` connects the proxy to a `StdioServerTransport`. `createProxyServer` returns the configured `Server` without connecting — useful for testing request handlers without a live transport.
190
208
 
191
209
  ---
192
210
 
211
+ ### `HttpProxyOptions` · `startHttpProxy()`
212
+
213
+ ```ts
214
+ interface HttpProxyOptions {
215
+ port?: number; // Default: 3000
216
+ host?: string; // Default: all interfaces
217
+ path?: string; // Default: '/mcp'
218
+ }
219
+
220
+ function startHttpProxy(
221
+ backend: BackendClient,
222
+ options?: ProxyOptions,
223
+ httpOptions?: HttpProxyOptions,
224
+ ): Promise<http.Server>;
225
+ ```
226
+
227
+ Starts the proxy over Streamable HTTP with stateful sessions. Each client connection is assigned an `mcp-session-id`. Upstream list-change notifications (`tools/list_changed`, `resources/list_changed`, `prompts/list_changed`) are fanned out to all active sessions when the upstream advertises them.
228
+
229
+ ```ts
230
+ import { createBackendClient, startHttpProxy } from 'mcpose';
231
+
232
+ const backend = await createBackendClient({ url: 'http://upstream-mcp-server/mcp' });
233
+ const server = await startHttpProxy(backend, { toolMiddleware: [loggingMW] }, { port: 8080 });
234
+ // HTTP server is now listening on port 8080 at /mcp
235
+ ```
236
+
237
+ On shutdown, active proxy sessions are closed before the underlying `http.Server` finishes closing.
238
+
239
+ **Limitations:**
240
+ - Sessions have no idle timeout.
241
+ - SSE reconnect replay is not supported (no `EventStore`).
242
+
243
+ ---
244
+
245
+ ### `mcpose/testing`
246
+
247
+ ```ts
248
+ import { createMockBackendClient, runToolMiddleware } from 'mcpose/testing';
249
+ ```
250
+
251
+ `createMockBackendClient()` returns an in-memory backend stub with capability lookup and notification hooks. It works with both `createProxyServer()` and `startHttpProxy()` tests.
252
+
253
+ ---
254
+
193
255
  ## Recipe: PII redaction
194
256
 
195
257
  The origin use case for mcpose: a financial-grade MCP server where every Elasticsearch tool response must be scrubbed of PII before it reaches the LLM or the audit log.
@@ -239,7 +301,7 @@ The array order guarantees: PII is redacted *before* the audit layer ever sees t
239
301
 
240
302
  ## Roadmap
241
303
 
242
- - [ ] **HTTP/SSE server transport** — currently the proxy emits only a stdio server; add a streamable HTTP/SSE server-side transport so mcpose can front HTTP-based clients without a subprocess wrapper
304
+ - [x] **HTTP/SSE server transport** — `startHttpProxy()` adds a Streamable HTTP server-side transport with stateful sessions
243
305
  - [ ] **ATXP protocol support** — enable MCP monetization by implementing the ATXP (Agent Transaction Protocol) standard, letting tool providers attach pricing and billing metadata to responses
244
306
 
245
307
  ---
@@ -1,34 +1,21 @@
1
1
  /**
2
- * Factory for connecting to the backend MCP server.
3
- *
4
- * Supports two transport modes:
5
- * - **stdio** (default): spawns the backend server as a child process.
6
- * - **HTTP/SSE**: connects to an already-running HTTP MCP server.
7
- *
8
- * Returns a connected `@modelcontextprotocol/sdk` Client, which exposes the
9
- * full MCP protocol surface (listTools, callTool, listResources, readResource,
10
- * listPrompts, getPrompt) with exact MCP type fidelity — important for a
11
- * transparent proxy that must not transform protocol shapes.
12
- *
13
- * @module
2
+ * Backend MCP client factory.
3
+ * Modes: stdio (spawns child process) or HTTP/SSE (connects to running server).
14
4
  */
15
5
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
16
- /** Connection options for the backend MCP server. */
6
+ /** Backend connection config. */
17
7
  export interface BackendConfig {
18
- /** Shell command to spawn the backend server (e.g., `"node"`). Required when not using `url`. */
8
+ /** Shell command to spawn backend (e.g. `"node"`). Required if no `url`. */
19
9
  command?: string;
20
- /** Arguments passed to the command (e.g., `["/path/to/server.mjs"]`). */
10
+ /** Args passed to command (e.g. `["/path/to/server.mjs"]`). */
21
11
  args?: string[];
22
- /** HTTP/SSE URL of an already-running backend server. Takes precedence over stdio when set. */
12
+ /** HTTP/SSE URL of running backend. Takes precedence over stdio. */
23
13
  url?: string;
24
14
  }
25
15
  export type BackendClient = Client;
26
16
  /**
27
- * Creates and connects an MCP client to the backend server.
28
- *
29
- * @param config - Backend connection details (stdio or HTTP).
30
- * @returns A connected MCP SDK Client ready for tool/resource/prompt calls.
31
- * @throws If neither `command` nor `url` is provided, or if the connection fails.
17
+ * Creates and connects an MCP client to the backend.
18
+ * @throws If neither `command` nor `url` provided, or connection fails.
32
19
  */
33
20
  export declare function createBackendClient(config: BackendConfig): Promise<BackendClient>;
34
21
  //# sourceMappingURL=backendClient.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"backendClient.d.ts","sourceRoot":"","sources":["../src/backendClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAInE,qDAAqD;AACrD,MAAM,WAAW,aAAa;IAC5B,iGAAiG;IACjG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,+FAA+F;IAC/F,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAEnC;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,aAAa,CAAC,CAqBxB"}
1
+ {"version":3,"file":"backendClient.d.ts","sourceRoot":"","sources":["../src/backendClient.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAInE,iCAAiC;AACjC,MAAM,WAAW,aAAa;IAC5B,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+DAA+D;IAC/D,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,oEAAoE;IACpE,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,aAAa,GAAG,MAAM,CAAC;AAEnC;;;GAGG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,aAAa,CAAC,CAqBxB"}
@@ -1,32 +1,19 @@
1
1
  /**
2
- * Factory for connecting to the backend MCP server.
3
- *
4
- * Supports two transport modes:
5
- * - **stdio** (default): spawns the backend server as a child process.
6
- * - **HTTP/SSE**: connects to an already-running HTTP MCP server.
7
- *
8
- * Returns a connected `@modelcontextprotocol/sdk` Client, which exposes the
9
- * full MCP protocol surface (listTools, callTool, listResources, readResource,
10
- * listPrompts, getPrompt) with exact MCP type fidelity — important for a
11
- * transparent proxy that must not transform protocol shapes.
12
- *
13
- * @module
2
+ * Backend MCP client factory.
3
+ * Modes: stdio (spawns child process) or HTTP/SSE (connects to running server).
14
4
  */
15
5
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
16
6
  import { StdioClientTransport } from '@modelcontextprotocol/sdk/client/stdio.js';
17
7
  import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
18
8
  /**
19
- * Creates and connects an MCP client to the backend server.
20
- *
21
- * @param config - Backend connection details (stdio or HTTP).
22
- * @returns A connected MCP SDK Client ready for tool/resource/prompt calls.
23
- * @throws If neither `command` nor `url` is provided, or if the connection fails.
9
+ * Creates and connects an MCP client to the backend.
10
+ * @throws If neither `command` nor `url` provided, or connection fails.
24
11
  */
25
12
  export async function createBackendClient(config) {
26
13
  if (!config.command && !config.url) {
27
14
  throw new Error('mcpose: either command or url must be provided in BackendConfig');
28
15
  }
29
- const client = new Client({ name: 'mcpose-backend', version: '1.0.0' }, { capabilities: {} });
16
+ const client = new Client({ name: 'mcpose-backend', version: '1.1.1' }, { capabilities: {} });
30
17
  const transport = config.url
31
18
  ? new StreamableHTTPClientTransport(new URL(config.url))
32
19
  : new StdioClientTransport({
@@ -1 +1 @@
1
- {"version":3,"file":"backendClient.js","sourceRoot":"","sources":["../src/backendClient.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAcnG;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAqB;IAErB,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,iEAAiE,CAClE,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,EAAE,EAC5C,EAAE,YAAY,EAAE,EAAE,EAAE,CACrB,CAAC;IAEF,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG;QAC1B,CAAC,CAAC,IAAI,6BAA6B,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACxD,CAAC,CAAC,IAAI,oBAAoB,CAAC;YACvB,OAAO,EAAE,MAAM,CAAC,OAAQ;YACxB,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE;SACxB,CAAC,CAAC;IAEP,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,MAAM,CAAC;AAChB,CAAC"}
1
+ {"version":3,"file":"backendClient.js","sourceRoot":"","sources":["../src/backendClient.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,6BAA6B,EAAE,MAAM,oDAAoD,CAAC;AAcnG;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,MAAqB;IAErB,IAAI,CAAC,MAAM,CAAC,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,iEAAiE,CAClE,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,EAAE,EAC5C,EAAE,YAAY,EAAE,EAAE,EAAE,CACrB,CAAC;IAEF,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG;QAC1B,CAAC,CAAC,IAAI,6BAA6B,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACxD,CAAC,CAAC,IAAI,oBAAoB,CAAC;YACvB,OAAO,EAAE,MAAM,CAAC,OAAQ;YACxB,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE;SACxB,CAAC,CAAC;IAEP,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,OAAO,MAAM,CAAC;AAChB,CAAC"}
package/dist/core.d.ts CHANGED
@@ -1,85 +1,80 @@
1
- /**
2
- * Generic MCP proxy core.
3
- *
4
- * Wires an MCP server (exposed to the LLM) to an upstream MCP client,
5
- * applying composed middleware pipelines to tool calls and resource reads.
6
- *
7
- * @module
8
- */
1
+ /** MCP proxy core: wires server→upstream through middleware pipelines. */
2
+ import * as http from 'node:http';
9
3
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
10
4
  import { type CallToolRequest, type CallToolResult, type CompatibilityCallToolResult, type ReadResourceRequest, type ReadResourceResult } from '@modelcontextprotocol/sdk/types.js';
11
5
  import { type Middleware } from './middleware.js';
12
6
  import type { BackendClient } from './backendClient.js';
13
7
  /**
14
- * Middleware for MCP tool calls.
15
- *
16
- * Uses `CompatibilityCallToolResult` because `Client.callTool()` returns a
17
- * union that includes the legacy `{ toolResult }` shape (protocol 2024-10-07).
18
- * Middleware implementations should narrow with `hasToolContent(result)` before
19
- * accessing `.content` or `.isError`.
8
+ * Middleware for tool calls.
9
+ * Uses `CompatibilityCallToolResult` to cover legacy `{ toolResult }` shape
10
+ * (protocol 2024-10-07). Narrow with `hasToolContent()` before accessing `.content`.
20
11
  */
21
12
  export type ToolMiddleware = Middleware<CallToolRequest, CompatibilityCallToolResult>;
22
- /** Middleware for MCP resource reads. */
13
+ /** Middleware for resource reads. */
23
14
  export type ResourceMiddleware = Middleware<ReadResourceRequest, ReadResourceResult>;
24
15
  /**
25
- * Type guard that narrows a {@link CompatibilityCallToolResult} to the modern
26
- * {@link CallToolResult} shape (i.e. the result has a `content` array).
27
- *
28
- * Use this in middleware implementations to safely access `.content` and
29
- * `.isError` without casts, since both union members carry an index signature
30
- * (`[x: string]: unknown`) that would otherwise make property access `unknown`.
16
+ * Narrows `CompatibilityCallToolResult` to `CallToolResult` (has `.content` array).
17
+ * Both union members carry `[x: string]: unknown`, so this avoids unsafe casts.
31
18
  */
32
19
  export declare function hasToolContent(r: CompatibilityCallToolResult): r is CallToolResult;
33
- /** Options for the proxy server. */
20
+ /** HTTP transport options for {@link startHttpProxy}. */
21
+ export interface HttpProxyOptions {
22
+ /** Default: 3000 */
23
+ port?: number;
24
+ /** Default: all interfaces */
25
+ host?: string;
26
+ /** Default: '/mcp' */
27
+ path?: string;
28
+ }
29
+ /** Proxy server options. */
34
30
  export interface ProxyOptions {
35
31
  /**
36
- * Ordered middleware stack for tool calls in response-processing order.
37
- * The first element processes the response first (innermost layer).
38
- * `pipe()` is called internally — no need to wrap manually.
39
- *
40
- * @example
41
- * toolMiddleware: [piiMW, auditMW] // pii redacts first, audit logs clean data
32
+ * Tool middleware in response-processing order (first = innermost).
33
+ * @example [piiMW, auditMW] // pii redacts first, audit logs clean data
42
34
  */
43
35
  toolMiddleware?: ReadonlyArray<ToolMiddleware>;
44
- /**
45
- * Ordered middleware stack for resource reads in response-processing order.
46
- * The first element processes the response first (innermost layer).
47
- */
36
+ /** Resource middleware in response-processing order (first = innermost). */
48
37
  resourceMiddleware?: ReadonlyArray<ResourceMiddleware>;
49
- /** Tool names that bypass all middleware — raw upstream response forwarded as-is. */
38
+ /** Tools that skip middleware — upstream response forwarded as-is. */
50
39
  passThroughTools?: ReadonlyArray<string>;
51
- /** Resource URIs that bypass all middleware — raw upstream response forwarded as-is. */
40
+ /** Resources that skip middleware — upstream response forwarded as-is. */
52
41
  passThroughResources?: ReadonlyArray<string>;
53
- /** Tool names hidden from list_tools AND rejected at runtime with MethodNotFound. */
42
+ /** Tools hidden from list_tools and rejected at runtime with MethodNotFound. */
54
43
  hiddenTools?: ReadonlyArray<string>;
55
- /** Resource URIs hidden from list_resources AND rejected at runtime with InvalidRequest. */
44
+ /** Resources hidden from list_resources and rejected at runtime with InvalidRequest. */
56
45
  hiddenResources?: ReadonlyArray<string>;
57
46
  }
58
47
  /**
59
- * Creates and wires a proxy MCP server without connecting it to a transport.
48
+ * Creates a proxy MCP server without connecting it to a transport.
60
49
  *
61
- * Mirrors the upstream's tool/resource/prompt list and registers request
62
- * handlers that route through the provided middleware pipelines. Prompts are
63
- * forwarded as-is (no middleware applied).
50
+ * Mirrors upstream tool/resource/prompt lists and routes requests through
51
+ * middleware pipelines. Prompts are forwarded as-is.
64
52
  *
65
- * Separating creation from connection makes the server fully testable: tests
66
- * can call `createProxyServer(mockUpstream, options)` and inspect or invoke
67
- * the registered handlers without spawning a stdio transport.
53
+ * Uses low-level `Server` (not `McpServer`) transparent proxying requires
54
+ * generic list interception; `McpServer.tool()` needs names upfront.
68
55
  *
69
- * @param upstream - Connected (or mock) upstream MCP client.
70
- * @param options - Optional middleware stacks for tools and resources.
71
- * @returns A configured {@link Server} that is ready to be connected.
56
+ * @param backend - Connected (or mock) upstream MCP client.
57
+ * @param options - Middleware stacks, hidden/passthrough sets.
58
+ * @returns Configured {@link Server} ready to connect.
72
59
  */
73
60
  export declare function createProxyServer(backend: BackendClient, options?: ProxyOptions): Server;
74
61
  /**
75
- * Starts the proxy MCP server on stdio.
62
+ * Starts the proxy on stdio.
63
+ * Calls {@link createProxyServer} then connects to `StdioServerTransport`.
64
+ * Use `createProxyServer` directly for testable access to the server.
65
+ */
66
+ export declare function startProxy(backend: BackendClient, options?: ProxyOptions): Promise<void>;
67
+ /**
68
+ * Starts the proxy over Streamable HTTP with stateful sessions.
69
+ *
70
+ * Sessions keyed by `mcp-session-id`. Upstream notifications fanned out to
71
+ * all active sessions via their GET SSE stream.
76
72
  *
77
- * Convenience wrapper that calls {@link createProxyServer} then connects the
78
- * result to a `StdioServerTransport`. Use `createProxyServer` directly when
79
- * you need a testable handle to the configured server.
73
+ * **Limitations:**
74
+ * - Sessions never expire.
75
+ * - No `EventStore` SSE reconnect replay unsupported.
80
76
  *
81
- * @param upstream - Connected upstream MCP client.
82
- * @param options - Optional middleware stacks for tools and resources.
77
+ * @returns Promise resolving to the listening `http.Server`.
83
78
  */
84
- export declare function startProxy(backend: BackendClient, options?: ProxyOptions): Promise<void>;
79
+ export declare function startHttpProxy(backend: BackendClient, options?: ProxyOptions, httpOptions?: HttpProxyOptions): Promise<http.Server>;
85
80
  //# sourceMappingURL=core.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAEnE,OAAO,EASL,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,2BAA2B,EAChC,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EACxB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;;;;;;;GAOG;AACH,MAAM,MAAM,cAAc,GAAG,UAAU,CACrC,eAAe,EACf,2BAA2B,CAC5B,CAAC;AAEF,yCAAyC;AACzC,MAAM,MAAM,kBAAkB,GAAG,UAAU,CACzC,mBAAmB,EACnB,kBAAkB,CACnB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAC5B,CAAC,EAAE,2BAA2B,GAC7B,CAAC,IAAI,cAAc,CAErB;AAED,oCAAoC;AACpC,MAAM,WAAW,YAAY;IAC3B;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAE/C;;;OAGG;IACH,kBAAkB,CAAC,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;IAEvD,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAEzC,wFAAwF;IACxF,oBAAoB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAE7C,qFAAqF;IACrF,WAAW,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAEpC,4FAA4F;IAC5F,eAAe,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACzC;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,YAAiB,GACzB,MAAM,CAoER;AAED;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CAGf"}
1
+ {"version":3,"file":"core.d.ts","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"AAAA,0EAA0E;AAC1E,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAElC,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAGnE,OAAO,EAYL,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,2BAA2B,EAChC,KAAK,mBAAmB,EACxB,KAAK,kBAAkB,EAExB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG,UAAU,CACrC,eAAe,EACf,2BAA2B,CAC5B,CAAC;AAEF,qCAAqC;AACrC,MAAM,MAAM,kBAAkB,GAAG,UAAU,CACzC,mBAAmB,EACnB,kBAAkB,CACnB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,CAAC,EAAE,2BAA2B,GAC7B,CAAC,IAAI,cAAc,CAErB;AAED,yDAAyD;AACzD,MAAM,WAAW,gBAAgB;IAC/B,oBAAoB;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,8BAA8B;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,4BAA4B;AAC5B,MAAM,WAAW,YAAY;IAC3B;;;OAGG;IACH,cAAc,CAAC,EAAE,aAAa,CAAC,cAAc,CAAC,CAAC;IAE/C,4EAA4E;IAC5E,kBAAkB,CAAC,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAC;IAEvD,sEAAsE;IACtE,gBAAgB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAEzC,0EAA0E;IAC1E,oBAAoB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAE7C,gFAAgF;IAChF,WAAW,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAEpC,wFAAwF;IACxF,eAAe,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;CACzC;AAqID;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,YAAiB,GACzB,MAAM,CA4ER;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,YAAiB,EAC1B,WAAW,GAAE,gBAAqB,GACjC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAyEtB"}
package/dist/core.js CHANGED
@@ -1,105 +1,244 @@
1
- /**
2
- * Generic MCP proxy core.
3
- *
4
- * Wires an MCP server (exposed to the LLM) to an upstream MCP client,
5
- * applying composed middleware pipelines to tool calls and resource reads.
6
- *
7
- * @module
8
- */
1
+ /** MCP proxy core: wires server→upstream through middleware pipelines. */
2
+ import * as http from 'node:http';
3
+ import { randomUUID } from 'node:crypto';
9
4
  import { Server } from '@modelcontextprotocol/sdk/server/index.js';
10
5
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
11
- import { CallToolRequestSchema, ErrorCode, GetPromptRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, McpError, ReadResourceRequestSchema, } from '@modelcontextprotocol/sdk/types.js';
6
+ import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js';
7
+ import { CallToolRequestSchema, ErrorCode, GetPromptRequestSchema, ListPromptsRequestSchema, ListResourcesRequestSchema, ListToolsRequestSchema, McpError, PromptListChangedNotificationSchema, ReadResourceRequestSchema, ResourceListChangedNotificationSchema, ToolListChangedNotificationSchema, } from '@modelcontextprotocol/sdk/types.js';
12
8
  import { pipe } from './middleware.js';
13
9
  /**
14
- * Type guard that narrows a {@link CompatibilityCallToolResult} to the modern
15
- * {@link CallToolResult} shape (i.e. the result has a `content` array).
16
- *
17
- * Use this in middleware implementations to safely access `.content` and
18
- * `.isError` without casts, since both union members carry an index signature
19
- * (`[x: string]: unknown`) that would otherwise make property access `unknown`.
10
+ * Narrows `CompatibilityCallToolResult` to `CallToolResult` (has `.content` array).
11
+ * Both union members carry `[x: string]: unknown`, so this avoids unsafe casts.
20
12
  */
21
13
  export function hasToolContent(r) {
22
14
  return Array.isArray(r.content);
23
15
  }
16
+ const listChangedBuses = new WeakMap();
17
+ function createProxyCapabilities(backend) {
18
+ const upstream = backend.getServerCapabilities();
19
+ return {
20
+ ...(upstream?.tools
21
+ ? { tools: upstream.tools.listChanged ? { listChanged: true } : {} }
22
+ : {}),
23
+ ...(upstream?.resources
24
+ ? { resources: upstream.resources.listChanged ? { listChanged: true } : {} }
25
+ : {}),
26
+ ...(upstream?.prompts
27
+ ? { prompts: upstream.prompts.listChanged ? { listChanged: true } : {} }
28
+ : {}),
29
+ };
30
+ }
31
+ function createRequestOptions(extra = {}) {
32
+ const progressToken = extra._meta?.progressToken;
33
+ const onprogress = progressToken && extra.sendNotification
34
+ ? ({ progress, total, message, }) => {
35
+ void extra.sendNotification?.({
36
+ method: 'notifications/progress',
37
+ params: {
38
+ progressToken,
39
+ progress,
40
+ ...(total === undefined ? {} : { total }),
41
+ ...(message === undefined ? {} : { message }),
42
+ },
43
+ });
44
+ }
45
+ : undefined;
46
+ if (!extra.signal && !onprogress)
47
+ return undefined;
48
+ return {
49
+ ...(extra.signal ? { signal: extra.signal } : {}),
50
+ ...(onprogress ? { onprogress } : {}),
51
+ };
52
+ }
53
+ function registerListChangedForwarders(backend, server, capabilities) {
54
+ if (!capabilities.tools?.listChanged &&
55
+ !capabilities.resources?.listChanged &&
56
+ !capabilities.prompts?.listChanged) {
57
+ return;
58
+ }
59
+ let bus = listChangedBuses.get(backend);
60
+ if (!bus) {
61
+ const servers = new Set();
62
+ const fanOut = async (notify) => {
63
+ await Promise.allSettled([...servers].map((proxyServer) => notify(proxyServer)));
64
+ };
65
+ if (capabilities.tools?.listChanged) {
66
+ backend.setNotificationHandler(ToolListChangedNotificationSchema, () => fanOut((proxyServer) => proxyServer.sendToolListChanged()));
67
+ }
68
+ if (capabilities.prompts?.listChanged) {
69
+ backend.setNotificationHandler(PromptListChangedNotificationSchema, () => fanOut((proxyServer) => proxyServer.sendPromptListChanged()));
70
+ }
71
+ if (capabilities.resources?.listChanged) {
72
+ backend.setNotificationHandler(ResourceListChangedNotificationSchema, () => fanOut((proxyServer) => proxyServer.sendResourceListChanged()));
73
+ }
74
+ bus = { servers };
75
+ listChangedBuses.set(backend, bus);
76
+ }
77
+ bus.servers.add(server);
78
+ const prevOnClose = server.onclose;
79
+ let active = true;
80
+ server.onclose = () => {
81
+ if (!active)
82
+ return;
83
+ active = false;
84
+ bus.servers.delete(server);
85
+ if (!bus.servers.size)
86
+ listChangedBuses.delete(backend);
87
+ prevOnClose?.();
88
+ };
89
+ }
24
90
  /**
25
- * Creates and wires a proxy MCP server without connecting it to a transport.
91
+ * Creates a proxy MCP server without connecting it to a transport.
26
92
  *
27
- * Mirrors the upstream's tool/resource/prompt list and registers request
28
- * handlers that route through the provided middleware pipelines. Prompts are
29
- * forwarded as-is (no middleware applied).
93
+ * Mirrors upstream tool/resource/prompt lists and routes requests through
94
+ * middleware pipelines. Prompts are forwarded as-is.
30
95
  *
31
- * Separating creation from connection makes the server fully testable: tests
32
- * can call `createProxyServer(mockUpstream, options)` and inspect or invoke
33
- * the registered handlers without spawning a stdio transport.
96
+ * Uses low-level `Server` (not `McpServer`) transparent proxying requires
97
+ * generic list interception; `McpServer.tool()` needs names upfront.
34
98
  *
35
- * @param upstream - Connected (or mock) upstream MCP client.
36
- * @param options - Optional middleware stacks for tools and resources.
37
- * @returns A configured {@link Server} that is ready to be connected.
99
+ * @param backend - Connected (or mock) upstream MCP client.
100
+ * @param options - Middleware stacks, hidden/passthrough sets.
101
+ * @returns Configured {@link Server} ready to connect.
38
102
  */
39
103
  export function createProxyServer(backend, options = {}) {
104
+ const capabilities = createProxyCapabilities(backend);
40
105
  const toolPipeline = pipe(options.toolMiddleware ?? []);
41
106
  const resourcePipeline = pipe(options.resourceMiddleware ?? []);
42
107
  const hiddenToolSet = new Set(options.hiddenTools ?? []);
43
108
  const passThroughToolSet = new Set(options.passThroughTools ?? []);
44
109
  const hiddenResourceSet = new Set(options.hiddenResources ?? []);
45
110
  const passThroughResourceSet = new Set(options.passThroughResources ?? []);
46
- // NOTE: Using the low-level Server intentionally a transparent proxy must
47
- // intercept list_tools / list_resources generically without knowing tool names
48
- // upfront. McpServer.tool() requires pre-registering each tool by name, which
49
- // breaks dynamic forwarding. The SDK explicitly carves out this pattern:
50
- // "Only use Server for advanced use cases."
51
- const server = new Server({ name: 'mcpose', version: '1.0.0' }, { capabilities: { tools: {}, resources: {}, prompts: {} } });
111
+ const server = new Server({ name: 'mcpose', version: '1.1.1' }, { capabilities });
112
+ registerListChangedForwarders(backend, server, capabilities);
52
113
  // ── Tool handlers ──────────────────────────────────────────────────────────
53
- server.setRequestHandler(ListToolsRequestSchema, async () => {
54
- const result = await backend.listTools();
55
- if (!hiddenToolSet.size)
56
- return result;
57
- return { ...result, tools: result.tools.filter((t) => !hiddenToolSet.has(t.name)) };
58
- });
59
- server.setRequestHandler(CallToolRequestSchema, (req) => {
60
- const name = req.params.name;
61
- if (hiddenToolSet.has(name)) {
62
- throw new McpError(ErrorCode.MethodNotFound, `Tool not found: ${name}`);
63
- }
64
- if (passThroughToolSet.has(name)) {
65
- return backend.callTool(req.params, undefined);
66
- }
67
- return toolPipeline(req, (r) => backend.callTool(r.params, undefined));
68
- });
114
+ if (capabilities.tools) {
115
+ server.setRequestHandler(ListToolsRequestSchema, async (req, extra) => {
116
+ const result = await backend.listTools(req.params, createRequestOptions(extra));
117
+ if (!hiddenToolSet.size)
118
+ return result;
119
+ return { ...result, tools: result.tools.filter((t) => !hiddenToolSet.has(t.name)) };
120
+ });
121
+ server.setRequestHandler(CallToolRequestSchema, (req, extra) => {
122
+ const name = req.params.name;
123
+ const requestOptions = createRequestOptions(extra);
124
+ if (hiddenToolSet.has(name)) {
125
+ throw new McpError(ErrorCode.MethodNotFound, `Tool not found: ${name}`);
126
+ }
127
+ if (passThroughToolSet.has(name)) {
128
+ return backend.callTool(req.params, undefined, requestOptions);
129
+ }
130
+ return toolPipeline(req, (r) => backend.callTool(r.params, undefined, requestOptions));
131
+ });
132
+ }
69
133
  // ── Resource handlers ──────────────────────────────────────────────────────
70
- server.setRequestHandler(ListResourcesRequestSchema, async () => {
71
- const result = await backend.listResources();
72
- if (!hiddenResourceSet.size)
73
- return result;
74
- return { ...result, resources: result.resources.filter((r) => !hiddenResourceSet.has(r.uri)) };
75
- });
76
- server.setRequestHandler(ReadResourceRequestSchema, (req) => {
77
- const uri = req.params.uri;
78
- if (hiddenResourceSet.has(uri)) {
79
- throw new McpError(ErrorCode.InvalidRequest, `Resource not found: ${uri}`);
80
- }
81
- if (passThroughResourceSet.has(uri)) {
82
- return backend.readResource(req.params);
83
- }
84
- return resourcePipeline(req, (r) => backend.readResource(r.params));
85
- });
134
+ if (capabilities.resources) {
135
+ server.setRequestHandler(ListResourcesRequestSchema, async (req, extra) => {
136
+ const result = await backend.listResources(req.params, createRequestOptions(extra));
137
+ if (!hiddenResourceSet.size)
138
+ return result;
139
+ return { ...result, resources: result.resources.filter((r) => !hiddenResourceSet.has(r.uri)) };
140
+ });
141
+ server.setRequestHandler(ReadResourceRequestSchema, (req, extra) => {
142
+ const uri = req.params.uri;
143
+ const requestOptions = createRequestOptions(extra);
144
+ if (hiddenResourceSet.has(uri)) {
145
+ throw new McpError(ErrorCode.InvalidRequest, `Resource not found: ${uri}`);
146
+ }
147
+ if (passThroughResourceSet.has(uri)) {
148
+ return backend.readResource(req.params, requestOptions);
149
+ }
150
+ return resourcePipeline(req, (r) => backend.readResource(r.params, requestOptions));
151
+ });
152
+ }
86
153
  // ── Prompt handlers (pass-through) ────────────────────────────────────────
87
- server.setRequestHandler(ListPromptsRequestSchema, () => backend.listPrompts());
88
- server.setRequestHandler(GetPromptRequestSchema, (req) => backend.getPrompt(req.params));
154
+ if (capabilities.prompts) {
155
+ server.setRequestHandler(ListPromptsRequestSchema, (req, extra) => backend.listPrompts(req.params, createRequestOptions(extra)));
156
+ server.setRequestHandler(GetPromptRequestSchema, (req, extra) => backend.getPrompt(req.params, createRequestOptions(extra)));
157
+ }
89
158
  return server;
90
159
  }
91
160
  /**
92
- * Starts the proxy MCP server on stdio.
93
- *
94
- * Convenience wrapper that calls {@link createProxyServer} then connects the
95
- * result to a `StdioServerTransport`. Use `createProxyServer` directly when
96
- * you need a testable handle to the configured server.
97
- *
98
- * @param upstream - Connected upstream MCP client.
99
- * @param options - Optional middleware stacks for tools and resources.
161
+ * Starts the proxy on stdio.
162
+ * Calls {@link createProxyServer} then connects to `StdioServerTransport`.
163
+ * Use `createProxyServer` directly for testable access to the server.
100
164
  */
101
165
  export async function startProxy(backend, options = {}) {
102
166
  const server = createProxyServer(backend, options);
103
167
  await server.connect(new StdioServerTransport());
104
168
  }
169
+ /**
170
+ * Starts the proxy over Streamable HTTP with stateful sessions.
171
+ *
172
+ * Sessions keyed by `mcp-session-id`. Upstream notifications fanned out to
173
+ * all active sessions via their GET SSE stream.
174
+ *
175
+ * **Limitations:**
176
+ * - Sessions never expire.
177
+ * - No `EventStore` → SSE reconnect replay unsupported.
178
+ *
179
+ * @returns Promise resolving to the listening `http.Server`.
180
+ */
181
+ export function startHttpProxy(backend, options = {}, httpOptions = {}) {
182
+ const mcpPath = httpOptions.path ?? '/mcp';
183
+ const port = httpOptions.port ?? 3000;
184
+ const host = httpOptions.host;
185
+ // session ID → { transport, proxyServer }
186
+ const sessions = new Map();
187
+ const server = http.createServer((req, res) => {
188
+ const handle = async () => {
189
+ const url = new URL(req.url ?? '/', 'http://localhost');
190
+ const method = req.method ?? '';
191
+ if (url.pathname !== mcpPath || !['GET', 'POST', 'DELETE'].includes(method)) {
192
+ res.writeHead(404).end();
193
+ return;
194
+ }
195
+ const sessionId = req.headers['mcp-session-id'];
196
+ if (typeof sessionId === 'string') {
197
+ // Route to existing session
198
+ const session = sessions.get(sessionId);
199
+ if (!session) {
200
+ res.writeHead(404).end();
201
+ return;
202
+ }
203
+ await session.transport.handleRequest(req, res);
204
+ }
205
+ else {
206
+ // New session (initialize request)
207
+ const proxyServer = createProxyServer(backend, options);
208
+ const transport = new StreamableHTTPServerTransport({
209
+ sessionIdGenerator: randomUUID,
210
+ onsessioninitialized: (id) => { sessions.set(id, { transport, proxyServer }); },
211
+ onsessionclosed: (id) => { sessions.delete(id); },
212
+ });
213
+ await proxyServer.connect(transport);
214
+ await transport.handleRequest(req, res);
215
+ }
216
+ };
217
+ handle().catch((err) => {
218
+ if (!res.headersSent)
219
+ res.writeHead(500).end();
220
+ void err;
221
+ });
222
+ });
223
+ const rawClose = server.close.bind(server);
224
+ let shuttingDown = false;
225
+ server.close = ((callback) => {
226
+ if (shuttingDown)
227
+ return rawClose(callback);
228
+ shuttingDown = true;
229
+ const activeSessions = [...sessions.values()];
230
+ sessions.clear();
231
+ void Promise.allSettled(activeSessions.map(({ proxyServer }) => proxyServer.close())).finally(() => {
232
+ rawClose(callback);
233
+ });
234
+ return server;
235
+ });
236
+ return new Promise((resolve, reject) => {
237
+ server.once('error', reject);
238
+ server.listen(port, ...(host ? [host] : []), () => {
239
+ server.off('error', reject);
240
+ resolve(server);
241
+ });
242
+ });
243
+ }
105
244
  //# sourceMappingURL=core.js.map
package/dist/core.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"core.js","sourceRoot":"","sources":["../src/core.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -2,6 +2,6 @@ export type { Middleware } from './middleware.js';
2
2
  export { compose } from './middleware.js';
3
3
  export type { BackendConfig, BackendClient } from './backendClient.js';
4
4
  export { createBackendClient } from './backendClient.js';
5
- export type { ProxyOptions, ToolMiddleware, ResourceMiddleware, } from './core.js';
6
- export { hasToolContent, createProxyServer, startProxy } from './core.js';
5
+ export type { ProxyOptions, HttpProxyOptions, ToolMiddleware, ResourceMiddleware, } from './core.js';
6
+ export { hasToolContent, createProxyServer, startProxy, startHttpProxy } from './core.js';
7
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,YAAY,EACV,YAAY,EACZ,cAAc,EACd,kBAAkB,GACnB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAE1C,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACvE,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,YAAY,EACV,YAAY,EACZ,gBAAgB,EAChB,cAAc,EACd,kBAAkB,GACnB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  export { compose } from './middleware.js';
2
2
  export { createBackendClient } from './backendClient.js';
3
- export { hasToolContent, createProxyServer, startProxy } from './core.js';
3
+ export { hasToolContent, createProxyServer, startProxy, startHttpProxy } from './core.js';
4
4
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAOzD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG1C,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAQzD,OAAO,EAAE,cAAc,EAAE,iBAAiB,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC"}
@@ -1,62 +1,30 @@
1
1
  /**
2
- * Generic Koa-style middleware composition for MCP request/response pipelines.
2
+ * Koa-style middleware composition for MCP request/response pipelines.
3
3
  *
4
- * A middleware is a pure function:
5
- * (req, next) => Promise<Res>
4
+ * `(req, next) => Promise<Res>` call `next(req)` to delegate downstream.
5
+ * Middlewares wrap like an onion: outer runs before+after inner.
6
6
  *
7
- * Calling `next(req)` passes control to the next middleware in the chain.
8
- * The innermost `next` is the actual upstream call. Middlewares wrap it like
9
- * an onion: outer layers execute code before AND after inner layers.
10
- *
11
- * Execution order with `pipe([piiMW, auditMW])` (or equivalently `compose([auditMW, piiMW])`):
7
+ * `pipe([piiMW, auditMW])` execution order:
12
8
  * 1. auditMW enter → capture startTime
13
9
  * 2. piiMW enter → call next
14
10
  * 3. upstream call → raw response
15
11
  * 4. piiMW exit → redact PII
16
- * 5. auditMW exit → log clean result (never logs raw PII)
17
- *
18
- * @module
19
- */
20
- /**
21
- * A single middleware unit. Receives a request and a `next` function to
22
- * call the remainder of the pipeline. May transform the request before
23
- * calling `next` or transform the response after.
24
- *
25
- * @typeParam Req - Request type (e.g., `CallToolRequest`)
26
- * @typeParam Res - Response type (e.g., `CallToolResult`)
12
+ * 5. auditMW exit → log clean result
27
13
  */
14
+ /** Single middleware unit. May transform req before `next` or res after. */
28
15
  export type Middleware<Req, Res> = (req: Req, next: (req: Req) => Promise<Res>) => Promise<Res>;
29
16
  /**
30
- * Composes an ordered array of middlewares into a single middleware using the
31
- * onion (Koa-style) model. The first middleware is the outermost layer.
32
- *
33
- * The returned function accepts the initial request and an innermost `next`
34
- * (typically the upstream I/O call).
35
- *
36
- * @param middlewares - Ordered list of middlewares, outermost first.
37
- * @returns A single composed middleware.
17
+ * Composes middlewares into one, outermost-first (Koa-style).
38
18
  *
39
19
  * @example
40
- * ```ts
41
20
  * const pipeline = compose([auditMW, piiMW]);
42
21
  * const result = await pipeline(req, (r) => upstream.callTool(r.params));
43
- * ```
44
22
  */
45
23
  export declare function compose<Req, Res>(middlewares: ReadonlyArray<Middleware<Req, Res>>): Middleware<Req, Res>;
46
24
  /**
47
- * Composes middlewares in response-processing order (internal helper used by mcpose core).
48
- *
49
- * The first element processes the response first it is the innermost layer.
50
- * `pipe([piiMW, auditMW])` expresses "pii redacts first, then audit logs the clean result",
51
- * which is equivalent to `compose([auditMW, piiMW])` (outermost-first).
52
- *
53
- * This is an internal utility. Consumers pass plain arrays to `ProxyOptions` which
54
- * calls `pipe()` internally — there is no need to call `pipe()` directly.
55
- *
56
- * Equivalent to `compose([...middlewares].reverse())`.
57
- *
58
- * @param middlewares - Middlewares in response-processing order (first processes response first).
59
- * @returns A single composed middleware.
25
+ * Like `compose` but in response-processing order (first = innermost).
26
+ * `pipe([piiMW, auditMW])` ≡ `compose([auditMW, piiMW])`.
27
+ * Used internally by mcpose coreconsumers pass arrays to `ProxyOptions`.
60
28
  */
61
29
  export declare function pipe<Req, Res>(middlewares: ReadonlyArray<Middleware<Req, Res>>): Middleware<Req, Res>;
62
30
  //# sourceMappingURL=middleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,UAAU,CAAC,GAAG,EAAE,GAAG,IAAI,CACjC,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,KAC7B,OAAO,CAAC,GAAG,CAAC,CAAC;AAElB;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,EAC9B,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAC/C,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAkBtB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,GAAG,EAC3B,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAC/C,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAEtB"}
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,4EAA4E;AAC5E,MAAM,MAAM,UAAU,CAAC,GAAG,EAAE,GAAG,IAAI,CACjC,GAAG,EAAE,GAAG,EACR,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,GAAG,CAAC,KAC7B,OAAO,CAAC,GAAG,CAAC,CAAC;AAElB;;;;;;GAMG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,GAAG,EAC9B,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAC/C,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAkBtB;AAED;;;;GAIG;AACH,wBAAgB,IAAI,CAAC,GAAG,EAAE,GAAG,EAC3B,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,GAC/C,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAEtB"}
@@ -1,37 +1,22 @@
1
1
  /**
2
- * Generic Koa-style middleware composition for MCP request/response pipelines.
2
+ * Koa-style middleware composition for MCP request/response pipelines.
3
3
  *
4
- * A middleware is a pure function:
5
- * (req, next) => Promise<Res>
4
+ * `(req, next) => Promise<Res>` call `next(req)` to delegate downstream.
5
+ * Middlewares wrap like an onion: outer runs before+after inner.
6
6
  *
7
- * Calling `next(req)` passes control to the next middleware in the chain.
8
- * The innermost `next` is the actual upstream call. Middlewares wrap it like
9
- * an onion: outer layers execute code before AND after inner layers.
10
- *
11
- * Execution order with `pipe([piiMW, auditMW])` (or equivalently `compose([auditMW, piiMW])`):
7
+ * `pipe([piiMW, auditMW])` execution order:
12
8
  * 1. auditMW enter → capture startTime
13
9
  * 2. piiMW enter → call next
14
10
  * 3. upstream call → raw response
15
11
  * 4. piiMW exit → redact PII
16
- * 5. auditMW exit → log clean result (never logs raw PII)
17
- *
18
- * @module
12
+ * 5. auditMW exit → log clean result
19
13
  */
20
14
  /**
21
- * Composes an ordered array of middlewares into a single middleware using the
22
- * onion (Koa-style) model. The first middleware is the outermost layer.
23
- *
24
- * The returned function accepts the initial request and an innermost `next`
25
- * (typically the upstream I/O call).
26
- *
27
- * @param middlewares - Ordered list of middlewares, outermost first.
28
- * @returns A single composed middleware.
15
+ * Composes middlewares into one, outermost-first (Koa-style).
29
16
  *
30
17
  * @example
31
- * ```ts
32
18
  * const pipeline = compose([auditMW, piiMW]);
33
19
  * const result = await pipeline(req, (r) => upstream.callTool(r.params));
34
- * ```
35
20
  */
36
21
  export function compose(middlewares) {
37
22
  return (req, next) => {
@@ -48,19 +33,9 @@ export function compose(middlewares) {
48
33
  };
49
34
  }
50
35
  /**
51
- * Composes middlewares in response-processing order (internal helper used by mcpose core).
52
- *
53
- * The first element processes the response first it is the innermost layer.
54
- * `pipe([piiMW, auditMW])` expresses "pii redacts first, then audit logs the clean result",
55
- * which is equivalent to `compose([auditMW, piiMW])` (outermost-first).
56
- *
57
- * This is an internal utility. Consumers pass plain arrays to `ProxyOptions` which
58
- * calls `pipe()` internally — there is no need to call `pipe()` directly.
59
- *
60
- * Equivalent to `compose([...middlewares].reverse())`.
61
- *
62
- * @param middlewares - Middlewares in response-processing order (first processes response first).
63
- * @returns A single composed middleware.
36
+ * Like `compose` but in response-processing order (first = innermost).
37
+ * `pipe([piiMW, auditMW])` ≡ `compose([auditMW, piiMW])`.
38
+ * Used internally by mcpose coreconsumers pass arrays to `ProxyOptions`.
64
39
  */
65
40
  export function pipe(middlewares) {
66
41
  return compose([...middlewares].reverse());
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAeH;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,OAAO,CACrB,WAAgD;IAEhD,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;QACnB,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;QAEf,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,UAAe,EAAgB,EAAE;YAC5D,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;gBACf,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAC;YACnE,CAAC;YACD,KAAK,GAAG,CAAC,CAAC;YAEV,MAAM,EAAE,GACN,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEjE,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACpE,CAAC,CAAC;QAEF,OAAO,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1B,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,IAAI,CAClB,WAAgD;IAEhD,OAAO,OAAO,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AAC7C,CAAC"}
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAQH;;;;;;GAMG;AACH,MAAM,UAAU,OAAO,CACrB,WAAgD;IAEhD,OAAO,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE;QACnB,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;QAEf,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,UAAe,EAAgB,EAAE;YAC5D,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;gBACf,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC,CAAC;YACnE,CAAC;YACD,KAAK,GAAG,CAAC,CAAC;YAEV,MAAM,EAAE,GACN,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAEjE,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QACpE,CAAC,CAAC;QAEF,OAAO,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC1B,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,IAAI,CAClB,WAAgD;IAEhD,OAAO,OAAO,CAAC,CAAC,GAAG,WAAW,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;AAC7C,CAAC"}
package/dist/testing.d.ts CHANGED
@@ -1,78 +1,48 @@
1
1
  /**
2
- * Framework-agnostic test helpers for code that uses mcpose middleware.
3
- *
4
- * **No test framework imports** — this module has zero dependencies on
5
- * vitest, jest, or mocha. Import it in any test environment.
6
- *
2
+ * Test helpers for mcpose middleware. No test framework imports — works in any env.
7
3
  * @module mcpose/testing
8
4
  */
9
- import type { CallToolRequest, CallToolResult, ReadResourceResult, Tool, Resource, Prompt, CallToolRequestParams, GetPromptResult } from '@modelcontextprotocol/sdk/types.js';
5
+ import type { CallToolRequest, CallToolResult, ReadResourceResult, Tool, Resource, Prompt, CallToolRequestParams, GetPromptResult, ServerCapabilities } from '@modelcontextprotocol/sdk/types.js';
10
6
  import type { ToolMiddleware } from './core.js';
11
7
  import type { BackendClient } from './backendClient.js';
12
8
  /**
13
- * Calls a {@link ToolMiddleware} and narrows the result to {@link CallToolResult}.
14
- *
15
- * Eliminates the boilerplate `isCallToolResult` guard that every test of a
16
- * `ToolMiddleware` must otherwise repeat. Throws a clear error if the upstream
17
- * returns the legacy `{ toolResult }` protocol shape.
18
- *
19
- * @param mw - The middleware under test.
20
- * @param req - The tool call request to pass in.
21
- * @param next - The innermost handler (simulates the upstream or next middleware).
9
+ * Runs a `ToolMiddleware` and narrows result to `CallToolResult`.
10
+ * Throws if upstream returns legacy `{ toolResult }` shape.
22
11
  *
23
12
  * @example
24
- * ```ts
25
13
  * const result = await runToolMiddleware(mw, req, async () => mockResult);
26
14
  * expect(result.content[0]).toMatchObject({ type: 'text' });
27
- * ```
28
15
  */
29
16
  export declare function runToolMiddleware(mw: ToolMiddleware, req: CallToolRequest, next: (req: CallToolRequest) => Promise<CallToolResult>): Promise<CallToolResult>;
30
- /**
31
- * Configuration for the mock backend client.
32
- */
17
+ /** Config for mock backend client. */
33
18
  export interface MockBackendClientOptions {
34
- /** Tools advertised by the mock upstream. Default: `[]`. */
19
+ /** Default: tools/resources/prompts enabled */
20
+ capabilities?: ServerCapabilities;
21
+ /** Default: `[]` */
35
22
  tools?: Tool[];
36
23
  /**
37
- * Response for `callTool`. Can be a static result or a factory function
38
- * that receives the call params and returns a per-call result.
39
- *
24
+ * Static result or factory `(params) => result` for `callTool`.
40
25
  * Default: `{ content: [{ type: 'text', text: 'mock response' }] }`
41
26
  */
42
27
  callToolResponse?: CallToolResult | ((params: CallToolRequestParams) => CallToolResult);
43
- /** Resources advertised by the mock upstream. Default: `[]`. */
28
+ /** Default: `[]` */
44
29
  resources?: Resource[];
45
- /**
46
- * Response for `readResource`.
47
- *
48
- * Default: `{ contents: [{ uri: '', text: 'mock resource' }] }`
49
- */
30
+ /** Default: `{ contents: [{ uri: '', text: 'mock resource' }] }` */
50
31
  readResourceResponse?: ReadResourceResult;
51
- /** Prompts advertised by the mock upstream. Default: `[]`. */
32
+ /** Default: `[]` */
52
33
  prompts?: Prompt[];
53
- /**
54
- * Response for `getPrompt`.
55
- *
56
- * Default: `{ messages: [] }`
57
- */
34
+ /** Default: `{ messages: [] }` */
58
35
  getPromptResponse?: GetPromptResult;
59
36
  }
60
37
  /**
61
- * Creates a plain object implementing {@link BackendClient} for use in tests.
62
- *
63
- * No real process is spawned and no network connection is made. All methods
64
- * return configurable in-memory responses, making it possible to test the full
65
- * `compose([auditMW, piiMW])` pipeline in a unit test.
38
+ * Creates an in-memory `BackendClient` for unit tests. No process/network.
66
39
  *
67
40
  * @example
68
- * ```ts
69
41
  * const backend = createMockBackendClient({
70
42
  * callToolResponse: { content: [{ type: 'text', text: 'John Doe: 123-45-6789' }] },
71
43
  * });
72
- * // Now compose real middlewares against it:
73
44
  * const pipeline = compose([auditMW, piiToolMW]);
74
45
  * const result = await pipeline(req, (r) => backend.callTool(r.params, undefined));
75
- * ```
76
46
  */
77
47
  export declare function createMockBackendClient(options?: MockBackendClientOptions): BackendClient;
78
48
  //# sourceMappingURL=testing.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EAId,kBAAkB,EAClB,IAAI,EACJ,QAAQ,EACR,MAAM,EACN,qBAAqB,EAGrB,eAAe,EAChB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAMxD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,cAAc,EAClB,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,cAAc,CAAC,GACtD,OAAO,CAAC,cAAc,CAAC,CAQzB;AAMD;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,4DAA4D;IAC5D,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf;;;;;OAKG;IACH,gBAAgB,CAAC,EACb,cAAc,GACd,CAAC,CAAC,MAAM,EAAE,qBAAqB,KAAK,cAAc,CAAC,CAAC;IACxD,gEAAgE;IAChE,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,kBAAkB,CAAC;IAC1C,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB;;;;OAIG;IACH,iBAAiB,CAAC,EAAE,eAAe,CAAC;CACrC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,wBAA6B,GACrC,aAAa,CAkCf"}
1
+ {"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EAId,kBAAkB,EAClB,IAAI,EACJ,QAAQ,EACR,MAAM,EACN,qBAAqB,EAGrB,eAAe,EACf,kBAAkB,EACnB,MAAM,oCAAoC,CAAC;AAE5C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,EAAE,EAAE,cAAc,EAClB,GAAG,EAAE,eAAe,EACpB,IAAI,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,cAAc,CAAC,GACtD,OAAO,CAAC,cAAc,CAAC,CAQzB;AAED,sCAAsC;AACtC,MAAM,WAAW,wBAAwB;IACvC,+CAA+C;IAC/C,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,oBAAoB;IACpB,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC;IACf;;;OAGG;IACH,gBAAgB,CAAC,EACb,cAAc,GACd,CAAC,CAAC,MAAM,EAAE,qBAAqB,KAAK,cAAc,CAAC,CAAC;IACxD,oBAAoB;IACpB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,oEAAoE;IACpE,oBAAoB,CAAC,EAAE,kBAAkB,CAAC;IAC1C,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,kCAAkC;IAClC,iBAAiB,CAAC,EAAE,eAAe,CAAC;CACrC;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,OAAO,GAAE,wBAA6B,GACrC,aAAa,CA8Cf"}
package/dist/testing.js CHANGED
@@ -1,23 +1,11 @@
1
1
  import { hasToolContent } from './core.js';
2
- // ---------------------------------------------------------------------------
3
- // Pain Point 1: runToolMiddleware
4
- // ---------------------------------------------------------------------------
5
2
  /**
6
- * Calls a {@link ToolMiddleware} and narrows the result to {@link CallToolResult}.
7
- *
8
- * Eliminates the boilerplate `isCallToolResult` guard that every test of a
9
- * `ToolMiddleware` must otherwise repeat. Throws a clear error if the upstream
10
- * returns the legacy `{ toolResult }` protocol shape.
11
- *
12
- * @param mw - The middleware under test.
13
- * @param req - The tool call request to pass in.
14
- * @param next - The innermost handler (simulates the upstream or next middleware).
3
+ * Runs a `ToolMiddleware` and narrows result to `CallToolResult`.
4
+ * Throws if upstream returns legacy `{ toolResult }` shape.
15
5
  *
16
6
  * @example
17
- * ```ts
18
7
  * const result = await runToolMiddleware(mw, req, async () => mockResult);
19
8
  * expect(result.content[0]).toMatchObject({ type: 'text' });
20
- * ```
21
9
  */
22
10
  export async function runToolMiddleware(mw, req, next) {
23
11
  const result = await mw(req, next);
@@ -27,24 +15,23 @@ export async function runToolMiddleware(mw, req, next) {
27
15
  return result;
28
16
  }
29
17
  /**
30
- * Creates a plain object implementing {@link BackendClient} for use in tests.
31
- *
32
- * No real process is spawned and no network connection is made. All methods
33
- * return configurable in-memory responses, making it possible to test the full
34
- * `compose([auditMW, piiMW])` pipeline in a unit test.
18
+ * Creates an in-memory `BackendClient` for unit tests. No process/network.
35
19
  *
36
20
  * @example
37
- * ```ts
38
21
  * const backend = createMockBackendClient({
39
22
  * callToolResponse: { content: [{ type: 'text', text: 'John Doe: 123-45-6789' }] },
40
23
  * });
41
- * // Now compose real middlewares against it:
42
24
  * const pipeline = compose([auditMW, piiToolMW]);
43
25
  * const result = await pipeline(req, (r) => backend.callTool(r.params, undefined));
44
- * ```
45
26
  */
46
27
  export function createMockBackendClient(options = {}) {
28
+ const capabilities = options.capabilities ?? {
29
+ tools: {},
30
+ resources: {},
31
+ prompts: {},
32
+ };
47
33
  return {
34
+ getServerCapabilities: () => capabilities,
48
35
  listTools: async () => ({
49
36
  tools: options.tools ?? [],
50
37
  }),
@@ -64,6 +51,9 @@ export function createMockBackendClient(options = {}) {
64
51
  prompts: options.prompts ?? [],
65
52
  }),
66
53
  getPrompt: async (_params) => options.getPromptResponse ?? { messages: [] },
54
+ setNotificationHandler: () => undefined,
55
+ removeNotificationHandler: () => undefined,
56
+ close: async () => undefined,
67
57
  };
68
58
  }
69
59
  //# sourceMappingURL=testing.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAuBA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAI3C,8EAA8E;AAC9E,kCAAkC;AAClC,8EAA8E;AAE9E;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,EAAkB,EAClB,GAAoB,EACpB,IAAuD;IAEvD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACb,8FAA8F,CAC/F,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAuCD;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,uBAAuB,CACrC,UAAoC,EAAE;IAEtC,OAAO;QACL,SAAS,EAAE,KAAK,IAA8B,EAAE,CAAC,CAAC;YAChD,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;SAC3B,CAAC;QAEF,QAAQ,EAAE,KAAK,EACb,MAA6B,EACJ,EAAE;YAC3B,MAAM,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC;YACtC,IAAI,OAAO,IAAI,KAAK,UAAU;gBAAE,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;YACpD,OAAO,IAAI,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC;QACxE,CAAC;QAED,aAAa,EAAE,KAAK,IAAkC,EAAE,CAAC,CAAC;YACxD,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,EAAE;SACnC,CAAC;QAEF,YAAY,EAAE,KAAK,EACjB,OAAkC,EACL,EAAE,CAC/B,OAAO,CAAC,oBAAoB,IAAI;YAC9B,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;SAC/C;QAEH,WAAW,EAAE,KAAK,IAAgC,EAAE,CAAC,CAAC;YACpD,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;SAC/B,CAAC;QAEF,SAAS,EAAE,KAAK,EACd,OAA+B,EACL,EAAE,CAC5B,OAAO,CAAC,iBAAiB,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;KACpB,CAAC;AAChC,CAAC"}
1
+ {"version":3,"file":"testing.js","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAI3C;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,EAAkB,EAClB,GAAoB,EACpB,IAAuD;IAEvD,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACnC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5B,MAAM,IAAI,KAAK,CACb,8FAA8F,CAC/F,CAAC;IACJ,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAyBD;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CACrC,UAAoC,EAAE;IAEtC,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,IAAI;QAC3C,KAAK,EAAE,EAAE;QACT,SAAS,EAAE,EAAE;QACb,OAAO,EAAE,EAAE;KACZ,CAAC;IAEF,OAAO;QACL,qBAAqB,EAAE,GAAuB,EAAE,CAAC,YAAY;QAE7D,SAAS,EAAE,KAAK,IAA8B,EAAE,CAAC,CAAC;YAChD,KAAK,EAAE,OAAO,CAAC,KAAK,IAAI,EAAE;SAC3B,CAAC;QAEF,QAAQ,EAAE,KAAK,EACb,MAA6B,EACJ,EAAE;YAC3B,MAAM,IAAI,GAAG,OAAO,CAAC,gBAAgB,CAAC;YACtC,IAAI,OAAO,IAAI,KAAK,UAAU;gBAAE,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC;YACpD,OAAO,IAAI,IAAI,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC,EAAE,CAAC;QACxE,CAAC;QAED,aAAa,EAAE,KAAK,IAAkC,EAAE,CAAC,CAAC;YACxD,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,EAAE;SACnC,CAAC;QAEF,YAAY,EAAE,KAAK,EACjB,OAAkC,EACL,EAAE,CAC/B,OAAO,CAAC,oBAAoB,IAAI;YAC9B,QAAQ,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,CAAC;SAC/C;QAEH,WAAW,EAAE,KAAK,IAAgC,EAAE,CAAC,CAAC;YACpD,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;SAC/B,CAAC;QAEF,SAAS,EAAE,KAAK,EACd,OAA+B,EACL,EAAE,CAC5B,OAAO,CAAC,iBAAiB,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;QAE/C,sBAAsB,EAAE,GAAG,EAAE,CAAC,SAAS;QACvC,yBAAyB,EAAE,GAAG,EAAE,CAAC,SAAS;QAC1C,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,SAAS;KACD,CAAC;AAChC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcpose",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "Composable FP (Koa-style) middleware proxy builder for any MCP server",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",