MCP Is Dead Simple. And That's Exactly the Problem A developer built a working Model Context Protocol (MCP) integration for an AI code-review agent named Steve, adding an HR server backed by SQLite that exposes four tools β€” get_employee_record, file_complaint, nominate_for_promotion and others β€” so the agent can file complaints and promotion nominations. The author reports that a basic MCP server takes roughly 150 lines of repetitive code and the client side about 100 more, arguing the protocol's core concept is simple to implement but that complications emerge later. 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 https://dev.to/sylwia-lask/the-dirty-secret-behind-ai-agents-demo--273d . 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 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. 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 https://dev.to/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. But first things first Repo: https://github.com/sylwia-lask/code-review-agent/tree/feat/steve-mcp-hr 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 https://github.com/sylwia-lask , please feel free to jump in Especially the pinned ones. @nyaomaru https://dev.to/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? 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