Skip to content

[BUG] Native MCP tool calls fail when OpenAI-compatible providers return string arguments #2610

Description

@vamsi-01

Bug Description

Lightspeed Stack Version

The issue has been reproduced in library mode with the following versions:

1. Lightspeed Stack 0.6.2

  • Image: quay.io/lightspeed-core/lightspeed-stack@sha256:1317d65e10c34183de36144a8c9effc81a28aacae62f5ba6be448b60

2. Latest development image

  • Source commit: 546d0ef70913751b46b5a3f83a637abbab0e19c1
  • OGX version: 1.2.5
  • Image digest: sha256:384cfbabc43dbcb7d0335cd32a1e8a37cbb978d022a3a999c758c33856947147

Providers / Models

  1. remote::vllm

    • Model: ibm-granite/granite-4.0-h-small
  2. remote::openai

    • Model: qwen2.5:7b served through local Ollama

MCP Server

  • FastMCP: 4.0.1
  • Transport: Streamable HTTP
  • Endpoint: http://mcp-server:9000/mcp

Describe the Bug

LSCore fails while processing a native MCP tool call from an OpenAI-compatible model.

The model correctly selects an MCP tool and returns its arguments using the standard OpenAI function-calling format, where arguments is represented as a JSON string.

LSCore passes this raw string directly to ToolCallSummary.args, which expects a dictionary. This results in a Pydantic validation error.

The request fails before LSCore invokes the MCP tool, receives a tool result, or generates a final response.

This issue reproduces in LSCore library mode, where OGX runs embedded inside the LSCore image. Server mode was explored separately but was not used for the final reproduction.


To Reproduce

  1. Start LSCore in library mode with an embedded OGX configuration.

  2. Configure either of the following providers:

    provider_type: remote::vllm
    provider_id: granite-h-small

    or:

    provider_type: remote::openai
    provider_id: ollama
  3. Configure a FastMCP Streamable HTTP server:

    mcp_servers:
      - name: test-mcp
        url: http://mcp-server:9000/mcp
  4. Expose a simple MCP tool, for example:

    @mcp.tool()
    def get_subscriptions(offset: int = 0, limit: int = 10) -> dict:
        return {"data": [], "offset": offset, "limit": limit}
  5. Submit an agent request:

    curl -N -sS -X POST http://127.0.0.1:8080/v1/streaming_query \
      -H 'Content-Type: application/json' \
      -d '{"query":"List my subscriptions."}'
  6. Observe successful MCP tool discovery followed by a ToolCallSummary validation error.


Expected Behavior

LSCore should:

  1. Discover the MCP tool.
  2. Parse the model-provided JSON tool arguments.
  3. Invoke get_subscriptions on the MCP server.
  4. Return the MCP result to the model.
  5. Generate and stream the final agent response.

Actual Behavior / Error Output

The request fails with:

pydantic_core._pydantic_core.ValidationError:
1 validation error for ToolCallSummary
args
  Input should be a valid dictionary
  input_value='{\n  "limit": 20\n}'
  input_type=str

Relevant code path

lightspeed_stack/utils/agents/tool_processor.py
└── summarize_native_tool_call()

The failing path passes:

args.get("tool_args")

directly to:

ToolCallSummary.args

However, tool_args is a JSON string for OpenAI-compatible function calls rather than a dictionary.


Additional Context

  • The issue occurs after model inference and MCP tool discovery succeed.
  • It reproduces with both:
    • Granite 4.0 H Small through remote::vllm
    • Qwen 2.5 7B through remote::openai / Ollama
  • It affects both:
    • /v1/query
    • /v1/streaming_query
  • The model/provider behavior is OpenAI-compatible: function-call arguments are returned as JSON strings.
  • The MCP server is successfully discovered and the tool is available before the failure occurs.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions