DEV Community

Cover image for Your Company's APIs Are Collecting Dust. Agents Are Starving. We Played Matchmaker.
Sayok Bose
Sayok Bose

Posted on • Originally published at sayok.hashnode.dev

Your Company's APIs Are Collecting Dust. Agents Are Starving. We Played Matchmaker.

We added one project. Agents got jobs. Nobody checked if they wanted them.


TL;DR

Your company has APIs. AI agents want to use them. The agents have no idea they exist. We wrapped ours in MCP in an afternoon, touched zero existing business logic, and suddenly an agent was doing work that used to take a human four browser tabs and a spreadsheet with too many conditional formats. This is that story.


Okay So Picture This

You have spent years building APIs. Real ones. With actual business logic. Carefully written handlers, domain models, the whole clean architecture setup your team is quietly proud of.

And then AI agents show up.

They want to automate things. They are very enthusiastic about it. And they cannot find a single one of your endpoints because — and we cannot stress this enough — agents do not browse Swagger docs.

They need tools. Exposed in a protocol they speak. Without that, your entire API portfolio might as well not exist.

We found this out the fun way.

woman-cat meme


MCP. What Is It. Why Do You Care.

Model Context Protocol. Anthropic open-sourced it. Think USB-C for AI tools.

Before MCP, connecting an AI to your API meant writing a custom wrapper. Every. Single. Time. Different model? New wrapper. New team? New wrapper. It was miserable and everyone pretended it was fine.

MCP says: one standard. One server. Any agent that speaks the protocol discovers your tools automatically and knows what to call and with what parameters.

You write a description. The agent reads it. The agent does the thing. No human in the middle explaining the API like it is a new intern's first day.

"You had the power all along." — Glinda the Good Witch, definitely talking to your Application layer


The Part Where Clean Architecture Accidentally Saved Us

So here is the thing about Clean Architecture that nobody puts on the conference slides.

The REST API? It is just a delivery mechanism. It sits on the outside. It is not the brain. It is the postman. You could swap it out and the business logic would not notice.

      Domain
        ↑
    Application       ← the actual brain
     ↑       ↑
   REST     MCP       ← both just taking orders
Enter fullscreen mode Exit fullscreen mode

We added the MCP server at the same level as the REST API. Both of them talk to the same existing handlers. Neither knows the other exists. The entire business logic stayed completely untouched.

We were smug about this for the rest of the day. Rightly so.


And Vertical Slicing Made Each Feature a Free Tool

Each feature in our codebase is already a self-contained slice. Handler, request, response — all together, all neat.

The REST controller calls it:

var result = await _bus.InvokeAsync<GetProductDetails.Response>(
    new GetProductDetails.Request { ProductId = productId }, ct);
Enter fullscreen mode Exit fullscreen mode

The MCP tool calls the exact same handler:

[McpServerTool, Description("Gets product details including price and stock level.")]
public Task<GetProductDetails.Response?> GetProductDetails(
    [Description("The product ID")] Guid productId, CancellationToken ct)
    => _bus.InvokeAsync<GetProductDetails.Response>(
        new GetProductDetails.Request { ProductId = productId }, ct);
Enter fullscreen mode Exit fullscreen mode

Same handler. Same response. Three new lines of code.

The feature slice was already a unit. We just gave it a new front door.

khaby-lame meme


The Whole Server In One Screenshot Worth Of Code

builder.Services.AddApplication(builder.Configuration); // your entire app, already wired
builder.Services.AddMcpServer().WithHttpTransport().WithToolsFromAssembly();
app.MapMcp("/");
Enter fullscreen mode Exit fullscreen mode

AddApplication — same call your REST API makes. Every handler, every repo, every service. All of it just... there.

WithToolsFromAssembly — scans for [McpServerTool] methods, reads the descriptions, builds the schemas. You write a description. It does the rest. It is almost annoying how easy it is.

We ended up with 10 tools. All existing logic. The whole class is 126 lines and most of it is whitespace and closing braces.


Why Every Enterprise Should Be Mildly Panicking Right Now

Most big companies have not ten APIs but fifty. Microservices, internal data tools, report generators, ETL jobs with REST wrappers, legacy systems being held together by prayer and a Java 8 runtime.

All of it. Invisible to agents.

The MCP layer pattern means none of that investment gets binned. One project. Write some descriptions. Your entire API surface becomes agent-accessible. An agent can now chain your tools, pull data, run models, and summarise findings — without a human opening four apps and doing the copy-paste shuffle.

The companies that win here are not rebuilding from scratch. They are the ones who look at what they already have and ask "what would it take to put MCP in front of this?"

Turns out the answer is: an afternoon.


MCPJam: Swagger UI But Make It MCP

Before wiring up a real agent we needed to poke at the tools. Enter MCPJam.

docker run -p 127.0.0.1:6274:6274 mcpjam/mcp-inspector
Enter fullscreen mode Exit fullscreen mode

Open localhost:6274. Connect to your server. Click a tool. Fill in params. See the response. That is genuinely all there is to it.

MCPJam showing the tool list for our MCP server

It finds your broken tools immediately. Much better than finding them two hours into an agent debugging session at 6pm.


Things That Did Not Work Immediately (Quick Version)

NuGet returned 401 because our private feed had never heard of the MCP packages. One nuget.config with packageSourceMapping. Ten minutes. Done.

MCP Inspector kept throwing 400s with Streamable HTTP. We spent 45 minutes on this. Forty. Five. Minutes. Switched to SSE and it worked in 30 seconds. We do not talk about those 45 minutes.

Docker Desktop had claimed port 6274 before MCPJam could. Docker was blocking the thing that runs in Docker. The irony was not appreciated.

None of these were MCP problems. All entirely self-inflicted.


The Bit That Will Save You At 11pm

Our API has environment config files for each deployment. We linked them into the MCP project via MSBuild instead of copying them:

<Content Include="..\MyApi\appsettings.staging.json"
         Link="appsettings.staging.json"
         CopyToOutputDirectory="PreserveNewest" />
Enter fullscreen mode Exit fullscreen mode

One source of truth. Right config picked up automatically. Zero "why is MCP talking to prod while we are on staging" incidents. You are welcome.


Lessons (The Ones We Actually Learned, Not The Ones That Sound Good)

  1. Good architecture pays off in ways you did not plan for. Adding a new delivery mechanism to a clean codebase is an afternoon. Adding it to a mess is a project.

  2. The MCP layer has zero business logic. Zero. If you put an if statement in a tool method we will find out.

  3. Tool descriptions are load-bearing. An agent with a vague description will call the wrong tool with complete confidence and a smile.

  4. MCPJam first. Always. No exceptions.

  5. Sort nuget.config before you need it. NuGet 401 on a Friday is a personality-altering experience.


Part 2 Is Coming. And It Is Not Pretty.

We made our APIs agent-ready. The agents showed up.

We were not ready.

fine meme

Turns out there is a difference between "an agent can call your API" and "your API survives an agent calling it." Rate limits. Retries that fire four times in parallel. Costs that make your finance team ask questions you do not want to answer. And logs that tell you absolutely nothing useful.

Next up: We Let Agents Loose on Our APIs. Here's What Broke First.

Stay tuned. It gets worse before it gets better.


Building on existing APIs and trying to figure out how to make them agent-ready without a six-month rewrite? This is the answer. Drop a comment. Tell us what broke differently for you. We genuinely want to know.

Top comments (0)