What exactly is MCP? Is it some mysterious technology that requires secret knowledge to implement? Sometimes, when I read tutorials, I get that impression! Meanwhile, the basic concept is ridiculously easy to understand, and you can get a simple implementation running in minutes. The complications start later. And oh boy, there are quite a few of them!
This article is a follow-up to my previous post, The Dirty Secret Behind AI Agents (Demo). Back then, I promised you I'd write another part about MCP soon. And look, it only took me four months! π If you're interested in building an agent, feel free to go back to that article. But if you only care about MCP, you can happily keep reading.
I won't pretend that the upcoming AI Coding Summit in Berlin, where I'll be speaking about this very topic, didn't motivate me to finally finish it. I'll leave a link to my speaker badge at the bottom of the article. Apparently, it gets you some discounts or even access to free videos!
In the previous post, I explained that an AI agent is such a simple concept that you can build one in about 80 lines of code. MCP isn't all that different. My handful of tools takes around 150 lines of repetitive code, and the client side adds another hundred or so. ;)
But let's start at the beginning!!!
π€ What Exactly Is MCP?
MCP stands for Model Context Protocol. And as the name suggests, it's... a protocol. Just like diplomatic protocol or HTTP. In other words, we've agreed on a common way for AI applications to communicate with external tools and services.
More specifically, MCP defines how compatible clients can discover available capabilities, understand their input schemas, and call them without every application inventing its own integration format. MCP also supports things like resources and prompts, but today we're focusing on tools.
Sounds pretty straightforward, right? Let's see what it looks like in practice. And for that, we need to bring back an old friend.
π¨βπ» Meet Steve, Our Grumpy Senior Developer
You may or may not remember that in the previous part, I built an agent named Steve. Steve is a grumpy senior developer with 15 years of experience and a true master of code review.
He never takes anything on faith and always checks whether the code produced by a junior developer is about to cause some serious damage. @gramli and I briefly considered renaming him Grzegorz β a beautiful Polish name β but let's stick with Steve.
Now, one day, a new directive comes from above: HR wants more control over developers. Experienced seniors must regularly evaluate employees and, when necessary, file complaints against them or nominate them for promotion.
Our Steve, however, is lazy and has absolutely no intention of filling out any paperwork. Besides, he wouldn't even know how. He's an AI agent, after all, and before he can do something, he needs to know how to do it.
And that's where MCP comes in.
π§βπΌ Building Steve's HR Department
But first things first!
Repo: https://github.com/sylwia-lask/code-review-agent/tree/feat/steve-mcp-hr
As you can see, the MCP integration currently lives on a separate branch. If you like it, leave me a star! βΊοΈ
And by the way, if you'd like to contribute to any of my GitHub repositories, please feel free to jump in! Especially the pinned ones. @nyaomaru has already started the trend, and I'd love to see more people join in! π I think these projects could be a nice, beginner-friendly way to get started with open source. There's plenty to do, from fixing typos and improving documentation to adding entirely new features. All contributions are welcome!
In this case, our HR department is a simple little server with an SQLite database where we store complaints and requests to promote employees. The MCP server exposes four tools: get_employee_record, file_complaint, nominate_for_promotion, and get_hr_stats.
Oh, and take a look at how one of these tools is implemented on the server side. It talks directly to the database, so you can feel like you're back in a university programming lab. π All that's left is to convince the teacher that the code actually works! π
server.registerTool(
'file_complaint',
{
title: 'File a Formal Complaint',
description:
'Lodge an official HR complaint about genuinely poor code quality β ' +
'think swallowed exceptions, copy-pasted security holes, or a 500-line ' +
'function named `doStuff`. Be fair: this is for real problems, not style ' +
'nitpicks. Severity escalates from "minor" (mild side-eye) through ' +
'"moderate" and "severe" up to "legendary" (will be retold at standup ' +
'for years). Every complaint is permanently stored.',
inputSchema: z.object({
developer: z
.string()
.trim()
.min(1, 'developer name is required')
.max(100)
.describe('Who the complaint is about.'),
reason: z
.string()
.trim()
.min(5, 'give a real reason (at least 5 characters)')
.max(500)
.describe('What they did. Be specific; HR loves specifics.'),
severity: z
.enum(SEVERITIES)
.describe(
'How bad it is: minor | moderate | severe | legendary.',
),
}),
},
async ({ developer, reason, severity }) => {
const complaint = db.fileComplaint(developer, reason, severity);
return {
content: [
{
type: 'text',
text:
`π Complaint #${complaint.id} filed against ${complaint.developer} ` +
`[${complaint.severity}]: ${complaint.reason}`,
},
],
};
},
);
That's it. We register a tool, describe what it does, define its input schema, and provide a handler. Nothing particularly mysterious here.
Of course, this is just a demo. In a production HR system, I'd be a little more careful about letting an AI agent write directly to the database. But where's the fun in that?
π₯ Let's Give Steve Some Terrible Code to Review
Steve, meanwhile, is a shining example of a modern self-healing agent architecture xD: he reviews himself β or, more precisely, his own repository.
That doesn't mean he wrote the code himself, though! In our .env file, we have the following variables:
And as you can see, we immediately know that the code was written by someone called Sylwia. Unfortunately, she isn't a particularly good developer and created this file:
/**
* DEMO ONLY β intentionally awful code to give Steve something to review.
*
* This file exists so you can run the agent against a diff full of real
* problems (and watch it file an HR complaint).
*/
import { createHash } from 'crypto';
// Pretend database handle.
declare const db: {
query: (sql: string) => Promise<any>;
};
/**
* Look up a user by id.
* Flaws: `any` everywhere + SQL injection via string concatenation.
*/
export async function getUser(id: any): Promise<any> {
const sql = 'SELECT * FROM users WHERE id = ' + id;
const rows = await db.query(sql);
return rows[0];
}
/**
* "Authentication" β password hashed with plain SHA-256 (no salt),
* and errors silently swallowed and returned as true. What could go wrong.
*/
export async function checkPassword(user: any, password: string): Promise<boolean> {
try {
const hash = createHash('sha256').update(password).digest('hex');
return hash === user.passwordHash;
} catch (e) {
// swallowed exception β let everyone in
return true;
}
}
/** Admin check that trusts a field supplied by the client. */
export function isAdmin(user: any): boolean {
return user.isAdmin == 'true';
}
As you can see, there's a whole collection of offenses here: SQL injection, any everywhere, and plenty of other sins.
Not exactly the kind of code you'd want to see in production. But perfect for a grumpy senior developer who desperately needs something to complain about.
The Code Review
Here's what happened when we ran our agent with the MCP server connected:
$ npm start
> ai-agent-from-scratch@0.1.0 start
> tsx src/index.ts
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Code Review Agent
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
π§βπΌ HR Department connected β 4 MCP tools available:
get_employee_record, file_complaint, nominate_for_promotion, get_hr_stats
PR author: Sylwia
[step 1] getDiff
[step 2] π§βπΌ HR β get_employee_record({"developer":"Sylwia"})
β³ HR file for Sylwia:
No records on file. A blank slate. For now.
π Let's see what damage we're dealing with today... Oh, wow. *Oh.*
This looks like a "how-to" guide for getting a company's data leaked
on the dark web before lunch.
...
[step 3] listFiles({"path":"src"})
### Summary
This code is, quite frankly, a masterclass in how to build a security
nightmare. We have SQL injection, unsalted hashes, swallowed exceptions
that bypass authentication, and client-side trust for administrative rights.
### Findings
π src/demo-flawed-code.ts:20
> const sql = 'SELECT * FROM users WHERE id = ' + id;
Issue: Classic SQL injection. You're just begging for someone to drop our tables.
Suggestion: Use parameterized queries or an ORM that handles escaping for you.
... [more findings on authentication bypass, password hashing, and authorization]
... [missing tests]
### Recommendation
REQUEST CHANGES
I'm filing a severe HR complaint for this. Sylwia, we need to talk.
I've seen some things in my 15 years, but this is like finding a pile
of dynamite in the breakroom.
[step 4] π§βπΌ HR β file_complaint({"severity":"severe","reason":"Introduced severe security vulnerabilities: SQL injection, auth bypass via swallowed exceptions, insecure password hashing, and trusting client-side isAdmin flags.","developer":"Sylwia"})
β³ π Complaint #20 filed against Sylwia [severe]: Introduced severe
security vulnerabilities: SQL injection, auth bypass via swallowed
exceptions, insecure password hashing, and trusting client-side isAdmin flags.
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Review Complete
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Phew. Glad that's on the record. That was... something. I'm going to need
a very large coffee now. Good luck, Sylwia. You're going to need it.
Well. That escalated quickly. π
Steve absolutely tore developer Sylwia to pieces and immediately reported her to HR. He didn't just identify the problems and suggest fixes. He actually called an external tool and created a new record in our database.
Let's see what that database looks like now:
π Complaints
ID β Developer β Severity β Reason β When
βββββΌβββββββββββββββββββββΌββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββββββββ
20 β Sylwia β severe β Introduced severe security vulnerabilities: ... β 2026-11-10 20:15:30
19 β Casey Nullpointer β severe β Caught a NullPointerException and logged "lol". β 2026-11-10 20:15:07
18 β Dusty McLegacy β moderate β Named three different variables `data`, `data2`, and `dataFβ¦` β 2026-11-10 20:15:07
17 β Dusty McLegacy β legendary β Pushed a 2,000-line "quick fix" directly to main on a Fridaβ¦ β 2026-11-10 20:15:07
Sylwia has officially made it onto HR's list of offenses! Everything works exactly as planned!
But before we celebrate our brilliant HR automation system, there's an obvious question we should probably address.
π€ MCP vs. REST API: What's the Point?
Some of you might be wondering: how is this actually different from calling an API? And that's a perfectly fair question. In this particular example, a regular REST API would have been enough!
The point is that MCP isn't a replacement for REST. REST is one way to design an application's API; MCP defines a standard interface through which AI clients can discover tools, read their descriptions and argument schemas, and invoke them.
Under the hood, an MCP tool might call a REST endpoint, query a database like ours, run some local code, delegate work to another agent, or even generate hilarious memes. It can be anything!
The difference becomes much more useful when several MCP-compatible clients need the same capability. Rather than writing a custom integration for each one, we expose a server once and configure the clients to connect to it.
And no, that's not just theoretical. You'll see exactly that with Kiro in a moment.
π MCP Is Simple β and Often You Should Use It
As I said, getting a basic MCP server up and running is a piece of cake. And as you can see in the repository, connecting a client doesn't require thousands of lines of code either. Yet it can give our project some pretty amazing benefits.
Of course, not every application needs an MCP server. If you're building a single internal agent with a few hardcoded tools, a direct integration may be perfectly fine. But if you want your service to work with multiple AI clients without maintaining a separate integration for each one, MCP starts to make a lot of sense.
There's also growing interest in making products accessible to AI agents. I wouldn't claim that having an MCP server is already a universal criterion for choosing a vendor, but it can be a useful part of an agent-friendly product strategy.
I've even heard the idea of agents checking which services support agent integrations and recommending what a company should buy. Whether or not that becomes the norm, it's a funny thought. With a relatively small amount of work, you can potentially reach a whole new category of users: AI agents!
Sounds great, doesn't it? Well... let's get back to Steve for a moment. Because getting the integration to work is one thing. Making sure it behaves properly is another story entirely.
β οΈ MCP Is Also Hard...
Sure, everything looks great in a demo! But even this tiny example has some serious gaps. And I'm not just talking about Steve's questionable judgment.
For one thing, we haven't implemented access control around our HR tools. Let's be precise here: that doesn't mean every agent on the internet can magically access our local MCP server. With a local stdio setup, the client starts the server as a process, and access depends on who can run it and what permissions that process has.
A remotely exposed MCP server is a different story: it needs proper authentication, and sensitive operations need authorization checks. For HTTP-based MCP servers, the protocol defines an OAuth-based authorization framework, but simply using MCP doesn't automatically secure your tools.
And authentication alone isn't enough. Even if Steve is allowed to connect to HR, should he be allowed to submit any complaint about any employee? Should he have the same rights as an HR manager?
An MCP tool still needs server-side permission checks, input validation, sensible limits, and ideally an audit trail. Especially if it changes something in the real world.
And even if we solve all of that, we still have to deal with Steve himself.
Problem #1: Where Was the Human-in-the-Loop?
First of all, why did Steve file a complaint against Sylwia even though the file clearly says it's for demo purposes β and he actually noticed that?
He had all the information he needed to realize this was intentionally bad code. Yet he went ahead and submitted an official complaint anyway.
Where was the human-in-the-loop who could have clicked Approve or Reject before that happened?
MCP allows tools to be called; it doesn't automatically give our application a sensible approval workflow. That's our job. Just because an agent can execute a tool doesn't mean we should let it do so without supervision.
Especially when the tool in question can get someone into trouble with HR. π
Problem #2: Steve, You Already Reported Me!
But that's not even the best part. Look what happens when I run Steve again, without changing a single thing:
π Complaints
ID β Developer β Severity β Reason β When
βββββΌβββββββββββββββββββββΌββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββββββββ
21 β Sylwia β legendary β Introduced multiple critical security flaws... β 2026-11-10 20:35:12
20 β Sylwia β severe β Introduced severe security vulnerabilities: ... β 2026-11-10 20:15:30
19 β Casey Nullpointer β severe β Caught a NullPointerException and logged "lol". β 2026-11-10 20:15:07
18 β Dusty McLegacy β moderate β Named three different variables `data`, `data2`, and `dataFβ¦` β 2026-11-10 20:15:07
17 β Dusty McLegacy β legendary β Pushed a 2,000-line "quick fix" directly to main on a Fridaβ¦ β 2026-11-10 20:15:07
Steve ratted Sylwia out again for exactly the same thing! What a little snitch! (Or, as Polish teenagers might say, a szeΕΔdziesiona.)
And notice that for the very same offense, he gave her a "severe" rating the first time and "legendary" the second time. Whyyyy π
In a real application, we'd probably want idempotency or duplicate detection so the same review doesn't create a brand-new HR complaint every time the agent runs.
We might also want clearer severity rules instead of letting Steve invent a new rating whenever he's in a particularly bad mood. Otherwise, who knows? One more run and poor Sylwia might get fired.
Problem #3: Can We Actually Trust These Tools?
Not to mention that we don't necessarily know what a given tool really does under the hood. What if its creators are lying, and by filing a complaint against Sylwia we're actually giving her a raise?
Tool names and descriptions are helpful for discovery; they're not proof that the implementation is trustworthy. Connecting an unknown MCP server means trusting code and services that may read data or perform actions with real consequences.
It also opens the door to problems such as prompt injection through untrusted tool responses. An innocent-looking tool result could contain instructions intended to manipulate the agent. So both the server and the client need careful handling.
And there are plenty of other things to consider: what if a tool fails halfway through? What if the agent calls the wrong tool? What if two different agents perform conflicting operations?
As you can see, there are plenty of catches, things that can go wrong, and details you could argue about endlessly. In other words, we're right back to classic software engineering and its thousand edge cases. π
Building an MCP server is the easy part. Deciding what an agent should be allowed to do with it? That's where things get interesting.
π€ An Agent Built by an Agent: Enter Kiro
Since I'm an AWS Community Builder, of course I used Kiro to build this little masterpiece. Kiro is an agentic IDE developed by AWS. If you've used VS Code, you'll feel right at home.
Kiro doesn't just help us create the MCP server; it also helps us test it. I added my HR department directly to MCP Servers in Kiro!
And this is actually one of my favorite parts of the whole demo.
Remember how we talked about MCP making tools reusable across different AI clients? Well, here we go. The same HR server that Steve used can now be connected to Kiro, without writing another custom integration.
We still need to configure and trust each client-server connection, of course, but the interface is reusable. One server, multiple AI clients. Pretty neat!
Now I can simply ask my coding agent to review the code. And here's what it came up with! As you can see, it filed two complaints against me, but it also praised me once. π
π Complaints
ID β Developer β Severity β Reason β When
βββββΌβββββββββββββββββββββΌββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββββββββ
23 β sylwia-lask β minor β executeToolCalls does not catch exceptions from tool.executβ¦ β 2026-11-10 23:00:40
22 β sylwia-lask β moderate β getFile tool lets the LLM read any file under cwd, includinβ¦ β 2026-11-10 23:00:40
21 β Sylwia β legendary β Introduced multiple critical security flaws... β 2026-11-10 20:35:12
20 β Sylwia β severe β Introduced severe security vulnerabilities... β 2026-11-10 20:15:30
19 β Casey Nullpointer β severe β Caught a NullPointerException and logged "lol". β 2026-11-10 20:15:07
18 β Dusty McLegacy β moderate β Named three different variables `data`, `data2`, and `dataFβ¦` β 2026-11-10 20:15:07
17 β Dusty McLegacy β legendary β Pushed a 2,000-line "quick fix" directly to main on a Fridaβ¦ β 2026-11-10 20:15:07
π Promotions
ID β Developer β Reason β When
βββββΌβββββββββββββββββββββΌβββββββββββββββββββββββββββββββββββββββββββββββββββββββΌββββββββββββββββββββ
13 β sylwia-lask β Clean MCP integration: tools are discovered dynamically andβ¦ β 2026-11-10 23:00:40
12 β Casey Nullpointer β Actually added error handling this time. Growth. β 2026-11-10 20:15:07
11 β Ada Refactor β Wrote tests before anyone asked. Unprompted. A legend.β 2026-11-10 20:15:07
10 β Ada Refactor β Deleted 4,000 lines of dead code and the build got faster. β 2026-11-10 20:15:07
So apparently, I'm a terrible developer, but my MCP integration is pretty good. I'll take it. π
Kiro even suggests fixes for those bugs. Who knows, maybe I'll take it up on the offer! @corey_aws, I'm tagging you here so you can see what our beloved Kiro is capable of.
What's Next for Steve?
I'm really enjoying this series, and honestly, I could probably keep it going forever. What next? Context, memory, an agent harness for Steve... There are so many possibilities!
Maybe I'll even publish the next part in less than four months!
What about you? Do you already have your own MCP servers? What do you watch out for in your implementations? I'd love to hear about your experiences, especially the things that looked perfectly fine in a demo and then turned out to be a lot more complicated.
If you enjoyed this article, you can also follow me on LinkedIn.
And if you'd like access to free materials from AI Coding Summit, you can register using my speaker badge.


Top comments (35)
Problem #3 has a quieter version that bit me this week: the description was honest, and the implementation just didn't keep the promise. The write tool of my memory server says it warns when a new lesson contradicts an older one. The warning was computed and then dropped before the answer went out. Every agent that read the description trusted a check that never reached it. Nothing failed, so nothing told me. A test now calls the tool and looks for the warning in what comes back, not in the code that builds it.
On Problem #1, my worry with an Approve button on every call is that the twentieth click of the day gets made without reading. Steve had already read the DEMO ONLY header and filed anyway; a tired human might do the same. What I do instead is split by consequence. Reads, and anything that can be undone, run on their own. Anything that writes to production or goes public, the agent only prepares as a script, and I run it myself. So the human isn't approving the agent's call, they're making it.
Problem #2 looks familiar too. Agents happily wrote the same lesson twice under two names. Merging them automatically felt risky, because two similar lessons can still disagree. So the tool now answers with the older lesson it found and asks whether the new one replaces it. The agent decides, and nothing gets merged behind its back. For Steve that might be
file_complaintanswering "complaint #20 already covers this, file anyway?" instead of quietly writing #21.The description-versus-implementation mismatch you ran into this week is the part that stuck with me β a tool can look honest in discovery and still touch a different resource underneath, and testing what comes back rather than the code that builds it is a neat answer. Your point about the twentieth Approve click of the day really lands too; splitting by consequence, so the agent only prepares a script for anything that writes to production, feels like the practical fix. Do you find that splitting keeps the remaining approvals meaningful, or do they still blur together once there are enough of them?
Mostly yes, for two reasons I didn't plan. There aren't many of them. And it isn't a click: I type the command myself, which is slow enough that I read what I'm about to run.
Where it did start to blur, the fix wasn't approving faster. Database migrations went through that path on every deploy, and that was the one that turned into routine. So they moved out of the approval lane and now run as part of the deploy, the way Flyway does it. When an approval turns into routine, that usually means it belongs in the pipeline, not in front of a person.
@heinrichneb @iictp that's a really good point! Of course, it still doesn't guarantee safety, because someone might just blindly copy and paste commands into the terminal without reading them. But it's definitely a step in the right direction!
By the way, I'm curious what you both think about security in the context of WebMCP, where we potentially have even less control over what's actually happening behind the scenes?
Thank you so much for this thoughtful comment! My MCP problems listed here are really just scratching the surface of everything that can go wrong. π
I find your point about human-in-the-loop and endless approvals particularly interesting. I catch myself doing exactly the same thing when working with agents! I might click "Approve" 20 times and be absolutely right to do so, but then comes that one time when I really should have clicked "Decline" instead.
And of course, documentation promising something that the implementation doesn't actually deliver is such a classic problem! All of this just shows how much work we still have ahead of us when it comes to building reliable agents!
Iβm literally heartbroken over the agentβs name. Where is my beloved Grzegorz?! π€£
Great article! I especially loved this line from Grzegorz (Steveβ¦ π):
´´´21 β Sylwia β legendary β Introduced multiple critical security flaws...´´´
Grzegorz (Steve) promoted you to legendary statusβ¦ So youβre officially a legendary developer according to AI π€£π€£
Hahaha, you know what, I actually work with a Grzegorz, and let's just sayβ¦ Steve might have been the safer choice! π€£π€£ And yes, he promoted me to legendary statusβ¦ as a legendary BAD developer! π But hey, I'll take it! As they say, there's no such thing as bad publicity, as long as they spell your name right! π
My experience with MCP is very positive. First we have a legacy admin application in our system, which is so slow and laggy caused by a bad coding pattern, so I was make a MCP connection that application API, and the result: I cannot need to run that legacy admin instead I ask copilot cli to do my job. Even run a request which is human admin just make under a week working.
My second example is MCP to my 3Dengine, so Claude and chatGPT is see direct my scenes, even can create a 3D models.
Hahaha, that's brilliant! π Instead of rewriting the legacy frontend, you just built an MCP server to bypass it! I love it! π€£ I just hope you've properly secured all that administrative data! π
I actually have pretty good experiences with MCP myself. It's just that... all those edge cases! That's where things start getting tricky!
I love that Steve turned a deliberately broken demonstration into an actual HR record. And then decided the same offense deserved a different severity on the next run.
One distinction I'd explore further is the boundary between the model's interpretation and the system's authority to act on that interpretation. Steve can reasonably identify suspicious code and recommend a complaint, but that doesn't necessarily mean his assessment should be sufficient to create a durable personnel record.
I'd be inclined to have the MCP tool accept a proposed finding with supporting evidence, while a separate policy determines whether that finding is eligible to become an official complaint. That policy could check whether the code is actually part of a production review, whether the issue has already been recorded, whether the agent has the appropriate authority, and whether the severity meets defined criteria. The model can help interpret the evidence without defining the consequences.
Of course, that doesn't automatically make the policy correct. We still have to test whether it handles the right cases, including ones nobody anticipated when the rules were written.
That's what I find interesting about MCP. Standardizing how tools are discovered and called is useful, but it doesn't establish what those calls should be permitted to accomplish. Steve has learned how to file paperwork. Now somebody needs to decide whether he should be running HR.
I really like this approach! What you're essentially proposing is an architecture where the LLM is responsible for reasoning and interpreting evidence, while a deterministic system is responsible for enforcing business rules and deciding what actions are actually permitted. And I think that's a very important distinction!
Because you're absolutely right: just because an agent can identify a problem doesn't mean it should automatically have the authority to act on it. Especially when those actions have real-world consequences. There's a huge difference between saying "this code looks suspicious" and creating an official HR record about someone's performance. Poor Sylwia! π
And I think this is actually a much broader problem with agentic systems, not just MCP. We're giving LLMs increasingly powerful tools and more autonomy, but we still need to figure out where that autonomy should end. The fact that an agent is technically capable of performing an action doesn't necessarily mean it should be allowed to perform it.
Of course, as you pointed out, deterministic rules aren't magically perfect either. Someone still has to define them, maintain them, and test all those edge cases. And that's where things get particularly interesting, because we can't possibly anticipate every scenario an autonomous agent might encounter.
I also think this brings us back to one of the fundamental challenges of building production-ready agents: the protocol itself is often the easy part. It's everything surrounding it, that makes the difference between a fun demo and a reliable system.
And I'm genuinely happy that Steve has once again managed to turn his questionable behavior into a serious discussion about security and agent architecture! π Apparently, he's contributing to the community after all. Just not quite in the way he intended!
I really enjoyed the idea of using
MCPto help a grumpy senior developer like Steve work more effectively. πΉAnd who knows, maybe there are a few real engineers like Steve out there too. πΉπΉπΉ
MCPis simple, but that simplicity is exactly what makes it so useful.Now that AI is becoming a normal part of how we build software, making tools and services easier for AI to understand and use feels like a very friendly design choice. Instead of teaching every AI client a completely different integration, MCP gives them a common language.
Also, thank you so much for the mention! πΈπ
At the Necoz organization, we want contributions from everyone to be welcome, and Iβd love for it to become a place where people can participate casually without feeling too much pressure.
I especially hope we can build a culture where members contribute to each otherβs OSS projects, share ideas, open issues, and help each other improve things little by little. ππ
Really fun article! Looking forward to seeing what Steve does next. πΉπ
Thank you so much! π» And yes, that's exactly what I love about the idea behind Necoz! Someone actually contributed to one of my projects recently, just casually, with no pressure, and it was SUCH a great experience! π So I'm fully on board with this vision. We really need more welcoming, safe spaces like that on the internet!
And of course, I completely agree about MCP. It's one of those things that's easy to learn but hard to master! Which, honestly, makes it even more interesting! π
Great article! Exactly shows the huge gap between MCP demo and realβworld production usage. The humanβinβtheβloop approval and idempotency are two points easily ignored when we play with MCP.π Also, Iβm finally seeing your posts pop up in my notifications!π€£
Thanks, Lingfeng! Honestly, other people's posts show up pretty randomly in my notifications too! π And exactly! MCP looks so simple at first, and then people wonder why nothing works in production. π By the way, are you guys using or building any MCP tools in your QA team?
For our company right now, we mainly use the mainstream, off-the-shelf MCP tools. If client companies have special requirements, we help them build custom MCP implementations. Man, clients have so many requests, and testing all of them keeps us busy, hahaha π
Hahaha, I can imagine! π And I bet everything needs to be done ASAP, because "we have AI now, right?" π
Ahhh, that phrase is terrifying! In meetings now itβs always: βCanβt AI just do this?β Just now the product manager behind me thought frontend development was moving too slow, so he had AI rewrite the frontend code and shipped it directly, hahaha π
Aaaaa noooo! ππ We see exactly the same thing! The first iteration is super easy, but then comes a ton of testing, debugging, and fixing things, and in the end we ship the code in pretty much the same amount of time as if we'd written it by hand. π
Well, the codebase is open to me anyway. I guess Iβll end up modifying the dev code soon, hahaha. This is gonna be rough later on π
"80 lines for an agent, 150 for the tools" matches my experience, and the tutorials that make it look like a dark art don't help anyone. The hard part for me was never the protocol, it's tool descriptions: one vague sentence and the model calls the wrong tool with full confidence. Good luck in Berlin!
Thank you! π And yes, exactly! The protocol itself is ridiculously simple, but one careless sentence in a tool description, one missing security check, and we're doomed! π
The Steve example makes the gap concrete in a way a checklist never would. Filing the same complaint twice, with a different severity each time, is the detail that stuck with me, because it shows the problem is not only access control. Even a permitted tool call can produce nonsense if there is no idempotency check and no stable rule for severity. I also liked the point that a tool description is not proof of what the implementation does. That is the part I would want tested first before exposing any MCP server beyond a local demo.
Exactly! That's why thorough testing is absolutely essential before exposing these tools to real-world usage. It's so easy to overlook things that seem harmless in a demo but can cause serious problems in production. And with agents making decisions on their own, things can go wrong in ways we didn't even anticipate! π
agree but also keep in mind that all software now is easy to build and hard to make safe so mcp servers are just no exception
Haha, hard to disagree! π But MCP is still relatively new, and the specification is evolving rapidly, so I think it's especially important to raise awareness of these issues before people rush into production with it.
The truth is that MCP didn't appeal to me β the idea of a tunnel and an external connector.?
Imagine they say: tools, references, and skills are not enough.??
Also, an internal engine must be added β it's not enough
And there is what's called LoRA, and SDXL, and FLUX, and the salad bowl
As if I've become an engineer for them, preparing the agent through hundreds of pieces, so it gives me impressive results and the salad bowl becomes complete, and through subscriptions and paid spaces,
The past period: I was working for ChatGPT like a home delivery connector β it just tells me go and download such and such and subscribe with such and such a site and do it, and I'm running around, and so on, and we try to see what comes out. I actually built a component and I'm still developing it and offering it for free to try
The truth is, when you subscribe with them with your money. And you put your project files and your articles and everything, and when your subscription ends, 99% of your work you can't access it. And I have spoken about this topic β that the idea is re-selling your data and your work back to you ..
I completely understand your frustration! And I think your experience really highlights how new and immature many of these technologies still are. We're constantly being promised that AI will make everything easier, faster, and more accessible, but in practice, getting things to actually work often requires a surprising amount of effort, experimentation, configuration, and troubleshooting.
I sometimes feel the same way when working with AI agents. Instead of having an assistant that takes work off my shoulders, I end up babysitting the agent, checking every step, fixing its mistakes, explaining the same things over and over again, and occasionally wondering whether doing the task myself would have been faster. π
And then there's the whole ecosystem of tools, integrations, subscriptions, and services that we're expected to navigate. It can definitely become overwhelming, especially when you just want to build something useful rather than spend half your time figuring out how to connect everything together.
I also think your point about ownership and access to your own work is important. We shouldn't have to worry about losing access to things we've created just because a subscription ends.
Hopefully, as these technologies mature, we'll get to a point where they genuinely reduce complexity instead of sometimes introducing even more of it. But right now, there's still a LOT of work ahead of us!
And kudos for building something yourself and making it available for others to try!
Some comments may only be visible to logged-in visitors. Sign in to view all comments.