Skip to content

[BUG]: Tool invocation fails with Pydantic validation errors  #2512

@BenjaminNechicattu

Description

@BenjaminNechicattu

🐞 Bug Summary

Tool invocation fails with Pydantic validation errors when returning resource_link content.


🧩 Affected Component

Select the area of the project impacted:

  • mcpgateway - API
  • mcpgateway - UI (admin panel)
  • mcpgateway.wrapper - stdio wrapper
  • Federation or Transports
  • CLI, Makefiles, or shell scripts
  • Container setup (Docker/Podman/Compose)
  • Other (explain below)

🔁 Steps to Reproduce

  1. resiter a gateway with moody server https://screening-ai-services.npe.moodys.cloud/mcp
  2. Invoke tool screenAndWait

🤔 Expected Behavior

What should have happened instead?


📓 Logs / Error Output

Paste any relevant stack traces or logs here.
⚠️ Do not paste secrets, credentials, or tokens.

2026-01-27T11:21:19 - httpcore.http11 - DEBUG - response_closed.started
2026-01-27T11:21:19 - httpcore.http11 - DEBUG - response_closed.complete
2026-01-27T11:21:19 - httpcore.connection - DEBUG - close.started
2026-01-27T11:21:19 - httpcore.connection - DEBUG - close.complete
2026-01-27T11:21:19 - mcpgateway.services.structured_logger - INFO - [tool_service] MCP tool call completed: screenAndWait
2026-01-27T11:21:19 - mcpgateway.services.structured_logger - ERROR - [tool_service] Tool 'sayujya-mcp-moody-jan-27-v3-screenandwait' invocation failed
2026-01-27T11:21:19 - mcpgateway.transports.streamablehttp_transport - ERROR - Error calling tool 'sayujya-mcp-moody-jan-27-v3-screenandwait': Tool invocation failed: 18 validation errors for CallToolResult
content.0.TextContent.type
  Input should be 'text' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.0.TextContent.text
  Field required [type=missing, input_value={'name': 'Legal Disclaime...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.0.ImageContent.type
  Input should be 'image' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.0.ImageContent.data
  Field required [type=missing, input_value={'name': 'Legal Disclaime...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.0.AudioContent.type
  Input should be 'audio' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.0.AudioContent.data
  Field required [type=missing, input_value={'name': 'Legal Disclaime...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.0.ResourceLink.uri
  Input should be a valid string [type=string_type, input_value=AnyUrl('file://moodys-legal-disclaimer/'), input_type=AnyUrl]
    For further information visit https://errors.pydantic.dev/2.12/v/string_type
content.0.EmbeddedResource.type
  Input should be 'resource' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.0.EmbeddedResource.resource
  Field required [type=missing, input_value={'name': 'Legal Disclaime...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.2.TextContent.type
  Input should be 'text' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.2.TextContent.text
  Field required [type=missing, input_value={'name': 'gridEntityGroun...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.2.ImageContent.type
  Input should be 'image' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.2.ImageContent.data
  Field required [type=missing, input_value={'name': 'gridEntityGroun...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.2.AudioContent.type
  Input should be 'audio' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.2.AudioContent.data
  Field required [type=missing, input_value={'name': 'gridEntityGroun...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.2.ResourceLink.uri
  Input should be a valid string [type=string_type, input_value=AnyUrl('grid-entities://8...b517-fd4e0e24997f.json'), input_type=AnyUrl]
    For further information visit https://errors.pydantic.dev/2.12/v/string_type
content.2.EmbeddedResource.type
  Input should be 'resource' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.2.EmbeddedResource.resource
  Field required [type=missing, input_value={'name': 'gridEntityGroun...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
Traceback (most recent call last):
  File "/Users/benjamin/Documents/Projects/ibm_projects/mcpgateway/mcp-context-forge/mcpgateway/services/tool_service.py", line 3202, in invoke_tool
    tool_result = ToolResult(content=filtered_response, structured_content=structured, is_error=is_err, meta=getattr(tool_call_result, "meta", None))
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/benjamin/Documents/Projects/ibm_projects/mcpgateway/mcp-context-forge/.venv/lib/python3.11/site-packages/pydantic/main.py", line 250, in __init__
    validated_self = self.__pydantic_validator__.validate_python(data, self_instance=self)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
pydantic_core._pydantic_core.ValidationError: 18 validation errors for CallToolResult
content.0.TextContent.type
  Input should be 'text' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.0.TextContent.text
  Field required [type=missing, input_value={'name': 'Legal Disclaime...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.0.ImageContent.type
  Input should be 'image' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.0.ImageContent.data
  Field required [type=missing, input_value={'name': 'Legal Disclaime...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.0.AudioContent.type
  Input should be 'audio' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.0.AudioContent.data
  Field required [type=missing, input_value={'name': 'Legal Disclaime...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.0.ResourceLink.uri
  Input should be a valid string [type=string_type, input_value=AnyUrl('file://moodys-legal-disclaimer/'), input_type=AnyUrl]
    For further information visit https://errors.pydantic.dev/2.12/v/string_type
content.0.EmbeddedResource.type
  Input should be 'resource' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.0.EmbeddedResource.resource
  Field required [type=missing, input_value={'name': 'Legal Disclaime...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.2.TextContent.type
  Input should be 'text' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.2.TextContent.text
  Field required [type=missing, input_value={'name': 'gridEntityGroun...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.2.ImageContent.type
  Input should be 'image' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.2.ImageContent.data
  Field required [type=missing, input_value={'name': 'gridEntityGroun...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.2.AudioContent.type
  Input should be 'audio' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.2.AudioContent.data
  Field required [type=missing, input_value={'name': 'gridEntityGroun...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.2.ResourceLink.uri
  Input should be a valid string [type=string_type, input_value=AnyUrl('grid-entities://8...b517-fd4e0e24997f.json'), input_type=AnyUrl]
    For further information visit https://errors.pydantic.dev/2.12/v/string_type
content.2.EmbeddedResource.type
  Input should be 'resource' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.2.EmbeddedResource.resource
  Field required [type=missing, input_value={'name': 'gridEntityGroun...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Users/benjamin/Documents/Projects/ibm_projects/mcpgateway/mcp-context-forge/mcpgateway/transports/streamablehttp_transport.py", line 516, in call_tool
    result = await tool_service.invoke_tool(
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/benjamin/Documents/Projects/ibm_projects/mcpgateway/mcp-context-forge/mcpgateway/services/tool_service.py", line 3246, in invoke_tool
    raise ToolInvocationError(f"Tool invocation failed: {error_message}")
mcpgateway.services.tool_service.ToolInvocationError: Tool invocation failed: 18 validation errors for CallToolResult
content.0.TextContent.type
  Input should be 'text' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.0.TextContent.text
  Field required [type=missing, input_value={'name': 'Legal Disclaime...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.0.ImageContent.type
  Input should be 'image' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.0.ImageContent.data
  Field required [type=missing, input_value={'name': 'Legal Disclaime...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.0.AudioContent.type
  Input should be 'audio' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.0.AudioContent.data
  Field required [type=missing, input_value={'name': 'Legal Disclaime...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.0.ResourceLink.uri
  Input should be a valid string [type=string_type, input_value=AnyUrl('file://moodys-legal-disclaimer/'), input_type=AnyUrl]
    For further information visit https://errors.pydantic.dev/2.12/v/string_type
content.0.EmbeddedResource.type
  Input should be 'resource' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.0.EmbeddedResource.resource
  Field required [type=missing, input_value={'name': 'Legal Disclaime...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.2.TextContent.type
  Input should be 'text' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.2.TextContent.text
  Field required [type=missing, input_value={'name': 'gridEntityGroun...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.2.ImageContent.type
  Input should be 'image' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.2.ImageContent.data
  Field required [type=missing, input_value={'name': 'gridEntityGroun...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.2.AudioContent.type
  Input should be 'audio' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.2.AudioContent.data
  Field required [type=missing, input_value={'name': 'gridEntityGroun...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
content.2.ResourceLink.uri
  Input should be a valid string [type=string_type, input_value=AnyUrl('grid-entities://8...b517-fd4e0e24997f.json'), input_type=AnyUrl]
    For further information visit https://errors.pydantic.dev/2.12/v/string_type
content.2.EmbeddedResource.type
  Input should be 'resource' [type=literal_error, input_value='resource_link', input_type=str]
    For further information visit https://errors.pydantic.dev/2.12/v/literal_error
content.2.EmbeddedResource.resource
  Field required [type=missing, input_value={'name': 'gridEntityGroun...'type': 'resource_link'}, input_type=dict]
    For further information visit https://errors.pydantic.dev/2.12/v/missing
2026-01-27T11:21:19 - mcp.server.lowlevel.server - DEBUG - Response sent
2026-01-27T11:21:19 - mcp.server.streamable_http - INFO - Terminating session: None
2026-01-27T11:21:19 - mcpgateway.plugins.auth_pre_check - INFO - [WXO_AUTH] Auth audit: POST /servers/09792051036f4725b5f1e3437fb0d5ce/mcp -> 200 (auth_present=True, client=127.0.0.1)
2026-01-27T11:21:19 - mcpgateway.services.structured_logger - INFO - [http_gateway] Request completed: POST /servers/09792051036f4725b5f1e3437fb0d5ce/mcp - 200

🧠 Environment Info

You can retrieve most of this from the /version endpoint.

Key Value
Version or commit e.g. v0.9.0 or main@a1b2c3d
Runtime e.g. Python 3.11, Gunicorn
Platform / OS e.g. Ubuntu 22.04, macOS
Container e.g. Docker, Podman, none

🧩 Additional Context (optional)

Add any configuration details, flags, or related issues.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingwxowxo integration

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions