mcpose 1.0.0 → 1.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 CHANGED
@@ -190,6 +190,39 @@ function createProxyServer(backend: BackendClient, options?: ProxyOptions): Serv
190
190
 
191
191
  ---
192
192
 
193
+ ### `HttpProxyOptions` · `startHttpProxy()`
194
+
195
+ ```ts
196
+ interface HttpProxyOptions {
197
+ port?: number; // Default: 3000
198
+ host?: string; // Default: all interfaces
199
+ path?: string; // Default: '/mcp'
200
+ }
201
+
202
+ function startHttpProxy(
203
+ backend: BackendClient,
204
+ options?: ProxyOptions,
205
+ httpOptions?: HttpProxyOptions,
206
+ ): Promise<http.Server>;
207
+ ```
208
+
209
+ 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.
210
+
211
+ ```ts
212
+ import { createBackendClient, startHttpProxy } from 'mcpose';
213
+
214
+ const backend = await createBackendClient({ url: 'http://upstream-mcp-server/mcp' });
215
+ const server = await startHttpProxy(backend, { toolMiddleware: [loggingMW] }, { port: 8080 });
216
+ // HTTP server is now listening on port 8080 at /mcp
217
+ ```
218
+
219
+ **Limitations:**
220
+ - Two `startHttpProxy` calls sharing the same `backend` will overwrite each other's notification handlers (last call wins).
221
+ - Sessions are only cleaned up on `DELETE` or server close — there is no idle timeout.
222
+ - SSE reconnect replay is not supported (no `EventStore`).
223
+
224
+ ---
225
+
193
226
  ## Recipe: PII redaction
194
227
 
195
228
  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 +272,7 @@ The array order guarantees: PII is redacted *before* the audit layer ever sees t
239
272
 
240
273
  ## Roadmap
241
274
 
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
275
+ - [x] **HTTP/SSE server transport** — `startHttpProxy()` adds a Streamable HTTP server-side transport with stateful sessions
243
276
  - [ ] **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
277
 
245
278
  ---
@@ -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,26 +1,13 @@
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) {
@@ -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,81 @@
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
+ * - Two calls with same `backend` overwrite notification handlers (last wins).
75
+ * - Sessions never expire only cleaned up on DELETE or server close.
76
+ * - No `EventStore` → SSE reconnect replay unsupported.
80
77
  *
81
- * @param upstream - Connected upstream MCP client.
82
- * @param options - Optional middleware stacks for tools and resources.
78
+ * @returns Promise resolving to the listening `http.Server`.
83
79
  */
84
- export declare function startProxy(backend: BackendClient, options?: ProxyOptions): Promise<void>;
80
+ export declare function startHttpProxy(backend: BackendClient, options?: ProxyOptions, httpOptions?: HttpProxyOptions): Promise<http.Server>;
85
81
  //# 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,EACxB,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;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,YAAiB,GACzB,MAAM,CA+DR;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,YAAiB,GACzB,OAAO,CAAC,IAAI,CAAC,CAGf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,aAAa,EACtB,OAAO,GAAE,YAAiB,EAC1B,WAAW,GAAE,gBAAqB,GACjC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAiEtB"}
package/dist/core.js CHANGED
@@ -1,40 +1,30 @@
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
  }
24
16
  /**
25
- * Creates and wires a proxy MCP server without connecting it to a transport.
17
+ * Creates a proxy MCP server without connecting it to a transport.
26
18
  *
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).
19
+ * Mirrors upstream tool/resource/prompt lists and routes requests through
20
+ * middleware pipelines. Prompts are forwarded as-is.
30
21
  *
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.
22
+ * Uses low-level `Server` (not `McpServer`) transparent proxying requires
23
+ * generic list interception; `McpServer.tool()` needs names upfront.
34
24
  *
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.
25
+ * @param backend - Connected (or mock) upstream MCP client.
26
+ * @param options - Middleware stacks, hidden/passthrough sets.
27
+ * @returns Configured {@link Server} ready to connect.
38
28
  */
39
29
  export function createProxyServer(backend, options = {}) {
40
30
  const toolPipeline = pipe(options.toolMiddleware ?? []);
@@ -43,11 +33,6 @@ export function createProxyServer(backend, options = {}) {
43
33
  const passThroughToolSet = new Set(options.passThroughTools ?? []);
44
34
  const hiddenResourceSet = new Set(options.hiddenResources ?? []);
45
35
  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
36
  const server = new Server({ name: 'mcpose', version: '1.0.0' }, { capabilities: { tools: {}, resources: {}, prompts: {} } });
52
37
  // ── Tool handlers ──────────────────────────────────────────────────────────
53
38
  server.setRequestHandler(ListToolsRequestSchema, async () => {
@@ -89,17 +74,85 @@ export function createProxyServer(backend, options = {}) {
89
74
  return server;
90
75
  }
91
76
  /**
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.
77
+ * Starts the proxy on stdio.
78
+ * Calls {@link createProxyServer} then connects to `StdioServerTransport`.
79
+ * Use `createProxyServer` directly for testable access to the server.
100
80
  */
101
81
  export async function startProxy(backend, options = {}) {
102
82
  const server = createProxyServer(backend, options);
103
83
  await server.connect(new StdioServerTransport());
104
84
  }
85
+ /**
86
+ * Starts the proxy over Streamable HTTP with stateful sessions.
87
+ *
88
+ * Sessions keyed by `mcp-session-id`. Upstream notifications fanned out to
89
+ * all active sessions via their GET SSE stream.
90
+ *
91
+ * **Limitations:**
92
+ * - Two calls with same `backend` overwrite notification handlers (last wins).
93
+ * - Sessions never expire — only cleaned up on DELETE or server close.
94
+ * - No `EventStore` → SSE reconnect replay unsupported.
95
+ *
96
+ * @returns Promise resolving to the listening `http.Server`.
97
+ */
98
+ export function startHttpProxy(backend, options = {}, httpOptions = {}) {
99
+ const mcpPath = httpOptions.path ?? '/mcp';
100
+ const port = httpOptions.port ?? 3000;
101
+ const host = httpOptions.host;
102
+ // session ID → { transport, proxyServer }
103
+ const sessions = new Map();
104
+ // Fan upstream notifications to all active sessions' SSE streams.
105
+ backend.setNotificationHandler(ToolListChangedNotificationSchema, async () => {
106
+ await Promise.all([...sessions.values()].map(({ proxyServer }) => proxyServer.sendToolListChanged()));
107
+ });
108
+ backend.setNotificationHandler(PromptListChangedNotificationSchema, async () => {
109
+ await Promise.all([...sessions.values()].map(({ proxyServer }) => proxyServer.sendPromptListChanged()));
110
+ });
111
+ backend.setNotificationHandler(ResourceListChangedNotificationSchema, async () => {
112
+ await Promise.all([...sessions.values()].map(({ proxyServer }) => proxyServer.sendResourceListChanged()));
113
+ });
114
+ const server = http.createServer((req, res) => {
115
+ const handle = async () => {
116
+ const url = new URL(req.url ?? '/', 'http://localhost');
117
+ const method = req.method ?? '';
118
+ if (url.pathname !== mcpPath || !['GET', 'POST', 'DELETE'].includes(method)) {
119
+ res.writeHead(404).end();
120
+ return;
121
+ }
122
+ const sessionId = req.headers['mcp-session-id'];
123
+ if (typeof sessionId === 'string') {
124
+ // Route to existing session
125
+ const session = sessions.get(sessionId);
126
+ if (!session) {
127
+ res.writeHead(404).end();
128
+ return;
129
+ }
130
+ await session.transport.handleRequest(req, res);
131
+ }
132
+ else {
133
+ // New session (initialize request)
134
+ const proxyServer = createProxyServer(backend, options);
135
+ const transport = new StreamableHTTPServerTransport({
136
+ sessionIdGenerator: randomUUID,
137
+ onsessioninitialized: (id) => { sessions.set(id, { transport, proxyServer }); },
138
+ onsessionclosed: (id) => { sessions.delete(id); },
139
+ });
140
+ await proxyServer.connect(transport);
141
+ await transport.handleRequest(req, res);
142
+ }
143
+ };
144
+ handle().catch((err) => {
145
+ if (!res.headersSent)
146
+ res.writeHead(500).end();
147
+ void err;
148
+ });
149
+ });
150
+ return new Promise((resolve, reject) => {
151
+ server.once('error', reject);
152
+ server.listen(port, ...(host ? [host] : []), () => {
153
+ server.off('error', reject);
154
+ resolve(server);
155
+ });
156
+ });
157
+ }
105
158
  //# 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":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,SAAS,EACT,sBAAsB,EACtB,wBAAwB,EACxB,0BAA0B,EAC1B,sBAAsB,EACtB,QAAQ,EACR,yBAAyB,GAM1B,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAmB,MAAM,iBAAiB,CAAC;AAsBxD;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAC5B,CAA8B;IAE9B,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC;AAiCD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,iBAAiB,CAC/B,OAAsB,EACtB,UAAwB,EAAE;IAE1B,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC;IACxD,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC;IAEhE,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IACzD,MAAM,kBAAkB,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,gBAAgB,IAAI,EAAE,CAAC,CAAC;IACnE,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC;IACjE,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,oBAAoB,IAAI,EAAE,CAAC,CAAC;IAE3E,4EAA4E;IAC5E,+EAA+E;IAC/E,8EAA8E;IAC9E,yEAAyE;IACzE,4CAA4C;IAC5C,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,EACpC,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,EAAE,CAC5D,CAAC;IAEF,8EAA8E;IAE9E,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,SAAS,EAAE,CAAC;QACzC,IAAI,CAAC,aAAa,CAAC,IAAI;YAAE,OAAO,MAAM,CAAC;QACvC,OAAO,EAAE,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;IACtF,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,CAAC,GAAG,EAAE,EAAE;QACtD,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;QAC7B,IAAI,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,mBAAmB,IAAI,EAAE,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACjC,OAAO,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;QACjD,CAAC;QACD,OAAO,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IACzE,CAAC,CAAC,CAAC;IAEH,8EAA8E;IAE9E,MAAM,CAAC,iBAAiB,CAAC,0BAA0B,EAAE,KAAK,IAAI,EAAE;QAC9D,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,aAAa,EAAE,CAAC;QAC7C,IAAI,CAAC,iBAAiB,CAAC,IAAI;YAAE,OAAO,MAAM,CAAC;QAC3C,OAAO,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;IACjG,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,iBAAiB,CAAC,yBAAyB,EAAE,CAAC,GAAG,EAAE,EAAE;QAC1D,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC;QAC3B,IAAI,iBAAiB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,uBAAuB,GAAG,EAAE,CAAC,CAAC;QAC7E,CAAC;QACD,IAAI,sBAAsB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACpC,OAAO,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,gBAAgB,CAAC,GAAG,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IACtE,CAAC,CAAC,CAAC;IAEH,6EAA6E;IAE7E,MAAM,CAAC,iBAAiB,CAAC,wBAAwB,EAAE,GAAG,EAAE,CACtD,OAAO,CAAC,WAAW,EAAE,CACtB,CAAC;IAEF,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,CAAC,GAAG,EAAE,EAAE,CACvD,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,CAC9B,CAAC;IAEF,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,OAAsB,EACtB,UAAwB,EAAE;IAE1B,MAAM,MAAM,GAAG,iBAAiB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACnD,MAAM,MAAM,CAAC,OAAO,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;AACnD,CAAC"}
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,46 @@
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
5
  import type { CallToolRequest, CallToolResult, ReadResourceResult, Tool, Resource, Prompt, CallToolRequestParams, GetPromptResult } 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: `[]` */
35
20
  tools?: Tool[];
36
21
  /**
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
- *
22
+ * Static result or factory `(params) => result` for `callTool`.
40
23
  * Default: `{ content: [{ type: 'text', text: 'mock response' }] }`
41
24
  */
42
25
  callToolResponse?: CallToolResult | ((params: CallToolRequestParams) => CallToolResult);
43
- /** Resources advertised by the mock upstream. Default: `[]`. */
26
+ /** Default: `[]` */
44
27
  resources?: Resource[];
45
- /**
46
- * Response for `readResource`.
47
- *
48
- * Default: `{ contents: [{ uri: '', text: 'mock resource' }] }`
49
- */
28
+ /** Default: `{ contents: [{ uri: '', text: 'mock resource' }] }` */
50
29
  readResourceResponse?: ReadResourceResult;
51
- /** Prompts advertised by the mock upstream. Default: `[]`. */
30
+ /** Default: `[]` */
52
31
  prompts?: Prompt[];
53
- /**
54
- * Response for `getPrompt`.
55
- *
56
- * Default: `{ messages: [] }`
57
- */
32
+ /** Default: `{ messages: [] }` */
58
33
  getPromptResponse?: GetPromptResult;
59
34
  }
60
35
  /**
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.
36
+ * Creates an in-memory `BackendClient` for unit tests. No process/network.
66
37
  *
67
38
  * @example
68
- * ```ts
69
39
  * const backend = createMockBackendClient({
70
40
  * callToolResponse: { content: [{ type: 'text', text: 'John Doe: 123-45-6789' }] },
71
41
  * });
72
- * // Now compose real middlewares against it:
73
42
  * const pipeline = compose([auditMW, piiToolMW]);
74
43
  * const result = await pipeline(req, (r) => backend.callTool(r.params, undefined));
75
- * ```
76
44
  */
77
45
  export declare function createMockBackendClient(options?: MockBackendClientOptions): BackendClient;
78
46
  //# 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,EAChB,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,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,CAkCf"}
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,21 +15,14 @@ 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 = {}) {
47
28
  return {
@@ -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":"AAmBA,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;AAuBD;;;;;;;;;GASG;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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mcpose",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Composable FP (Koa-style) middleware proxy builder for any MCP server",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",