MCP servers: handle duplicate tool calls from client retries
An MCP client that loses a response may send the same tools/call again. How an MCP server in Python can return the first result instead of acting twice.
Why an MCP server sees the same call twice
A client that loses the response to tools/call (a dropped connection, a timeout) cannot know whether
the tool ran. Some clients send the call again. Tools can declare an idempotentHint annotation, but that
is a hint the tool gives about itself, not a mechanism that removes duplicates. A tool that creates a ticket or
sends a message has to handle the repeat itself.
Once-only tools in an MCP server (Python SDK)
The Call4Agents MCP adapter records each call. A repeat in the same session returns the first answer. The
Context parameter is left out of the key, and the run id is the Mcp-Session-Id of a
streamable-HTTP session. On stdio there is no session id, so name the run yourself:
from mcp.server.mcpserver import MCPServer, Context
import call4agents as c4a
from call4agents.adapters import mcp as c4a_mcp
c4a.init()
server = MCPServer("helpdesk")
@server.tool()
@c4a_mcp.effect(run=lambda ctx: "client-7") # stdio: name the client yourself
def create_ticket(title: str, ctx: Context) -> str:
return tickets.create(title)
pip install call4agents mcp
python -m call4agents.examples.mcp_tool # prints {'tickets_created': 1, 'same_answer': True}
The same tool can also pass a stable idempotency key to the API behind it with
c4a.idempotency_headers().