getsentry / getsentry/sentry-python

MCPIntegration bypasses ignore_errors when FastMCP wraps exceptions in ToolError

Aberta
#5,473 2 comentários 0 reações 1 responsável Reivindicada por @alexander-alderman-webb Ver no GitHub
Bug Errors Python
Linguagem predominante
Python
Estrelas
2.2k
Forks
669
Merge médio
1d 40min
PRs com merge (30d)
212

Descrição

## Problem

The `MCPIntegration` (auto-enabled since sentry-sdk 2.45) captures exceptions that should be filtered by `ignore_errors` because it sees the FastMCP-wrapped `ToolError` instead of the original exception type.

When using `ignore_errors` to suppress specific exception types raised by MCP tool handlers, the filtering doesn't work because of the order of exception wrapping:

1. Tool handler raises a custom exception (e.g. `ExpectedToolError`)
2. FastMCP's `tool_manager.call_tool()` catches it and wraps it in `ToolError`: `raise ToolError(...) from e`
3. `ToolError` propagates up through FastMCP's `_call_tool_mcp`
4. The `MCPIntegration`'s `_async_handler_wrapper` catches `ToolError` and calls `sentry_sdk.capture_exception(e)` ([link](https://github.com/getsentry/sentry-python/blob/master/sentry_sdk/integrations/mcp.py#L429))
5. `_is_ignored_error` checks `issubclass(ToolError, ExpectedToolError)` → **False** → event is sent to Sentry

The `ignore_errors` configuration never sees the original exception type because FastMCP has already wrapped it.

## Expected Behavior

Exceptions listed in `ignore_errors` (or their subclasses) should not be sent to Sentry, even when FastMCP wraps them in `ToolError`. The integration should either walk the exception chain (`__cause__`) or skip capturing exceptions that are already handled by the framework.

## Reproduction

```python
import sentry_sdk
from sentry_sdk.integrations.mcp import MCPIntegration
from fastmcp import FastMCP

class ExpectedToolError(Exception):
"""Should not be reported to Sentry."""
pass

sentry_sdk.init(
dsn="...",
ignore_errors=[ExpectedToolError],
)

mcp = FastMCP("test")

@mcp.tool()
def my_tool() -> str:
raise ExpectedToolError("This is expected and should not go to Sentry")
```

When `my_tool` is called, the `ExpectedToolError` ends up in Sentry because the MCPIntegration captures the wrapping `ToolError`.

## Workaround

Disable the `MCPIntegration` if you handle MCP error reporting yourself:

```python
sentry_sdk.init(
dsn="...",
disabled_integrations=[MCPIntegration()],
ignore_errors=[ExpectedToolError],
)
```

## Environment

- sentry-sdk: 2.51.0
- fastmcp: 2.14.4
- mcp: 1.26.0
- Python: 3.13

Guia de contribuição

Abrir o guia de contribuição

Avaliação

Esta issue ainda não foi avaliada.

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.