Skip to content

feat(mcp): stateless transport shim — Slice B-1 (#1511) - #1518

Closed
Lexus2016 wants to merge 1 commit into
mainfrom
evolution/issue-1511-mcp-stateless-b1
Closed

feat(mcp): stateless transport shim — Slice B-1 (#1511)#1518
Lexus2016 wants to merge 1 commit into
mainfrom
evolution/issue-1511-mcp-stateless-b1

Conversation

@Lexus2016

Copy link
Copy Markdown
Owner

Summary

Implements Slice B-1 of the MCP 2026-07-28 stateless transport migration (issue #1511, parent #1287).

Changes

  • HERMES_MCP_STATELESS env flag — default OFF, zero behavioral change unless enabled
  • _detect_stateless_support(config) — reads env flag + per-server stateless: true config key; both must be truthy
  • synthesize_capabilities() — constructs an InitializeResult-shaped SimpleNamespace with all three capability families (tools, resources, prompts) so existing capability gates work without a live session
  • _initialize_or_synthesize() — helper method on MCPServerTask that skips session.initialize() in stateless mode and returns synthesized caps; delegates to the real handshake otherwise
  • All 4 transport call sites wired — stdio, SSE, streamable_http new API, streamablehttp deprecated API

Design

  • Feature flag defaults OFF → no behavioral change for any existing deployment
  • Per-server opt-in via stateless: true in config.yaml (requires global env flag too)
  • Synthesized caps object is permissive (all capabilities ON) — a future slice may probe .well-known/mcp to narrow the set
  • Existing capability gates (_advertises_tools(), _select_utility_schemas()) are capability-source-agnostic and work unchanged with synthesized caps

Test plan

  • 14 unit tests (tests/tools/test_mcp_stateless_b1.py) — all pass
  • Tests cover: env flag gating, per-server config opt-in/out, synthesized caps shape, _initialize_or_synthesize() both paths
  • No existing MCP tests broken (flag defaults OFF)

Scope

This is Slice B-1 only. B-2 (stateless RPC adapter, header injection, per-call sessions) and B-3 (mock tests) are separate issues (#1512, #1513).

Closes #1511

Add HERMES_MCP_STATELESS env flag (default OFF), _detect_stateless_support(),
synthesize_capabilities(), and _initialize_or_synthesize() helper that
skips session.initialize() in stateless mode and synthesizes an
InitializeResult-shaped object so existing capability gates keep working.

All 4 transport call sites (stdio, SSE, streamable_http new, streamablehttp
deprecated) are wired through the helper. Zero behavioral change unless
HERMES_MCP_STATELESS=1 is set AND per-server config has stateless: true.

Closes #1511
@github-actions github-actions Bot added bug Something isn't working security labels Jul 30, 2026
@Lexus2016

Copy link
Copy Markdown
Owner Author

Superseded by #1519 (newer implementation of the same issue #1511 — MCP stateless B-1). #1519 is cleaner (methods on MCPServerTask vs module-level functions) and #1518 has a spurious deletion of 'return reason' at the SSE reconnect path. Closing this duplicate to avoid confusion.

@Lexus2016 Lexus2016 closed this Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working security

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[MCP Stateless] Slice B-1: Capability-detection flag + synthesize_capabilities()

1 participant