Skip to content

fix(oni-mcp): preserve legacy routing over future request metadata - #40

Merged
LIghtJUNction merged 3 commits into
mainfrom
agent/onimcp-legacy-routing-precedence
Sep 15, 2026
Merged

LIghtJUNction merged 3 commits into
mainfrom
agent/onimcp-legacy-routing-precedence

Conversation

@LIghtJUNction

@LIghtJUNction LIghtJUNction commented Sep 15, 2026 •

Copy link
Copy Markdown
Owner

Root cause / external basis

Official MCP C# SDK PR modelcontextprotocol/csharp-sdk#1852 (merged 2026-09-13, commit 324ccd83c357acf611e1cf3a6935a945ee600442) fixes a P1 interoperability problem where ChatGPT negotiated the legacy 2025-11-25 era but later sent reserved _meta fields introduced by 2026-07-28. The SDK now treats an established legacy session or an explicit supported legacy transport version as authoritative; future reserved metadata stays opaque and must not silently switch the request into the modern era.

OniMcp's TryHandleModernPost previously selected the modern path when either the HTTP protocol header or body _meta.io.modelcontextprotocol/protocolVersion was 2026-07-28. That could divert a valid legacy-session request into modern header validation and return -32020 HeaderMismatch.

Design

  • Explicit supported legacy Mcp-Protocol-Version values stay on the existing initialize/session path even if the body carries future metadata.
  • An established legacy Mcp-Session-Id stays on the legacy path when there is no explicit modern transport header.
  • An explicit 2026-07-28 header still wins over a legacy session id; this avoids accidental downgrade of an authoritatively modern request.
  • Headerless body metadata can still select modern handling, where the existing strict modern header validation remains unchanged.
  • No legacy capabilities/session state are populated from future _meta.

Files

  • mods/OniMcp/Server/McpHttpServerModernProtocol.cs
  • tests/OniMcp.ModernProtocol.Tests/Program.cs

Regression coverage

Raw HTTP tests now cover:

  1. legacy initialize followed by tools/list with explicit 2025-11-25 plus future 2026 _meta => remains legacy and succeeds;
  2. established legacy session with no protocol header plus future 2026 _meta => remains legacy and succeeds;
  3. explicit 2026-07-28 plus a legacy session id => remains modern and returns the expected modern tools/list method-not-found result;
  4. headerless request with 2026 metadata still reaches modern validation and returns -32020 for the missing modern protocol header;
  5. existing SEP-2164 modern resource-not-found regression remains covered.

Compatibility / risk

This is transport routing only. It does not change game state, tools, world-editor behavior, save data, Tasks, or the modern capability advertisement. Legacy 2025-11-25 / 2025-06-18 behavior is preserved; strict modern validation is preserved once the request is authoritatively modern.

No actual ONI runtime is required to validate the routing logic, but the pinned ONI reference build should still compile this change before merge.

Refs #24

Sourcery 摘要

在混合时代的请求元数据中,保留权威的旧版和现代 MCP 传输路由。

错误修复:

  • 当请求包含未来预留元数据时,为受支持的旧版协议标头和已建立的旧版会话保留旧版 MCP 路由。
  • 即使请求包含旧版会话标识符,也让明确指定的现代请求继续使用现代路径。

增强功能:

  • 保留基于现代元数据的路由,以及对无标头现代请求严格执行的缺失标头验证。
  • 扩展原始 HTTP 回归测试,覆盖混合时代路由、会话保留、明确的现代路由优先级以及现有资源错误。

测试:

  • 添加线级测试,验证存在未来请求元数据时旧版和现代协议的优先级。
Original summary in English

Summary by Sourcery

Preserve authoritative legacy and modern MCP transport routing across mixed-era request metadata.

Bug Fixes:

  • Preserve legacy MCP routing for supported legacy protocol headers and established legacy sessions when requests include future reserved metadata.
  • Keep explicitly modern requests on the modern path even when they include a legacy session identifier.

Enhancements:

  • Retain modern metadata-based routing and strict missing-header validation for headerless modern requests.
  • Expand raw HTTP regression coverage for mixed-era routing, session preservation, explicit modern precedence, and existing resource errors.

Tests:

  • Add wire-level coverage for legacy and modern protocol precedence when future request metadata is present.

Copilot AI lite review requested due to automatic review settings September 15, 2026 01:27
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @LIghtJUNction, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 3 days and 5 hours by commenting @sourcery-ai review. Upgrade to get a review now.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
🔒 Security Review ✅ Completed 2026-09-15T01:31:48.381317Z bddc39e PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@sourcery-ai

sourcery-ai Bot commented Sep 15, 2026

Copy link
Copy Markdown

审查者指南

更新现代 POST 路由逻辑:将受支持的旧版标头和已建立的旧版会话视为高于未来预留元数据的权威来源,同时允许显式现代标头优先,并保留无标头现代验证。新增覆盖两种兼容方向的线路级回归测试,并确认不会意外更改旧版会话状态。

保留旧版行为的 MCP POST 路由流程图

flowchart TD
    A[HTTP POST request] --> B[TryHandleModernPost]
    B --> C{IsSupportedProtocolVersion protocolVersion}
    C -->|yes| L[Legacy initialize or session path]
    C -->|no| D{explicitModern header}
    D -->|no| E{IsSessionActive sessionId}
    E -->|yes| L
    E -->|no| F{modern metadata signal}
    D -->|yes| M[Modern handling]
    F -->|yes| M
    F -->|no| N[Request not handled as modern]
    M --> O[Strict modern header validation]
Loading

文件级变更

变更 详细信息 文件
在检测现代元数据之前,优先进行权威的旧版路由。
  • 将受支持的旧版协议标头直接路由到现有的旧版路径。
  • 除非存在显式现代标头,否则继续使用旧版处理活动的旧版会话。
  • 允许显式现代标头覆盖旧版会话,同时保留基于无标头元数据的现代选择和严格验证。
mods/OniMcp/Server/McpHttpServerModernProtocol.cs
新增原始 HTTP 回归测试,覆盖混合时代路由,并保留现有的现代行为检查。
  • 验证未来元数据不会将显式或基于会话的旧版请求转走。
  • 验证即使存在旧版会话,显式现代标头仍会使用现代处理。
  • 验证无标头现代元数据仍会产生缺少标头的验证错误,并且旧版会话归属保持不变。
  • 保留 SEP-2164 资源未找到回归测试,同时将请求辅助函数扩展为支持可选标头。
tests/OniMcp.ModernProtocol.Tests/Program.cs

可能相关的问题


提示和命令

与 Sourcery 交互

  • 触发新的审查: 在拉取请求中评论 @sourcery-ai review。
  • 继续讨论: 直接回复 Sourcery 的审查评论。
  • 根据审查评论生成 GitHub issue: 回复审查评论,请 Sourcery 根据该评论创建 issue。你也可以使用 @sourcery-ai issue 回复审查评论,以根据该评论创建 issue。
  • 生成拉取请求标题: 在拉取请求标题的任意位置写入 @sourcery-ai,即可随时生成标题。你也可以在拉取请求中评论 @sourcery-ai title,以随时(重新)生成标题。
  • 生成拉取请求摘要: 在拉取请求正文的任意位置写入 @sourcery-ai summary,即可在指定位置随时生成 PR 摘要。你也可以在拉取请求中评论 @sourcery-ai summary,以随时(重新)生成摘要。
  • 生成审查者指南: 在拉取请求中评论 @sourcery-ai guide,即可随时(重新)生成审查者指南。
  • 解决所有 Sourcery 评论: 在拉取请求中评论 @sourcery-ai resolve,即可解决所有 Sourcery 评论。如果你已经处理完所有评论且不想再看到它们,此功能会很有用。
  • 忽略所有 Sourcery 审查: 在拉取请求中评论 @sourcery-ai dismiss,即可忽略所有现有的 Sourcery 审查。如果你希望从新的审查开始,这尤其有用——别忘了评论 @sourcery-ai review 来触发新的审查!

自定义使用体验

访问你的控制面板以:

  • 启用或禁用审查功能,例如 Sourcery 生成的拉取请求摘要、审查者指南等。
  • 更改审查语言。
  • 添加、删除或编辑自定义审查说明。
  • 调整其他审查设置。

获取帮助

Original review guide in English

Reviewer's Guide

Updates modern POST routing to treat supported legacy headers and established legacy sessions as authoritative over future reserved metadata, while allowing explicit modern headers to win and preserving headerless modern validation. Adds wire-level regressions covering both compatibility directions and confirms no unintended legacy session state changes.

Flow diagram for legacy-preserving MCP POST routing

flowchart TD
    A[HTTP POST request] --> B[TryHandleModernPost]
    B --> C{IsSupportedProtocolVersion protocolVersion}
    C -->|yes| L[Legacy initialize or session path]
    C -->|no| D{explicitModern header}
    D -->|no| E{IsSessionActive sessionId}
    E -->|yes| L
    E -->|no| F{modern metadata signal}
    D -->|yes| M[Modern handling]
    F -->|yes| M
    F -->|no| N[Request not handled as modern]
    M --> O[Strict modern header validation]
Loading

File-Level Changes

Change Details Files
Prioritize authoritative legacy routing before modern metadata detection.
  • Route supported legacy protocol headers directly to the existing legacy path.
  • Keep active legacy sessions on legacy handling unless an explicit modern header is present.
  • Allow an explicit modern header to override a legacy session, while preserving headerless metadata-based modern selection and strict validation.
mods/OniMcp/Server/McpHttpServerModernProtocol.cs
Add raw HTTP regression coverage for mixed-era routing and preserve existing modern behavior checks.
  • Verify future metadata does not divert explicit or session-based legacy requests.
  • Verify explicit modern headers remain modern even with a legacy session.
  • Verify headerless modern metadata still produces the missing-header validation error and legacy session ownership is unchanged.
  • Retain the SEP-2164 resource-not-found regression while generalizing the request helper for optional headers.
tests/OniMcp.ModernProtocol.Tests/Program.cs

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants