Guillaume Duvernay

I stopped using MCP for most of my work

AI efficiencyagentsMCP

For a few months now I’ve avoided MCP whenever I have the choice, and used something else instead. I don’t have a problem with the protocol. I have a problem with what it costs me on the work I do every day, which is a lot of repetitive operations across a CRM, a CMS and a few analytics tools.

This is the written version of a video I published, with the same examples.

The setup never held across harnesses

I switch between Claude Code, Codex and Antigravity depending on what I’m doing. Each of them connects MCP servers its own way. Sometimes it’s a JSON config file. Sometimes there’s an official plugin to find, and when there isn’t, you add a custom server by hand.

So every time I opened a session in a different harness, I wasn’t sure I had everything connected. Some servers had dropped and needed re-authenticating. I’d start the work and find out halfway through.

On a team plan it gets worse. In Claude Code, only the admin can add custom connectors before they’re available to everyone, so a teammate who needs one waits.

That’s friction I can live with. The part that really costs me is further down.

Tool descriptions cost you before you ask anything

When an MCP server is connected, it exposes its tools to the client. For a CRM that’s things like list contacts, get a contact, create a contact, edit a contact. Each tool carries a description saying when to use it, plus the shape of the payload it expects.

All of that sits in the session. Connect ten servers with twenty tools each and you’re carrying two hundred tool descriptions and their schemas into every conversation, including the ones where you use two of them.

Ten servers at twenty tools is an illustrative count, not a measurement of any particular setup. What it shows is the shape: a fixed budget, most of it spent before the conversation starts.
Every one of these is loaded whether or not the session touches it. The two marked are the ones a typical session calls.

Clients are getting better here. Claude Code can reveal tools progressively instead of loading every description up front, and there are other approaches where the agent searches for the tool it needs. So I expect this one to mostly go away on its own, which is why it’s not my main complaint.

The agent retypes what you already have

Say you ask your agent to push two hundred contacts from a CSV into your CRM. The file is right there on your laptop, properly formatted.

The agent still has to write every tool call itself, character by character: the tool name, then the payload with the contact’s name, email and whatever else. Two hundred times. Usually not in parallel.

The costs here are shapes rather than measurements. The middle row scales with your file and the others don't.

What I’d want is for the agent to look at the CSV, work out how the headers map to the CRM’s fields, and then move the data without reading it into itself. That’s a transformation, and most clients can’t do it, so they rewrite instead.

It’s also unreliable. Past a couple of hundred records, an agent gets lazy and does half of them, or makes a small mistake in the middle that you find later.

Seven minutes to change one number

This is the one that made me stop using MCP for the work I repeat.

I manage a website in Webflow. Articles live in a CMS collection, one row per article, and the body is rich text, which Webflow stores as inline HTML. A typical article is two thousand words.

I asked the agent to find an article and change one number in it, 70 to 80.

Finding it was instant. Then Webflow’s MCP has one tool for this: edit a CMS item, where you pass the fields you want to change along with their new values. There’s no search and replace inside a field. So to change two characters, the agent read the whole body back, retyped all two thousand words with the new number in the middle, and sent the whole thing.

The seven minutes and the 20% are what I measured on my own session that day, on one article.

One fix would be smarter tools: a search and replace endpoint on a CMS field. That would help, and it’s not something I can make happen on someone else’s server.

The other fix doesn’t need anyone’s permission. Pull the article once, write it to a local file, edit it there with the tools the harness is already good at, and push it back.

The middle column is the whole difference. Editing a file is what these harnesses are best at, and none of that edit passes through the model.

You can’t limit what comes back

An MCP call always returns something, and whatever it returns becomes part of your context window.

Ask for your twenty most recent articles because you want their publication dates, and unless the server happens to expose a fields parameter, you get twenty full articles. Bodies included. Two thousand words each, plus every other field in the collection.

Unless the server exposes a parameter for it, the payload lands whole, and it stays in the window for the rest of the session.

The API was already there

A lot of MCP servers are a wrapper around an API the company already had.

Webflow, HubSpot and the rest have documented REST APIs that have been public for years. That’s what Zapier, Make, n8n and Softr built their connectors on. When those companies shipped an MCP server, most of them mapped their existing endpoints into the protocol. So it’s a second interface onto the same operations.

Where a platform keeps its MCP and its API in parity, the interface you pick doesn't change what you can do with it.

And your agent can call an API perfectly well. In a Codex or Claude Code session it writes the request and runs it from your machine. The difference is that an API call can sit inside a script.

That one difference is what fixes the retyping. The agent looks at your CSV, works out the mapping once, writes a script that loops over the rows and makes one call each, and then runs it. From that point there’s no model in the loop at all. The script runs until it’s done.

Write a skill, not a tool list

An API isn’t self-explanatory, and that’s what MCP actually gives you. Tell an agent to “use the HubSpot API” and it will guess from whatever it remembers. Usually close, but not exact.

But APIs are documented, usually with an OpenAPI spec you can point at or let the agent find. And for anything you do more than once, you write it down.

# Skill: CSV to CRM contacts

We never use the CRM MCP. Everything goes through the REST API.

## Endpoints we use
- `POST /crm/v3/objects/contacts` for one contact
- `POST /crm/v3/objects/contacts/batch/create` for up to 100 per call
- Full reference: https://developers.hubspot.com/docs/api/crm/contacts

## Auth
The key lives in `.env` at the repo root as `CRM_KEY`. Read it with
`source .env` inside the script. Never print it, never paste it into a
message.

## Mapping
Inspect the CSV headers first, then map to the CRM fields. Ask before
guessing on anything that isn't an obvious match.

Once that file exists, the agent knows how you talk to your CRM, which endpoints you use and how to authenticate. It stops guessing, and you get the same reliability MCP was giving you.

CLIs work the same way and are often better. Agents are good at terminal commands, most CLIs document themselves through help output, and many handle OAuth for you: you log in once in the browser and the token sits on your machine. Under the hood it’s usually the same API again.

The key stays in the file

This is where APIs are genuinely more work than MCP. Most MCP servers now use OAuth, so you click through a login page and you’re done. With an API you’re usually holding a key.

I keep one .env file at the root of the folder the agent works in, and I tell the agent the key is there and how to use it: through a command that reads it into the script, never by printing it into the conversation. The agent knows the key exists and where it lives. It never sees the value.

Chain it like the terminal already does

Once calls live in scripts, you can put them end to end, and the model only sees what comes out.

Take something I do regularly: find the three articles I haven’t touched in the longest time, pull how they’re performing, and decide what to rewrite.

Through MCP, every intermediate response would have landed in the context window. Here the first three steps never reach the model at all.

The agent gets a short, structured report and does what it’s actually good at, which is reading it and telling me what to fix. It never saw the twenty articles it sorted through.

Nobody needs an API key on their laptop

The obvious objection: we’re ten people on a marketing team, does everyone now keep API keys on their machine?

No. What we built at Softr is a proxy. Each person has one key of their own. They call the proxy with it, the proxy knows who they are, and it routes the request to the right service using the key it holds for that service.

The permission layer is the part we had no way to build before. A raw key carries the same scopes for everyone who holds it.

Permissions are the part I care about most. An API key is scoped when you create it, and after that everyone holding it can do the same things. Through the proxy we whitelist operations, so our Webflow key can be read-only for most of the team and let a content manager create and edit. Nobody can delete an article by accident, and there was nothing for anyone to install.

When MCP is still the right tool

I’m not arguing against MCP. For one-off work it’s the fastest thing there is, and I still use it.

Nothing here says pick one for everything. The cost of MCP shows up with volume and repetition, so that's where it's worth replacing.

The moment to look at this is when a real part of your work runs through an agent talking to your tools. Before that, setting things up is most of the work, and MCP wins on that.

After that, it’s worth an afternoon. Ask your agent what endpoints your tools expose, have it write the skill with you, and run one of your recurring tasks both ways. The difference shows up immediately on anything with volume in it.

Sources