Title: Error when calling MCP tool with arguments and tool name in live environment · Issue #662 · modelcontextprotocol/python-sdk · GitHub
Open Graph Title: Error when calling MCP tool with arguments and tool name in live environment · Issue #662 · modelcontextprotocol/python-sdk
X Title: Error when calling MCP tool with arguments and tool name in live environment · Issue #662 · modelcontextprotocol/python-sdk
Description: Describe the bug I am experiencing an issue when calling the MCP tool with arguments and tool name in the live environment using Railway. I am hosting both the FastAPI with the MCP client and the MCP server on Railway. The tool call work...
Open Graph Description: Describe the bug I am experiencing an issue when calling the MCP tool with arguments and tool name in the live environment using Railway. I am hosting both the FastAPI with the MCP client and the M...
X Description: Describe the bug I am experiencing an issue when calling the MCP tool with arguments and tool name in the live environment using Railway. I am hosting both the FastAPI with the MCP client and the M...
Opengraph URL: https://github.com/modelcontextprotocol/python-sdk/issues/662
X: @github
Domain: github.com
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Error when calling MCP tool with arguments and tool name in live environment","articleBody":"**Describe the bug**\nI am experiencing an issue when calling the MCP tool with arguments and tool name in the live environment using Railway. I am hosting both the FastAPI with the MCP client and the MCP server on Railway. The tool call works fine in the local environment, but when deployed on Railway (live), the tool does not work as expected. The issue arises after the LLM response with arguments and the tool name.\n\nIn the local environment, I use the SSE protocol to interact with the MCP server and everything works fine. However, in the live environment, the tool call fails despite receiving all tools correctly from the MCP server when the app starts.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Deploy the FastAPI application with the MCP client and MCP server on Railway.\n2. Use the LLM response with arguments and the tool name.\n3. Observe that the tool call works on the local environment but fails in the live environment.\n\n**Expected behavior**\nThe tool call should work correctly both in the local environment and live environment. It should successfully invoke the tool when passing the correct arguments and tool name.\n\n**Screenshots**\n\n\n\n**Desktop (please complete the following information):**\n - OS: Windows 10\n - Browser chrome\n - Version 136.0.7103.93\n\n**Additional context**\n- The tool call works locally, but not in the live environment.\n- Both environments use the same configuration, but there seems to be a difference in how the SSE protocol behaves between local and live setups. \n\nhere is my code mcp client+fast api\nfrom contextlib import asynccontextmanager\nfrom fastapi import FastAPI\nfrom pydantic import BaseModel\nfrom config import SERVER_URL\nfrom mcp_client import McpClient\nfrom fastapi.middleware.cors import CORSMiddleware\nfrom fastapi import HTTPException\nfrom mcp import ClientSession\nfrom mcp.client.sse import sse_client\n\nclass QuerySchema(BaseModel):\n query:str\n\n@asynccontextmanager\nasync def lifespan(app:FastAPI):\n client = McpClient()\n try:\n connected = await client.connect_to_server('http://127.0.0.1:3000/sse')\n # connected = await client.connect_to_server(f'{SERVER_URL}')\n if not connected:\n raise HTTPException(\n status_code=500, detail=\"Failed to connect to MCP server\"\n )\n app.state.client = client\n print(\"app start\")\n # print(app.state.client)\n yield \n except Exception as e:\n raise HTTPException(status_code=500, detail=\"Error during lifespan\") from e\n finally:\n # shutdown when app close\n print(\"app close\")\n await client.clenup()\n\napp = FastAPI(title=\"MCP CLIENT CALCULATOR\",lifespan=lifespan)\n\n\n# Add CORS middleware\napp.add_middleware(\n CORSMiddleware,\n allow_origins=[\"*\"], # Allows all origins\n allow_credentials=True,\n allow_methods=[\"*\"], # Allows all methods\n allow_headers=[\"*\"], # Allows all headers\n)\n\n\n\n@app.post('/query')\nasync def caluclator(request:QuerySchema):\n try:\n response = await app.state.client.process_query(request.query)\n # print (response.status_code)\n print (\"response_tool\",response)\n return response\n\n except Exception as e:\n raise HTTPException(status_code=500, detail=f\"Error {e}\") from e\n \n\nif __name__ == \"__main__\":\n import uvicorn \n uvicorn.run(app,host='0.0.0.0',port=8000)\n\nmcp_client.py file\nfrom fastapi import HTTPException\nfrom mcp import ClientSession\nfrom mcp.client.sse import sse_client\nfrom typing import Optional\nfrom contextlib import AsyncExitStack\nfrom google import genai\nfrom config import GOOGLE_API_KEY\nfrom google.genai import types\nclass McpClient:\n def __init__(self):\n self.tools = []\n self.messages = []\n self.session:Optional[ClientSession] = None\n self.exit_stack = AsyncExitStack()\n self.client = genai.Client(api_key=GOOGLE_API_KEY)\n \n async def connect_to_server(self,path:str):\n try:\n read,write = await self.exit_stack.enter_async_context(sse_client(url=path))\n self.session = await self.exit_stack.enter_async_context(ClientSession(read,write))\n await self.session.initialize()\n # get all the tools\n # get all the tools\n self.tools = await self.get_mcp_tools()\n print(self.tools)\n return True\n \n except Exception as e:\n raise\n \n async def get_mcp_tools(self):\n try:\n # print(awaitself.session.list_tools())\n response = await self.session.list_tools()\n return response.tools\n except Exception as e:\n raise(e) \n \n async def process_query(self,query:str):\n try:\n \"\"\" when user hit the query save in self.messages\"\"\" \n self.messages = [types.Content(role=\"user\",parts=[types.Part(text=query)])]\n # print()\n # print(\"first message with query\",self.messages)\n # print()\n while True:\n \"\"\"now call the call_llm function to get response from gemini\"\"\" \n response = await self.call_llm()\n # print(\"response---\u003e\u003e\u003e\",response)\n content = response.candidates[0].content\n parts = content.parts\n \n # print()\n # print(\"second message with fnction call by llm\",self.messages)\n # print()\n \n # if response.candidates[0].content.parts[0].function_call:\n if parts and parts[0].function_call:\n \"\"\"After call call_llm llm return the function tool that we send with useer query and all tools fetch from mcp server and now append with self.messages funtion call send by llm according to query\"\"\"\n self.messages.append(\n types.Content(role=response.candidates[0].content.role,parts=[types.Part(function_call=parts[0].function_call)])\n )\n \n function_call = parts[0].function_call\n print(f\"Function to call: {function_call.name}\")\n print(f\"Arguments: {function_call.args}\")\n try:\n \"\"\"After get tool send by llm now call that tool to mcp server to fetch data according to that function and append result to self.messages \"\"\"\n result = await self.session.call_tool(name=function_call.name,arguments=function_call.args)\n \n self.messages.append(\n types.Content(role=\"tool_use\",\n parts=[types.Part.from_function_response(\n name=function_call.name,\n response={\"result\":result}\n )]),\n \n )\n # print()\n # print(\"third message from mcp server tool give by llm\",self.messages)\n \"\"\"now finally send this self.messages list to llm to get final result that get from mcp server by calling tool purpose of this call to llm to get more understandable answer\"\"\"\n # print()\n final_result = self.client.models.generate_content(\n model=\"gemini-2.5-flash-preview-04-17\",\n config=types.GenerateContentConfig(temperature=1),\n contents=self.messages\n )\n self.messages.append(\n types.Content(role=final_result.candidates[0].content.role,parts=[types.Part(text=final_result.candidates[0].content.parts[0].text)]) \n )\n break\n except Exception as e:\n # print(f\"error get tool response of {function_call.name}\")\n # print(f\"error get tool response of {function_call.args}\")\n raise HTTPException(status_code=500,details = f\"Error calling tool {e}\")\n else:\n print(\"No function call found in the response.\")\n print(response.candidates[0].content.parts[0].text)\n self.messages.append(\n types.Content(\n role=content.role,\n parts=[types.Part(text=response.candidates[0].content.parts[0].text)]\n )\n \n )\n break\n return self.messages\n \n except Exception as e:\n raise(e)\n\n async def call_llm(self):\n \"\"\"Call llm with tools get when app start first time and with self.messages having user quer and user role\"\"\"\n try:\n available_tools = [\n types.Tool(\n function_declarations=[\n {\n \"name\": tool.name,\n \"description\": tool.description,\n \"parameters\": {\n k: v\n for k, v in tool.inputSchema.items()\n if k not in [\"additionalProperties\", \"$schema\"]\n },\n }\n ]\n )\n for tool in self.tools\n ]\n # print(available_tools)\n return self.client.models.generate_content(\n model=\"gemini-2.5-flash-preview-04-17\",\n config=types.GenerateContentConfig(temperature=1,tools=available_tools),\n contents=self.messages\n )\n except Exception as e:\n raise(e)\n\n async def call_tool(self,arguments:dict):\n try:\n # print(a,b,operator)\n response = await self.session.call_tool(name=\"mcpCalculator\",arguments=arguments)\n return response\n\n except Exception as e:\n raise(e)\n \n async def clenup(self):\n try:\n await self.exit_stack.aclose()\n print(\"Disconnected from MCP server\")\n except Exception as e:\n raise(e)\n","author":{"url":"https://github.com/Muhammadtalha678","@type":"Person","name":"Muhammadtalha678"},"datePublished":"2025-05-08T07:07:38.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":1},"url":"https://github.com/662/python-sdk/issues/662"}
| route-pattern | /_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format) |
| route-controller | voltron_issues_fragments |
| route-action | issue_layout |
| fetch-nonce | v2:b6415dd7-4e0c-41be-6971-78e41cd4dc2d |
| current-catalog-service-hash | 81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114 |
| request-id | 8AB0:345E8A:25ED8D:338814:6A57F90D |
| html-safe-nonce | 2742c648abc98ece4376f01972b8cca24f1c17aa4c0a729fa9cb305973f0a2f2 |
| visitor-payload | eyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4QUIwOjM0NUU4QToyNUVEOEQ6MzM4ODE0OjZBNTdGOTBEIiwidmlzaXRvcl9pZCI6IjEzMzgyMjg2NjA2NTA4OTk3MjUiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ== |
| visitor-hmac | a59075644186fb54a47da36295b208a00f8497e6a7084e0cd00b5fdeba225525 |
| hovercard-subject-tag | issue:3048033485 |
| github-keyboard-shortcuts | repository,issues,copilot |
| google-site-verification | Apib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I |
| octolytics-url | https://collector.github.com/github/collect |
| analytics-location | / |
| fb:app_id | 1401488693436528 |
| apple-itunes-app | app-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/modelcontextprotocol/python-sdk/662/issue_layout |
| twitter:image | https://opengraph.githubassets.com/5318e7d94d4d6edb368585c48ef5ed7fe1c804811daab0d670f708ed4cfd915a/modelcontextprotocol/python-sdk/issues/662 |
| twitter:card | summary_large_image |
| og:image | https://opengraph.githubassets.com/5318e7d94d4d6edb368585c48ef5ed7fe1c804811daab0d670f708ed4cfd915a/modelcontextprotocol/python-sdk/issues/662 |
| og:image:alt | Describe the bug I am experiencing an issue when calling the MCP tool with arguments and tool name in the live environment using Railway. I am hosting both the FastAPI with the MCP client and the M... |
| og:image:width | 1200 |
| og:image:height | 600 |
| og:site_name | GitHub |
| og:type | object |
| og:author:username | Muhammadtalha678 |
| hostname | github.com |
| expected-hostname | github.com |
| None | 49c8c15fabcbf356d607a90ca115c13b273e42ff8b74155de050fd229a9b0121 |
| turbo-cache-control | no-preview |
| go-import | github.com/modelcontextprotocol/python-sdk git https://github.com/modelcontextprotocol/python-sdk.git |
| octolytics-dimension-user_id | 182288589 |
| octolytics-dimension-user_login | modelcontextprotocol |
| octolytics-dimension-repository_id | 862584018 |
| octolytics-dimension-repository_nwo | modelcontextprotocol/python-sdk |
| octolytics-dimension-repository_public | true |
| octolytics-dimension-repository_is_fork | false |
| octolytics-dimension-repository_network_root_id | 862584018 |
| octolytics-dimension-repository_network_root_nwo | modelcontextprotocol/python-sdk |
| turbo-body-classes | logged-out env-production page-responsive |
| disable-turbo | false |
| browser-stats-url | https://api.github.com/_private/browser/stats |
| browser-errors-url | https://api.github.com/_private/browser/errors |
| release | 3fb1f684e7a833eb1b2d01d39875a2b52cb4fe9b |
| ui-target | full |
| theme-color | #1e2327 |
| color-scheme | light dark |
Links:
Viewport: width=device-width