@mcpfn/testing 0.0.1 → 0.0.2

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/dist/index.d.cts CHANGED
@@ -1,40 +1,45 @@
1
- import { ClientCapabilities, Tool, CallToolResult, CreateTaskResult, Task, ListTasksResult, Resource, ResourceTemplate, ReadResourceResult, Prompt, GetPromptResult, CompleteRequest, CompleteResult } from '@modelcontextprotocol/sdk/types.js';
1
+ import { ClientCapabilities, Implementation, Tool, CallToolResult, CreateTaskResult, Task, ListTasksResult, Resource, ResourceTemplate, ReadResourceResult, Prompt, GetPromptResult, CompleteRequest, CompleteResult, ServerCapabilities } from '@modelcontextprotocol/sdk/types.js';
2
2
  import { McpFnServer, McpFnManifest } from '@mcpfn/core';
3
+ import { McpFnClient, McpFnClientMediatedHandlers, McpFnClientEventSink, McpFnDiagnosticSink, McpFnTarget, McpFnClientEventKind, McpFnTargetDescriptor, McpFnDiagnosticEvent } from '@mcpfn/client';
3
4
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
4
- export { MCPFN_OAUTH_EXTENSION_GRANTS, McpFnAuthAssertionError, McpFnAuthCredential, McpFnAuthCredentialKind, McpFnAuthCredentialRequest, McpFnAuthProbeScenario, McpFnAuthProviderAdapter, McpFnAuthProviderCapabilities, McpFnAuthRegressionOptions, McpFnAuthScenarioResult, McpFnAuthTarget, McpFnBearerChallenge, McpFnFetchAuthTargetOptions, McpFnMockOAuthAuthorizationServer, McpFnMockOAuthServerOptions, McpFnMockOAuthTokenSet, McpFnOAuthCallback, McpFnOAuthClientMetadata, McpFnOAuthClientMetadataFixtureOptions, McpFnOAuthClientMetadataVariants, McpFnPkcePair, McpFnStartMockOAuthServerOptions, McpFnStartedMockOAuthServer, apiKeyCredential, assertAuthRegressionSuite, assertAuthorizationCodeClientMetadata, assertBearerResourceChallenge, bearerCredential, createFetchAuthTarget, createOAuthClientMetadataFixture, createOAuthClientMetadataVariants, createPkcePair, parseBearerChallenge, runAuthRegressionSuite, startMockOAuthAuthorizationServer } from './auth.cjs';
5
+ import { RequestOptions } from '@modelcontextprotocol/sdk/shared/protocol.js';
6
+ export { MCPFN_NAMED_OAUTH_HOST_FIXTURES, MCPFN_OAUTH_EXTENSION_GRANTS, McpFnAuthAssertionError, McpFnAuthCredential, McpFnAuthCredentialKind, McpFnAuthCredentialRequest, McpFnAuthProbeScenario, McpFnAuthProviderAdapter, McpFnAuthProviderCapabilities, McpFnAuthRegressionOptions, McpFnAuthScenarioResult, McpFnAuthTarget, McpFnBearerChallenge, McpFnFetchAuthTargetOptions, McpFnMockOAuthAuthorizationServer, McpFnMockOAuthServerOptions, McpFnMockOAuthTokenSet, McpFnNamedOAuthHostFixture, McpFnOAuthCallback, McpFnOAuthClientMetadata, McpFnOAuthClientMetadataFixtureOptions, McpFnOAuthClientMetadataVariants, McpFnPkcePair, McpFnStartMockOAuthServerOptions, McpFnStartedMockOAuthServer, apiKeyCredential, assertAuthRegressionSuite, assertAuthorizationCodeClientMetadata, assertBearerResourceChallenge, bearerCredential, createFetchAuthTarget, createOAuthClientMetadataFixture, createOAuthClientMetadataVariants, createPkcePair, parseBearerChallenge, runAuthRegressionSuite, startMockOAuthAuthorizationServer } from './auth.cjs';
5
7
  import '@modelcontextprotocol/sdk/server/auth/types.js';
6
8
 
7
9
  interface McpFnTestClientOptions {
8
10
  capabilities?: ClientCapabilities;
11
+ handlers?: McpFnClientMediatedHandlers;
12
+ events?: McpFnClientEventSink;
9
13
  /** Install roots, sampling, elicitation, or notification handlers before initialize. */
10
14
  configure?(client: Client): void | Promise<void>;
15
+ diagnostics?: McpFnDiagnosticSink;
11
16
  }
12
17
  declare class McpFnTestClient<TContext = undefined> {
13
- readonly client: Client;
14
- private readonly server;
15
- private closed;
18
+ readonly session: McpFnClient;
16
19
  private constructor();
20
+ get client(): Client;
17
21
  static connect<TContext>(server: McpFnServer<TContext>, info?: {
18
22
  name: string;
19
23
  version: string;
20
24
  }, options?: McpFnTestClientOptions): Promise<McpFnTestClient<TContext>>;
21
- listTools(): Promise<Tool[]>;
22
- callTool(name: string, args?: Record<string, unknown>): Promise<CallToolResult>;
23
- createToolTask(name: string, args?: Record<string, unknown>, options?: {
25
+ static connectTarget<TContext = undefined>(target: McpFnTarget, info?: Implementation, options?: McpFnTestClientOptions): Promise<McpFnTestClient<TContext>>;
26
+ listTools(options?: RequestOptions): Promise<Tool[]>;
27
+ callTool(name: string, args?: Record<string, unknown>, options?: RequestOptions): Promise<CallToolResult>;
28
+ createToolTask(name: string, args?: Record<string, unknown>, task?: {
24
29
  ttl?: number;
25
- }): Promise<CreateTaskResult>;
26
- getTask(taskId: string): Promise<Task>;
27
- getTaskResult(taskId: string): Promise<CallToolResult>;
28
- listTasks(cursor?: string): Promise<ListTasksResult>;
29
- cancelTask(taskId: string): Promise<Task>;
30
- listResources(): Promise<Resource[]>;
31
- listResourceTemplates(): Promise<ResourceTemplate[]>;
32
- readResource(uri: string): Promise<ReadResourceResult>;
33
- subscribeResource(uri: string): Promise<void>;
34
- unsubscribeResource(uri: string): Promise<void>;
35
- listPrompts(): Promise<Prompt[]>;
36
- getPrompt(name: string, args?: Record<string, string>): Promise<GetPromptResult>;
37
- complete(params: CompleteRequest["params"]): Promise<CompleteResult>;
30
+ }, options?: RequestOptions): Promise<CreateTaskResult>;
31
+ getTask(taskId: string, options?: RequestOptions): Promise<Task>;
32
+ getTaskResult(taskId: string, options?: RequestOptions): Promise<CallToolResult>;
33
+ listTasks(cursor?: string, options?: RequestOptions): Promise<ListTasksResult>;
34
+ cancelTask(taskId: string, options?: RequestOptions): Promise<Task>;
35
+ listResources(options?: RequestOptions): Promise<Resource[]>;
36
+ listResourceTemplates(options?: RequestOptions): Promise<ResourceTemplate[]>;
37
+ readResource(uri: string, options?: RequestOptions): Promise<ReadResourceResult>;
38
+ subscribeResource(uri: string, options?: RequestOptions): Promise<void>;
39
+ unsubscribeResource(uri: string, options?: RequestOptions): Promise<void>;
40
+ listPrompts(options?: RequestOptions): Promise<Prompt[]>;
41
+ getPrompt(name: string, args?: Record<string, string>, options?: RequestOptions): Promise<GetPromptResult>;
42
+ complete(params: CompleteRequest["params"], options?: RequestOptions): Promise<CompleteResult>;
38
43
  close(): Promise<void>;
39
44
  }
40
45
 
@@ -69,8 +74,30 @@ interface OfficialConformanceResult {
69
74
  stdout: string;
70
75
  stderr: string;
71
76
  }
77
+ interface AuthenticatedConformanceProxy {
78
+ /** Loopback URL to pass to the official conformance runner. */
79
+ url: string;
80
+ close(): Promise<void>;
81
+ }
82
+ interface AuthenticatedConformanceProxyOptions {
83
+ /** Fixed loopback MCP URL. Requests cannot select a different origin or path. */
84
+ url: string;
85
+ /** Headers injected into requests using the proxy's own authority. Values are never logged. */
86
+ headers: HeadersInit;
87
+ }
88
+ interface AuthenticatedOfficialConformanceOptions extends OfficialConformanceOptions {
89
+ headers: HeadersInit;
90
+ }
91
+ /**
92
+ * Start a loopback-only streaming proxy for runners that cannot send auth
93
+ * headers. Authenticated requests use one fixed upstream authority and path.
94
+ * Host-manipulation probes are forwarded without injected credentials.
95
+ */
96
+ declare function createAuthenticatedConformanceProxy(options: AuthenticatedConformanceProxyOptions): Promise<AuthenticatedConformanceProxy>;
72
97
  declare function buildOfficialConformanceArgs(options: OfficialConformanceOptions): string[];
73
98
  declare function runOfficialConformance(options: OfficialConformanceOptions): Promise<OfficialConformanceResult>;
99
+ /** Run the pinned official suite against an authenticated MCP endpoint. */
100
+ declare function runAuthenticatedOfficialConformance(options: AuthenticatedOfficialConformanceOptions): Promise<OfficialConformanceResult>;
74
101
 
75
102
  type McpFnServerFeature = "tools" | "resources" | "prompts" | "completions" | "tasks" | "logging";
76
103
  interface McpFnHostProfile {
@@ -129,8 +156,20 @@ declare const MCPFN_HOST_PROFILES: {
129
156
  };
130
157
  declare function checkHostCompatibility(manifest: McpFnManifest, profile: McpFnHostProfile): McpFnHostCompatibilityResult;
131
158
 
132
- interface McpFnScenario {
159
+ type McpFnScenarioSideEffect = "none" | "idempotent" | "non-idempotent";
160
+ interface McpFnScenarioBase {
161
+ formatVersion?: 1;
133
162
  name: string;
163
+ /** Defaults to the runner timeout. */
164
+ timeoutMs?: number;
165
+ sideEffect?: McpFnScenarioSideEffect;
166
+ status?: "complete" | "incomplete";
167
+ incompleteReason?: string;
168
+ /** Environment-backed placeholders used by this scenario, never their values. */
169
+ variables?: string[];
170
+ }
171
+ interface McpFnToolScenario extends McpFnScenarioBase {
172
+ kind?: "tools.call";
134
173
  tool: string;
135
174
  arguments?: Record<string, unknown>;
136
175
  expect?: {
@@ -140,13 +179,190 @@ interface McpFnScenario {
140
179
  };
141
180
  verify?(result: CallToolResult): void | Promise<void>;
142
181
  }
182
+ interface McpFnInventoryScenario extends McpFnScenarioBase {
183
+ kind: "tools.list" | "resources.list" | "resources.templates.list" | "prompts.list";
184
+ expectNames?: string[];
185
+ }
186
+ interface McpFnResourceScenario extends McpFnScenarioBase {
187
+ kind: "resources.read" | "resources.subscribe" | "resources.unsubscribe";
188
+ uri: string;
189
+ expect?: unknown;
190
+ }
191
+ interface McpFnPromptScenario extends McpFnScenarioBase {
192
+ kind: "prompts.get";
193
+ prompt: string;
194
+ arguments?: Record<string, string>;
195
+ expect?: unknown;
196
+ }
197
+ interface McpFnInitializeScenario extends McpFnScenarioBase {
198
+ kind: "initialize";
199
+ expectCapabilities?: Record<string, unknown>;
200
+ }
201
+ interface McpFnCreateTaskScenario extends McpFnScenarioBase {
202
+ kind: "tools.call:task";
203
+ tool: string;
204
+ arguments?: Record<string, unknown>;
205
+ task?: {
206
+ ttl?: number;
207
+ };
208
+ expect?: unknown;
209
+ }
210
+ interface McpFnTaskScenario extends McpFnScenarioBase {
211
+ kind: "tasks.get" | "tasks.result" | "tasks.cancel" | "tasks.list";
212
+ taskId?: string;
213
+ cursor?: string;
214
+ expect?: unknown;
215
+ }
216
+ interface McpFnEventScenario extends McpFnScenarioBase {
217
+ kind: "events.expect";
218
+ event: McpFnClientEventKind;
219
+ minimum?: number;
220
+ expectPayload?: unknown;
221
+ }
222
+ interface McpFnAuthScenario extends McpFnScenarioBase {
223
+ kind: "auth.assert";
224
+ phase: string;
225
+ expect: {
226
+ outcome: "allowed" | "denied";
227
+ code?: string;
228
+ };
229
+ input?: Record<string, unknown>;
230
+ }
231
+ type McpFnScenario = McpFnToolScenario | McpFnInventoryScenario | McpFnResourceScenario | McpFnPromptScenario | McpFnInitializeScenario | McpFnCreateTaskScenario | McpFnTaskScenario | McpFnEventScenario | McpFnAuthScenario;
232
+ interface McpFnScenarioArtifact {
233
+ formatVersion: 1;
234
+ kind: "mcpfn.scenarios";
235
+ status: "complete" | "incomplete";
236
+ scenarios: McpFnScenario[];
237
+ variables?: string[];
238
+ incompleteReason?: string;
239
+ }
240
+ type McpFnRecordedOperation = {
241
+ kind: "tools.call";
242
+ name: string;
243
+ arguments?: Record<string, unknown>;
244
+ } | {
245
+ kind: "tools.call:task";
246
+ name: string;
247
+ arguments?: Record<string, unknown>;
248
+ task?: {
249
+ ttl?: number;
250
+ };
251
+ } | {
252
+ kind: "resources.read";
253
+ uri: string;
254
+ } | {
255
+ kind: "resources.subscribe";
256
+ uri: string;
257
+ } | {
258
+ kind: "resources.unsubscribe";
259
+ uri: string;
260
+ } | {
261
+ kind: "prompts.get";
262
+ name: string;
263
+ arguments?: Record<string, string>;
264
+ } | {
265
+ kind: "tasks.get";
266
+ taskId: string;
267
+ } | {
268
+ kind: "tasks.result";
269
+ taskId: string;
270
+ } | {
271
+ kind: "tasks.cancel";
272
+ taskId: string;
273
+ } | {
274
+ kind: "tasks.list";
275
+ cursor?: string;
276
+ };
277
+ type McpFnRecordedOperationResult = CallToolResult | ReadResourceResult | GetPromptResult | CreateTaskResult | Task | ListTasksResult | void;
143
278
  interface McpFnScenarioResult {
279
+ formatVersion: 1;
144
280
  name: string;
145
- tool: string;
146
- status: "passed" | "failed";
281
+ operation: string;
282
+ tool?: string;
283
+ status: "passed" | "failed" | "incomplete";
284
+ sideEffect: McpFnScenarioSideEffect;
147
285
  durationMs: number;
148
286
  error?: string;
287
+ /** Observed client events discarded while this scenario was running. */
288
+ droppedObservedEvents?: number;
289
+ }
290
+ interface McpFnScenarioReport {
291
+ formatVersion: 1;
292
+ kind: "mcpfn.scenario-report";
293
+ status: "complete" | "incomplete";
294
+ manifestHash?: string;
295
+ total: number;
296
+ passed: number;
297
+ failed: number;
298
+ incomplete: number;
299
+ droppedResults: number;
300
+ droppedObservedEvents: number;
301
+ incompleteReason?: string;
302
+ results: McpFnScenarioResult[];
303
+ }
304
+ /** Convert an observed production-client operation into the shared runner contract. */
305
+ declare function createMcpFnScenario(name: string, operation: McpFnRecordedOperation, result: McpFnRecordedOperationResult): McpFnScenario;
306
+ /** Validate an unknown scenario module before it reaches the shared runner. */
307
+ declare function validateMcpFnScenarios(value: unknown): McpFnScenario[];
308
+ declare function createMcpFnScenarioArtifact(scenarios: McpFnScenario[], options?: Omit<McpFnScenarioArtifact, "formatVersion" | "kind" | "scenarios">): McpFnScenarioArtifact;
309
+ declare function runScenarios(client: McpFnTestClient<unknown>, scenarios: McpFnScenario[], options?: McpFnScenarioRunOptions): Promise<McpFnScenarioResult[]>;
310
+ interface McpFnScenarioRunOptions {
311
+ defaultTimeoutMs?: number;
312
+ maxScenarios?: number;
313
+ maxErrorBytes?: number;
314
+ /** Observed client-event count cap. Defaults to 500. */
315
+ maxObservedEvents?: number;
316
+ variables?: Record<string, string | undefined>;
317
+ auth?(scenario: McpFnAuthScenario, signal: AbortSignal): Promise<{
318
+ outcome: "allowed" | "denied";
319
+ code?: string;
320
+ }>;
321
+ }
322
+ declare function createMcpFnScenarioReport(results: McpFnScenarioResult[], options?: {
323
+ manifestHash?: string;
324
+ maxBytes?: number;
325
+ }): McpFnScenarioReport;
326
+
327
+ interface RunMcpFnTargetSuiteOptions {
328
+ target: McpFnTarget;
329
+ scenarios?: McpFnScenario[];
330
+ manifest?: McpFnManifest;
331
+ expectedToolNames?: readonly string[];
332
+ clientInfo?: Implementation;
333
+ client?: McpFnTestClientOptions;
334
+ scenarioRun?: NonNullable<Parameters<typeof runScenarios>[2]>;
335
+ /** Aggregate JSON size cap. Defaults to 1 MiB. */
336
+ maxReportBytes?: number;
337
+ /** Diagnostic timeline count cap. Defaults to 500. */
338
+ maxTimelineEvents?: number;
339
+ }
340
+ interface McpFnTargetSuiteReport {
341
+ formatVersion: 1;
342
+ kind: "mcpfn.target-suite-report";
343
+ status: "complete" | "incomplete";
344
+ runtime: {
345
+ node: string;
346
+ scenarioFormatVersion: 1;
347
+ };
348
+ ok: boolean;
349
+ target: McpFnTargetDescriptor;
350
+ server?: Implementation;
351
+ capabilities?: ServerCapabilities;
352
+ manifestChecked: boolean;
353
+ manifestHash?: string;
354
+ total: number;
355
+ passed: number;
356
+ failed: number;
357
+ incomplete: number;
358
+ droppedResults: number;
359
+ droppedObservedEvents: number;
360
+ incompleteReason?: string;
361
+ timeline: McpFnDiagnosticEvent[];
362
+ droppedTimelineEvents: number;
363
+ results: McpFnScenarioResult[];
149
364
  }
150
- declare function runScenarios(client: McpFnTestClient<unknown>, scenarios: McpFnScenario[]): Promise<McpFnScenarioResult[]>;
365
+ /** Runs local, stdio, HTTP, or custom targets through the production session engine. */
366
+ declare function runMcpFnTargetSuite(options: RunMcpFnTargetSuiteOptions): Promise<McpFnTargetSuiteReport>;
151
367
 
152
- export { type AssertManifestContractOptions, MCPFN_HOST_PROFILES, McpFnAssertionError, type McpFnHostCompatibilityIssue, type McpFnHostCompatibilityResult, type McpFnHostProfile, type McpFnScenario, type McpFnScenarioResult, type McpFnServerFeature, McpFnTestClient, type McpFnTestClientOptions, OFFICIAL_CONFORMANCE_VERSION, type OfficialConformanceOptions, type OfficialConformanceResult, assertManifestContract, assertStructuredTextParity, buildOfficialConformanceArgs, checkHostCompatibility, runOfficialConformance, runScenarios, stableJson };
368
+ export { type AssertManifestContractOptions, type AuthenticatedConformanceProxy, type AuthenticatedConformanceProxyOptions, type AuthenticatedOfficialConformanceOptions, MCPFN_HOST_PROFILES, McpFnAssertionError, type McpFnAuthScenario, type McpFnCreateTaskScenario, type McpFnEventScenario, type McpFnHostCompatibilityIssue, type McpFnHostCompatibilityResult, type McpFnHostProfile, type McpFnInitializeScenario, type McpFnInventoryScenario, type McpFnPromptScenario, type McpFnRecordedOperation, type McpFnRecordedOperationResult, type McpFnResourceScenario, type McpFnScenario, type McpFnScenarioArtifact, type McpFnScenarioBase, type McpFnScenarioReport, type McpFnScenarioResult, type McpFnScenarioRunOptions, type McpFnScenarioSideEffect, type McpFnServerFeature, type McpFnTargetSuiteReport, type McpFnTaskScenario, McpFnTestClient, type McpFnTestClientOptions, type McpFnToolScenario, OFFICIAL_CONFORMANCE_VERSION, type OfficialConformanceOptions, type OfficialConformanceResult, type RunMcpFnTargetSuiteOptions, assertManifestContract, assertStructuredTextParity, buildOfficialConformanceArgs, checkHostCompatibility, createAuthenticatedConformanceProxy, createMcpFnScenario, createMcpFnScenarioArtifact, createMcpFnScenarioReport, runAuthenticatedOfficialConformance, runMcpFnTargetSuite, runOfficialConformance, runScenarios, stableJson, validateMcpFnScenarios };
package/dist/index.d.ts CHANGED
@@ -1,40 +1,45 @@
1
- import { ClientCapabilities, Tool, CallToolResult, CreateTaskResult, Task, ListTasksResult, Resource, ResourceTemplate, ReadResourceResult, Prompt, GetPromptResult, CompleteRequest, CompleteResult } from '@modelcontextprotocol/sdk/types.js';
1
+ import { ClientCapabilities, Implementation, Tool, CallToolResult, CreateTaskResult, Task, ListTasksResult, Resource, ResourceTemplate, ReadResourceResult, Prompt, GetPromptResult, CompleteRequest, CompleteResult, ServerCapabilities } from '@modelcontextprotocol/sdk/types.js';
2
2
  import { McpFnServer, McpFnManifest } from '@mcpfn/core';
3
+ import { McpFnClient, McpFnClientMediatedHandlers, McpFnClientEventSink, McpFnDiagnosticSink, McpFnTarget, McpFnClientEventKind, McpFnTargetDescriptor, McpFnDiagnosticEvent } from '@mcpfn/client';
3
4
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
4
- export { MCPFN_OAUTH_EXTENSION_GRANTS, McpFnAuthAssertionError, McpFnAuthCredential, McpFnAuthCredentialKind, McpFnAuthCredentialRequest, McpFnAuthProbeScenario, McpFnAuthProviderAdapter, McpFnAuthProviderCapabilities, McpFnAuthRegressionOptions, McpFnAuthScenarioResult, McpFnAuthTarget, McpFnBearerChallenge, McpFnFetchAuthTargetOptions, McpFnMockOAuthAuthorizationServer, McpFnMockOAuthServerOptions, McpFnMockOAuthTokenSet, McpFnOAuthCallback, McpFnOAuthClientMetadata, McpFnOAuthClientMetadataFixtureOptions, McpFnOAuthClientMetadataVariants, McpFnPkcePair, McpFnStartMockOAuthServerOptions, McpFnStartedMockOAuthServer, apiKeyCredential, assertAuthRegressionSuite, assertAuthorizationCodeClientMetadata, assertBearerResourceChallenge, bearerCredential, createFetchAuthTarget, createOAuthClientMetadataFixture, createOAuthClientMetadataVariants, createPkcePair, parseBearerChallenge, runAuthRegressionSuite, startMockOAuthAuthorizationServer } from './auth.js';
5
+ import { RequestOptions } from '@modelcontextprotocol/sdk/shared/protocol.js';
6
+ export { MCPFN_NAMED_OAUTH_HOST_FIXTURES, MCPFN_OAUTH_EXTENSION_GRANTS, McpFnAuthAssertionError, McpFnAuthCredential, McpFnAuthCredentialKind, McpFnAuthCredentialRequest, McpFnAuthProbeScenario, McpFnAuthProviderAdapter, McpFnAuthProviderCapabilities, McpFnAuthRegressionOptions, McpFnAuthScenarioResult, McpFnAuthTarget, McpFnBearerChallenge, McpFnFetchAuthTargetOptions, McpFnMockOAuthAuthorizationServer, McpFnMockOAuthServerOptions, McpFnMockOAuthTokenSet, McpFnNamedOAuthHostFixture, McpFnOAuthCallback, McpFnOAuthClientMetadata, McpFnOAuthClientMetadataFixtureOptions, McpFnOAuthClientMetadataVariants, McpFnPkcePair, McpFnStartMockOAuthServerOptions, McpFnStartedMockOAuthServer, apiKeyCredential, assertAuthRegressionSuite, assertAuthorizationCodeClientMetadata, assertBearerResourceChallenge, bearerCredential, createFetchAuthTarget, createOAuthClientMetadataFixture, createOAuthClientMetadataVariants, createPkcePair, parseBearerChallenge, runAuthRegressionSuite, startMockOAuthAuthorizationServer } from './auth.js';
5
7
  import '@modelcontextprotocol/sdk/server/auth/types.js';
6
8
 
7
9
  interface McpFnTestClientOptions {
8
10
  capabilities?: ClientCapabilities;
11
+ handlers?: McpFnClientMediatedHandlers;
12
+ events?: McpFnClientEventSink;
9
13
  /** Install roots, sampling, elicitation, or notification handlers before initialize. */
10
14
  configure?(client: Client): void | Promise<void>;
15
+ diagnostics?: McpFnDiagnosticSink;
11
16
  }
12
17
  declare class McpFnTestClient<TContext = undefined> {
13
- readonly client: Client;
14
- private readonly server;
15
- private closed;
18
+ readonly session: McpFnClient;
16
19
  private constructor();
20
+ get client(): Client;
17
21
  static connect<TContext>(server: McpFnServer<TContext>, info?: {
18
22
  name: string;
19
23
  version: string;
20
24
  }, options?: McpFnTestClientOptions): Promise<McpFnTestClient<TContext>>;
21
- listTools(): Promise<Tool[]>;
22
- callTool(name: string, args?: Record<string, unknown>): Promise<CallToolResult>;
23
- createToolTask(name: string, args?: Record<string, unknown>, options?: {
25
+ static connectTarget<TContext = undefined>(target: McpFnTarget, info?: Implementation, options?: McpFnTestClientOptions): Promise<McpFnTestClient<TContext>>;
26
+ listTools(options?: RequestOptions): Promise<Tool[]>;
27
+ callTool(name: string, args?: Record<string, unknown>, options?: RequestOptions): Promise<CallToolResult>;
28
+ createToolTask(name: string, args?: Record<string, unknown>, task?: {
24
29
  ttl?: number;
25
- }): Promise<CreateTaskResult>;
26
- getTask(taskId: string): Promise<Task>;
27
- getTaskResult(taskId: string): Promise<CallToolResult>;
28
- listTasks(cursor?: string): Promise<ListTasksResult>;
29
- cancelTask(taskId: string): Promise<Task>;
30
- listResources(): Promise<Resource[]>;
31
- listResourceTemplates(): Promise<ResourceTemplate[]>;
32
- readResource(uri: string): Promise<ReadResourceResult>;
33
- subscribeResource(uri: string): Promise<void>;
34
- unsubscribeResource(uri: string): Promise<void>;
35
- listPrompts(): Promise<Prompt[]>;
36
- getPrompt(name: string, args?: Record<string, string>): Promise<GetPromptResult>;
37
- complete(params: CompleteRequest["params"]): Promise<CompleteResult>;
30
+ }, options?: RequestOptions): Promise<CreateTaskResult>;
31
+ getTask(taskId: string, options?: RequestOptions): Promise<Task>;
32
+ getTaskResult(taskId: string, options?: RequestOptions): Promise<CallToolResult>;
33
+ listTasks(cursor?: string, options?: RequestOptions): Promise<ListTasksResult>;
34
+ cancelTask(taskId: string, options?: RequestOptions): Promise<Task>;
35
+ listResources(options?: RequestOptions): Promise<Resource[]>;
36
+ listResourceTemplates(options?: RequestOptions): Promise<ResourceTemplate[]>;
37
+ readResource(uri: string, options?: RequestOptions): Promise<ReadResourceResult>;
38
+ subscribeResource(uri: string, options?: RequestOptions): Promise<void>;
39
+ unsubscribeResource(uri: string, options?: RequestOptions): Promise<void>;
40
+ listPrompts(options?: RequestOptions): Promise<Prompt[]>;
41
+ getPrompt(name: string, args?: Record<string, string>, options?: RequestOptions): Promise<GetPromptResult>;
42
+ complete(params: CompleteRequest["params"], options?: RequestOptions): Promise<CompleteResult>;
38
43
  close(): Promise<void>;
39
44
  }
40
45
 
@@ -69,8 +74,30 @@ interface OfficialConformanceResult {
69
74
  stdout: string;
70
75
  stderr: string;
71
76
  }
77
+ interface AuthenticatedConformanceProxy {
78
+ /** Loopback URL to pass to the official conformance runner. */
79
+ url: string;
80
+ close(): Promise<void>;
81
+ }
82
+ interface AuthenticatedConformanceProxyOptions {
83
+ /** Fixed loopback MCP URL. Requests cannot select a different origin or path. */
84
+ url: string;
85
+ /** Headers injected into requests using the proxy's own authority. Values are never logged. */
86
+ headers: HeadersInit;
87
+ }
88
+ interface AuthenticatedOfficialConformanceOptions extends OfficialConformanceOptions {
89
+ headers: HeadersInit;
90
+ }
91
+ /**
92
+ * Start a loopback-only streaming proxy for runners that cannot send auth
93
+ * headers. Authenticated requests use one fixed upstream authority and path.
94
+ * Host-manipulation probes are forwarded without injected credentials.
95
+ */
96
+ declare function createAuthenticatedConformanceProxy(options: AuthenticatedConformanceProxyOptions): Promise<AuthenticatedConformanceProxy>;
72
97
  declare function buildOfficialConformanceArgs(options: OfficialConformanceOptions): string[];
73
98
  declare function runOfficialConformance(options: OfficialConformanceOptions): Promise<OfficialConformanceResult>;
99
+ /** Run the pinned official suite against an authenticated MCP endpoint. */
100
+ declare function runAuthenticatedOfficialConformance(options: AuthenticatedOfficialConformanceOptions): Promise<OfficialConformanceResult>;
74
101
 
75
102
  type McpFnServerFeature = "tools" | "resources" | "prompts" | "completions" | "tasks" | "logging";
76
103
  interface McpFnHostProfile {
@@ -129,8 +156,20 @@ declare const MCPFN_HOST_PROFILES: {
129
156
  };
130
157
  declare function checkHostCompatibility(manifest: McpFnManifest, profile: McpFnHostProfile): McpFnHostCompatibilityResult;
131
158
 
132
- interface McpFnScenario {
159
+ type McpFnScenarioSideEffect = "none" | "idempotent" | "non-idempotent";
160
+ interface McpFnScenarioBase {
161
+ formatVersion?: 1;
133
162
  name: string;
163
+ /** Defaults to the runner timeout. */
164
+ timeoutMs?: number;
165
+ sideEffect?: McpFnScenarioSideEffect;
166
+ status?: "complete" | "incomplete";
167
+ incompleteReason?: string;
168
+ /** Environment-backed placeholders used by this scenario, never their values. */
169
+ variables?: string[];
170
+ }
171
+ interface McpFnToolScenario extends McpFnScenarioBase {
172
+ kind?: "tools.call";
134
173
  tool: string;
135
174
  arguments?: Record<string, unknown>;
136
175
  expect?: {
@@ -140,13 +179,190 @@ interface McpFnScenario {
140
179
  };
141
180
  verify?(result: CallToolResult): void | Promise<void>;
142
181
  }
182
+ interface McpFnInventoryScenario extends McpFnScenarioBase {
183
+ kind: "tools.list" | "resources.list" | "resources.templates.list" | "prompts.list";
184
+ expectNames?: string[];
185
+ }
186
+ interface McpFnResourceScenario extends McpFnScenarioBase {
187
+ kind: "resources.read" | "resources.subscribe" | "resources.unsubscribe";
188
+ uri: string;
189
+ expect?: unknown;
190
+ }
191
+ interface McpFnPromptScenario extends McpFnScenarioBase {
192
+ kind: "prompts.get";
193
+ prompt: string;
194
+ arguments?: Record<string, string>;
195
+ expect?: unknown;
196
+ }
197
+ interface McpFnInitializeScenario extends McpFnScenarioBase {
198
+ kind: "initialize";
199
+ expectCapabilities?: Record<string, unknown>;
200
+ }
201
+ interface McpFnCreateTaskScenario extends McpFnScenarioBase {
202
+ kind: "tools.call:task";
203
+ tool: string;
204
+ arguments?: Record<string, unknown>;
205
+ task?: {
206
+ ttl?: number;
207
+ };
208
+ expect?: unknown;
209
+ }
210
+ interface McpFnTaskScenario extends McpFnScenarioBase {
211
+ kind: "tasks.get" | "tasks.result" | "tasks.cancel" | "tasks.list";
212
+ taskId?: string;
213
+ cursor?: string;
214
+ expect?: unknown;
215
+ }
216
+ interface McpFnEventScenario extends McpFnScenarioBase {
217
+ kind: "events.expect";
218
+ event: McpFnClientEventKind;
219
+ minimum?: number;
220
+ expectPayload?: unknown;
221
+ }
222
+ interface McpFnAuthScenario extends McpFnScenarioBase {
223
+ kind: "auth.assert";
224
+ phase: string;
225
+ expect: {
226
+ outcome: "allowed" | "denied";
227
+ code?: string;
228
+ };
229
+ input?: Record<string, unknown>;
230
+ }
231
+ type McpFnScenario = McpFnToolScenario | McpFnInventoryScenario | McpFnResourceScenario | McpFnPromptScenario | McpFnInitializeScenario | McpFnCreateTaskScenario | McpFnTaskScenario | McpFnEventScenario | McpFnAuthScenario;
232
+ interface McpFnScenarioArtifact {
233
+ formatVersion: 1;
234
+ kind: "mcpfn.scenarios";
235
+ status: "complete" | "incomplete";
236
+ scenarios: McpFnScenario[];
237
+ variables?: string[];
238
+ incompleteReason?: string;
239
+ }
240
+ type McpFnRecordedOperation = {
241
+ kind: "tools.call";
242
+ name: string;
243
+ arguments?: Record<string, unknown>;
244
+ } | {
245
+ kind: "tools.call:task";
246
+ name: string;
247
+ arguments?: Record<string, unknown>;
248
+ task?: {
249
+ ttl?: number;
250
+ };
251
+ } | {
252
+ kind: "resources.read";
253
+ uri: string;
254
+ } | {
255
+ kind: "resources.subscribe";
256
+ uri: string;
257
+ } | {
258
+ kind: "resources.unsubscribe";
259
+ uri: string;
260
+ } | {
261
+ kind: "prompts.get";
262
+ name: string;
263
+ arguments?: Record<string, string>;
264
+ } | {
265
+ kind: "tasks.get";
266
+ taskId: string;
267
+ } | {
268
+ kind: "tasks.result";
269
+ taskId: string;
270
+ } | {
271
+ kind: "tasks.cancel";
272
+ taskId: string;
273
+ } | {
274
+ kind: "tasks.list";
275
+ cursor?: string;
276
+ };
277
+ type McpFnRecordedOperationResult = CallToolResult | ReadResourceResult | GetPromptResult | CreateTaskResult | Task | ListTasksResult | void;
143
278
  interface McpFnScenarioResult {
279
+ formatVersion: 1;
144
280
  name: string;
145
- tool: string;
146
- status: "passed" | "failed";
281
+ operation: string;
282
+ tool?: string;
283
+ status: "passed" | "failed" | "incomplete";
284
+ sideEffect: McpFnScenarioSideEffect;
147
285
  durationMs: number;
148
286
  error?: string;
287
+ /** Observed client events discarded while this scenario was running. */
288
+ droppedObservedEvents?: number;
289
+ }
290
+ interface McpFnScenarioReport {
291
+ formatVersion: 1;
292
+ kind: "mcpfn.scenario-report";
293
+ status: "complete" | "incomplete";
294
+ manifestHash?: string;
295
+ total: number;
296
+ passed: number;
297
+ failed: number;
298
+ incomplete: number;
299
+ droppedResults: number;
300
+ droppedObservedEvents: number;
301
+ incompleteReason?: string;
302
+ results: McpFnScenarioResult[];
303
+ }
304
+ /** Convert an observed production-client operation into the shared runner contract. */
305
+ declare function createMcpFnScenario(name: string, operation: McpFnRecordedOperation, result: McpFnRecordedOperationResult): McpFnScenario;
306
+ /** Validate an unknown scenario module before it reaches the shared runner. */
307
+ declare function validateMcpFnScenarios(value: unknown): McpFnScenario[];
308
+ declare function createMcpFnScenarioArtifact(scenarios: McpFnScenario[], options?: Omit<McpFnScenarioArtifact, "formatVersion" | "kind" | "scenarios">): McpFnScenarioArtifact;
309
+ declare function runScenarios(client: McpFnTestClient<unknown>, scenarios: McpFnScenario[], options?: McpFnScenarioRunOptions): Promise<McpFnScenarioResult[]>;
310
+ interface McpFnScenarioRunOptions {
311
+ defaultTimeoutMs?: number;
312
+ maxScenarios?: number;
313
+ maxErrorBytes?: number;
314
+ /** Observed client-event count cap. Defaults to 500. */
315
+ maxObservedEvents?: number;
316
+ variables?: Record<string, string | undefined>;
317
+ auth?(scenario: McpFnAuthScenario, signal: AbortSignal): Promise<{
318
+ outcome: "allowed" | "denied";
319
+ code?: string;
320
+ }>;
321
+ }
322
+ declare function createMcpFnScenarioReport(results: McpFnScenarioResult[], options?: {
323
+ manifestHash?: string;
324
+ maxBytes?: number;
325
+ }): McpFnScenarioReport;
326
+
327
+ interface RunMcpFnTargetSuiteOptions {
328
+ target: McpFnTarget;
329
+ scenarios?: McpFnScenario[];
330
+ manifest?: McpFnManifest;
331
+ expectedToolNames?: readonly string[];
332
+ clientInfo?: Implementation;
333
+ client?: McpFnTestClientOptions;
334
+ scenarioRun?: NonNullable<Parameters<typeof runScenarios>[2]>;
335
+ /** Aggregate JSON size cap. Defaults to 1 MiB. */
336
+ maxReportBytes?: number;
337
+ /** Diagnostic timeline count cap. Defaults to 500. */
338
+ maxTimelineEvents?: number;
339
+ }
340
+ interface McpFnTargetSuiteReport {
341
+ formatVersion: 1;
342
+ kind: "mcpfn.target-suite-report";
343
+ status: "complete" | "incomplete";
344
+ runtime: {
345
+ node: string;
346
+ scenarioFormatVersion: 1;
347
+ };
348
+ ok: boolean;
349
+ target: McpFnTargetDescriptor;
350
+ server?: Implementation;
351
+ capabilities?: ServerCapabilities;
352
+ manifestChecked: boolean;
353
+ manifestHash?: string;
354
+ total: number;
355
+ passed: number;
356
+ failed: number;
357
+ incomplete: number;
358
+ droppedResults: number;
359
+ droppedObservedEvents: number;
360
+ incompleteReason?: string;
361
+ timeline: McpFnDiagnosticEvent[];
362
+ droppedTimelineEvents: number;
363
+ results: McpFnScenarioResult[];
149
364
  }
150
- declare function runScenarios(client: McpFnTestClient<unknown>, scenarios: McpFnScenario[]): Promise<McpFnScenarioResult[]>;
365
+ /** Runs local, stdio, HTTP, or custom targets through the production session engine. */
366
+ declare function runMcpFnTargetSuite(options: RunMcpFnTargetSuiteOptions): Promise<McpFnTargetSuiteReport>;
151
367
 
152
- export { type AssertManifestContractOptions, MCPFN_HOST_PROFILES, McpFnAssertionError, type McpFnHostCompatibilityIssue, type McpFnHostCompatibilityResult, type McpFnHostProfile, type McpFnScenario, type McpFnScenarioResult, type McpFnServerFeature, McpFnTestClient, type McpFnTestClientOptions, OFFICIAL_CONFORMANCE_VERSION, type OfficialConformanceOptions, type OfficialConformanceResult, assertManifestContract, assertStructuredTextParity, buildOfficialConformanceArgs, checkHostCompatibility, runOfficialConformance, runScenarios, stableJson };
368
+ export { type AssertManifestContractOptions, type AuthenticatedConformanceProxy, type AuthenticatedConformanceProxyOptions, type AuthenticatedOfficialConformanceOptions, MCPFN_HOST_PROFILES, McpFnAssertionError, type McpFnAuthScenario, type McpFnCreateTaskScenario, type McpFnEventScenario, type McpFnHostCompatibilityIssue, type McpFnHostCompatibilityResult, type McpFnHostProfile, type McpFnInitializeScenario, type McpFnInventoryScenario, type McpFnPromptScenario, type McpFnRecordedOperation, type McpFnRecordedOperationResult, type McpFnResourceScenario, type McpFnScenario, type McpFnScenarioArtifact, type McpFnScenarioBase, type McpFnScenarioReport, type McpFnScenarioResult, type McpFnScenarioRunOptions, type McpFnScenarioSideEffect, type McpFnServerFeature, type McpFnTargetSuiteReport, type McpFnTaskScenario, McpFnTestClient, type McpFnTestClientOptions, type McpFnToolScenario, OFFICIAL_CONFORMANCE_VERSION, type OfficialConformanceOptions, type OfficialConformanceResult, type RunMcpFnTargetSuiteOptions, assertManifestContract, assertStructuredTextParity, buildOfficialConformanceArgs, checkHostCompatibility, createAuthenticatedConformanceProxy, createMcpFnScenario, createMcpFnScenarioArtifact, createMcpFnScenarioReport, runAuthenticatedOfficialConformance, runMcpFnTargetSuite, runOfficialConformance, runScenarios, stableJson, validateMcpFnScenarios };