<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Jorge Rojas</title>
    <description>The latest articles on DEV Community by Jorge Rojas (@chorch_md).</description>
    <link>https://dev.to/chorch_md</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4205296%2F788af3dd-da69-49d7-aa10-b41ee2c21f8e.png</url>
      <title>DEV Community: Jorge Rojas</title>
      <link>https://dev.to/chorch_md</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/chorch_md"/>
    <language>en</language>
    <item>
      <title>Wiring process around an MCP agent (so it does not ship SEO slop)</title>
      <dc:creator>Jorge Rojas</dc:creator>
      <pubDate>Sun, 25 Oct 2026 02:10:52 +0000</pubDate>
      <link>https://dev.to/chorch_md/wiring-process-around-an-mcp-agent-so-it-does-not-ship-seo-slop-4ed0</link>
      <guid>https://dev.to/chorch_md/wiring-process-around-an-mcp-agent-so-it-does-not-ship-seo-slop-4ed0</guid>
      <description>&lt;p&gt;If you write a technical blog as a side quest, you already know the pattern. You open Claude or Cursor, ask for a post, get something that looks finished, and then spend an hour deleting filler, inventing a keyword strategy you never measured, and wondering whether you just published the same intent as last month's article under a new title.&lt;/p&gt;

&lt;p&gt;Developers are good at shipping code. Most of us are not SEO people. We still need a changelog, a how-to, or a post that answer engines can quote without embarrassment. The agent can write. What it usually lacks is process: a profile of the product, a calendar of topics, a list of facts you will stand behind, and a hard line between "draft ready" and "live on the blog".&lt;/p&gt;

&lt;p&gt;That gap is why a lot of "AI SEO" tools sell you tokens or finished volume. Another design is possible: keep generation in the subscription you already pay for, and put the process in a remote MCP server the agent can call. This post is about that design choice, what the human still owns, and why we refuse a publish tool. seodraft is the concrete case we built; the debate is the point.&lt;/p&gt;

&lt;h2&gt;
  
  
  The fork: sell tokens, or wrap the agent you already have
&lt;/h2&gt;

&lt;p&gt;Most AI writing products put generation on their bill. You chat inside their UI, they call a model, and the meter runs on their side. Content factories go further: they sell finished posts, often with auto-publish into WordPress.&lt;/p&gt;

&lt;p&gt;There is a third shape if your client already speaks MCP. The agent stays Claude, ChatGPT, Cursor, or Codex. A remote server exposes tools for planning, drafting, checking, and delivering a file. The server does not call a model. It holds state and rules. Calls do not add a per-token line from that product.&lt;/p&gt;

&lt;p&gt;Tradeoffs are honest:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you will not connect an agent, nothing writes. There is no captive chat that "just works" without your subscription.&lt;/li&gt;
&lt;li&gt;If you want unattended auto-publish, this is the wrong architecture. Process without a publish tool is a feature, not a missing checkbox.&lt;/li&gt;
&lt;li&gt;If you already live in Cursor or Claude Code, wiring process into tools you can list and call feels natural. If you do not, a hosted chat product may fit better.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We picked the third shape for seodraft because we are developers who already pay for agents, not because wrapping MCP is trendy. The interesting question for this community is whether &lt;em&gt;you&lt;/em&gt; want process in tools, or generation in someone else's meter.&lt;/p&gt;

&lt;h2&gt;
  
  
  What "remote MCP" changes in practice
&lt;/h2&gt;

&lt;p&gt;An MCP server exposes tools an AI client can list and call. Local means a process on your machine. Remote means a URL.&lt;/p&gt;

&lt;p&gt;For a content loop, remote + OAuth is nicer than a long-lived local binary: nothing to keep alive, same rows as a browser UI, and a bearer token per request. Streamable HTTP without a server session id means a dropped connection is just "send the next call". Stale writes can refuse with a version conflict instead of overwriting what you edited in the UI.&lt;/p&gt;

&lt;p&gt;A minimal client entry looks like any other remote MCP URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"content-process"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://example.com/mcp"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Auth discovery, dynamic client registration, and PKCE can all start from that URL. The first authenticated tool call is better proof of "connected" than a settings toggle.&lt;/p&gt;

&lt;p&gt;None of that is SEO-specific. It is the same pattern as wrapping a issue tracker or a deploy API. The SEO part is which tools you expose and which ones you refuse to expose.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the agent can drive (and what we leave out)
&lt;/h2&gt;

&lt;p&gt;Group tools by stage, the way you would group CLI subcommands:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Plan&lt;/strong&gt;: topics, research, calendar.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Write&lt;/strong&gt;: load a write skill, read a product profile and internal link graph, pick the next slot, upsert a post.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Review&lt;/strong&gt;: run the rules check, list evidence the human accepted, mark ready to export.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deliver&lt;/strong&gt;: send a &lt;code&gt;draft: true&lt;/code&gt; file to a git target, check delivery status.&lt;/p&gt;

&lt;p&gt;There is &lt;strong&gt;no publish tool&lt;/strong&gt;. Approval can mean "rules passed" and "file delivered as draft". Shipping to production stays in your CMS, your PR, or your hand. That split is intentional. An agent that can research and draft should not be one tool call away from overwriting the homepage.&lt;/p&gt;

&lt;p&gt;Optional SERP or volume data is another boundary. If the server never holds a shared vendor key, the human connects their own account (or lives with unmeasured estimates). Cost shows before a paid call. That is the same discipline you want for any tool that can spend money.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the human still owns
&lt;/h2&gt;

&lt;p&gt;Three decisions do not belong to the model:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Evidence.&lt;/strong&gt; The agent cites only numbers, cases, and lessons you accepted. Invented "studies show 73%" is a process failure, not a style failure.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rules verdict.&lt;/strong&gt; Checks are deterministic code: keyword placement, an answer under every H2, your own evidence, no filler list, cannibalization as a hard stop. Same draft, same verdict. After two failed redrafts the slot stops. No grinding until something slips through.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ship.&lt;/strong&gt; Export Markdown, HTML, or a git draft. Nothing goes live until you move it.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you skip those, you get the familiar blog of interchangeable posts that answer engines ignore and readers bounce from. If you keep them, the agent is a fast junior writer with a checklist, not an unsupervised content factory.&lt;/p&gt;

&lt;h2&gt;
  
  
  A concrete build (ours)
&lt;/h2&gt;

&lt;p&gt;We wired this as &lt;a href="https://seodraft.app/features/mcp-server" rel="noopener noreferrer"&gt;seodraft's remote MCP server&lt;/a&gt;: Streamable HTTP, OAuth, dozens of tools in the stages above, no publish tool, optional DataForSEO on your own credentials. The write skill the agent loads before drafting is public at seodraft.app/skill if you want to read the brief shape without connecting anything.&lt;/p&gt;

&lt;p&gt;That paragraph is the product mention. The rest of the post stands without it. You could rebuild the same boundaries on a private server for an internal docs site tomorrow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Open questions for people wiring agents
&lt;/h2&gt;

&lt;p&gt;I am curious how others draw the line:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do you let an agent open a PR, or only write files under &lt;code&gt;draft/&lt;/code&gt;?&lt;/li&gt;
&lt;li&gt;Do you keep evidence in a DB, a markdown folder, or a Notion dump the model is allowed to invent from?&lt;/li&gt;
&lt;li&gt;When a draft fails the same rule twice, do you stop the slot or let the human override?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We stopped the slot and refused publish. That feels right for a public blog. It may be wrong for an internal changelog. Tell me where you land.&lt;/p&gt;

</description>
      <category>mcp</category>
      <category>seo</category>
      <category>ai</category>
      <category>cursor</category>
    </item>
  </channel>
</rss>
