I have an MCP server that plans and publishes the posts on my own blog. It has twenty tools, which is five more than I recommend in the article where I recommend fifteen. Here is what broke, in the order I found it, ending with the one that was still broken while I was writing this up.
The check I wrote to catch bad publishing does not check most of my platforms
The pre-publish verifier dispatches on platform name. Medium has rules, dev.to has rules, Telegram and Hacker News and the Stack Exchange sites have rules. Everything else falls through to a default branch that records an informational finding: no verifier for this platform. The overall verdict is computed as "no error-level findings", and an informational finding is not an error, so the entry passes green.
My guardrail against tools that report success without doing the work reports success without doing any work, every time it meets a platform it does not recognise.
That is not hypothetical. The campaign that published this very series runs across four platforms with no verifier at all — X, LinkedIn, the newsletter, and the calendar entries that are checklists rather than publications. Every one of them will pass the pre-publish check with a clean bill, and the clean bill means nothing. The fix is two lines — make the default a warning instead of information — and the reason it was information is embarrassingly ordinary: I wrote the default branch before there was anything for it to catch, and never went back.
The tab that closed while the platform was still saving
The one that cost real articles. My Medium adapter drives a signed-in browser, because Medium's write API has been left to rot. It waited for the address bar to change to the new draft's edit URL, treated that as done, and closed the tab. Medium saves the editor's contents incrementally, over background requests that had not finished.
On 25 July 2026 I audited all twenty-five calendar entries carrying a published URL. Twelve live posts were truncated to between 41% and 72% of the text I had sent, some missing their code blocks. A thirteenth answered HTTP 410. All of them had returned a valid URL and ok.
The interesting part is the hypothesis I held for weeks and had to drop: "browser automation is unreliable, APIs are reliable". Not what the data says. dev.to came through intact, and so did two other platforms I drive through exactly the same browser. The dividing line was one submission against many — a single POST with nothing left to arrive afterwards, versus a body accepted in instalments by a client that stopped watching after the first one. The survivors confirm it: announcements of around 1,500 characters finished saving before the tab closed.
The failure detector that read the article it was publishing
The same adapter searched the page's text for the phrases Medium shows when a save fails, one of which is "something is wrong". The page's text includes the article being published. One article contained the sentence "if something is wrong you flip back". A successful run was declared a failure, the retry ran, and a duplicate draft appeared.
Never read status out of prose. If the only way to learn an outcome is to hunt for words in running text, you have guessed it, and prose will eventually contain your keyword at the worst possible moment.
What actually changed in the design
Before all this the server had one check. Now it has three, and the point is that each answers a question the other two cannot:
- Before publishing: will this text survive the adapter at all — tables where the editor has no table block, unclosed fences, an H1 duplicating the title field.
- After publishing: is the URL alive and picking up views. This is the check that existed and lied to me for weeks, because a truncated article is a perfectly healthy web page.
- After publishing: is what is now on the server the same as what I sent. This is the one that did not exist.
The third is not clever. It renders each published URL in the signed-in browser that owns it — Medium blocks anonymous fetches, and drafts are private to their account — scrolls to the bottom, and compares two signals against the stored body: the number of code blocks, and whether the text of the last link is present. In these articles the last link lives in the closing "further reading" block, which makes it the first casualty of truncation. It has a second mode that opens everything in a browser signed in to nothing, because an author always sees his own article in full, so a paywall or a login wall is invisible from the publishing account.
Two decisions I would keep
A person still presses the button on Medium. The adapter creates a draft and stops. dev.to, Telegram and Stack Exchange go out live because a bad post there is fixable at a price I will pay; a truncated Medium story has a URL people have already seen, and re-uploading replays the race that broke it. Automate to the last reversible step, and let the irreversible one be a decision.
And the most useful tool in this project is one that does not exist. The little server that reads my message archive can fetch by key and cannot search, on purpose. Search lives in an admin query builder where you write the SQL, see the SQL, and fix it when it returns the wrong thing. Do not put a tool in front of a model when the value of the underlying thing is that a human can see it working.
Full write-up, with the audit table and the completeness script: https://dorokhovich.com/blog/building-my-mcp-server-what-broke — and why the server exists at all is https://dorokhovich.com/blog/building-my-mcp-server-why
Source: my own server and its runbook, audited 25 July 2026. One server, twenty tools, a sample of twenty-five publications. Not evidence about agents in general.
One real question: in your own tooling, what does the default branch do when it meets a case you did not plan for — warn, or stay quiet? Mine stayed quiet for months and I would like to know whether that is the common default or just mine.
Top comments (0)