When 'Just Use MCP' Is the Right Call — and When It Isn't

By: on May 22, 2026
A couple of pipes connected to the side of a building

The Comment I Keep Bracing For

If you write about the bot proxy pattern — putting credentials behind a Unix socket so the agent never sees them — there's an obvious objection waiting: "Dude, just use MCP. Why reinvent the wheel? There's probably a slick MCP server that does what your fifty-line shell script does, with a logo and a maintainer."

It's a fair point, and I want to take the strong version of it seriously. MCP is a real, well-designed standard. It solves genuine problems: how do I plug a tool into an agent without writing custom glue every time — and how do I make that tool work across Claude Desktop, Cursor, and a teammate's agent without maintaining five bespoke scripts.

So this isn't "MCP bad." It's narrower than that: for the handful of tools I use every single day, inside my own single-host setup, I still write my own thin proxy and call the API directly. Not instead of MCP everywhere — just there. Here's the reasoning, including the part where the objection turns out to be right.

The short version: if you have a coding agent, the integration MCP hands you — the glue — is the cheap part. What I don't want to give up is control over how the tool's response lands in the agent's context. And, as we'll see, that control isn't really MCP-versus-bespoke at all. It's "did I write this integration, or did someone else."

Underneath, the Part I Care About Is Just an API Call

Here's the honest version. MCP is more than "an HTTP call with a logo" — it standardizes tool discovery, typed input schemas, and a clean way for one server to serve many agents. It runs locally over stdio or remotely over HTTP, and it has primitives beyond plain tool calls (resources, prompts). That's real engineering, and it's why it caught on.

But for a lot of the integrations I actually build, the logic I care about is small: call an upstream API, shape the response, hand it to the agent. That core I can write with curl and jq. So can you. So can your coding agent.

When I want my agent to fetch a web page through headless Chromium, I open Claude Code and say "write me a proxy that exposes a Unix socket, validates URLs against an allowlist, renders with Chromium, cleans with readability, returns markdown." Twenty minutes later I have the proxy from the previous post. Fifty lines of bash. I own every line. The "upstream API" in that case is Chromium itself, but the shape is identical for every other integration: agent calls my CLI, CLI calls the real API, response comes back in exactly the form I chose.

The "write custom glue every time" problem is real — but a coding agent shrinks it. If your agent can write a 50-line proxy in twenty minutes, the integration itself stops being the expensive part. What MCP also buys — discovery, schemas, cross-client portability — is genuine value too. It's just not value I need for a tool that only ever runs in my own gateway.

What You Lose When You Adopt Someone Else's MCP Server

Notice the words "someone else's" — they're doing the real work here. The pitch for adopting a third-party MCP server is "drop it in and your agent gets a new capability." That's the feature. It's also the cost. Here's what you give up when the integration is a black box you didn't write:

You don't control the response shape. The MCP server returns whatever JSON the author thought was useful. Maybe it's a 4KB dump of every field the upstream API exposes. Maybe it's a tight summary. You don't get to decide. Your agent burns tokens reading fields it doesn't care about, and you can't strip them without forking the server.

You don't control the prompt surface. Every tool call returns text. That text becomes context for the next agent turn. If you wrote the proxy, you can decide what guidance goes in the response — "this returned 200 results, consider filtering by date" or "the API returned a deprecation warning, don't use this endpoint after June." A third-party MCP server returns whatever it returns. You can't inject your own hints.

You don't control the debug surface. When something goes wrong — and something always goes wrong — your debugging starts with "let me read the source of this MCP server I didn't write." With a 50-line shell script, debugging starts with cat proxy.sh and ends two minutes later. The whole call path fits on one screen.

You don't control the failure mode. Does the MCP server retry on 429? Does it cache? Does it leak the credential into the error message? You're auditing someone else's defaults. With your own proxy, the defaults are whatever you wrote, and you wrote them on purpose.

"So Write Your Own MCP Server"

This is the strongest comeback, and it's correct. Every one of those four problems vanishes the moment you author the server — you control the response shape, the embedded hints, the retries, the error redaction, all of it. Which is the real point I want to land: none of this is MCP-versus-bespoke. It's self-authored versus someone else's. A proxy you wrote and an MCP server you wrote give you the same control. A third-party shell script and a third-party MCP server take the same control away. The protocol was never the variable.

So why do I reach for a CLI-behind-a-socket instead of writing my own MCP server? The honest, less-technical answer comes first: I build my own agents — OpenClaw today, whatever I write next — and for anything I build myself, I want the tools it uses to be things I fully own and understand. That's the main draw. Control here isn't a means to an end; it is the end. When the agent is mine, I don't want a layer in the middle whose behavior I have to take on faith.

The architecture just makes that cheap. My agents run on one host under OpenClaw, where the security model is an exec allowlist: I grant the agent specific binaries, and credentials live in separate proxy users the agent literally can't read. Adding a tool to that model is one allowlist entry. Standing up an MCP server is another long-running process to run, sandbox, and lock down to the same standard. For a single-host setup, that's more moving parts for control I already have. If I needed the same tool in Claude Desktop, Cursor, and a teammate's agent, I'd write the MCP server without hesitation — portability is exactly what it's for.

The Extra Mile: Tool Responses Are Prompts

This is the part I want to drive home, because it's the thing that turned me from "MCP-curious" to "I'll keep writing my own."

Every tool response your agent receives goes straight into the context window. It's not "data." It's prompt. It shapes what the agent does next. Which means the shape of your tool's output is a prompt engineering decision, not just an API design decision.

Here's a concrete example. My calendar proxy used to return raw Google Calendar JSON:

{
  "items": [
    {"id": "abc123", "summary": "Standup", "start": {"dateTime": "2026-05-23T09:00:00-07:00", "timeZone": "America/Los_Angeles"}, "end": {"dateTime": "2026-05-23T09:15:00-07:00", "timeZone": "America/Los_Angeles"}, "attendees": [...], "creator": {...}, "organizer": {...}, "hangoutLink": "...", "conferenceData": {...}}
  ]
}

The agent spent half its context budget on fields it never used. Worse, it kept hallucinating about hangoutLink being present when it wasn't, because it had seen the field name once and assumed it always existed.

I rewrote the proxy response to look like this:

Today, Sat May 23:
  09:00–09:15  Standup
  14:00–15:00  1:1 with Sam

(2 events. Use `calendar week` for the full week.)

Same data. One-tenth the tokens. Zero hallucinations about fields that don't exist. And a hint at the end — that parenthetical — that steers the agent toward the right follow-up tool without me ever asking it to. That last line is a prompt, embedded in a tool response, that I could not have added if I were consuming a third-party MCP server.

This is the same principle I wrote about in encoding agent understanding into your code — make the artifact teach the next reader (or the next agent session) what it needs to know. Tool responses are part of that artifact surface. Most people leave them on default. You don't have to.

Bespoke Proxies Give You a Real Eval Loop

Once you own the proxy, you also own the test surface. I run my proxies' responses through the same grid sweep harness I use for prompts. Different response shapes, different padding, different summary styles — see which one the agent handles best.

You can't grid-sweep a third-party MCP server's output without forking it. With your own proxy, the response template is a string variable. Change it, re-run, score, iterate. The proxy becomes part of the evaluation surface instead of a black box that sits between you and the model.

This is the loop I keep coming back to: generate → judge → iterate. Tool responses are one of the things you should be iterating on. Your coding agent can help you do it, the same way it helps you iterate on prompts — but only if you own the code.

The Honest Cost: You Own Every Bug, Too

"I own every line" cuts both ways. A fifty-line shell proxy is easy to read — and easy to get subtly wrong. URL validation, redirect handling, socket permissions, whether a credential leaks into an error message: those are exactly the edges that bite, and a script you wrote on a Tuesday afternoon has had one set of eyes on them. A widely-used MCP server has had many. When I actually sat down and audited my own proxies, I found sharp edges I'd glossed over — "fits on one screen" is not the same as "correct," and it's definitely not the same as "secure."

So price it in honestly: bespoke means you own the response shape and the maintenance and the security review. For tools I live in every day, that trade is worth it. For tools I touch once a quarter, it usually isn't — which is the whole point of the next section.

When MCP Is Actually the Right Call

I'm not anti-MCP. There are cases where it's clearly the answer:

  • You're shipping a product. If users will install your integration into their agent, MCP is the protocol they expect. Don't make them learn your weird Unix socket shape.
  • You're integrating with a vendor's MCP server that's actually maintained. If GitHub ships an official MCP server, you should probably use it before you go write your own GitHub proxy. Their server already handles auth, rate limiting, and pagination correctly. Don't reinvent unless you have a reason.
  • You don't have a coding agent (or don't want to use one for this). If you're a non-developer trying to wire a calendar into Claude Desktop, MCP is the path. Click install. Done.
  • You need cross-agent portability. If the same integration has to work in Claude Desktop, Cursor, and three internal tools, a standard protocol beats five bespoke scripts.

The pattern I've landed on: use MCP at the boundaries (vendor integrations, cross-tool portability, anything I'd hand to a non-developer), and use bespoke proxies for everything inside my own system. The two coexist fine. They're solving different problems.

The "Dude" Test

Whenever someone tells me to "just use MCP," I ask myself one question: do I want to control how the agent experiences this tool, or do I want someone else to make those choices for me?

For my calendar, my web fetcher, my Sonarr proxy, my internal bridge between bots — I want to make those choices. The response shape, the embedded prompts, the failure modes, the audit trail. Every one of those is a knob I'm turning to make the agent work better. Giving up the knobs to standardize on a protocol is a trade I won't make for tools I use every day.

For the tools I touch once a quarter, where I just need the capability and don't care about the experience? Sure, install the MCP server. Move on with your life.

Try This Before You Install Your Next MCP Server ⚡

Takes 20 minutes. You'll know if you should switch.

  1. Pick one MCP server you're using. Find the upstream API it wraps. It's almost always a documented HTTP endpoint with an OpenAPI spec or a few curl examples in the README.
  2. Ask your coding agent to write a proxy that calls that API directly. Same socat-and-jq shape from the proxy pattern post. Have it return a tight, summarized response instead of raw API JSON.
  3. Run the same agent task against both and compare token usage, accuracy, and how often the agent hallucinates about fields. If your bespoke proxy wins, you have your answer.

If the MCP server wins, great — keep using it. But you'll have done the comparison instead of taking the standard on faith. That's the whole point.

MCP is a fine answer — especially at the boundaries, and especially when you write the server yourself. But if you have a coding agent, the glue is the cheap part. For the tools you live in every day, it's worth owning how their answers reach the model.

Header image by Sebastian Morelli-Peyton on Unsplash

Content on this blog was created using human and AI-assisted workflows described here. Original ideas and editorial decisions by Justin Quaintance.