Skip to content

Random error thrown on response #88

Closed
@MarkusPfundstein

Description

@MarkusPfundstein

Describe the bug
Sometimes, I see a stacktrace printed in the logs of my mcp server. Claude eventually succeeds to response but I think its good to investigate it.

To Reproduce
Its hard to reproduce as it does not always happen. The code in my codebase that caused it to happen is this one:

    def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | EmbeddedResource]:

        user_id = args.get(toolhandler.USER_ID_ARG)
        if not user_id:
            raise RuntimeError(f"Missing required argument: {toolhandler.USER_ID_ARG}")

        gmail_service = gmail.GmailService(user_id=user_id)
        query = args.get('query')
        max_results = args.get('max_results', 100)
        emails = gmail_service.query_emails(query=query, max_results=max_results)

        return [
            TextContent(
                type="text",
                text=json.dumps(emails, indent=2)
            )
        ]

Called in this context

@app.call_tool()
async def call_tool(name: str, arguments: Any) -> Sequence[TextContent | ImageContent | EmbeddedResource]:
    """Handle tool calls for command line run."""
    
    if not isinstance(arguments, dict):
        raise RuntimeError("arguments must be dictionary")
    
    if toolhandler.USER_ID_ARG not in arguments:
        raise RuntimeError("user_id argument is missing in dictionary.")

    setup_oauth2(user_id=arguments.get(toolhandler.USER_ID_ARG, ""))

    tool_handler = get_tool_handler(name)
    if not tool_handler:
        raise ValueError(f"Unknown tool: {name}")

    try:
        return tool_handler.run_tool(arguments)
    except Exception as e:
        logger.error(str(e))
        raise RuntimeError(f"Caught Exception. Error: {str(e)}")

The RunTime Error is NOT thrown

Expected behavior
No stacktrace?

Desktop (please complete the following information):

  • MAC OSX
  • Python 3.13
  • mcp 1.1.0

Additional context

Here is a full log

+ Exception Group Traceback (most recent call last):
  |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/mcp/server/stdio.py", line 83, in stdio_server
  |     yield read_stream, write_stream
  |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/src/mcp_gsuite/server.py", line 161, in main
  |     await app.run(
  |     ...<3 lines>...
  |     )
  |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/mcp/server/__init__.py", line 423, in run
  |     async with ServerSession(
  |                ~~~~~~~~~~~~~^
  |         read_stream, write_stream, initialization_options
  |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |     ) as session:
  |     ^
  |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/mcp/shared/session.py", line 122, in __aexit__
  |     return await self._task_group.__aexit__(exc_type, exc_val, exc_tb)
  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py", line 763, in __aexit__
  |     raise BaseExceptionGroup(
  |         "unhandled errors in a TaskGroup", self._exceptions
  |     )
  | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
  +-+---------------- 1 ----------------
    | Traceback (most recent call last):
    |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/mcp/shared/session.py", line 235, in _receive_loop
    |     notification = self._receive_notification_type.model_validate(
    |         message.root.model_dump(
    |             by_alias=True, mode="json", exclude_none=True
    |         )
    |     )
    |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/pydantic/main.py", line 627, in model_validate
    |     return cls.__pydantic_validator__.validate_python(
    |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
    |         obj, strict=strict, from_attributes=from_attributes, context=context
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |     )
    |     ^
    | pydantic_core._pydantic_core.ValidationError: 5 validation errors for ClientNotification
    | ProgressNotification.method
    |   Input should be 'notifications/progress' [type=literal_error, input_value='cancelled', input_type=str]
    |     For further information visit https://errors.pydantic.dev/2.10/v/literal_error
    | ProgressNotification.params.progressToken
    |   Field required [type=missing, input_value={'requestId': 20, 'reason... -2: Request timed out'}, input_type=dict]
    |     For further information visit https://errors.pydantic.dev/2.10/v/missing
    | ProgressNotification.params.progress
    |   Field required [type=missing, input_value={'requestId': 20, 'reason... -2: Request timed out'}, input_type=dict]
    |     For further information visit https://errors.pydantic.dev/2.10/v/missing
    | InitializedNotification.method
    |   Input should be 'notifications/initialized' [type=literal_error, input_value='cancelled', input_type=str]
    |     For further information visit https://errors.pydantic.dev/2.10/v/literal_error
    | RootsListChangedNotification.method
    |   Input should be 'notifications/roots/list_changed' [type=literal_error, input_value='cancelled', input_type=str]
    |     For further information visit https://errors.pydantic.dev/2.10/v/literal_error
    +------------------------------------

During handling of the above exception, another exception occurred:

  + Exception Group Traceback (most recent call last):
  |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/bin/mcp-gsuite", line 8, in <module>
  |     sys.exit(main())
  |              ~~~~^^
  |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/src/mcp_gsuite/__init__.py", line 6, in main
  |     asyncio.run(server.main())
  |     ~~~~~~~~~~~^^^^^^^^^^^^^^^
  |   File "/opt/homebrew/Cellar/python@3.13/3.13.0_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/runners.py", line 194, in run
  |     return runner.run(main)
  |            ~~~~~~~~~~^^^^^^
  |   File "/opt/homebrew/Cellar/python@3.13/3.13.0_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/runners.py", line 118, in run
  |     return self._loop.run_until_complete(task)
  |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^
  |   File "/opt/homebrew/Cellar/python@3.13/3.13.0_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/base_events.py", line 721, in run_until_complete
  |     return future.result()
  |            ~~~~~~~~~~~~~^^
  |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/src/mcp_gsuite/server.py", line 160, in main
  |     async with stdio_server() as (read_stream, write_stream):
  |                ~~~~~~~~~~~~^^
  |   File "/opt/homebrew/Cellar/python@3.13/3.13.0_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/contextlib.py", line 235, in __aexit__
  |     await self.gen.athrow(value)
  |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/mcp/server/stdio.py", line 80, in stdio_server
  |     async with anyio.create_task_group() as tg:
  |                ~~~~~~~~~~~~~~~~~~~~~~~^^
  |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py", line 763, in __aexit__
  |     raise BaseExceptionGroup(
  |         "unhandled errors in a TaskGroup", self._exceptions
  |     )
  | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
  +-+---------------- 1 ----------------
    | Traceback (most recent call last):
    |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/anyio/streams/memory.py", line 242, in send
    |     self.send_nowait(item)
    |     ~~~~~~~~~~~~~~~~^^^^^^
    |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/anyio/streams/memory.py", line 225, in send_nowait
    |     raise WouldBlock
    | anyio.WouldBlock
    | 
    | During handling of the above exception, another exception occurred:
    | 
    | Traceback (most recent call last):
    |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/mcp/server/__init__.py", line 467, in run
    |     await message.respond(
    |     ...<4 lines>...
    |     )
    |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/mcp/shared/session.py", line 58, in respond
    |     await self._session._send_response(
    |         request_id=self.request_id, response=response
    |     )
    |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/mcp/shared/session.py", line 196, in _send_response
    |     await self._write_stream.send(JSONRPCMessage(jsonrpc_error))
    |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/anyio/streams/memory.py", line 248, in send
    |     await send_event.wait()
    |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py", line 1747, in wait
    |     await self._event.wait()
    |   File "/opt/homebrew/Cellar/python@3.13/3.13.0_1/Frameworks/Python.framework/Versions/3.13/lib/python3.13/asyncio/locks.py", line 213, in wait
    |     await fut
    | asyncio.exceptions.CancelledError: Cancelled by cancel scope 1040d7c50
    | 
    | During handling of the above exception, another exception occurred:
    | 
    | Exception Group Traceback (most recent call last):
    |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/mcp/server/stdio.py", line 83, in stdio_server
    |     yield read_stream, write_stream
    |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/src/mcp_gsuite/server.py", line 161, in main
    |     await app.run(
    |     ...<3 lines>...
    |     )
    |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/mcp/server/__init__.py", line 423, in run
    |     async with ServerSession(
    |                ~~~~~~~~~~~~~^
    |         read_stream, write_stream, initialization_options
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |     ) as session:
    |     ^
    |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/mcp/shared/session.py", line 122, in __aexit__
    |     return await self._task_group.__aexit__(exc_type, exc_val, exc_tb)
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py", line 763, in __aexit__
    |     raise BaseExceptionGroup(
    |         "unhandled errors in a TaskGroup", self._exceptions
    |     )
    | ExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
    +-+---------------- 1 ----------------
      | Traceback (most recent call last):
      |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/mcp/shared/session.py", line 235, in _receive_loop
      |     notification = self._receive_notification_type.model_validate(
      |         message.root.model_dump(
      |             by_alias=True, mode="json", exclude_none=True
      |         )
      |     )
      |   File "/Users/markus/experiments/claude-mvp/mcp-gsuite/.venv/lib/python3.13/site-packages/pydantic/main.py", line 627, in model_validate
      |     return cls.__pydantic_validator__.validate_python(
      |            ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^
      |         obj, strict=strict, from_attributes=from_attributes, context=context
      |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      |     )
      |     ^
      | pydantic_core._pydantic_core.ValidationError: 5 validation errors for ClientNotification
      | ProgressNotification.method
      |   Input should be 'notifications/progress' [type=literal_error, input_value='cancelled', input_type=str]
      |     For further information visit https://errors.pydantic.dev/2.10/v/literal_error
      | ProgressNotification.params.progressToken
      |   Field required [type=missing, input_value={'requestId': 20, 'reason... -2: Request timed out'}, input_type=dict]
      |     For further information visit https://errors.pydantic.dev/2.10/v/missing
      | ProgressNotification.params.progress
      |   Field required [type=missing, input_value={'requestId': 20, 'reason... -2: Request timed out'}, input_type=dict]
      |     For further information visit https://errors.pydantic.dev/2.10/v/missing
      | InitializedNotification.method
      |   Input should be 'notifications/initialized' [type=literal_error, input_value='cancelled', input_type=str]
      |     For further information visit https://errors.pydantic.dev/2.10/v/literal_error
      | RootsListChangedNotification.method
      |   Input should be 'notifications/roots/list_changed' [type=literal_error, input_value='cancelled', input_type=str]
      |     For further information visit https://errors.pydantic.dev/2.10/v/literal_error

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions