codex-plugin-doctor 1.51.0 → 1.53.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 +17 -2
- package/dist/core/bounded-http-client.d.ts +23 -0
- package/dist/core/bounded-http-client.js +241 -0
- package/dist/core/doctor-export-bundle.js +3 -1
- package/dist/core/output-contract.js +50 -1
- package/dist/core/release-check.d.ts +4 -0
- package/dist/core/release-check.js +4 -0
- package/dist/core/release-evidence.d.ts +4 -0
- package/dist/core/release-evidence.js +113 -7
- package/dist/core/remote-mcp-probe.d.ts +17 -0
- package/dist/core/remote-mcp-probe.js +284 -0
- package/dist/core/remote-network-policy.d.ts +24 -0
- package/dist/core/remote-network-policy.js +125 -0
- package/dist/core/remote-oauth-readiness.d.ts +12 -0
- package/dist/core/remote-oauth-readiness.js +295 -0
- package/dist/core/remote-transport-reliability.d.ts +18 -0
- package/dist/core/remote-transport-reliability.js +243 -0
- package/dist/core/remote-url-policy.d.ts +7 -0
- package/dist/core/remote-url-policy.js +49 -0
- package/dist/core/runtime-plan.d.ts +3 -0
- package/dist/core/runtime-plan.js +34 -2
- package/dist/core/runtime-policy.js +5 -1
- package/dist/core/runtime-probe.d.ts +10 -1
- package/dist/core/runtime-probe.js +89 -29
- package/dist/core/sse-observation.d.ts +7 -0
- package/dist/core/sse-observation.js +67 -0
- package/dist/core/validate-plugin.js +35 -3
- package/dist/domain/types.d.ts +26 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/mcp/generic-mcp-doctor.d.ts +4 -0
- package/dist/mcp/generic-mcp-doctor.js +15 -5
- package/dist/reporting/render-markdown-report.js +38 -12
- package/dist/reporting/render-text-report.js +32 -10
- package/dist/rules/rule-catalog.js +289 -1
- package/dist/run-cli.js +172 -5
- package/dist/security/security-audit.js +34 -7
- package/package.json +1 -1
|
@@ -38,17 +38,39 @@ function appendRuntimeScorecard(lines, result) {
|
|
|
38
38
|
lines.push(`prompts/list: ${result.runtimeScorecard.promptsList}`);
|
|
39
39
|
lines.push(`prompts/get: ${result.runtimeScorecard.promptGet}`);
|
|
40
40
|
const conformance = result.runtimeScorecard.conformance;
|
|
41
|
-
if (
|
|
42
|
-
|
|
41
|
+
if (conformance) {
|
|
42
|
+
lines.push("", "MCP Conformance", "---------------");
|
|
43
|
+
lines.push(`Protocol version: ${conformance.protocolVersion ?? "unavailable"}`);
|
|
44
|
+
lines.push(`Profile: ${conformance.profile ?? "unavailable"}`);
|
|
45
|
+
lines.push(`Capability consistency: ${conformance.capabilityConsistency}`);
|
|
46
|
+
lines.push(`Task declarations: ${conformance.taskDeclarations}`);
|
|
47
|
+
lines.push(`Tasks list: ${conformance.tasksList}`);
|
|
48
|
+
lines.push(`Schema dialect: ${conformance.schemaDialect}`);
|
|
49
|
+
lines.push(`Overall: ${conformance.overall}`);
|
|
50
|
+
}
|
|
51
|
+
const remote = result.runtimeScorecard.remote;
|
|
52
|
+
if (remote) {
|
|
53
|
+
lines.push("", "Remote MCP Scorecard", "--------------------");
|
|
54
|
+
lines.push(`transport: ${remote.transport}`);
|
|
55
|
+
lines.push(`network safety: ${remote.networkSafety}`);
|
|
56
|
+
lines.push(`initialize: ${remote.initialize}`);
|
|
57
|
+
lines.push(`content type: ${remote.contentType}`);
|
|
58
|
+
lines.push(`session: ${remote.session}`);
|
|
59
|
+
lines.push(`protocol headers: ${remote.protocolHeaders}`);
|
|
60
|
+
lines.push(`authorization: ${remote.authorization}`);
|
|
61
|
+
lines.push(`overall: ${remote.overall}`);
|
|
62
|
+
if (remote.reliability) {
|
|
63
|
+
const reliability = remote.reliability;
|
|
64
|
+
lines.push("", "Remote Transport Reliability", "----------------------------");
|
|
65
|
+
lines.push(`GET SSE: ${reliability.getSse}`);
|
|
66
|
+
lines.push(`Session propagation: ${reliability.sessionPropagation}`);
|
|
67
|
+
lines.push(`Resumability: ${reliability.resumability}`);
|
|
68
|
+
lines.push(`Disconnect safety: ${reliability.disconnectSafety}`);
|
|
69
|
+
lines.push(`Session restart: ${reliability.sessionRestart}`);
|
|
70
|
+
lines.push(`Termination: ${reliability.termination}`);
|
|
71
|
+
lines.push(`Overall: ${reliability.overall}`);
|
|
72
|
+
}
|
|
43
73
|
}
|
|
44
|
-
lines.push("", "MCP Conformance", "---------------");
|
|
45
|
-
lines.push(`Protocol version: ${conformance.protocolVersion ?? "unavailable"}`);
|
|
46
|
-
lines.push(`Profile: ${conformance.profile ?? "unavailable"}`);
|
|
47
|
-
lines.push(`Capability consistency: ${conformance.capabilityConsistency}`);
|
|
48
|
-
lines.push(`Task declarations: ${conformance.taskDeclarations}`);
|
|
49
|
-
lines.push(`Tasks list: ${conformance.tasksList}`);
|
|
50
|
-
lines.push(`Schema dialect: ${conformance.schemaDialect}`);
|
|
51
|
-
lines.push(`Overall: ${conformance.overall}`);
|
|
52
74
|
}
|
|
53
75
|
export function renderTextReport(result, options = {}) {
|
|
54
76
|
const ascii = options.ascii ?? false;
|
|
@@ -161,6 +161,24 @@ export const ruleCatalog = [
|
|
|
161
161
|
fix: "Add `command` for stdio servers or `url` for remote servers.",
|
|
162
162
|
example: '{ "command": "node", "args": ["server.js"] }'
|
|
163
163
|
},
|
|
164
|
+
{
|
|
165
|
+
id: "mcp.server.transport.conflict",
|
|
166
|
+
category: "mcp",
|
|
167
|
+
defaultSeverity: "fail",
|
|
168
|
+
summary: "An MCP server defines both command and URL transports.",
|
|
169
|
+
why: "Clients cannot select a transport deterministically when a server defines both process and remote connection settings.",
|
|
170
|
+
fix: "Keep either command for stdio or url for remote MCP, but not both.",
|
|
171
|
+
example: '{ "url": "https://example.com/mcp" }'
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
id: "plugin.mcp.server.transport.conflict",
|
|
175
|
+
category: "mcp",
|
|
176
|
+
defaultSeverity: "fail",
|
|
177
|
+
summary: "A bundled MCP server defines both command and URL transports.",
|
|
178
|
+
why: "Codex cannot select a transport deterministically when a bundled server defines both process and remote connection settings.",
|
|
179
|
+
fix: "Keep either command for stdio or url for remote MCP, but not both.",
|
|
180
|
+
example: '{ "url": "https://example.com/mcp" }'
|
|
181
|
+
},
|
|
164
182
|
{
|
|
165
183
|
id: "plugin.security.path_traversal",
|
|
166
184
|
category: "security",
|
|
@@ -245,12 +263,66 @@ export const ruleCatalog = [
|
|
|
245
263
|
{
|
|
246
264
|
id: "plugin.security.insecure_http_url",
|
|
247
265
|
category: "security",
|
|
248
|
-
defaultSeverity: "
|
|
266
|
+
defaultSeverity: "fail",
|
|
249
267
|
summary: "An MCP server uses a plain HTTP URL.",
|
|
250
268
|
why: "Plain HTTP can expose MCP traffic and does not verify endpoint identity on non-local networks.",
|
|
251
269
|
fix: "Use HTTPS for remote MCP servers; reserve HTTP for explicit localhost development endpoints.",
|
|
252
270
|
example: '{ "url": "https://example.com/mcp" }'
|
|
253
271
|
},
|
|
272
|
+
{
|
|
273
|
+
id: "plugin.security.remote_mcp_url.invalid",
|
|
274
|
+
category: "security",
|
|
275
|
+
defaultSeverity: "fail",
|
|
276
|
+
summary: "An MCP server URL is not an absolute HTTP or HTTPS URL.",
|
|
277
|
+
why: "Clients cannot reliably connect to malformed or relative remote MCP endpoints.",
|
|
278
|
+
fix: "Use an absolute HTTPS URL, or an explicit localhost HTTP development URL.",
|
|
279
|
+
example: '{ "url": "https://example.com/mcp" }'
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
id: "plugin.security.remote_mcp_url.unsupported_scheme",
|
|
283
|
+
category: "security",
|
|
284
|
+
defaultSeverity: "fail",
|
|
285
|
+
summary: "An MCP server URL uses an unsupported scheme.",
|
|
286
|
+
why: "Remote MCP transport supports only HTTP and HTTPS endpoints.",
|
|
287
|
+
fix: "Use an HTTPS URL, or an explicit localhost HTTP development URL.",
|
|
288
|
+
example: '{ "url": "https://example.com/mcp" }'
|
|
289
|
+
},
|
|
290
|
+
{
|
|
291
|
+
id: "plugin.security.remote_mcp_url.credentials",
|
|
292
|
+
category: "security",
|
|
293
|
+
defaultSeverity: "fail",
|
|
294
|
+
summary: "An MCP server URL embeds credentials.",
|
|
295
|
+
why: "URL credentials can leak through configuration, logs, reports, and package artifacts.",
|
|
296
|
+
fix: "Remove URL credentials and configure authentication outside the endpoint URL.",
|
|
297
|
+
example: '{ "url": "https://example.com/mcp" }'
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
id: "plugin.security.remote_mcp_url.query",
|
|
301
|
+
category: "security",
|
|
302
|
+
defaultSeverity: "fail",
|
|
303
|
+
summary: "An MCP server URL contains a query string.",
|
|
304
|
+
why: "Query strings can carry secrets and make endpoint configuration ambiguous.",
|
|
305
|
+
fix: "Remove the query string from the MCP endpoint URL.",
|
|
306
|
+
example: '{ "url": "https://example.com/mcp" }'
|
|
307
|
+
},
|
|
308
|
+
{
|
|
309
|
+
id: "plugin.security.remote_mcp_url.fragment",
|
|
310
|
+
category: "security",
|
|
311
|
+
defaultSeverity: "fail",
|
|
312
|
+
summary: "An MCP server URL contains a fragment.",
|
|
313
|
+
why: "Fragments are not sent to servers and can hide misleading endpoint configuration.",
|
|
314
|
+
fix: "Remove the fragment from the MCP endpoint URL.",
|
|
315
|
+
example: '{ "url": "https://example.com/mcp" }'
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
id: "plugin.security.remote_mcp_url.ip_literal",
|
|
319
|
+
category: "security",
|
|
320
|
+
defaultSeverity: "fail",
|
|
321
|
+
summary: "An MCP server URL uses a numeric IP literal.",
|
|
322
|
+
why: "Numeric IP endpoints bypass hostname-based endpoint review and are not an accepted remote MCP shape.",
|
|
323
|
+
fix: "Use a reviewed hostname; use localhost only for local development.",
|
|
324
|
+
example: '{ "url": "https://example.com/mcp" }'
|
|
325
|
+
},
|
|
254
326
|
{
|
|
255
327
|
id: "plugin.security.mcp_binds_all_interfaces",
|
|
256
328
|
category: "security",
|
|
@@ -376,6 +448,222 @@ export const ruleCatalog = [
|
|
|
376
448
|
why: "MCP stdio transport requires newline-delimited JSON-RPC messages on stdout.",
|
|
377
449
|
fix: "Send logs to stderr and reserve stdout for JSON-RPC protocol messages only.",
|
|
378
450
|
example: "Use `console.error` for diagnostics in Node stdio servers."
|
|
451
|
+
},
|
|
452
|
+
{
|
|
453
|
+
id: "plugin.runtime.remote.network_not_approved",
|
|
454
|
+
category: "runtime",
|
|
455
|
+
defaultSeverity: "fail",
|
|
456
|
+
summary: "Remote MCP probing was not explicitly approved.",
|
|
457
|
+
why: "Remote initialization creates outbound network traffic.",
|
|
458
|
+
fix: "Review the plan, then use --runtime --allow-network; add --allow-local-network only for localhost HTTP.",
|
|
459
|
+
example: "codex-plugin-doctor mcp . --runtime --allow-network"
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
id: "plugin.runtime.remote.url.invalid",
|
|
463
|
+
category: "runtime",
|
|
464
|
+
defaultSeverity: "fail",
|
|
465
|
+
summary: "A remote MCP endpoint URL is unsafe or unsupported.",
|
|
466
|
+
why: "Credentials, queries, fragments, IP literals, and unsupported schemes bypass the remote probe boundary.",
|
|
467
|
+
fix: "Use an absolute HTTPS URL without credentials, query parameters, fragments, or IP literals.",
|
|
468
|
+
example: "https://mcp.example/mcp"
|
|
469
|
+
},
|
|
470
|
+
{
|
|
471
|
+
id: "plugin.runtime.remote.transport.timeout",
|
|
472
|
+
category: "runtime",
|
|
473
|
+
defaultSeverity: "fail",
|
|
474
|
+
summary: "The remote MCP initialize request timed out.",
|
|
475
|
+
why: "A bounded probe cannot safely negotiate an unavailable endpoint.",
|
|
476
|
+
fix: "Make the endpoint reachable and complete initialize within the configured timeout.",
|
|
477
|
+
example: "Return a valid initialize response promptly."
|
|
478
|
+
},
|
|
479
|
+
{
|
|
480
|
+
id: "plugin.runtime.remote.transport.response_too_large",
|
|
481
|
+
category: "runtime",
|
|
482
|
+
defaultSeverity: "fail",
|
|
483
|
+
summary: "The remote MCP response exceeded the bounded probe limit.",
|
|
484
|
+
why: "Unbounded remote responses can exhaust local resources.",
|
|
485
|
+
fix: "Return a compact initialize response and keep discovery metadata bounded.",
|
|
486
|
+
example: "Return only the MCP initialize result."
|
|
487
|
+
},
|
|
488
|
+
{
|
|
489
|
+
id: "plugin.runtime.remote.transport.failed",
|
|
490
|
+
category: "runtime",
|
|
491
|
+
defaultSeverity: "fail",
|
|
492
|
+
summary: "The remote MCP transport request failed.",
|
|
493
|
+
why: "Protocol negotiation cannot proceed without a safe bounded connection.",
|
|
494
|
+
fix: "Verify endpoint reachability, TLS, and remote network policy eligibility.",
|
|
495
|
+
example: "Use a public HTTPS endpoint or explicitly approved localhost HTTP."
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
id: "plugin.runtime.remote.http_status.invalid",
|
|
499
|
+
category: "runtime",
|
|
500
|
+
defaultSeverity: "fail",
|
|
501
|
+
summary: "The remote MCP initialize response used an unexpected HTTP status.",
|
|
502
|
+
why: "Streamable HTTP initialization requires a successful response before negotiation.",
|
|
503
|
+
fix: "Return HTTP 200 for initialize or publish valid OAuth discovery metadata for protected endpoints.",
|
|
504
|
+
example: "HTTP/1.1 200 OK"
|
|
505
|
+
},
|
|
506
|
+
{
|
|
507
|
+
id: "plugin.runtime.remote.content_type.invalid",
|
|
508
|
+
category: "runtime",
|
|
509
|
+
defaultSeverity: "fail",
|
|
510
|
+
summary: "The remote MCP initialize response used an unsupported content type.",
|
|
511
|
+
why: "The probe can only validate JSON or Server-Sent Events protocol responses.",
|
|
512
|
+
fix: "Return application/json or text/event-stream with a JSON-RPC response.",
|
|
513
|
+
example: "Content-Type: application/json"
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
id: "plugin.runtime.remote.session.invalid",
|
|
517
|
+
category: "runtime",
|
|
518
|
+
defaultSeverity: "fail",
|
|
519
|
+
summary: "The remote MCP session header is invalid.",
|
|
520
|
+
why: "An invalid session identifier cannot be safely replayed on the initialized notification.",
|
|
521
|
+
fix: "Return MCP-Session-Id only as visible ASCII characters.",
|
|
522
|
+
example: "MCP-Session-Id: session-123"
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
id: "plugin.runtime.remote.initialize.invalid",
|
|
526
|
+
category: "runtime",
|
|
527
|
+
defaultSeverity: "fail",
|
|
528
|
+
summary: "The remote MCP initialize JSON-RPC result is invalid.",
|
|
529
|
+
why: "Invalid negotiation results leave capabilities and protocol version unknown.",
|
|
530
|
+
fix: "Return a JSON-RPC 2.0 initialize result for protocol version 2025-11-25.",
|
|
531
|
+
example: '{ "jsonrpc": "2.0", "id": 1, "result": { "protocolVersion": "2025-11-25" } }'
|
|
532
|
+
},
|
|
533
|
+
{
|
|
534
|
+
id: "plugin.runtime.remote.initialized.failed",
|
|
535
|
+
category: "runtime",
|
|
536
|
+
defaultSeverity: "fail",
|
|
537
|
+
summary: "The remote MCP server did not acknowledge notifications/initialized.",
|
|
538
|
+
why: "The session may not be ready for subsequent protocol traffic.",
|
|
539
|
+
fix: "Accept a successful initialized notification at the configured MCP endpoint.",
|
|
540
|
+
example: "Return HTTP 204 to notifications/initialized."
|
|
541
|
+
},
|
|
542
|
+
{
|
|
543
|
+
id: "plugin.runtime.remote.authorization.metadata.invalid",
|
|
544
|
+
category: "runtime",
|
|
545
|
+
defaultSeverity: "fail",
|
|
546
|
+
summary: "Remote OAuth discovery metadata is invalid.",
|
|
547
|
+
why: "Protected MCP endpoints cannot be assessed safely without valid authorization metadata.",
|
|
548
|
+
fix: "Publish valid HTTPS protected-resource and authorization-server metadata.",
|
|
549
|
+
example: "https://mcp.example/.well-known/oauth-protected-resource"
|
|
550
|
+
},
|
|
551
|
+
{
|
|
552
|
+
id: "plugin.runtime.remote.authorization.metadata.unavailable",
|
|
553
|
+
category: "runtime",
|
|
554
|
+
defaultSeverity: "fail",
|
|
555
|
+
summary: "Remote OAuth discovery metadata is unavailable.",
|
|
556
|
+
why: "Authorization readiness cannot be confirmed without bounded metadata responses.",
|
|
557
|
+
fix: "Make protected-resource and authorization-server metadata available over HTTPS.",
|
|
558
|
+
example: "Return application/json discovery metadata."
|
|
559
|
+
},
|
|
560
|
+
{
|
|
561
|
+
id: "plugin.runtime.remote.reliability.get.status",
|
|
562
|
+
category: "runtime",
|
|
563
|
+
defaultSeverity: "fail",
|
|
564
|
+
summary: "The remote MCP endpoint rejected the SSE transport request.",
|
|
565
|
+
why: "Clients cannot rely on server-to-client streaming when an accepted SSE request does not return the expected status.",
|
|
566
|
+
fix: "Return HTTP 200 with a valid SSE response, or HTTP 405 when GET streaming is not supported.",
|
|
567
|
+
example: "HTTP/1.1 405 Method Not Allowed"
|
|
568
|
+
},
|
|
569
|
+
{
|
|
570
|
+
id: "plugin.runtime.remote.reliability.get.content_type",
|
|
571
|
+
category: "runtime",
|
|
572
|
+
defaultSeverity: "fail",
|
|
573
|
+
summary: "The remote MCP endpoint returned a non-SSE media type for GET streaming.",
|
|
574
|
+
why: "Clients cannot interpret a successful streaming response unless it is declared as Server-Sent Events.",
|
|
575
|
+
fix: "Return Content-Type: text/event-stream for accepted GET streaming requests.",
|
|
576
|
+
example: "Content-Type: text/event-stream"
|
|
577
|
+
},
|
|
578
|
+
{
|
|
579
|
+
id: "plugin.runtime.remote.reliability.get.inconclusive",
|
|
580
|
+
category: "runtime",
|
|
581
|
+
defaultSeverity: "warn",
|
|
582
|
+
summary: "The remote MCP GET streaming check was inconclusive.",
|
|
583
|
+
why: "A bounded probe could not observe a complete SSE event, so streaming reliability remains uncertain.",
|
|
584
|
+
fix: "Emit complete SSE event frames promptly when server-to-client streaming is supported.",
|
|
585
|
+
example: "id: event-1\n\ndata: {}\n\n"
|
|
586
|
+
},
|
|
587
|
+
{
|
|
588
|
+
id: "plugin.runtime.remote.reliability.get.failed",
|
|
589
|
+
category: "runtime",
|
|
590
|
+
defaultSeverity: "fail",
|
|
591
|
+
summary: "The remote MCP GET streaming request could not be completed.",
|
|
592
|
+
why: "Clients cannot rely on server-to-client streaming when a bounded transport request fails.",
|
|
593
|
+
fix: "Keep the Streamable HTTP transport reachable within the configured request bounds.",
|
|
594
|
+
example: "Complete the GET request before the runtime timeout."
|
|
595
|
+
},
|
|
596
|
+
{
|
|
597
|
+
id: "plugin.runtime.remote.reliability.get.malformed",
|
|
598
|
+
category: "runtime",
|
|
599
|
+
defaultSeverity: "fail",
|
|
600
|
+
summary: "The remote MCP endpoint emitted malformed SSE framing.",
|
|
601
|
+
why: "Malformed event framing prevents clients from safely processing stream progress or reconnecting.",
|
|
602
|
+
fix: "Return complete SSE events with valid id and retry fields.",
|
|
603
|
+
example: "id: event-1\n\nevent: message\n\ndata: {}\n\n"
|
|
604
|
+
},
|
|
605
|
+
{
|
|
606
|
+
id: "plugin.runtime.remote.reliability.resume.status",
|
|
607
|
+
category: "runtime",
|
|
608
|
+
defaultSeverity: "fail",
|
|
609
|
+
summary: "The remote MCP endpoint rejected the SSE resume request.",
|
|
610
|
+
why: "Clients cannot resume a dropped stream when the reconnect response has an unexpected status.",
|
|
611
|
+
fix: "Return HTTP 200 for an accepted Last-Event-ID reconnect request.",
|
|
612
|
+
example: "HTTP/1.1 200 OK"
|
|
613
|
+
},
|
|
614
|
+
{
|
|
615
|
+
id: "plugin.runtime.remote.reliability.resume.content_type",
|
|
616
|
+
category: "runtime",
|
|
617
|
+
defaultSeverity: "fail",
|
|
618
|
+
summary: "The remote MCP endpoint returned a non-SSE media type for a resume request.",
|
|
619
|
+
why: "Clients cannot process a resumed stream unless it is declared as Server-Sent Events.",
|
|
620
|
+
fix: "Return Content-Type: text/event-stream after accepting a Last-Event-ID reconnect request.",
|
|
621
|
+
example: "Content-Type: text/event-stream"
|
|
622
|
+
},
|
|
623
|
+
{
|
|
624
|
+
id: "plugin.runtime.remote.reliability.resume.inconclusive",
|
|
625
|
+
category: "runtime",
|
|
626
|
+
defaultSeverity: "warn",
|
|
627
|
+
summary: "The remote MCP SSE resume check was inconclusive.",
|
|
628
|
+
why: "A bounded probe could not confirm a complete resumed event, so reconnect reliability remains uncertain.",
|
|
629
|
+
fix: "Emit complete SSE event frames after accepting a reconnect.",
|
|
630
|
+
example: "Return one complete SSE event after a Last-Event-ID request."
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
id: "plugin.runtime.remote.reliability.resume.failed",
|
|
634
|
+
category: "runtime",
|
|
635
|
+
defaultSeverity: "fail",
|
|
636
|
+
summary: "The remote MCP SSE resume request could not be completed.",
|
|
637
|
+
why: "Clients cannot recover from a dropped stream when a bounded reconnect fails.",
|
|
638
|
+
fix: "Accept one bounded SSE reconnect using Last-Event-ID.",
|
|
639
|
+
example: "Honor the Last-Event-ID header on one reconnect."
|
|
640
|
+
},
|
|
641
|
+
{
|
|
642
|
+
id: "plugin.runtime.remote.reliability.resume.malformed",
|
|
643
|
+
category: "runtime",
|
|
644
|
+
defaultSeverity: "fail",
|
|
645
|
+
summary: "The remote MCP endpoint emitted malformed SSE framing after reconnecting.",
|
|
646
|
+
why: "Malformed resumed events prevent clients from safely continuing stream processing.",
|
|
647
|
+
fix: "Return complete SSE events with valid id and retry fields after reconnecting.",
|
|
648
|
+
example: "Return a complete event frame after reconnecting."
|
|
649
|
+
},
|
|
650
|
+
{
|
|
651
|
+
id: "plugin.runtime.remote.reliability.session_restart.failed",
|
|
652
|
+
category: "runtime",
|
|
653
|
+
defaultSeverity: "fail",
|
|
654
|
+
summary: "The remote MCP session could not be restarted.",
|
|
655
|
+
why: "Clients cannot recover from an expired MCP session when a fresh initialization sequence fails.",
|
|
656
|
+
fix: "Accept a fresh initialize sequence after an expired MCP session.",
|
|
657
|
+
example: "Return a valid initialize response after HTTP 404 for a session-bound request."
|
|
658
|
+
},
|
|
659
|
+
{
|
|
660
|
+
id: "plugin.runtime.remote.reliability.termination.failed",
|
|
661
|
+
category: "runtime",
|
|
662
|
+
defaultSeverity: "fail",
|
|
663
|
+
summary: "The remote MCP session could not be terminated.",
|
|
664
|
+
why: "A server that advertises session lifecycle support must safely handle the approved termination request.",
|
|
665
|
+
fix: "Return a successful response or HTTP 405 for a bounded MCP session DELETE request.",
|
|
666
|
+
example: "HTTP/1.1 204 No Content"
|
|
379
667
|
}
|
|
380
668
|
];
|
|
381
669
|
export function findRuleDefinition(id) {
|