Quick answer: When an MCP connection drops in the middle of a workflow, the safest behavior is to stop, verify what already happened, and then resume rather than blindly replaying the same tool calls. Retries are safe for read-only and idempotent tools, but a write that may have landed before the disconnect can be duplicated if the agent repeats it. Design the agent and the server so each step is verifiable and the recovery path is explicit.

How a mid-workflow drop appears

The agent is several steps into a task, for example creating a record, then updating it, then triggering a build. The transport, whether a local stdio process or a streamable HTTP connection, drops after the second call. The agent loses the connection and must decide whether to reconnect and retry. The danger is that the agent does not know whether the last call executed on the server, because the response never came back.

Tool typeState after a lost responseSafe recovery
Read-onlyNothing changedReconnect and call again
Idempotent writeRepeating has the same effectRetry the same call
Non-idempotent writeMay have partially or fully landedVerify first, then decide

Why blind retries cause duplicate writes

A request that times out or loses its connection has an ambiguous outcome. The server may have processed it fully and failed only while sending the response, or the connection may have broken before the handler ran. If the agent assumes the worst and re-creates a resource, you can end up with two records. This is the classic reason idempotency keys exist: they give the server a way to recognize a repeated request and return the original result instead of creating a duplicate.

Making the server safe to retry

Accept an idempotency key on write operations and persist it alongside the result, so a retried call with the same key returns the stored response. The agent should generate the key once per logical step and reuse the same key on retry, rather than minting a new one.

# First attempt and its retry carry the same key
POST /v1/orders
Idempotency-Key: order-20261104-7f3a
Content-Type: application/json

# If the first call landed, the server returns the stored result
# instead of creating a second order.

For tools generated from an OpenAPI operation, the method and the contract can indicate whether a call is idempotent, which lets the agent choose the correct recovery strategy automatically instead of guessing from the tool name.

A verifiable recovery flow

Structure the agent's resume logic around checking state rather than memory. On reconnect, read the current state of the resource involved in the ambiguous step, compare it to the intended outcome, and only then act.

async function resumeAfterDrop(step, resourceId) {
  await mcp.reconnect();
  if (step.tool.readOnly || step.tool.idempotent) {
    return mcp.call(step.name, step.args); // safe to repeat
  }
  const current = await mcp.call('get_order', { id: resourceId });
  if (current && current.status === step.intendedStatus) {
    return current; // the write already landed; do not duplicate it
  }
  return mcp.call(step.name, step.args); // it did not; proceed once
}

This requires the server to expose a read tool that returns the resource state. If an MCP server only offers writes and no way to query, the agent cannot recover safely and the system is forced into guessing, which is a design gap worth fixing.

Reconnect semantics on the transport

For streamable HTTP, the client should treat a dropped socket as a transport event and re-establish the session, then re-validate the session rather than assuming the server kept it. For stdio, a crashed child process must be restarted, and any in-memory state in that process is lost. The server should keep durable state outside the connection so a reconnect does not reset the workflow. Connection health and retries belong in the client layer, while the source of truth for what happened belongs on the server.

How an AI agent tends to mishandle it

An agent faced with a connection error often applies the simplest fix: re-run the whole failed sequence from the start. That re-creates resources that were already created and repeats side effects like emails or webhooks. When reviewing an agent's workflow, check whether the plan includes a verification step after any error and whether writes use idempotency keys. If the agent treats every failed call as "nothing happened," ask it to add read-after-reconnect checks. The reliable pattern is to assume nothing about the ambiguous call and let the server's current state answer the question.

Frequently asked questions

Can I just retry the tool call after reconnecting?

For read-only and idempotent tools, yes. For a non-idempotent write, query the resource first to see whether the call landed, or use an idempotency key so the server can deduplicate the retry.

What does an idempotency key do during a dropped connection?

It identifies a logical request across attempts. If the first request was processed, the server recognizes the repeated key and returns the stored result instead of performing the action a second time.

Who should keep the workflow state, the agent or the server?

The server holds the authoritative state. The agent's memory of what it intended is not reliable evidence after a disconnect. Always read the current server state to determine the resume point.

Does connection retry logic differ between stdio and HTTP?

The reconnect mechanics differ, with a restarted child process for stdio and a new session for HTTP, but the recovery principle is the same: verify durable state on the server before replaying ambiguous writes.

This is part of the Powerduck vs Cursor: API Contract Tools for AI Coding — start there for the full comparison of agent workflows and contract-verified reliability.