Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .github/workflows/shared.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
continue-on-error: true
strategy:
matrix:
python-version: ["3.10", "3.11", "3.12", "3.13"]
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
dep-resolution:
- name: lowest-direct
install-flags: "--upgrade --resolution lowest-direct"
Expand Down
16 changes: 10 additions & 6 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,22 @@ classifiers = [
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
]
dependencies = [
"anyio>=4.5",
"httpx>=0.27.1",
"httpx-sse>=0.4",
"pydantic>=2.11.0,<3.0.0",
"starlette>=0.27",
"pydantic>=2.12.0; python_version >= '3.14'",
"pydantic>=2.11.0; python_version < '3.14'",
"starlette>=0.48.0; python_version >= '3.14'",
"starlette>=0.27; python_version < '3.14'",
"python-multipart>=0.0.9",
"sse-starlette>=1.6.1",
"pydantic-settings>=2.5.2",
"uvicorn>=0.31.1; sys_platform != 'emscripten'",
"jsonschema>=4.20.0",
"pywin32>=310; sys_platform == 'win32'",
"pywin32>=311; sys_platform == 'win32'",
"pyjwt[crypto]>=2.10.1",
"typing-extensions>=4.9.0",
"typing-inspection>=0.4.1",
Expand Down Expand Up @@ -62,13 +65,14 @@ dev = [
"pytest-pretty>=1.2.0",
"inline-snapshot>=0.23.0",
"dirty-equals>=0.9.0",
"coverage[toml]==7.10.7",
"coverage[toml]>=7.13.1",
"pillow>=12.0",
]
docs = [
"mkdocs>=1.6.1",
"mkdocs-glightbox>=0.4.0",
"mkdocs-material[imaging]>=9.5.45",
"mkdocstrings-python>=1.12.2",
"mkdocs-material>=9.5.45",
"mkdocstrings-python>=2.0.1",
]

[build-system]
Expand Down
3 changes: 2 additions & 1 deletion src/mcp/server/fastmcp/utilities/context_injection.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ def find_context_parameter(fn: Callable[..., Any]) -> str | None:
# Get type hints to properly resolve string annotations
try:
hints = typing.get_type_hints(fn)
except Exception:
# TODO(Marcelo): Drop the pragma once https://github.com/coveragepy/coveragepy/issues/1987 is fixed.
except Exception: # pragma: no cover
# If we can't resolve type hints, we can't find the context parameter
return None

Expand Down
4 changes: 1 addition & 3 deletions src/mcp/server/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,5 @@ async def _handle_incoming(self, req: ServerRequestResponder) -> None:
await self._incoming_message_stream_writer.send(req)

@property
def incoming_messages(
self,
) -> MemoryObjectReceiveStream[ServerRequestResponder]:
def incoming_messages(self) -> MemoryObjectReceiveStream[ServerRequestResponder]:
return self._incoming_message_stream_reader
7 changes: 4 additions & 3 deletions tests/experimental/tasks/server/test_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,8 @@ async def run_server():
async with anyio.create_task_group() as tg:

async def handle_messages():
async for message in server_session.incoming_messages:
# TODO(Marcelo): Drop the pragma once https://github.com/coveragepy/coveragepy/issues/1987 is fixed.
async for message in server_session.incoming_messages: # pragma: no cover
await server._handle_message(message, server_session, {}, False)

tg.start_soon(handle_messages)
Expand Down Expand Up @@ -391,8 +392,8 @@ async def run_server():
),
) as server_session:
async with anyio.create_task_group() as tg:

async def handle_messages():
# TODO(Marcelo): Drop the pragma once https://github.com/coveragepy/coveragepy/issues/1987 is fixed.
async def handle_messages(): # pragma: no cover
async for message in server_session.incoming_messages:
await server._handle_message(message, server_session, {}, False)

Expand Down
3 changes: 2 additions & 1 deletion tests/server/test_lowlevel_input_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ async def run_server():
async with anyio.create_task_group() as tg:

async def handle_messages():
async for message in server_session.incoming_messages:
# TODO(Marcelo): Drop the pragma once https://github.com/coveragepy/coveragepy/issues/1987 is fixed.
async for message in server_session.incoming_messages: # pragma: no cover
await server._handle_message(message, server_session, {}, False)

tg.start_soon(handle_messages)
Expand Down
3 changes: 2 additions & 1 deletion tests/server/test_lowlevel_output_validation.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ async def run_server():
async with anyio.create_task_group() as tg:

async def handle_messages():
async for message in server_session.incoming_messages:
# TODO(Marcelo): Drop the pragma once https://github.com/coveragepy/coveragepy/issues/1987 is fixed.
async for message in server_session.incoming_messages: # pragma: no cover
await server._handle_message(message, server_session, {}, False)

tg.start_soon(handle_messages)
Expand Down
3 changes: 2 additions & 1 deletion tests/server/test_lowlevel_tool_annotations.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ async def run_server():
async with anyio.create_task_group() as tg:

async def handle_messages():
async for message in server_session.incoming_messages:
# TODO(Marcelo): Drop the pragma once https://github.com/coveragepy/coveragepy/issues/1987 is fixed.
async for message in server_session.incoming_messages: # pragma: no cover
await server._handle_message(message, server_session, {}, False)

tg.start_soon(handle_messages)
Expand Down
8 changes: 3 additions & 5 deletions tests/server/test_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -410,11 +410,9 @@ async def test_create_message_tool_result_validation():

# Case 8: empty messages list - skips validation entirely
# Covers the `if messages:` branch (line 280->302)
with anyio.move_on_after(0.01):
await session.create_message(
messages=[],
max_tokens=100,
)
# TODO(Marcelo): Drop the pragma once https://github.com/coveragepy/coveragepy/issues/1987 is fixed.
with anyio.move_on_after(0.01): # pragma: no cover
await session.create_message(messages=[], max_tokens=100)


@pytest.mark.anyio
Expand Down
17 changes: 11 additions & 6 deletions tests/shared/test_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@ async def make_request(client_session: ClientSession):
)

# Give cancellation time to process
with anyio.fail_after(1):
# TODO(Marcelo): Drop the pragma once https://github.com/coveragepy/coveragepy/issues/1987 is fixed.
with anyio.fail_after(1): # pragma: no cover
await ev_cancelled.wait()


Expand Down Expand Up @@ -176,7 +177,8 @@ async def make_request(client_session: ClientSession):
tg.start_soon(mock_server)
tg.start_soon(make_request, client_session)

with anyio.fail_after(2):
# TODO(Marcelo): Drop the pragma once https://github.com/coveragepy/coveragepy/issues/1987 is fixed.
with anyio.fail_after(2): # pragma: no cover
await ev_response_received.wait()

assert len(result_holder) == 1
Expand Down Expand Up @@ -232,7 +234,8 @@ async def make_request(client_session: ClientSession):
tg.start_soon(mock_server)
tg.start_soon(make_request, client_session)

with anyio.fail_after(2):
# TODO(Marcelo): Drop the pragma once https://github.com/coveragepy/coveragepy/issues/1987 is fixed.
with anyio.fail_after(2): # pragma: no cover
await ev_error_received.wait()

assert len(error_holder) == 1
Expand Down Expand Up @@ -287,7 +290,8 @@ async def make_request(client_session: ClientSession):
tg.start_soon(mock_server)
tg.start_soon(make_request, client_session)

with anyio.fail_after(2):
# TODO(Marcelo): Drop the pragma once https://github.com/coveragepy/coveragepy/issues/1987 is fixed.
with anyio.fail_after(2): # pragma: no cover
await ev_timeout.wait()


Expand Down Expand Up @@ -333,7 +337,8 @@ async def mock_server():
tg.start_soon(make_request, client_session)
tg.start_soon(mock_server)

with anyio.fail_after(1):
# TODO(Marcelo): Drop the pragma once https://github.com/coveragepy/coveragepy/issues/1987 is fixed.
with anyio.fail_after(1): # pragma: no cover
await ev_closed.wait()
with anyio.fail_after(1):
with anyio.fail_after(1): # pragma: no cover
await ev_response.wait()
Loading