Skip to content

Conversation

@dgenio
Copy link

@dgenio dgenio commented Nov 28, 2025

Summary

Implements baseline timeout behavior for MCP tool calls to prevent indefinite blocking.

Closes #1374

Changes

Server-Side Timeout

  • Added REQUEST_TIMEOUT error code (-32001) to src/mcp/types.py
  • Added tool_timeout_seconds setting to FastMCP with default of 300 seconds (5 minutes)
  • Wrapped tool execution in anyio.fail_after() to enforce timeouts
  • Error mapping: TimeoutError → McpError with REQUEST_TIMEOUT code

Configuration

  • Constructor parameter: FastMCP(tool_timeout_seconds=60.0)
  • Environment variable: FASTMCP_TOOL_TIMEOUT_SECONDS=120
  • Disable timeout: FastMCP(tool_timeout_seconds=None)

Testing

  • Added 8 comprehensive tests in test_tool_manager.py:
    • Timeout exceeded behavior
    • Fast completion before timeout
    • No timeout (None) behavior
    • Sync and async tool timeouts
    • Context injection compatibility
    • Error differentiation
    • FastMCP setting propagation

Documentation

  • Added "Tool Timeouts" section to README.md
  • Configuration examples and best practices
  • Error handling patterns for clients

Design Decisions

  • Conservative default (300s) to avoid breaking existing tools
  • Nullable timeout allows explicit disabling for long operations
  • Standard error code aligns with TypeScript SDK
  • Environment variable support for deployment flexibility

Client-Side

Client-side timeout handling already exists in BaseSession.send_request() and works correctly with the new server-side timeouts.

Testing

All new tests pass:

pytest tests/server/fastmcp/test_tool_manager.py::TestToolTimeout -v

Linting passes:

ruff check .

Checklist

  • Server-side timeout implementation
  • Configurable via settings and environment variables
  • Proper error code mapping (REQUEST_TIMEOUT)
  • Comprehensive tests added
  • Documentation updated
  • All linting checks pass
  • No changes to client-side (already has timeout support)

- Add REQUEST_TIMEOUT error code (-32001) to types.py
- Add tool_timeout_seconds setting to FastMCP (default: 300s)
- Wrap tool execution in anyio.fail_after() for timeout enforcement
- Raise McpError with REQUEST_TIMEOUT code when timeout is exceeded
- Add comprehensive tests for timeout behavior
- Update README with timeout configuration documentation

Implements baseline timeout behavior for MCP tool calls as described
in the PR requirements. Server-side timeout is configurable via
tool_timeout_seconds parameter or FASTMCP_TOOL_TIMEOUT_SECONDS env var.
Client-side timeout behavior already exists in BaseSession.
- Add blank line after 'Best practices' heading in README.md per markdownlint
- Wrap await example in async function to fix ruff F704/PLE1142 errors
- Skip sync tool timeout test since blocking operations don't respect anyio timeouts
@dgenio dgenio marked this pull request as ready for review November 28, 2025 12:18
@maxisbey
Copy link
Contributor

maxisbey commented Dec 3, 2025

Thanks for putting this together! A couple of notes:

This PR doesn't close #1374 - that issue is about client-side request timeouts (how long the client waits for a response), which is what the spec's timeout section refers to. This PR adds server-side tool execution timeouts (how long the server lets a tool run), which is a different concern and not part of the spec.

That said, server-side tool execution timeouts could be a useful defensive feature. We'll keep this in mind for V2 where we're planning some larger refactors. For now, leaving this open but not planning to merge in the near term.

AI Disclaimer

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.

No default timeout for requests (unlike TS SDK)

2 participants