Hi — I read through the create/update tools in mcp-server/src/tools while looking at how MCP servers handle retries on writes, and I think there's a real gap worth a second pair of eyes, not a bug report with a fix attached (I don't know your backend well enough to propose one).
What's provable from the client code:
postApi (lib/request.ts) has no idempotency key anywhere — not in the request body, not as a header. And when the fetch throws (a dropped connection, a timeout), it's caught and returns null exactly the same way a clean 4xx/5xx does:
} catch (error: any) {
logger.error("Error making Currents POST request:", error.toString());
return null;
}
Every caller of postApi then reports that as an unqualified failure — create-action.ts:
if (!data) {
return { content: [{ type: "text" as const, text: "Failed to create action" }] };
}
Same pattern in create-jira-issue.ts and the other create/update tools.
The gap: those two outcomes are not the same thing. "The request never reached you" is safe to retry. "The request reached you, created the thing, and the response was lost on the way back" is not — retrying that creates a second action, or a second Jira issue. From the client's side, both look identical: postApi returns null, the tool says "Failed," and an agent (or a human) doing the reasonable thing and retrying has no way to know which case it's in.
What I can't tell from here, and won't guess: whether /actions or /projects/:id/jira/issues on your side deduplicates a repeat POST — by name + matcher, by some other natural key, or not at all. If they do, this is a non-issue in practice and I've misread the risk. If they don't, a lost response after a real create is the failure mode that produces a duplicate action or a duplicate Jira issue with no error ever surfaced to the caller.
Happy to be told this is already handled server-side — genuinely asking, not asserting. If it isn't, I'd guess the smallest fix is either (a) an idempotency key the caller can set and you dedupe on, or (b) distinguishing "send failed" from "response lost" in postApi so retries are only offered where they're actually safe.
For transparency: I maintain small open-source exactly-once tooling (once, effectfence), so this is a problem I think about outside of this repo too. No pitch attached — flagging it either way.
Hi — I read through the create/update tools in
mcp-server/src/toolswhile looking at how MCP servers handle retries on writes, and I think there's a real gap worth a second pair of eyes, not a bug report with a fix attached (I don't know your backend well enough to propose one).What's provable from the client code:
postApi(lib/request.ts) has no idempotency key anywhere — not in the request body, not as a header. And when the fetch throws (a dropped connection, a timeout), it's caught and returnsnullexactly the same way a clean 4xx/5xx does:Every caller of
postApithen reports that as an unqualified failure —create-action.ts:Same pattern in
create-jira-issue.tsand the other create/update tools.The gap: those two outcomes are not the same thing. "The request never reached you" is safe to retry. "The request reached you, created the thing, and the response was lost on the way back" is not — retrying that creates a second action, or a second Jira issue. From the client's side, both look identical:
postApireturnsnull, the tool says "Failed," and an agent (or a human) doing the reasonable thing and retrying has no way to know which case it's in.What I can't tell from here, and won't guess: whether
/actionsor/projects/:id/jira/issueson your side deduplicates a repeat POST — byname+matcher, by some other natural key, or not at all. If they do, this is a non-issue in practice and I've misread the risk. If they don't, a lost response after a real create is the failure mode that produces a duplicate action or a duplicate Jira issue with no error ever surfaced to the caller.Happy to be told this is already handled server-side — genuinely asking, not asserting. If it isn't, I'd guess the smallest fix is either (a) an idempotency key the caller can set and you dedupe on, or (b) distinguishing "send failed" from "response lost" in
postApiso retries are only offered where they're actually safe.For transparency: I maintain small open-source exactly-once tooling (once, effectfence), so this is a problem I think about outside of this repo too. No pitch attached — flagging it either way.