Skip to content

fix(settings): restore MCP schema migration#4013

Open
neubig wants to merge 2 commits into
mainfrom
fix-settings-mcp-schema-migration
Open

fix(settings): restore MCP schema migration#4013
neubig wants to merge 2 commits into
mainfrom
fix-settings-mcp-schema-migration

Conversation

@neubig

@neubig neubig commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

This PR restores an explicit persisted settings migration for the MCP settings shape change from PR #3964 instead of relying on compatibility validators/shims.

Changes:

  • Bump AGENT_SETTINGS_SCHEMA_VERSION to 5.
  • Add a registered v4 -> v5 migration that persists MCP config in the SDK-native server map/auth shape.
  • Remove the mcp_config before-validators that accepted legacy MCP wrappers at the current schema version. Current-version settings now reject legacy mcpServers wrappers; only migrations accept old persisted shapes.
  • Move the MCP OAuth persisted-settings fixture from v4 to v5 and require agent-settings fixtures for versions 1-5.
  • Remove the event transport compatibility shim (event_compat.py) and its tests so event HTTP/WebSocket payloads are serialized directly rather than silently dropping newer event fields/tool kinds.

Test Plan

  • uv run pytest -q tests/sdk/test_settings.py tests/sdk/test_apply_agent_settings_diff.py tests/cross/test_check_persisted_settings_compat.py tests/sdk/mcp/test_create_mcp_tool.py tests/agent_server/test_settings_router.py tests/sdk/plugin/test_plugin_loader.py tests/sdk/conversation/test_local_conversation_plugins.py
  • uv run pytest -q tests/sdk/test_settings.py tests/cross/test_check_persisted_settings_compat.py tests/agent_server/test_event_router.py tests/agent_server/test_event_router_websocket.py tests/agent_server/test_settings_router.py
  • uv run ruff format openhands-agent-server/openhands/agent_server/event_router.py openhands-agent-server/openhands/agent_server/sockets.py tests/agent_server/test_event_router.py tests/agent_server/test_event_router_websocket.py openhands-sdk/openhands/sdk/settings/model.py tests/sdk/test_settings.py
  • uv run ruff check openhands-sdk/openhands/sdk/settings/model.py tests/cross/test_check_persisted_settings_compat.py tests/sdk/test_settings.py

This PR was created by an AI agent (OpenHands) on behalf of the user.


Agent Server images for this PR

GHCR package: https://github.com/OpenHands/agent-sdk/pkgs/container/agent-server

Variants & Base Images

Variant Architectures Base Image Docs / Tags
java amd64, arm64 eclipse-temurin:17-jdk Link
python amd64, arm64 nikolaik/python-nodejs:python3.13-nodejs22-slim Link
golang amd64, arm64 golang:1.21-bookworm Link

Pull (multi-arch manifest)

# Each variant is a multi-arch manifest supporting both amd64 and arm64
docker pull ghcr.io/openhands/agent-server:2b1a263-python

Run

docker run -it --rm \
  -p 8000:8000 \
  --name agent-server-2b1a263-python \
  ghcr.io/openhands/agent-server:2b1a263-python

All tags pushed for this build

ghcr.io/openhands/agent-server:2b1a263-golang-amd64
ghcr.io/openhands/agent-server:2b1a263c92f6741c5606cfbb020eb164be28605c-golang-amd64
ghcr.io/openhands/agent-server:fix-settings-mcp-schema-migration-golang-amd64
ghcr.io/openhands/agent-server:2b1a263-golang_tag_1.21-bookworm-amd64
ghcr.io/openhands/agent-server:2b1a263-golang-arm64
ghcr.io/openhands/agent-server:2b1a263c92f6741c5606cfbb020eb164be28605c-golang-arm64
ghcr.io/openhands/agent-server:fix-settings-mcp-schema-migration-golang-arm64
ghcr.io/openhands/agent-server:2b1a263-golang_tag_1.21-bookworm-arm64
ghcr.io/openhands/agent-server:2b1a263-java-amd64
ghcr.io/openhands/agent-server:2b1a263c92f6741c5606cfbb020eb164be28605c-java-amd64
ghcr.io/openhands/agent-server:fix-settings-mcp-schema-migration-java-amd64
ghcr.io/openhands/agent-server:2b1a263-eclipse-temurin_tag_17-jdk-amd64
ghcr.io/openhands/agent-server:2b1a263-java-arm64
ghcr.io/openhands/agent-server:2b1a263c92f6741c5606cfbb020eb164be28605c-java-arm64
ghcr.io/openhands/agent-server:fix-settings-mcp-schema-migration-java-arm64
ghcr.io/openhands/agent-server:2b1a263-eclipse-temurin_tag_17-jdk-arm64
ghcr.io/openhands/agent-server:2b1a263-python-amd64
ghcr.io/openhands/agent-server:2b1a263c92f6741c5606cfbb020eb164be28605c-python-amd64
ghcr.io/openhands/agent-server:fix-settings-mcp-schema-migration-python-amd64
ghcr.io/openhands/agent-server:2b1a263-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim-amd64
ghcr.io/openhands/agent-server:2b1a263-python-arm64
ghcr.io/openhands/agent-server:2b1a263c92f6741c5606cfbb020eb164be28605c-python-arm64
ghcr.io/openhands/agent-server:fix-settings-mcp-schema-migration-python-arm64
ghcr.io/openhands/agent-server:2b1a263-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim-arm64
ghcr.io/openhands/agent-server:2b1a263-golang
ghcr.io/openhands/agent-server:2b1a263c92f6741c5606cfbb020eb164be28605c-golang
ghcr.io/openhands/agent-server:fix-settings-mcp-schema-migration-golang
ghcr.io/openhands/agent-server:2b1a263-golang_tag_1.21-bookworm
ghcr.io/openhands/agent-server:2b1a263-java
ghcr.io/openhands/agent-server:2b1a263c92f6741c5606cfbb020eb164be28605c-java
ghcr.io/openhands/agent-server:fix-settings-mcp-schema-migration-java
ghcr.io/openhands/agent-server:2b1a263-eclipse-temurin_tag_17-jdk
ghcr.io/openhands/agent-server:2b1a263-python
ghcr.io/openhands/agent-server:2b1a263c92f6741c5606cfbb020eb164be28605c-python
ghcr.io/openhands/agent-server:fix-settings-mcp-schema-migration-python
ghcr.io/openhands/agent-server:2b1a263-nikolaik_s_python-nodejs_tag_python3.13-nodejs22-slim

About Multi-Architecture Support

  • Each variant tag (e.g., 2b1a263-python) is a multi-arch manifest supporting both amd64 and arm64
  • Docker automatically pulls the correct architecture for your platform
  • Individual architecture tags (e.g., 2b1a263-python-amd64) are also available if needed

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Python API breakage checks — ✅ PASSED

Result:PASSED

Action log

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

REST API breakage checks (OpenAPI) — ✅ PASSED

Result:PASSED

Action log

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Coverage

Coverage Report •
FileStmtsMissCoverMissing
openhands-agent-server/openhands/agent_server
   event_router.py54885%189–192, 202–203, 225–226
   sockets.py2334779%200, 203, 206, 284–286, 292–294, 297, 418–421, 426–427, 432–434, 440–442, 446, 448–449, 453–454, 457, 460, 462–463, 466–467, 505, 507, 526, 541–550, 560
openhands-sdk/openhands/sdk/settings
   model.py8087191%304, 322, 502, 512–515, 518, 531, 535, 541, 551, 557, 562, 657, 660–661, 667–670, 675, 679, 694, 697–699, 747, 752–753, 758, 779, 791, 840, 849, 896, 1083, 1108, 1110, 1112, 1114, 1116, 1118, 1120, 1122, 1124, 1126, 1383, 1385, 1712, 1732, 1885, 2014, 2053, 2079, 2215–2217, 2219, 2273, 2288, 2305, 2315, 2317, 2322, 2340, 2353, 2355, 2357, 2359, 2366
TOTAL35506720579% 

@all-hands-bot all-hands-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

✅ QA Report: PASS

The SDK settings API now migrates v4 MCP persisted payloads to schema version 5 while preserving SDK-native MCP server-map/auth data.

Does this PR achieve its stated goal?

Yes. I exercised the SDK settings validation path with realistic v4 persisted MCP payloads: an SDK-native OAuth server map and a legacy mcpServers wrapper. On origin/main, both payloads still validated/dumped as schema version 4; on PR commit 2404f41838a2f92fd504fde39f6a731d8fb6aa8d, the same inputs validated/dumped as schema version 5, the mcpServers wrapper was normalized away, and OAuth strategy/client/token state was preserved. That directly confirms the claimed v4 → v5 migration behavior works.

Phase Result
Environment Setup make build completed successfully with uv sync --dev and pre-commit hook setup.
CI Status ⚠️ GitHub reported 21 successful, 8 pending, 1 skipped, and 1 failing check (PR Description Check) when checked; I did not rerun tests.
Functional Verification ✅ Before/after SDK execution confirmed schema migration and MCP shape preservation.
Functional Verification

Test 1: v4 persisted MCP settings migrate to v5 and keep SDK-native shape

Step 1 — Reproduce / establish baseline without the fix:

Ran git checkout origin/main && OPENHANDS_SUPPRESS_BANNER=1 uv run python /tmp/qa_settings_migration_compare.py.

Relevant output:

CASE v4_sdk_native_oauth
{
  "auth_strategy": "oauth2",
  "dumped_schema_version": 4,
  "has_mcpServers_wrapper": false,
  "mcp_config_keys": [
    "superhuman-mail"
  ],
  "oauth_access_token": "**********",
  "oauth_client_id": "client-id",
  "settings_schema_version": 4
}
CASE v4_legacy_mcpServers_wrapper
{
  "auth_strategy": null,
  "dumped_schema_version": 4,
  "has_mcpServers_wrapper": false,
  "mcp_config_keys": [
    "weather"
  ],
  "oauth_access_token": null,
  "oauth_client_id": null,
  "settings_schema_version": 4
}

This confirms the baseline problem: v4 MCP settings can normalize the MCP shape, but they remain persisted/validated as schema version 4, so there is no explicit migration to the new persisted schema version.

Step 2 — Apply the PR's changes:

Checked out PR commit 2404f41838a2f92fd504fde39f6a731d8fb6aa8d.

Step 3 — Re-run with the fix in place:

Ran OPENHANDS_SUPPRESS_BANNER=1 uv run python /tmp/qa_settings_migration_compare.py.

Relevant output:

CASE v4_sdk_native_oauth
{
  "auth_strategy": "oauth2",
  "dumped_schema_version": 5,
  "has_mcpServers_wrapper": false,
  "mcp_config_keys": [
    "superhuman-mail"
  ],
  "oauth_access_token": "**********",
  "oauth_client_id": "client-id",
  "settings_schema_version": 5
}
CASE v4_legacy_mcpServers_wrapper
{
  "auth_strategy": null,
  "dumped_schema_version": 5,
  "has_mcpServers_wrapper": false,
  "mcp_config_keys": [
    "weather"
  ],
  "oauth_access_token": null,
  "oauth_client_id": null,
  "settings_schema_version": 5
}

This shows the fix works: the exact same v4 inputs now migrate to schema version 5, the legacy wrapper is not persisted, and the OAuth server-map auth fields remain present after validation/dump. The masked token is expected secret serialization behavior.

Issues Found

None from functional QA.

This review was generated by an AI agent (OpenHands) on behalf of the user.

Co-authored-by: openhands <openhands@all-hands.dev>
@neubig neubig force-pushed the fix-settings-mcp-schema-migration branch from 2404f41 to a5b9e19 Compare July 7, 2026 13:57
Co-authored-by: openhands <openhands@all-hands.dev>
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