poe-code 3.0.442-beta.1 → 3.0.443-beta.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poe-code",
3
- "version": "3.0.442-beta.1",
3
+ "version": "3.0.443-beta.1",
4
4
  "description": "CLI tool to configure Poe API for developer workflows.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,14 +1,17 @@
1
1
  import http from "node:http";
2
2
  import { createJwksTokenVerifier } from "mcp-oauth";
3
- import { createTestMcpServer, nodeFetch, TokenVerificationError } from "tiny-http-mcp-server";
4
- import { createOAuthTestServer, } from "tiny-oauth-test-server";
3
+ import { TokenVerificationError } from "tiny-http-mcp-server";
4
+ import { createTestMcpServer, nodeFetch } from "tiny-http-mcp-server/test-support";
5
+ import { createOAuthTestServer } from "tiny-oauth-test-server";
5
6
  import { hasOwnErrorCode } from "./error-codes.js";
6
7
  const PROTECTED_RESOURCE_METADATA_PATH = "/.well-known/oauth-protected-resource";
7
8
  function getProtectedResourceMetadataUrl(mcpUrl) {
8
9
  const url = new URL(mcpUrl);
9
- const protectedResourcePath = url.pathname === "/" ? "" : url.pathname.length > 1 && url.pathname.endsWith("/")
10
- ? url.pathname.slice(0, -1)
11
- : url.pathname;
10
+ const protectedResourcePath = url.pathname === "/"
11
+ ? ""
12
+ : url.pathname.length > 1 && url.pathname.endsWith("/")
13
+ ? url.pathname.slice(0, -1)
14
+ : url.pathname;
12
15
  return new URL(`${PROTECTED_RESOURCE_METADATA_PATH}${protectedResourcePath}`, url).toString();
13
16
  }
14
17
  function normalizePath(path) {
@@ -165,12 +168,10 @@ export function createMcpOAuthTestServer(options = {}) {
165
168
  }
166
169
  listenPending = false;
167
170
  throw lastError;
168
- },
171
+ }
169
172
  };
170
173
  async function listenOnce(hostname, requestedPort) {
171
- const oauthHostname = configuredIssuer === undefined
172
- ? hostname
173
- : normalizeHostForListen(configuredIssuer.hostname);
174
+ const oauthHostname = configuredIssuer === undefined ? hostname : normalizeHostForListen(configuredIssuer.hostname);
174
175
  const oauthPort = configuredIssuer === undefined
175
176
  ? await reservePort(oauthHostname)
176
177
  : Number(configuredIssuer.port.length > 0 ? configuredIssuer.port : "80");
@@ -184,8 +185,7 @@ export function createMcpOAuthTestServer(options = {}) {
184
185
  if (fixedPort === 0 && configuredResource === undefined) {
185
186
  do {
186
187
  fixedPort = await reservePort(hostname);
187
- } while (fixedPort === oauthPort &&
188
- normalizeHostForListen(hostname) === oauthHostname);
188
+ } while (fixedPort === oauthPort && normalizeHostForListen(hostname) === oauthHostname);
189
189
  }
190
190
  const oauth = createOAuthTestServer({
191
191
  issuer,
@@ -193,31 +193,31 @@ export function createMcpOAuthTestServer(options = {}) {
193
193
  staticClients: options.staticClients,
194
194
  defaultAuthorization: {
195
195
  autoApprove: options.autoApprove ?? false,
196
- scopes,
197
- },
196
+ scopes
197
+ }
198
198
  });
199
199
  let oauthHandle;
200
200
  let mcpHandle;
201
201
  try {
202
202
  oauthHandle = await oauth.listen({
203
203
  port: oauthPort,
204
- hostname: oauthHostname,
204
+ hostname: oauthHostname
205
205
  });
206
206
  const resource = configuredResource ?? buildUrl(hostname, fixedPort, mcpPath);
207
207
  const jwksVerifier = createJwksTokenVerifier({
208
208
  jwksUrl: `${oauth.issuer}/.well-known/jwks.json`,
209
- fetch: (input, init) => nodeFetch(input instanceof Request ? input.url : input, init),
209
+ fetch: (input, init) => nodeFetch(input instanceof Request ? input.url : input, init)
210
210
  });
211
211
  const verifier = {
212
212
  async verify(input) {
213
213
  if (isRevokedToken(oauth, input.token)) {
214
214
  throw new TokenVerificationError({
215
215
  error: "invalid_token",
216
- errorDescription: "token revoked",
216
+ errorDescription: "token revoked"
217
217
  });
218
218
  }
219
219
  return jwksVerifier.verify(input);
220
- },
220
+ }
221
221
  };
222
222
  mcpHandle = await createTestMcpServer({
223
223
  enableJsonResponse: true,
@@ -227,12 +227,12 @@ export function createMcpOAuthTestServer(options = {}) {
227
227
  bearerMethodsSupported: ["header"],
228
228
  scopesSupported: scopes,
229
229
  requiredScopes: scopes,
230
- verifier,
231
- },
230
+ verifier
231
+ }
232
232
  }).listenHttp({
233
233
  port: fixedPort,
234
234
  hostname,
235
- path: mcpPath,
235
+ path: mcpPath
236
236
  });
237
237
  const prmUrl = getProtectedResourceMetadataUrl(mcpHandle.url);
238
238
  const handle = {
@@ -245,16 +245,13 @@ export function createMcpOAuthTestServer(options = {}) {
245
245
  if (currentHandle !== handle) {
246
246
  return;
247
247
  }
248
- const results = await Promise.allSettled([
249
- mcpHandle?.close(),
250
- oauthHandle?.close(),
251
- ]);
248
+ const results = await Promise.allSettled([mcpHandle?.close(), oauthHandle?.close()]);
252
249
  const rejected = results.find((result) => result.status === "rejected");
253
250
  if (rejected !== undefined) {
254
251
  throw rejected.reason;
255
252
  }
256
253
  currentHandle = null;
257
- },
254
+ }
258
255
  };
259
256
  currentHandle = handle;
260
257
  return handle;
@@ -1,14 +1,13 @@
1
- export { createServer, defineSchema, Image, Audio, File, toContentBlocks, fileTypeFromBuffer, JSON_RPC_ERROR_CODES, ToolError, } from "../../tiny-stdio-mcp-server/dist/index.js";
2
- export type { Server, TypedSchema, ImageContent, AudioContent, EmbeddedResource, TextResourceContents, BlobResourceContents, ContentBlock, TextContent, FileTypeResult, ToolReturn, ServerOptions, ToolHandler, ToolDefinition, Tool, ToolAnnotations, ToolExecution, Icon, ContentAnnotations, ResourceLink, CallToolResult, PromptContentItem, PromptArgument, Prompt, PromptMessage, GetPromptResult, PromptHandler, PromptDefinition, Resource, ResourceTemplate, ResourceContents, ReadResourceResult, ResourceHandler, ResourceDefinition, ResourceTemplateDefinition, HandleResult, ContentItem, JSONSchema, JSONSchemaProperty, Transport, SDKTransport, JSONRPCRequest, JSONRPCResponse, JSONRPCError, JSONRPCMessage, JSONRPCNotification, InitializeResult, } from "../../tiny-stdio-mcp-server/dist/index.js";
3
- export { createExpressMiddleware, createExpressOAuthHandlers, createProtectedResourceMetadataRouter, } from "./express-middleware.js";
1
+ export { createServer, defineSchema, Image, Audio, File, toContentBlocks, fileTypeFromBuffer, JSON_RPC_ERROR_CODES, ToolError } from "../../tiny-stdio-mcp-server/dist/index.js";
2
+ export type { Server, TypedSchema, ImageContent, AudioContent, EmbeddedResource, TextResourceContents, BlobResourceContents, ContentBlock, TextContent, FileTypeResult, ToolReturn, ServerOptions, ToolHandler, ToolDefinition, Tool, ToolAnnotations, ToolExecution, Icon, ContentAnnotations, ResourceLink, CallToolResult, PromptContentItem, PromptArgument, Prompt, PromptMessage, GetPromptResult, PromptHandler, PromptDefinition, Resource, ResourceTemplate, ResourceContents, ReadResourceResult, ResourceHandler, ResourceDefinition, ResourceTemplateDefinition, HandleResult, ContentItem, JSONSchema, JSONSchemaProperty, Transport, SDKTransport, JSONRPCRequest, JSONRPCResponse, JSONRPCError, JSONRPCMessage, JSONRPCNotification, InitializeResult } from "../../tiny-stdio-mcp-server/dist/index.js";
3
+ export { createExpressMiddleware, createExpressOAuthHandlers, createProtectedResourceMetadataRouter } from "./express-middleware.js";
4
4
  export type { CreateExpressOAuthHandlersOptions } from "./express-middleware.js";
5
- export { createHttpServer, createProtectedResourceMetadataDocument, } from "./http-server.js";
5
+ export { createHttpServer, createProtectedResourceMetadataDocument } from "./http-server.js";
6
6
  export type { HttpToolContext, HttpToolHandler, HttpListenOptions, HttpServer, HttpServerHandle, HttpTransportOptions, ProtectedResourceMetadataOptions, TinyHttpMcpServerOAuthOptions } from "./http-server.js";
7
7
  export { TokenVerificationError } from "./auth.js";
8
- export type { RequestAuthInfo, TokenVerifier, VerifiedAccessToken, } from "./auth.js";
8
+ export type { RequestAuthInfo, TokenVerifier, VerifiedAccessToken } from "./auth.js";
9
9
  export { StreamableHttpTransport } from "./http-transport.js";
10
- export type { HttpObservabilityEvent, HttpObservabilityOptions, StreamableHttpTransportOptions, } from "./http-transport.js";
10
+ export type { HttpObservabilityEvent, HttpObservabilityOptions, StreamableHttpTransportOptions } from "./http-transport.js";
11
11
  export type { Session, SessionStore } from "./session.js";
12
12
  export { createJwksTokenVerifier } from "../../mcp-oauth/dist/index.js";
13
- export type { JwksTokenVerifier, JwksTokenVerifierOptions, JwksVerifiedAccessToken, } from "../../mcp-oauth/dist/index.js";
14
- export { createTestMcpServer, nodeFetch } from "./test-support.js";
13
+ export type { JwksTokenVerifier, JwksTokenVerifierOptions, JwksVerifiedAccessToken } from "../../mcp-oauth/dist/index.js";
@@ -1,7 +1,6 @@
1
- export { createServer, defineSchema, Image, Audio, File, toContentBlocks, fileTypeFromBuffer, JSON_RPC_ERROR_CODES, ToolError, } from "tiny-stdio-mcp-server";
2
- export { createExpressMiddleware, createExpressOAuthHandlers, createProtectedResourceMetadataRouter, } from "./express-middleware.js";
3
- export { createHttpServer, createProtectedResourceMetadataDocument, } from "./http-server.js";
1
+ export { createServer, defineSchema, Image, Audio, File, toContentBlocks, fileTypeFromBuffer, JSON_RPC_ERROR_CODES, ToolError } from "tiny-stdio-mcp-server";
2
+ export { createExpressMiddleware, createExpressOAuthHandlers, createProtectedResourceMetadataRouter } from "./express-middleware.js";
3
+ export { createHttpServer, createProtectedResourceMetadataDocument } from "./http-server.js";
4
4
  export { TokenVerificationError } from "./auth.js";
5
5
  export { StreamableHttpTransport } from "./http-transport.js";
6
6
  export { createJwksTokenVerifier } from "mcp-oauth";
7
- export { createTestMcpServer, nodeFetch } from "./test-support.js";
@@ -1,4 +1,5 @@
1
1
  import { type HttpServer } from "./http-server.js";
2
+ export declare function installInMemoryHttp(): void;
2
3
  export declare function nodeFetch(input: string | URL, init?: RequestInit): Promise<Response>;
3
4
  export declare function createTestMcpServer(options?: Partial<{
4
5
  name: string;
@@ -2,7 +2,7 @@ import http from "node:http";
2
2
  import https from "node:https";
3
3
  import { EventEmitter } from "node:events";
4
4
  import { Readable } from "node:stream";
5
- import { Audio, defineSchema, File, Image, } from "tiny-stdio-mcp-server";
5
+ import { Audio, defineSchema, File, Image } from "tiny-stdio-mcp-server";
6
6
  import { createHttpServer } from "./http-server.js";
7
7
  const TEST_PNG_BASE64 = "iVBORw0KGgo=";
8
8
  const TEST_MP3_BASE64 = "SUQzBAAAAAA=";
@@ -14,7 +14,7 @@ function getInMemoryHttpState() {
14
14
  target[IN_MEMORY_HTTP_STATE] = {
15
15
  installed: false,
16
16
  nextPort: 41_000,
17
- servers: new Map(),
17
+ servers: new Map()
18
18
  };
19
19
  }
20
20
  return target[IN_MEMORY_HTTP_STATE];
@@ -25,13 +25,8 @@ function normalizeRequestHostname(hostname) {
25
25
  }
26
26
  return hostname;
27
27
  }
28
- function shouldUseInMemoryHttp() {
29
- return process.env.VITEST !== undefined || process.env.NODE_ENV === "test";
30
- }
31
28
  function formatHostnameForOrigin(hostname) {
32
- return hostname.includes(":") && !hostname.startsWith("[")
33
- ? `[${hostname}]`
34
- : hostname;
29
+ return hostname.includes(":") && !hostname.startsWith("[") ? `[${hostname}]` : hostname;
35
30
  }
36
31
  function normalizeListenHostname(hostname) {
37
32
  if (hostname === undefined || hostname.length === 0) {
@@ -46,7 +41,7 @@ function parseListenArgs(args) {
46
41
  return {
47
42
  port: options.port ?? 0,
48
43
  hostname: normalizeListenHostname(options.host ?? options.hostname),
49
- callback,
44
+ callback
50
45
  };
51
46
  }
52
47
  const port = typeof args[0] === "number" ? args[0] : 0;
@@ -54,13 +49,10 @@ function parseListenArgs(args) {
54
49
  return {
55
50
  port,
56
51
  hostname: normalizeListenHostname(hostname),
57
- callback,
52
+ callback
58
53
  };
59
54
  }
60
- function installInMemoryHttp() {
61
- if (!shouldUseInMemoryHttp()) {
62
- return;
63
- }
55
+ export function installInMemoryHttp() {
64
56
  const state = getInMemoryHttpState();
65
57
  if (state.installed) {
66
58
  return;
@@ -68,6 +60,7 @@ function installInMemoryHttp() {
68
60
  state.installed = true;
69
61
  const originalAddress = http.Server.prototype.address;
70
62
  const originalClose = http.Server.prototype.close;
63
+ const originalFetch = globalThis.fetch.bind(globalThis);
71
64
  http.Server.prototype.listen = function listen(...args) {
72
65
  const { port: requestedPort, hostname, callback } = parseListenArgs(args);
73
66
  const port = requestedPort === 0 ? state.nextPort++ : requestedPort;
@@ -78,9 +71,9 @@ function installInMemoryHttp() {
78
71
  address: {
79
72
  address,
80
73
  family: address.includes(":") ? "IPv6" : "IPv4",
81
- port,
74
+ port
82
75
  },
83
- listening: true,
76
+ listening: true
84
77
  };
85
78
  this[IN_MEMORY_HTTP_META] = meta;
86
79
  state.servers.set(origin, this);
@@ -88,7 +81,7 @@ function installInMemoryHttp() {
88
81
  configurable: true,
89
82
  get() {
90
83
  return this[IN_MEMORY_HTTP_META]?.listening ?? false;
91
- },
84
+ }
92
85
  });
93
86
  queueMicrotask(() => {
94
87
  this.emit("listening");
@@ -114,12 +107,21 @@ function installInMemoryHttp() {
114
107
  });
115
108
  return this;
116
109
  };
110
+ globalThis.fetch = async (input, init = {}) => {
111
+ const normalized = normalizeFetchInput(input, init);
112
+ const inMemoryServer = getInMemoryServer(normalized.url);
113
+ if (inMemoryServer !== undefined) {
114
+ return fetchInMemory(inMemoryServer, normalized.url, normalized.init);
115
+ }
116
+ return originalFetch(input, init);
117
+ };
117
118
  }
118
119
  function getInMemoryServer(url) {
119
- if (!shouldUseInMemoryHttp()) {
120
+ const state = globalThis[IN_MEMORY_HTTP_STATE];
121
+ if (state?.installed !== true) {
120
122
  return undefined;
121
123
  }
122
- return getInMemoryHttpState().servers.get(url.origin);
124
+ return state.servers.get(url.origin);
123
125
  }
124
126
  async function readFetchBody(body) {
125
127
  if (body === undefined || body === null) {
@@ -149,14 +151,14 @@ async function fetchInMemory(server, url, init) {
149
151
  method: init.method ?? "GET",
150
152
  url: `${url.pathname}${url.search}`,
151
153
  headers: Object.fromEntries(headers.entries()),
152
- socket: {},
154
+ socket: {}
153
155
  });
154
156
  const response = new EventEmitter();
155
157
  let streamController;
156
158
  const responseBody = new ReadableStream({
157
159
  start(controller) {
158
160
  streamController = controller;
159
- },
161
+ }
160
162
  });
161
163
  response.statusCode = 200;
162
164
  response.statusMessage = "OK";
@@ -249,16 +251,13 @@ async function fetchInMemory(server, url, init) {
249
251
  });
250
252
  response.once("finish", resolve);
251
253
  });
252
- const responseContent = response.writableEnded
253
- ? Buffer.concat(response.chunks)
254
- : responseBody;
254
+ const responseContent = response.writableEnded ? Buffer.concat(response.chunks) : responseBody;
255
255
  return new Response(response.statusCode === 204 ? null : responseContent, {
256
256
  status: response.statusCode,
257
257
  statusText: response.statusMessage,
258
- headers: response.headerValues,
258
+ headers: response.headerValues
259
259
  });
260
260
  }
261
- installInMemoryHttp();
262
261
  function normalizeFetchInput(input, init = {}) {
263
262
  if (input instanceof Request) {
264
263
  return {
@@ -268,24 +267,13 @@ function normalizeFetchInput(input, init = {}) {
268
267
  method: init.method ?? input.method,
269
268
  headers: init.headers ?? input.headers,
270
269
  body: init.body ?? input.body,
271
- signal: init.signal ?? input.signal,
272
- },
270
+ signal: init.signal ?? input.signal
271
+ }
273
272
  };
274
273
  }
275
274
  return {
276
275
  url: new URL(String(input)),
277
- init,
278
- };
279
- }
280
- if (shouldUseInMemoryHttp()) {
281
- const originalFetch = globalThis.fetch.bind(globalThis);
282
- globalThis.fetch = async (input, init = {}) => {
283
- const normalized = normalizeFetchInput(input, init);
284
- const inMemoryServer = getInMemoryServer(normalized.url);
285
- if (inMemoryServer !== undefined) {
286
- return fetchInMemory(inMemoryServer, normalized.url, normalized.init);
287
- }
288
- return originalFetch(input, init);
276
+ init
289
277
  };
290
278
  }
291
279
  export async function nodeFetch(input, init = {}) {
@@ -302,7 +290,7 @@ export async function nodeFetch(input, init = {}) {
302
290
  hostname: normalizeRequestHostname(url.hostname),
303
291
  port: url.port.length > 0 ? Number(url.port) : url.protocol === "https:" ? 443 : 80,
304
292
  path: `${url.pathname}${url.search}`,
305
- headers: Object.fromEntries(headers.entries()),
293
+ headers: Object.fromEntries(headers.entries())
306
294
  }, (response) => {
307
295
  const responseHeaders = new Headers();
308
296
  for (const [key, value] of Object.entries(response.headers)) {
@@ -322,7 +310,7 @@ export async function nodeFetch(input, init = {}) {
322
310
  resolve(new Response(body, {
323
311
  status: response.statusCode ?? 0,
324
312
  statusText: response.statusMessage ?? "",
325
- headers: responseHeaders,
313
+ headers: responseHeaders
326
314
  }));
327
315
  });
328
316
  request.on("error", reject);
@@ -352,9 +340,9 @@ export async function nodeFetch(input, init = {}) {
352
340
  export function createTestMcpServer(options = {}) {
353
341
  const emptySchema = defineSchema({});
354
342
  const textSchema = defineSchema({
355
- text: { type: "string" },
343
+ text: { type: "string" }
356
344
  });
357
- return createHttpServer({
345
+ return (createHttpServer({
358
346
  name: options.name ?? "conformance-test-server",
359
347
  version: options.version ?? "1.0.0",
360
348
  ...(hasOwnProperty(options, "enableJsonResponse")
@@ -363,7 +351,7 @@ export function createTestMcpServer(options = {}) {
363
351
  ...(hasOwnProperty(options, "sessionIdGenerator")
364
352
  ? { sessionIdGenerator: options.sessionIdGenerator }
365
353
  : {}),
366
- ...(hasOwnProperty(options, "oauth") ? { oauth: options.oauth } : {}),
354
+ ...(hasOwnProperty(options, "oauth") ? { oauth: options.oauth } : {})
367
355
  })
368
356
  .tool("echo", "Echo input text", textSchema, ({ text }) => String(text))
369
357
  .tool("reverse", "Reverse input text", textSchema, ({ text }) => String(text).split("").reverse().join(""))
@@ -371,16 +359,16 @@ export function createTestMcpServer(options = {}) {
371
359
  .tool("get_user", "Return a test user object", defineSchema({ id: { type: "string" } }), ({ id }) => ({
372
360
  id: String(id),
373
361
  name: "Alice",
374
- role: "admin",
362
+ role: "admin"
375
363
  }), {
376
364
  type: "object",
377
365
  properties: {
378
366
  id: { type: "string" },
379
367
  name: { type: "string" },
380
- role: { type: "string" },
368
+ role: { type: "string" }
381
369
  },
382
370
  required: ["id", "name", "role"],
383
- additionalProperties: false,
371
+ additionalProperties: false
384
372
  })
385
373
  // Deliberately untyped fixture: exercises legacy JSON-array text fallback.
386
374
  .tool("get_list", "Return a numeric array", emptySchema, () => [1, 2, 3])
@@ -390,7 +378,7 @@ export function createTestMcpServer(options = {}) {
390
378
  .tool("get_mixed", "Return multiple content blocks", emptySchema, () => [
391
379
  Image.fromBase64(TEST_PNG_BASE64, "image/png"),
392
380
  "Caption for the image",
393
- File.fromText("notes"),
381
+ File.fromText("notes")
394
382
  ])
395
383
  .tool("throw_sync", "Throw synchronously", emptySchema, () => {
396
384
  throw new Error("sync boom");
@@ -403,7 +391,7 @@ export function createTestMcpServer(options = {}) {
403
391
  await new Promise((resolve) => setTimeout(resolve, 10));
404
392
  return "done";
405
393
  })
406
- .tool("large_output", "Return 100KB of text", emptySchema, () => "x".repeat(100_000));
394
+ .tool("large_output", "Return 100KB of text", emptySchema, () => "x".repeat(100_000)));
407
395
  }
408
396
  function hasOwnProperty(value, key) {
409
397
  return Object.prototype.hasOwnProperty.call(value, key);
@@ -2,7 +2,7 @@ import type { Client } from "@modelcontextprotocol/sdk/client/index.js";
2
2
  import type { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
3
3
  import type { HttpServer, HttpServerHandle } from "./http-server.js";
4
4
  import { type TokenVerifier } from "./auth.js";
5
- export { createTestMcpServer, nodeFetch } from "./test-support.js";
5
+ export { createTestMcpServer, installInMemoryHttp, nodeFetch } from "./test-support.js";
6
6
  export interface HttpTestPair {
7
7
  client: Client;
8
8
  transport: StreamableHTTPClientTransport;
@@ -56,4 +56,4 @@ export declare function createInMemoryTokenVerifier(options?: Partial<{
56
56
  now: () => number;
57
57
  }>): InMemoryTokenVerifier;
58
58
  export declare function createHttpTestPair(server: HttpServer): Promise<HttpTestPair>;
59
- export declare function createHttpTestPairWithTinyClient(server: HttpServer): Promise<TinyHttpTestPair | null>;
59
+ export declare function createHttpTestPairWithTinyClient(server: HttpServer): Promise<TinyHttpTestPair>;
@@ -1,12 +1,12 @@
1
- import { TokenVerificationError, } from "./auth.js";
2
- import { nodeFetch } from "./test-support.js";
3
- export { createTestMcpServer, nodeFetch } from "./test-support.js";
1
+ import { TokenVerificationError } from "./auth.js";
2
+ import { installInMemoryHttp, nodeFetch } from "./test-support.js";
3
+ export { createTestMcpServer, installInMemoryHttp, nodeFetch } from "./test-support.js";
4
4
  function cloneVerifiedAccessToken(token) {
5
5
  return {
6
6
  ...token,
7
7
  audience: [...token.audience],
8
8
  scopes: [...token.scopes],
9
- claims: structuredClone(token.claims),
9
+ claims: structuredClone(token.claims)
10
10
  };
11
11
  }
12
12
  export function createInMemoryTokenVerifier(options = {}) {
@@ -20,25 +20,25 @@ export function createInMemoryTokenVerifier(options = {}) {
20
20
  if (token === undefined) {
21
21
  throw new TokenVerificationError({
22
22
  error: "invalid_token",
23
- errorDescription: "unknown token",
23
+ errorDescription: "unknown token"
24
24
  });
25
25
  }
26
26
  if (!input.authorizationServers.includes(token.issuer)) {
27
27
  throw new TokenVerificationError({
28
28
  error: "invalid_token",
29
- errorDescription: "issuer mismatch",
29
+ errorDescription: "issuer mismatch"
30
30
  });
31
31
  }
32
32
  if (!token.audience.includes(input.resource)) {
33
33
  throw new TokenVerificationError({
34
34
  error: "invalid_token",
35
- errorDescription: "audience mismatch",
35
+ errorDescription: "audience mismatch"
36
36
  });
37
37
  }
38
38
  if (token.expiresAt <= now()) {
39
39
  throw new TokenVerificationError({
40
40
  error: "invalid_token",
41
- errorDescription: "token expired",
41
+ errorDescription: "token expired"
42
42
  });
43
43
  }
44
44
  if (input.requiredScopes.length > 0 &&
@@ -46,11 +46,11 @@ export function createInMemoryTokenVerifier(options = {}) {
46
46
  throw new TokenVerificationError({
47
47
  error: "insufficient_scope",
48
48
  errorDescription: "insufficient scope",
49
- scope: input.requiredScopes,
49
+ scope: input.requiredScopes
50
50
  });
51
51
  }
52
52
  return cloneVerifiedAccessToken(token);
53
- },
53
+ }
54
54
  },
55
55
  issueToken(input) {
56
56
  const token = input.token ?? `test-token-${nextTokenId++}`;
@@ -68,13 +68,13 @@ export function createInMemoryTokenVerifier(options = {}) {
68
68
  ...(input.subject === undefined
69
69
  ? {}
70
70
  : {
71
- sub: input.subject,
71
+ sub: input.subject
72
72
  }),
73
73
  ...(input.clientId === undefined
74
74
  ? {}
75
75
  : {
76
- client_id: input.clientId,
77
- }),
76
+ client_id: input.clientId
77
+ })
78
78
  };
79
79
  tokens.set(token, {
80
80
  token,
@@ -86,16 +86,16 @@ export function createInMemoryTokenVerifier(options = {}) {
86
86
  ...(input.subject === undefined
87
87
  ? {}
88
88
  : {
89
- subject: input.subject,
89
+ subject: input.subject
90
90
  }),
91
91
  ...(input.clientId === undefined
92
92
  ? {}
93
93
  : {
94
- clientId: input.clientId,
95
- }),
94
+ clientId: input.clientId
95
+ })
96
96
  });
97
97
  return token;
98
- },
98
+ }
99
99
  };
100
100
  }
101
101
  export async function createHttpTestPair(server) {
@@ -108,10 +108,11 @@ export async function createHttpTestPair(server) {
108
108
  catch (error) {
109
109
  throw new Error("createHttpTestPair requires @modelcontextprotocol/sdk; install it as a devDependency or use createHttpTestPairWithTinyClient", { cause: error });
110
110
  }
111
+ installInMemoryHttp();
111
112
  const handle = await server.listenHttp({ port: 0 });
112
113
  const client = new sdkClient.Client({ name: "sdk-test-client", version: "1.0.0" });
113
114
  const transport = new sdkTransport.StreamableHTTPClientTransport(new URL(handle.url), {
114
- fetch: nodeFetch,
115
+ fetch: nodeFetch
115
116
  });
116
117
  try {
117
118
  await client.connect(transport);
@@ -131,7 +132,7 @@ export async function createHttpTestPair(server) {
131
132
  if (rejected !== undefined) {
132
133
  throw rejected.reason;
133
134
  }
134
- },
135
+ }
135
136
  };
136
137
  }
137
138
  export async function createHttpTestPairWithTinyClient(server) {
@@ -139,13 +140,14 @@ export async function createHttpTestPairWithTinyClient(server) {
139
140
  try {
140
141
  tinyMcpClient = await import("tiny-mcp-client");
141
142
  }
142
- catch {
143
- return null;
143
+ catch (error) {
144
+ throw new Error("createHttpTestPairWithTinyClient requires tiny-mcp-client; install tiny-mcp-client as a devDependency", { cause: error });
144
145
  }
146
+ installInMemoryHttp();
145
147
  const handle = await server.listenHttp({ port: 0 });
146
148
  const requests = [];
147
149
  const client = new tinyMcpClient.McpClient({
148
- clientInfo: { name: "tiny-http-test-client", version: "1.0.0" },
150
+ clientInfo: { name: "tiny-http-test-client", version: "1.0.0" }
149
151
  });
150
152
  const transport = new tinyMcpClient.HttpTransport({
151
153
  url: handle.url,
@@ -169,10 +171,10 @@ export async function createHttpTestPairWithTinyClient(server) {
169
171
  method,
170
172
  sessionId: headers.get("mcp-session-id"),
171
173
  jsonRpcMethod,
172
- responseContentType: response.headers.get("content-type"),
174
+ responseContentType: response.headers.get("content-type")
173
175
  });
174
176
  return response;
175
- },
177
+ }
176
178
  });
177
179
  await client.connect(transport);
178
180
  return {
@@ -184,6 +186,6 @@ export async function createHttpTestPairWithTinyClient(server) {
184
186
  cleanup: async () => {
185
187
  await client.close();
186
188
  await handle.close();
187
- },
189
+ }
188
190
  };
189
191
  }
@@ -16,6 +16,10 @@
16
16
  "./testing": {
17
17
  "types": "./dist/testing.d.ts",
18
18
  "import": "./dist/testing.js"
19
+ },
20
+ "./test-support": {
21
+ "types": "./dist/test-support.d.ts",
22
+ "import": "./dist/test-support.js"
19
23
  }
20
24
  },
21
25
  "scripts": {