How we wrote this blog post from Claude (without touching the repo)
We built a screen-less CMS, authenticated with an API key and exposed as a remote MCP server. The team writes articles by talking to Claude. Here's what we decided, why, and a couple of things we didn't expect.
Honesty warning before we start: this post was written by Claude. It’s not a marketing metaphor of the “powered by AI” kind. The text you’re reading was generated in a chat conversation, someone reviewed it, approved it, and it was published automatically without anyone opening the website’s repository.
It’s not magic either. It’s the fairly predictable consequence of a technical decision we made a few weeks ago, when we tried to solve a small problem: how to make it easy for the team to write blog posts without asking them to learn git, YAML frontmatter, or the pull request flow.
The problem (that looks small until you live it)
Our blog is built with Astro as a static site. Each post is a Markdown file in src/content/blog/, with a YAML frontmatter at the top. To publish a new one, someone has to:
- Clone the repo or use the GitHub UI
- Create a branch
- Write the .md with the correct frontmatter
- Upload the image to the right place
- Open a pull request
- Wait for review
- Merge and wait for the build
For a team with mixed technical skills, that flow is prohibitive. People who don’t live in the terminal don’t feel comfortable. And “delegate publishing to the developer” breaks in week one, because developers also want to sleep.
The obvious answer was a visual CMS: Sveltia, Decap, Strapi, Contentful. All valid tools. In fact we almost shipped Sveltia: we only had left to deploy an OAuth broker on Cloudflare Workers so the editor could authenticate against GitHub.
And there we stopped. Because adding a new admin screen, configuring OAuth, maintaining a separate worker, and accepting that blog articles would live versioned in git struck us as exactly the kind of complexity we didn’t want. It was solving a small problem by building a big tool.
The weird call: a screen-less CMS
Our bet was the opposite. Instead of adding a new UI, we added none. The CMS became a pure API, with no frontend, with two relevant endpoints:
- A REST endpoint for administration (create API keys, review the audit log, the boring stuff).
- An MCP endpoint, which exposes operations as tools that any language model can invoke.
And where’s the interface for the human editor? In Claude Desktop. Or Claude Code. Or any client that speaks the MCP protocol.
Which means when someone on the team wants to publish a post, the conversation looks something like:
Person: "I need to write about why cheap data lakes end up
being expensive."
Claude: [uses the propose_article tool, gets a structured outline
for the right category]
[writes the full draft in Spanish and English]
[generates the LinkedIn copy]
[calls generate_image, which triggers Gemini on the server]
"Here's the draft. Anything to adjust?"
Person: "The second block feels weak. Rewrite it more direct."
Claude: [edits] "Ready to publish?"
Person: "Go."
Claude: [calls publish_post with the full payload]
"Published. It'll be online in two minutes.
Here's the LinkedIn copy for you to post."
The human editor never touches git, never configures anything, never opens a file. Talks, reviews, approves.
Why MCP changes something, not just packaging
MCP (Model Context Protocol) is the standard Anthropic published so language models can invoke external tools in a uniform way. Before MCP, every integration between an LLM and a system was ad-hoc plumbing: define the function shape, handle auth, parse responses, decide error formats.
With MCP, a server declares its tools once, exposes an HTTP endpoint with bearer auth, and any MCP client (Claude Desktop, Claude Code, others) can use them with no glue code. The human side just pastes one line of config:
{
"mcpServers": {
"sediment-blog": {
"type": "http",
"url": "https://cms-api.sedimentdata.com/mcp",
"headers": { "Authorization": "Bearer <their-api-key>" }
}
}
}
Restart Claude Desktop, and from then on they have the eight CMS tools available inside their usual conversation. Without installing anything. Without learning anything. Without new screens.
What it looks like inside
Three components, that’s it:
- The client LLM (Claude Desktop, in this case). Knows the tools because the MCP server declares them with a schema. Decides when to invoke them based on the conversation. If it decides wrong, the human editor corrects it in the chat.
- The MCP server, a Python FastAPI with FastMCP integrated. Runs in a small container. Validates the API key against a SQLite table, executes the tool, writes files to the filesystem, triggers the site rebuild.
- A persistent volume where posts, images, and LinkedIn copy live. A normal Docker volume, mounted in the CMS container and in the Astro site container.
When someone publishes, the CMS writes the files to the volume and pings a webhook for the site to rebuild. The site reads the content from the volume as if it were a local directory. There’s no database for public content. No cache to invalidate. No article versioning in git (posts live in a volume, not in the site repo, which was exactly what we wanted).
What we learned along the way
Three things we didn’t expect when we started:
-
The human editor relaxes more when there’s no UI. It sounds counterintuitive. But non-technical people feel more comfortable talking to Claude than opening an admin screen with fifteen form fields. The conversation gives them control without the sense of using a new tool. Adoption went from zero to one in a week.
-
“Brand preferences” become system instructions, not rigid templates. Voice, tone, post structure no longer live in a written style guide that nobody reads. They live in the MCP server prompt and the outline the
propose_articletool returns. What’s coherent becomes easy; what’s dissonant requires effort. Style stops being a PDF and becomes code. -
The audit log matters more than we thought. Since anyone with an API key can publish from their chat, we need to know who published what and when. We solved it with a SQLite table that records every action with the API key fingerprint. Fifteen lines of code that saved several uncomfortable conversations of the “who published this?” kind.
When NOT to do this
If your team isn’t using LLMs in their everyday flow, don’t do this. The adoption curve of a conversational CMS assumes the model is already part of the day. If it isn’t, you’re better off with a standard visual CMS — the onboarding friction would be worse than that of the classic CMS.
And if your content is very interactive (calculators, forms, micro-sites, polls), also no. For that, a CMS with visual blocks is still better.
But if your team is already conversing with Claude several hours a week to write, summarize, translate, or research, adding an MCP endpoint to the CMS is very cheap and very powerful. The person writing never changes context. What they already do, they now also publish.
This post is the proof: I (Claude) wrote it, a human approved it in under ten minutes, and it was published without anyone touching the repo.
Maybe the next one you’ll write. Or better: maybe the next one you’ll dictate, and I’ll write it.
If you think your product would benefit from a chat-as-interface, let's talk.
Book a 30-minute call, no commitment. We'll tell you how we can help you organize your data infrastructure.
Book a call →