Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
dd52713
Rewrite TestChildProcessCleanup with socket-based deterministic liven…
maxisbey Mar 12, 2026
2c73a2a
chore(deps): bump black from 25.1.0 to 26.3.1 in the uv group across …
dependabot[bot] Mar 13, 2026
e1fd62e
fix: close all memory stream ends in client transport cleanup (#2266)
maxisbey Mar 13, 2026
abfb482
refactor(examples): migrate all HTTP examples to streamable_http_app(…
maxisbey Mar 16, 2026
75a80b6
refactor: connect-first stream lifecycle for sse and streamable_http …
maxisbey Mar 16, 2026
1a2244f
fix: handle non-UTF-8 bytes in stdio server stdin (#2302)
maxisbey Mar 17, 2026
ff50351
ci: run strict-no-cover in scripts/test to catch stale pragmas locall…
maxisbey Mar 17, 2026
7826ade
test: convert test_integration.py to in-memory transport (fix flaky) …
maxisbey Mar 18, 2026
67201a9
test: fix WS test port race; narrow to single smoke test covering bot…
maxisbey Mar 18, 2026
20dd946
feat(client): store InitializeResult as initialize_result (#2300)
maxisbey Mar 18, 2026
5388bea
docs: generate hierarchical per-module API reference pages (#2103)
jonathanhefner Mar 18, 2026
883d893
test: rewrite cli.claude config tests to assert JSON output directly …
maxisbey Mar 19, 2026
92c693b
fix: cancel in-flight handlers when transport closes in server.run() …
maxisbey Mar 20, 2026
7ba4fb8
ci: skip claude.yml when comment is '@claude review' (#2337)
felixweinberger Mar 24, 2026
98f8ef2
Restrict httpx version to <1.0.0 (#2345)
Kludex Mar 25, 2026
3517a29
feat(server): restore `dependencies` parameter on MCPServer (#2358)
maxisbey Mar 27, 2026
fb2276b
ci: remove claude-code-review workflow (#2359)
maxisbey Mar 27, 2026
e6235d1
Propagate contextvars.Context through anyio streams without modifying…
Kludex Mar 31, 2026
3ce0f76
Don't block the event loop on sync resource and prompt functions (#2380)
maxisbey Mar 31, 2026
37891f4
Add basic OpenTelemetry tracing for client and server requests (#2381)
Kludex Mar 31, 2026
d5b9155
chore(deps): bump requests from 2.32.5 to 2.33.0 in the uv group acro…
dependabot[bot] Mar 31, 2026
cf4e435
Use shared `is_async_callable` instead of `inspect.iscoroutinefunctio…
Kludex Apr 8, 2026
f27d2aa
docs: fill migration guide gaps surfaced by automated upgrade eval (#…
maxisbey Apr 9, 2026
02ccedf
refactor!: make tool registration object-based
mplemay Apr 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 0 additions & 33 deletions .github/workflows/claude-code-review.yml

This file was deleted.

2 changes: 1 addition & 1 deletion .github/workflows/claude.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ on:
jobs:
claude:
if: |
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude') && !startsWith(github.event.comment.body, '@claude review')) ||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
Expand Down
19 changes: 16 additions & 3 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,31 @@ This document contains critical information about working with this codebase. Fo
- IMPORTANT: The `tests/client/test_client.py` is the most well designed test file. Follow its patterns.
- IMPORTANT: Be minimal, and focus on E2E tests: Use the `mcp.client.Client` whenever possible.
- Coverage: CI requires 100% (`fail_under = 100`, `branch = true`).
- Full check: `./scripts/test` (~20s, matches CI exactly)
- Targeted check while iterating:
- Full check: `./scripts/test` (~23s). Runs coverage + `strict-no-cover` on the
default Python. Not identical to CI: CI also runs 3.10–3.14 × {ubuntu, windows},
and some branch-coverage quirks only surface on specific matrix entries.
- Targeted check while iterating (~4s, deterministic):

```bash
uv run --frozen coverage erase
uv run --frozen coverage run -m pytest tests/path/test_foo.py
uv run --frozen coverage combine
uv run --frozen coverage report --include='src/mcp/path/foo.py' --fail-under=0
UV_FROZEN=1 uv run --frozen strict-no-cover
```

Partial runs can't hit 100% (coverage tracks `tests/` too), so `--fail-under=0`
and `--include` scope the report to what you actually changed.
and `--include` scope the report. `strict-no-cover` has no false positives on
partial runs — if your new test executes a line marked `# pragma: no cover`,
even a single-file run catches it.
- Coverage pragmas:
- `# pragma: no cover` — line is never executed. CI's `strict-no-cover` fails if
it IS executed. When your test starts covering such a line, remove the pragma.
- `# pragma: lax no cover` — excluded from coverage but not checked by
`strict-no-cover`. Use for lines covered on some platforms/versions but not
others.
- `# pragma: no branch` — excludes branch arcs only. coverage.py misreports the
`->exit` arc for nested `async with` on Python 3.11+ (worse on 3.14/Windows).
- Avoid `anyio.sleep()` with a fixed duration to wait for async operations. Instead:
- Use `anyio.Event` — set it in the callback/handler, `await event.wait()` in the test
- For stream messages, use `await stream.receive()` instead of `sleep()` + `receive_nowait()`
Expand Down
1 change: 0 additions & 1 deletion docs/api.md

This file was deleted.

22 changes: 1 addition & 21 deletions docs/experimental/tasks-server.md
Original file line number Diff line number Diff line change
Expand Up @@ -408,16 +408,10 @@ For custom error messages, call `task.fail()` before raising.
For web applications, use the Streamable HTTP transport:

```python
from collections.abc import AsyncIterator
from contextlib import asynccontextmanager

import uvicorn
from starlette.applications import Starlette
from starlette.routing import Mount

from mcp.server import Server
from mcp.server.experimental.task_context import ServerTaskContext
from mcp.server.streamable_http_manager import StreamableHTTPSessionManager
from mcp.types import (
CallToolResult, CreateTaskResult, TextContent, Tool, ToolExecution, TASK_REQUIRED,
)
Expand Down Expand Up @@ -462,22 +456,8 @@ async def handle_tool(name: str, arguments: dict) -> CallToolResult | CreateTask
return CallToolResult(content=[TextContent(type="text", text=f"Unknown: {name}")], isError=True)


def create_app():
session_manager = StreamableHTTPSessionManager(app=server)

@asynccontextmanager
async def lifespan(app: Starlette) -> AsyncIterator[None]:
async with session_manager.run():
yield

return Starlette(
routes=[Mount("/mcp", app=session_manager.handle_request)],
lifespan=lifespan,
)


if __name__ == "__main__":
uvicorn.run(create_app(), host="127.0.0.1", port=8000)
uvicorn.run(server.streamable_http_app(), host="127.0.0.1", port=8000)
```

## Testing Task Servers
Expand Down
35 changes: 35 additions & 0 deletions docs/hooks/gen_ref_pages.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""Generate the code reference pages and navigation."""

from pathlib import Path

import mkdocs_gen_files

nav = mkdocs_gen_files.Nav()

root = Path(__file__).parent.parent.parent
src = root / "src"

for path in sorted(src.rglob("*.py")):
module_path = path.relative_to(src).with_suffix("")
doc_path = path.relative_to(src).with_suffix(".md")
full_doc_path = Path("api", doc_path)

parts = tuple(module_path.parts)

if parts[-1] == "__init__":
parts = parts[:-1]
doc_path = doc_path.with_name("index.md")
full_doc_path = full_doc_path.with_name("index.md")
elif parts[-1].startswith("_"):
continue

nav[parts] = doc_path.as_posix()

with mkdocs_gen_files.open(full_doc_path, "w") as fd:
ident = ".".join(parts)
fd.write(f"::: {ident}")

mkdocs_gen_files.set_edit_path(full_doc_path, path.relative_to(root))

with mkdocs_gen_files.open("api/SUMMARY.md", "w") as nav_file:
nav_file.writelines(nav.build_literate_nav())
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,4 @@ npx -y @modelcontextprotocol/inspector

## API Reference

Full API documentation is available in the [API Reference](api.md).
Full API documentation is available in the [API Reference](api/mcp/index.md).
Loading
Loading