Dev.to AI πŸ€– Ai πŸ‘ 0 πŸ“– 5 min read

Your API's newest users are agents...

Who called your API last? For us, the honest answer is more and more often an agent. Claude Code debugging a flow. An assistant looking up an order. Someone's custom GPT. Our tools still assume a human pressing Send.

Who called your API last?

For us, the honest answer is more and more often an agent. Claude Code debugging a flow. An assistant looking up an order. Someone's custom GPT.

Our tools still assume a human pressing Send.

This post is about that gap. How we ran into it ourselves, how most teams handle it today, and what we changed.

How we ran into it

We run ApyHub, a catalog of utility APIs. This year we wanted assistants like Claude, ChatGPT, and Le Chat to call those APIs directly. So we built an MCP server and published it to the official MCP registry.

It worked. People used it.

Then we noticed something uncomfortable. We now had two descriptions of the same API.

One was the requests and tests we already trusted. The other was the MCP server, written by hand, sitting next to them.

Change an endpoint? Update both. Forget one? Find out when an agent breaks.

Testing the MCP side was its own chore. Connect an inspector, click a tool, read the JSON, close the tab. Next release, repeat from memory.

None of this is dramatic. It's just the kind of friction that adds up quietly until you notice you've built a second, worse copy of something you already had.

The three situations we kept hitting

When we looked closer, it was really three different problems. They all involve MCP, which is why they're easy to blur together. The difference is who is calling whom.

1. Your own coding agent, debugging blind

Checkout returns a 400. You ask Claude Code for help.

Today, you paste the error. Maybe a curl command. The agent reasons about what might be wrong. When it wants to test something, it writes its own curl, guesses the headers, and asks where the token lives.

You end up being the agent's hands.

What we wanted was simpler. The requests already exist in the project. Let the agent run them.

So that's what we built. We use Voiden for this, the open-source API tool we work on, where requests live as plain Markdown files in the repo. One button (or voiden agent in the terminal) and your coding agent can list, run, and inspect those requests. It calls the real endpoint and reads the real response. In our checkout example, it spots the missing header on its own.

This is on for the whole project by default. Our reasoning: it's you, your editor, and your own agent. Small trust boundary.

I'm fairly confident about that. But I know some teams will disagree, especially with production credentials in the environment. If that's you, I'd like to hear where you'd draw the line.

2. Someone else's agent, calling one endpoint

Your support assistant needs to issue refunds. Only refunds.

Today, someone writes an MCP server. Picks an SDK. Redefines the inputs as a schema. Wires up auth. Figures out secrets. Hosts it.

Now there's a new codebase describing an API you already had. It drifts. Nobody notices until an agent sends a field that was renamed two sprints ago.

This was exactly our ApyHub story.

What we do now: take the refund request that's already written and tested. Mark it as a tool. Choose which values the agent can set, in this case just the order ID. Secrets stay in your environment. That's the whole server.

Nothing is exposed until you mark it. Once other people's agents are involved, opt-in felt like the only honest default.

One rule is more opinionated. A tool is only available while its tests pass. Test goes red, tool goes offline.

That's strict. With a flaky test, it will annoy you. We chose it anyway, because an agent losing access felt better than an agent calling something nobody has verified lately.

Is that the right trade? I genuinely go back and forth. Curious what others think.

3. Testing an MCP server, yours or a vendor's

Two versions of this. You run your own MCP server and want to know it still works before a release. Or you're about to build on a vendor's server and want to see what it really returns.

Today: an inspector tab. Click, read, close. Gone. Or a one-off script that lives in someone's home folder.

What we wanted was the same thing we already had for REST. Save the call. Add assertions. Run it in CI.

So now an MCP call is just another block in the file. Point it at a server, pick a tool, check the response with the same auth and assertions you'd use anywhere else. Before a release, it confirms search_orders still returns the shape you expect. For a vendor's server, like Notion's, the file becomes a working reference the team can rerun.

The part I care about most

All three live in one file.

The request you test with is the one your agent runs. It's the one you publish as a tool. And it sits right next to your MCP tests.

One description of the API, instead of three that slowly disagree.

Because it's a plain file in the repo, changes go through a pull request. If someone widens what the refund tool accepts, a reviewer sees it in the diff.

That's the real point for me. Giving an agent access to an API is a permission decision. Permission decisions deserve a review trail.

Why we keep building this

Voiden isn't our core business. ApyHub pays for it. We build it because we use it every day, and when something bugs us enough, it ends up in the next release.

This one bugged us for months.

It shipped in 2.3, along with a few other things. The changelog has the full list if you're curious.

An open question, since I don't think anyone has this fully figured out yet:

how are you deciding what agents can touch in your APIs today? Config file? Gateway? Hand-written MCP server? Gut feeling?

I'd like to hear what's working, and what isn't.

If you want to poke at it: voiden.md Β· GitHub

πŸ“° Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.