If you've integrated a third-party AI API into a content pipeline before, you already know the pattern. Auth headers. Rate limit handling. A conditional branch to decide whether to call a second endpoint based on the first response. Retry logic for the inevitable timeout. None of that is hard, individually, but it adds up to real code you own, test, and maintain indefinitely, for a task that's conceptually simple: check this text, fix it if it needs fixing.
MCP changes where that logic lives. Here's the actual before-and-after, not the marketing version.
The traditional workflow
Say you're building a content pipeline that drafts text, checks it for AI-detectability, and humanizes the flagged sections before publishing. Calling a humanizer's REST API directly, the shape of that integration typically looks something like this:
import requests
import time
API_KEY = "your-api-key"
BASE_URL = "https://api.example-humanizer.com/v1"
def detect(text: str) -> dict:
resp = requests.post(
f"{BASE_URL}/detect",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"text": text},
timeout=10,
)
resp.raise_for_status()
return resp.json()
def humanize(text: str, preserve: list[str], mode: str = "balanced") -> dict:
resp = requests.post(
f"{BASE_URL}/humanize",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"text": text, "preserve": preserve, "mode": mode},
timeout=15,
)
resp.raise_for_status()
return resp.json()
def process_draft(draft: str, keywords: list[str]) -> str:
detection = detect(draft)
flagged_paragraphs = [
p for p in detection["paragraphs"] if p["score"] > 30
]
if not flagged_paragraphs:
return draft
# Now you own the orchestration: rebuild the document from
# flagged and unflagged sections, retry on rate limits, handle
# partial failures, log what changed, verify preservation...
result = draft
for para in flagged_paragraphs:
retries = 0
while retries < 3:
try:
humanized = humanize(para["text"], preserve=keywords)
result = result.replace(para["text"], humanized["text"])
break
except requests.exceptions.HTTPError as e:
if e.response.status_code == 429:
time.sleep(2 ** retries)
retries += 1
else:
raise
return result
That's a simplified version. A production version needs proper logging, a real backoff strategy, preservation verification against the compliance response, and probably a queue if you're processing anything at volume. None of this is exotic engineering, it's just boilerplate that exists purely because two systems need to talk to each other, and you're the one who has to write, test, and maintain the glue.
The MCP workflow
Here's the same task through Walter's MCP server connected to Claude:
Draft a 1,200-word article about [topic]. Detect which paragraphs read
as AI-generated. Humanize only the flagged sections, preserving these
keywords: [keyword list]. Return the final text and a summary of what
changed.
That's it. No auth code, because the host manages the connection once, at setup, not per request. No conditional branching logic, because the LLM reads the detection result and decides what to humanize the same way it reads any other context. No retry logic you wrote, because that's handled at the protocol/host level, not in your application code. No manual response parsing, because the result comes back as part of the conversation, not a JSON blob you have to unpack.
The setup itself is one config entry:
[mcp_servers.walterwrites]
url = "https://mcp-server.walterwrites.ai/mcp"
or, in Claude's UI, adding a custom connector with a name and a URL. Done once, used indefinitely, across every conversation.
What actually changed, structurally
The real shift isn't "fewer lines of code" as a vanity metric. It's where the orchestration logic lives.
In the traditional model, your application is responsible for: deciding when to call detect, interpreting the response, deciding whether and what to call humanize on, handling failures at every step, and reassembling the final output. That's real application logic, specific to this integration, that has nothing to do with your actual product.
In the MCP model, the LLM host owns that orchestration. It decides which tool to call based on the conversation, in what order, and how to handle the response, the same general-purpose reasoning it's already doing for everything else in the conversation. Your "integration code" is a config entry pointing at a URL. The tool-selection logic that used to live in your if statements now lives in the model's reasoning, driven by your prompt instead of your source code.
This is the actual point of MCP as a protocol: instead of writing custom orchestration code for every tool you want an AI system to use, you expose the tool once, in a standard format, and let the host's own reasoning handle when and how to call it.
Side-by-side
| Traditional REST integration | Walter MCP | |
|---|---|---|
| Auth handling | Your code, per request | Host-managed, once |
| Detect-then-humanize branching | Your conditional logic | Model's reasoning, driven by prompt |
| Retry/backoff | You write and maintain it | Handled at host/protocol level |
| Response parsing | You unpack JSON | Returned as conversational context |
| Adding a second AI client (e.g. ChatGPT) | Rewrite the integration | Same server, new client config |
| What you maintain long-term | Integration code + the pipeline logic | Just the pipeline logic |
That last row is arguably the biggest deal for anything long-lived. A REST integration is code you own forever, it needs updating when the API changes, needs its own test coverage, needs someone who remembers why a specific retry threshold was chosen two years ago. An MCP connection is closer to infrastructure, configured once, and the burden of keeping the tool-calling logic correct shifts to the host and server maintainers rather than sitting in your repo.
Where the traditional API approach still wins
Being straight about this, since the MCP model isn't strictly better for every case.
High-throughput batch jobs outside a conversational context. If you're processing 50,000 product descriptions overnight in a cron job, you want deterministic, directly-controlled API calls in a script, not an LLM conversation orchestrating tool calls. MCP is built around a host managing a conversation; a headless batch pipeline doesn't have that conversational context to begin with. Direct API access (Walter, like most serious tools in this space, still exposes one) is the right tool here.
When you need guaranteed, deterministic control flow. LLM-driven tool selection is reliable but not deterministic in the strict sense, the model decides when to call a tool based on reasoning over the prompt. If a compliance requirement means step B must always run after step A with zero exceptions, encoding that in your own application logic with direct API calls gives you a guarantee an LLM-orchestrated flow doesn't strictly provide.
Extremely latency-sensitive paths. A direct API call has one network hop. An MCP-orchestrated flow goes through the host's reasoning loop first, which adds latency that matters in some real-time contexts and doesn't matter at all in others.
If your workflow is genuinely conversational, iterative content drafting, an agent doing multi-step reasoning, anything where a human or another agent is in the loop deciding what to do next, MCP removes real, ongoing maintenance burden. If it's a deterministic, high-volume, headless pipeline, direct API integration is still the right call, and that's true regardless of which humanizer you're using.
Migrating an existing integration
If you've already got a REST-based integration and want to move the conversational parts of your workflow to MCP without ripping everything out:
- Keep the direct API integration for any headless/batch paths, that use case doesn't change.
- For anything conversational or agent-driven, add the MCP server as a connector in whatever host you're using (Claude, ChatGPT Developer Mode, Codex) rather than routing those calls through your existing REST client.
- Delete the orchestration code (the detect-then-humanize branching, the retry logic specific to that flow) for the paths you've moved, that's the actual payoff, not just an additional integration option sitting next to the old one.
The goal isn't running both forever. It's recognizing which parts of your pipeline are genuinely conversational (move to MCP, delete the glue code) and which are genuinely deterministic batch jobs (keep the direct API, it was never the wrong tool for that case).
FAQs
Does Walter still offer a direct REST API alongside MCP?
Yes. MCP is the right fit for conversational, host-driven workflows. Direct API access remains the better fit for headless batch processing and pipelines requiring deterministic control flow.
Is MCP slower than a direct API call?
There's more latency in an MCP-orchestrated flow than a single direct API call, since it goes through the host's reasoning loop first. For interactive, conversational use this is negligible. For latency-critical, high-frequency paths, direct API access is still the better choice.
Do I need to rewrite my whole pipeline to use MCP?
No. The two approaches are complementary, not mutually exclusive. Most teams keep direct API integration for batch/headless work and adopt MCP specifically for the conversational or agent-driven parts of their workflow.
What's the actual protocol-level benefit of MCP over a custom integration?
It solves the M×N integration problem: instead of writing custom glue code for every combination of AI host and external tool, a tool is exposed once via MCP and any compliant host can use it without additional integration work on either side.
Top comments (0)