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().

Related guides