fix(mcp): restore SDK v1 compatibility cap (#2978)

## Description

PR #2963 widened the MCP dependency to 2.x while Headroom's live MCP
server still uses the v1 low-level `Server.list_tools()` and
`Server.call_tool()` decorators. Fresh installs therefore crash before
serving tools. Restore the v1 cap until the explicit SDK 2.x port in
#2658 lands, and pin that compatibility contract with a regression test.

Closes #2977

## Type of Change

- [x] Bug fix (non-breaking change that fixes an issue)
- [ ] New feature (non-breaking change that adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update
- [ ] Performance improvement
- [ ] Code refactoring (no functional changes)

## Changes Made

- Restore `mcp>=1.28.1,<2.0.0` in the `proxy` and `mcp` extras.
- Regenerate `uv.lock`, resolving MCP 1.28.1 and removing the
incompatible 2.x transitive set.
- Add a dependency-contract test covering both shipping extras.

## Testing

- [x] Unit tests pass (`pytest`)
- [x] Linting passes (`ruff check .`)
- [ ] Type checking passes (`mypy headroom`)
- [x] New tests added for new functionality
- [x] Manual testing performed

### Test Output

```text
$ uv run pytest -q tests/test_mcp_dependency_contract.py tests/test_ccr_mcp_server.py tests/test_cli/test_mcp.py
41 passed in 0.56s

$ uv run ruff check tests/test_mcp_dependency_contract.py
All checks passed!

$ uv run ruff format --check tests/test_mcp_dependency_contract.py
1 file already formatted
```

## Real Behavior Proof

- Environment: macOS arm64, Python 3.13.14, uv-managed project
environment.
- Exact command / steps: resolve the `mcp` extra, inspect the installed
SDK version and v1 decorators, then instantiate
`HeadroomMCPServer(check_proxy=False)`.
- Observed result: `1.28.1 True True`; server construction returns a v1
`Server` successfully.
- Not tested: full stdio exchange against every external MCP client;
existing MCP unit and CLI suites cover server setup and handlers.

## Runtime Rollout Safety

- Rollout-managed feature(s): None; dependency resolution guard.
- Minimum rollout channel: Stable/default.
- Stable/default behavior changed: Fresh installs stop resolving the
incompatible MCP SDK 2.x release.
- Kill switch / disable path: Revert the dependency cap after #2658
lands.
- Unsafe override required: No.
- Qualification impact: MCP extras and proxy installs remain on the
maintained MCP 1.x line.
- Rollback path: Revert this PR; not recommended until the v2 server
port is merged and tested.

## Review Readiness

- [x] I have performed a self-review
- [x] This PR is ready for human review

## Checklist

- [x] My code follows the project's style guidelines
- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [x] I have added tests that prove my fix is effective or that my
feature works
- [x] New and existing unit tests pass locally with my changes
- [x] I did **not** edit `CHANGELOG.md` — it is generated by
release-please from my Conventional Commit PR title (a CI guard enforces
this)

## Screenshots (if applicable)

Not applicable.

## Additional Notes

The documentation change is the inline dependency rationale next to the
cap. The long-term migration remains #2658; this PR deliberately does
not mix that breaking SDK port into the release-blocker rollback.
This commit is contained in:
JD Davis 2026-08-13 12:35:03 -05:00 committed by GitHub
parent b7f342c153
commit 6077e5a149
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 132 additions and 113 deletions

View file

@ -78,7 +78,9 @@ proxy = [
"orjson>=3.9.14; platform_python_implementation != 'PyPy'",
"httpx[http2]>=0.24.0",
"openai>=2.14.0", # OpenAI API format support
"mcp>=1.28.1,<3.0.0", # MCP server (headroom_compress, retrieve, stats)
# The server still uses the v1 low-level Server decorator API. Keep this
# cap until the SDK 2.x port lands (GH #2658 / regression GH #2977).
"mcp>=1.28.1,<2.0.0", # MCP server (headroom_compress, retrieve, stats)
"magika>=0.6.0", # ML content detection for ContentRouter
"zstandard>=0.20.0", # Decompress zstd request bodies (Codex, etc.)
"websockets>=13.0", # WebSocket proxy for /v1/responses (Codex gpt-5.4+)
@ -225,7 +227,7 @@ autogen = [
]
# MCP server for Claude Code integration
mcp = [
"mcp>=1.28.1,<3.0.0",
"mcp>=1.28.1,<2.0.0",
"httpx>=0.24.0",
"starlette>=0.27.0",
"uvicorn>=0.23.0,<1.0",