Markdown supported · ⌘↵ to post
The ticket pattern is a good fit, and the HMAC plus allowlist section is the part I'd push hardest. One gap in the sample is that webhook_url is still an input the model supplies. Even with an allowlist, it is safer to have the server resolve the callback from the authenticated client or session, so the model never chooses where results go. I'd also dedupe on a hash of (user_id, tool_name, normalized input) and return the existing ticket, since a retrying agent otherwise queues duplicate 500MB exports. In the job, catching \Exception and writing 'failed' hides errors from the queue, so $tries and backoff never apply. Separating 'export failed' from 'webhook delivery failed' would let you retry delivery without redoing the four minute work.
How would you handle a ticket whose worker dies mid-run and leaves it in 'pending' forever, with a lease or heartbeat, or a sweeper job?
Hayrullah Kar
One detail in section 1 is worth adjusting. MCP is not limited to a blocking request and response. The Streamable HTTP transport can answer a tool call with a Server-Sent Events stream, no WebSockets needed, and the spec has
notifications/progressfor long calls. Your ticket pattern still makes sense behind a proxy with a hard idle timeout.