Skip to content

Python: [Bug]: Local stdio MCP works for calculator but fails for official matlab-mcp-core-server on LM Studio /v1/responses #4540

Closed

Description

@o3o1

Description

Observed the same behavior on two OpenAI-compatible Responses API backends:

  • local LM Studio host
  • Aliyun-hosted model service

On both backends, a simple local stdio MCP server such as calculator works on the same Agent Framework + MCPStdioTool + /v1/responses path, but the official matlab-mcp-core-server does not and fails before a real tool invocation completes.

This suggests the problem is narrower than "Responses API does not support local MCP" or "all local MCP servers fail". It appears to be specific to this class of MCP server.

Because Agent Framework implements local MCP by loading MCP tools and exposing them as normal tools/function calls, the current suspicion is that the incompatibility happens in that decomposition step: simpler MCP servers such as calculator still work, but matlab-mcp-core-server does not.

Code Sample

# Code Sample
## MATLAB ver.


import asyncio
import traceback
from pathlib import Path

from agent_framework import Agent, MCPStdioTool
from agent_framework.openai import OpenAIResponsesClient

BASE_URL = "http://127.0.0.1:1234/v1"
MODEL = "qwen/qwen3.5-9b"
PROMPT = "Please call detect_matlab_toolboxes and summarize the detected MATLAB version and toolbox names."
WORKING_DIR = Path("/Users/***/projects/skills-demo")
MATLAB_MCP_COMMAND = "/Users/***/Developer/mcp-servers/matlab-core/matlab-mcp-core-server"
MATLAB_ROOT = "/Applications/MATLAB_R2025b.app"
MATLAB_DISPLAY_MODE = "nodesktop"
ALLOWED_TOOLS = ["detect_matlab_toolboxes"]


async def main() -> int:
    client = OpenAIResponsesClient(
        model_id=MODEL,
        base_url=BASE_URL,
        api_key="lm-studio",
    )
    tool = MCPStdioTool(
        name="matlab",
        command=MATLAB_MCP_COMMAND,
        args=[
            f"--initial-working-folder={WORKING_DIR.resolve()}",
            "--disable-telemetry=true",
            f"--matlab-root={MATLAB_ROOT}",
            f"--matlab-display-mode={MATLAB_DISPLAY_MODE}",
        ],
        allowed_tools=ALLOWED_TOOLS or None,
        request_timeout=120,
        description="Official MATLAB MCP core server",
    )
    agent = Agent(
        client=client,
        instructions="Use the available tools when needed and answer the user request.",
        tools=[tool],
    )

    try:
        response = await agent.run(PROMPT)
    except Exception as exc:
        print(f"{type(exc).__name__}: {exc}")
        traceback.print_exc()
        return 1

    print(response.text)
    return 0


asyncio.run(main())


## Calculator ver.

Use the same structure as above, and replace only the MCP-specific constants, tool construction, and prompt:


- PROMPT = "Please call detect_matlab_toolboxes and summarize the detected MATLAB version and toolbox names."
- WORKING_DIR = Path("/Users/***/projects/skills-demo")
- MATLAB_MCP_COMMAND = "/Users/***/Developer/mcp-servers/matlab-core/matlab-mcp-core-server"
- MATLAB_ROOT = "/Applications/MATLAB_R2025b.app"
- MATLAB_DISPLAY_MODE = "nodesktop"
- ALLOWED_TOOLS = ["detect_matlab_toolboxes"]
+ PROMPT = "Please use the calculator tool to compute 17 * (5 + 3), and return only the final numeric result."
+ CALCULATOR_MCP_COMMAND = "uvx"
+ CALCULATOR_MCP_ARGS = ["mcp-server-calculator"]
+ ALLOWED_TOOLS = ["calculate"]

-     tool = MCPStdioTool(
-         name="matlab",
-         command=MATLAB_MCP_COMMAND,
-         args=[
-             f"--initial-working-folder={WORKING_DIR.resolve()}",
-             "--disable-telemetry=true",
-             f"--matlab-root={MATLAB_ROOT}",
-             f"--matlab-display-mode={MATLAB_DISPLAY_MODE}",
-         ],
-         allowed_tools=ALLOWED_TOOLS or None,
-         request_timeout=120,
-         description="Official MATLAB MCP core server",
-     )
+     tool = MCPStdioTool(
+         name="calculator",
+         command=CALCULATOR_MCP_COMMAND,
+         args=CALCULATOR_MCP_ARGS,
+         allowed_tools=ALLOWED_TOOLS or None,
+         request_timeout=120,
+         description="Simple calculator MCP server",
+     )

Error Messages / Stack Traces

## MATLAB Script

The main failure is a `400 invalid_request_error` returned from the OpenAI-compatible `Responses API` backend:


openai.BadRequestError: Error code: 400 - {
  'error': {
    'message': 'Invalid',
    'type': 'invalid_request_error',
    'param': 'tools.0.type',
    'code': 'invalid_string'
  }
}


Agent Framework then surfaces that as:


agent_framework.exceptions.ChatClientException:
<class 'agent_framework.openai._responses_client.OpenAIResponsesClient'>
service failed to complete the prompt:
Error code: 400 - {
  'error': {
    'message': 'Invalid',
    'type': 'invalid_request_error',
    'param': 'tools.0.type',
    'code': 'invalid_string'
  }
}


Minimal traceback:


File ".../mcp-test/repro_matlab_mcp.py", line 46, in main
    response = await agent.run(PROMPT)
File ".../site-packages/agent_framework/_agents.py", line 838, in _run_non_streaming
    response = await self.client.get_response(...)
File ".../site-packages/agent_framework/_tools.py", line 2139, in _get_response
    response = await super_get_response(...)
File ".../site-packages/agent_framework/openai/_responses_client.py", line 341, in _get_response
    self._handle_request_error(ex)
File ".../site-packages/agent_framework/openai/_responses_client.py", line 266, in _handle_request_error
    raise ChatClientException(...)


## Cleanup-time error

After the main MATLAB failure, there is also a separate cleanup-time exception from the stdio client:


RuntimeError: Attempted to exit cancel scope in a different task than it was entered in


This same cleanup issue can also appear after successful MCP runs, so it does not appear to be the primary cause of the MATLAB incompatibility.

Package Versions

agent-framework-core 1.0.0rc2, openai 2.24.0, mcp 1.26.0, anyio 4.12.1

Python Version

Python 3.13

Additional Context

No response

Activity

  1. added
    bugUsage: [Issues], Target: all issues (Legacy, prefer issue type: bug)
    on Mar 7, 2026
  2. added theissue type on Mar 7, 2026
  3. added
    pythonUsage: [Issues, PRs], Target: Python
    triageUsage: [Issues], Target: All issues that still need to be triaged
    on Mar 7, 2026
  4. moved this from Planned to In Progress in Agent Frameworkon Mar 9, 2026
  5. added a commit that references this issue on Mar 10, 2026
    bd9bf36
  6. moved this from In Progress to In Review in Agent Frameworkon Mar 10, 2026
  7. eavanvalkenburg commented on Mar 11, 2026

    @eavanvalkenburg
    Member

    So does this work against the OpenAI itself? if it's not a problem there, then we shouldn't fix this in our code, then we should raise a issue in LM Studio. CC Giles Odigwe (@giles17)

  8. o3o1 commented on Mar 11, 2026

    @o3o1
    Author

    So does this work against the OpenAI itself? if it's not a problem there, then we shouldn't fix this in our code, then we should raise a issue in LM Studio. CC @giles17

    Not working on OpenAI itself as well. Using v1/response with gpt-5-mini-2025-08-07, get the same results(works fine on calculator but failed with Matlab). The error message is as follows:

    Error code: 400 - {
      "error": {
        "message": "Invalid schema for function 'detect_matlab_toolboxes': In context=(), object schema missing properties.",
        "type": "invalid_request_error",
        "param": "tools[0].parameters",
        "code": "invalid_function_parameters"
      }
    }
    

    Got the same cleanup issue as well.
    RuntimeError: Attempted to exit cancel scope in a different task than it was entered in

  9. moved this from In Review to In Progress in Agent Frameworkon Mar 11, 2026
  10. eavanvalkenburg commented on Mar 12, 2026

    @eavanvalkenburg
    Member

    can you share what the actual failing schema is?

  11. o3o1 commented on Mar 12, 2026

    @o3o1
    Author

    can you share what the actual failing schema is?

    Code

    from __future__ import annotations
    
    import asyncio
    import traceback
    from pathlib import Path
    
    from agent_framework import Agent, MCPStdioTool
    from agent_framework.openai import OpenAIResponsesClient
    
    BASE_URL = "https://api.openai.com/v1"
    MODEL = "gpt-5-mini-2025-08-07"
    API_KEY = "sk-proj-***"
    PROMPT = "Please call detect_matlab_toolboxes and summarize the detected MATLAB version and toolbox names."
    WORKING_DIR = Path("/Users/***/projects/skills-demo")
    MATLAB_MCP_COMMAND = "/Users/***/Developer/mcp-servers/matlab-core/matlab-mcp-core-server"
    MATLAB_ROOT = "/Applications/MATLAB_R2025b.app"
    MATLAB_DISPLAY_MODE = "nodesktop"
    ALLOWED_TOOLS = ["detect_matlab_toolboxes"]
    
    
    async def main() -> int:
        client = OpenAIResponsesClient(
            model_id=MODEL,
            base_url=BASE_URL,
            api_key=API_KEY,
        )
        tool = MCPStdioTool(
            name="matlab",
            command=MATLAB_MCP_COMMAND,
            args=[
                f"--initial-working-folder={WORKING_DIR.resolve()}",
                "--disable-telemetry=true",
                f"--matlab-root={MATLAB_ROOT}",
                f"--matlab-display-mode={MATLAB_DISPLAY_MODE}",
            ],
            allowed_tools=ALLOWED_TOOLS or None,
            request_timeout=120,
            description="Official MATLAB MCP core server",
        )
        agent = Agent(
            client=client,
            instructions="Use the available tools when needed and answer the user request.",
            tools=[tool],
        )
    
        try:
            response = await agent.run(PROMPT)
        except Exception as exc:
            print(f"{type(exc).__name__}: {exc}")
            traceback.print_exc()
            return 1
    
        print(response.text)
        return 0
    
    
    if __name__ == "__main__":
        raise SystemExit(asyncio.run(main()))

    Console Output

    {"time":"2026-03-12T00:37:09.547765+08:00","level":"INFO","msg":"Initiating application startup"}
    {"time":"2026-03-12T00:37:09.54786+08:00","level":"INFO","msg":"Configuration state","DisableTelemetry":true,"LogLevel":"info","PreferredLocalMATLABRoot":"/Applications/MATLAB_R2025b.app","PreferredMATLABStartingDirectory":"/Users/***/projects/skills-demo","UseSingleMATLABSession":true,"InitializeMATLABOnStartup":false,"MATLABDisplayMode":"nodesktop"}
    {"time":"2026-03-12T00:37:09.547869+08:00","level":"INFO","msg":"Application directory state","log-dir":"/tmp/matlab-mcp-core-server-1818767616","id":"1404078382"}
    {"time":"2026-03-12T00:37:10.049857+08:00","level":"INFO","msg":"Application startup complete"}
    {"time":"2026-03-12T00:37:10.051644+08:00","level":"INFO","msg":"Added tools to MCP SDK server","count":5}
    {"time":"2026-03-12T00:37:10.051713+08:00","level":"INFO","msg":"Added additional tools to MCP SDK server","count":0}
    {"time":"2026-03-12T00:37:10.051767+08:00","level":"INFO","msg":"Added resources to MCP SDK server","count":2}
    ChatClientException: <class 'agent_framework.openai._responses_client.OpenAIResponsesClient'> service failed to complete the prompt: Error code: 400 - {'error': {'message': "Invalid schema for function 'detect_matlab_toolboxes': In context=(), object schema missing properties.", 'type': 'invalid_request_error', 'param': 'tools[0].parameters', 'code': 'invalid_function_parameters'}}
    Traceback (most recent call last):
      File "/Users/***/projects/skills-demo/.venv/lib/python3.13/site-packages/agent_framework/openai/_responses_client.py", line 339, in _get_response
        response = await client.responses.create(stream=False, **run_options)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/Users/***/projects/skills-demo/.venv/lib/python3.13/site-packages/openai/resources/responses/responses.py", line 2559, in create
        return await self._post(
               ^^^^^^^^^^^^^^^^^
        ...<43 lines>...
        )
        ^
      File "/Users/***/projects/skills-demo/.venv/lib/python3.13/site-packages/openai/_base_client.py", line 1884, in post
        return await self.request(cast_to, opts, stream=stream, stream_cls=stream_cls)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/Users/***/projects/skills-demo/.venv/lib/python3.13/site-packages/openai/_base_client.py", line 1669, in request
        raise self._make_status_error_from_response(err.response) from None
    openai.BadRequestError: Error code: 400 - {'error': {'message': "Invalid schema for function 'detect_matlab_toolboxes': In context=(), object schema missing properties.", 'type': 'invalid_request_error', 'param': 'tools[0].parameters', 'code': 'invalid_function_parameters'}}
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
      File "/Users/***/projects/skills-demo/mcp-test/repro_matlab_mcp.py", line 47, in main
        response = await agent.run(PROMPT)
                   ^^^^^^^^^^^^^^^^^^^^^^^
      File "/Users/***/projects/skills-demo/.venv/lib/python3.13/site-packages/agent_framework/_agents.py", line 838, in _run_non_streaming
        response = await self.client.get_response(  # type: ignore[call-overload]
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        ...<4 lines>...
        )
        ^
      File "/Users/***/projects/skills-demo/.venv/lib/python3.13/site-packages/agent_framework/_tools.py", line 2139, in _get_response
        response = await super_get_response(
                   ^^^^^^^^^^^^^^^^^^^^^^^^^
        ...<4 lines>...
        )
        ^
      File "/Users/***/projects/skills-demo/.venv/lib/python3.13/site-packages/agent_framework/openai/_responses_client.py", line 341, in _get_response
        self._handle_request_error(ex)
        ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^
      File "/Users/***/projects/skills-demo/.venv/lib/python3.13/site-packages/agent_framework/openai/_responses_client.py", line 266, in _handle_request_error
        raise ChatClientException(
        ...<2 lines>...
        ) from ex
    agent_framework.exceptions.ChatClientException: <class 'agent_framework.openai._responses_client.OpenAIResponsesClient'> service failed to complete the prompt: Error code: 400 - {'error': {'message': "Invalid schema for function 'detect_matlab_toolboxes': In context=(), object schema missing properties.", 'type': 'invalid_request_error', 'param': 'tools[0].parameters', 'code': 'invalid_function_parameters'}}
    {"time":"2026-03-12T00:37:10.774583+08:00","level":"INFO","msg":"Initiating application shutdown"}
    {"time":"2026-03-12T00:37:10.775757+08:00","level":"INFO","msg":"Application shutdown complete"}
    an error occurred during closing of asynchronous generator <async_generator object stdio_client at 0x108f90580>
    asyncgen: <async_generator object stdio_client at 0x108f90580>
      + Exception Group Traceback (most recent call last):
      |   File "/Users/***/projects/skills-demo/.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py", line 783, in __aexit__
      |     raise BaseExceptionGroup(
      |         "unhandled errors in a TaskGroup", self._exceptions
      |     ) from None
      | BaseExceptionGroup: unhandled errors in a TaskGroup (1 sub-exception)
      +-+---------------- 1 ----------------
        | Traceback (most recent call last):
        |   File "/Users/***/projects/skills-demo/.venv/lib/python3.13/site-packages/mcp/client/stdio/__init__.py", line 189, in stdio_client
        |     yield read_stream, write_stream
        | GeneratorExit
        +------------------------------------
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "/Users/***/projects/skills-demo/.venv/lib/python3.13/site-packages/mcp/client/stdio/__init__.py", line 183, in stdio_client
        anyio.create_task_group() as tg,
        ~~~~~~~~~~~~~~~~~~~~~~~^^
      File "/Users/***/projects/skills-demo/.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py", line 789, in __aexit__
        if self.cancel_scope.__exit__(type(exc), exc, exc.__traceback__):
           ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
      File "/Users/***/projects/skills-demo/.venv/lib/python3.13/site-packages/anyio/_backends/_asyncio.py", line 461, in __exit__
        raise RuntimeError(
        ...<2 lines>...
        )
    RuntimeError: Attempted to exit cancel scope in a different task than it was entered in
    
  12. eavanvalkenburg commented on Mar 12, 2026

    @eavanvalkenburg
    Member

    I would like the see the generated schema of the tools, not the code, I don't know this: MATLAB_MCP_COMMAND = "/Users/***/Developer/mcp-servers/matlab-core/matlab-mcp-core-server"

  13. o3o1 commented on Mar 12, 2026

    @o3o1
    Author

    I would like the see the generated schema of the tools, not the code, I don't know this: MATLAB_MCP_COMMAND = "/Users/***/Developer/mcp-servers/matlab-core/matlab-mcp-core-server"

    I captured the full request payloads sent to /v1/responses.

    The failing MATLAB case is:

    {
      "tools": [
        {
          "name": "detect_matlab_toolboxes",
          "parameters": {
            "type": "object",
            "additionalProperties": false
          },
          "strict": false,
          "type": "function",
          "description": "Returns information about installed MATLAB and toolboxes, including version numbers."
        }
      ],
      "input": [
        {
          "type": "message",
          "role": "system",
          "content": [
            {
              "type": "input_text",
              "text": "Use the available tools when needed and answer the user request."
            }
          ]
        },
        {
          "type": "message",
          "role": "user",
          "content": [
            {
              "type": "input_text",
              "text": "Please call detect_matlab_toolboxes and summarize the detected MATLAB version and toolbox names."
            }
          ]
        }
      ],
      "model": "gpt-5-mini-2025-08-07",
      "tool_choice": "auto"
    }

    The working calculator case is:

    {
      "tools": [
        {
          "name": "calculate",
          "parameters": {
            "properties": {
              "expression": {
                "title": "Expression",
                "type": "string"
              }
            },
            "required": [
              "expression"
            ],
            "title": "calculateArguments",
            "type": "object",
            "additionalProperties": false
          },
          "strict": false,
          "type": "function",
          "description": "Calculates/evaluates the given expression."
        }
      ],
      "input": [
        {
          "type": "message",
          "role": "system",
          "content": [
            {
              "type": "input_text",
              "text": "Use the available tools when needed and answer the user request."
            }
          ]
        },
        {
          "type": "message",
          "role": "user",
          "content": [
            {
              "type": "input_text",
              "text": "Please use the calculator tool to compute 17 * (5 + 3), and return only the final numeric result."
            }
          ]
        }
      ],
      "model": "gpt-5-mini-2025-08-07",
      "tool_choice": "auto"
    }

    The main structural difference is that the MATLAB tool is a zero argument tool and its parameters schema is an empty object schema.

  14. moved this from In Progress to In Review in Agent Frameworkon Mar 18, 2026
  15. moved this from In Review to Done in Agent Frameworkon Mar 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugUsage: [Issues], Target: all issues (Legacy, prefer issue type: bug)pythonUsage: [Issues, PRs], Target: Python

Type

Projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions