MCP Explained: Giving Your AI Assistant Hands

For the first couple of years of the LLM era, AI assistants had a strange disability: they could reason about your work but couldn't touch it. You'd paste a support ticket into a chat window, get a beautifully drafted reply, then copy it back out, open your helpdesk, find the ticket again, paste, and send. The model did the thinking; you were the hands.
The Model Context Protocol (MCP) is the fix for that, and it's worth understanding properly — not because the protocol itself is exciting (it's deliberately boring), but because it quietly changed what "AI assistant" means. An assistant with MCP doesn't summarize your ticket queue from a paste; it reads the queue, updates the tickets, and replies to the customers.
What MCP actually is
MCP is an open protocol, introduced by Anthropic in late 2024 and since adopted across the industry, that standardizes how AI applications connect to external tools and data. It has three roles:
- A server wraps some capability — your helpdesk, your database, your file system, GitHub — and exposes it as a set of named tools with typed inputs, plus optional resources (readable data like
helmdesk://tickets/open) and prompts (reusable templates). - A client is the AI application: Claude Desktop, Claude Code, Cursor, VS Code, Windsurf, and a growing list of others.
- The model sits inside the client and decides, mid-conversation, which tools to call and with what arguments.
The handshake is the part that matters. When a client connects to a server, it asks: what tools do you have? The server answers with a machine-readable catalog — each tool's name, a natural-language description, and a JSON Schema for its inputs:
{
"name": "list_tickets",
"description": "List support tickets, filterable by status, priority, and search term.",
"inputSchema": {
"type": "object",
"properties": {
"status": { "enum": ["new", "open", "pending", "resolved", "closed"] },
"search": { "type": "string" },
"limit": { "type": "integer", "maximum": 100 }
}
}
}
That's discovery. The model reads this catalog the way you'd skim an API reference, and from that point on it can call list_tickets whenever the conversation warrants it. No fine-tuning, no hardcoded integration in the client, no prompt full of pasted context. The description is the documentation, and the model is the reader.
Why this beat bespoke plugins
We tried the other approaches first, and each failed in an instructive way.
Per-app plugin stores (remember ChatGPT plugins?) coupled every integration to one vendor's runtime. Build a plugin for platform A and you'd rebuild it for platforms B and C — so most developers built for none, and the stores filled with abandoned experiments.
Bespoke function-calling integrations worked but didn't compose. Every team wired their own tools into their own agent with their own glue code. The tools weren't portable, weren't discoverable, and died with the internal project that spawned them.
Copy-paste — the default — scaled with human patience, which is to say it didn't.
MCP's bet was the same one USB made: standardize the connector, not the devices. A helpdesk vendor writes one MCP server and every MCP client can use it — including clients that didn't exist when the server was written. The economics flip from M×N integrations (every tool × every AI app) to M+N. That's the entire trick, and it's why adoption snowballed: each new server makes every client more useful, and each new client makes every server more valuable.
What a good tool surface looks like
Here's the part most explainers skip: having an MCP server is not the same as having a good one. The model is your API's consumer now, and models have a distinctive consumer profile — they read every description on every call, they take schemas literally, and they'll cheerfully do something dumb if the tool lets them. A few design rules follow:
Tool names should say what happens. reply_to_ticket beats create_message, because the model needs to predict consequences before it acts. If sending a reply also emails the customer, the description must say so — that's exactly the fact a careful model (or a careful human) needs before pulling the trigger.
Typed inputs are guardrails, not paperwork. An enum of valid statuses means the model literally cannot invent a "kinda-resolved" state. A maximum: 100 on limit means no accidental full-table pulls. Every constraint you encode in the schema is a mistake the model can no longer make.
Safe defaults, explicit danger. Reads should be effortless; writes should be unambiguous. A well-shaped surface makes list_tickets zero-risk to call speculatively, while destructive operations either don't exist (no delete_all_tickets, thank you) or require pointed, specific arguments. Scoped credentials belong underneath: hand your assistant a key that can read tickets and search articles but can't touch billing or webhooks, and the worst case shrinks accordingly.
Right-sized granularity. Twelve well-named tools beat eighty micro-endpoints — the catalog is context the model has to hold, and a bloated surface degrades tool choice. But too coarse fails too: one mega-tool with a mode parameter hides its capabilities from discovery. The heuristic: one tool per verb a human teammate would recognize.
A concrete flow: triaging a queue over MCP
Here's what this looks like end to end. You've connected your editor or Claude Desktop to your helpdesk's MCP server — with Helmdesk that's a one-liner (claude mcp add helmdesk -- npx -y @helmdesk/mcp) plus a scoped API key. You type:
"Go through this morning's new tickets. Anything that's a known issue, reply with the fix from our docs and mark it pending. Flag anything angry or billing-related for me — don't touch those."
The transcript underneath looks like this:
list_tickets { status: "new" }→ nine tickets.- For each,
get_ticket→ full thread. The model sorts them: five look like known issues, two mention refunds, two are ambiguous. - For the five:
search_articles { query: "webhook signature mismatch" }(and so on) → it finds matching KB articles, drafts replies grounded in them, callsreply_to_ticket, thenupdate_ticket { status: "pending" }. - For the four flagged: no writes. The model reports back: "Handled five known issues with doc links. Left four for you: two refund requests, one frustrated tone, one I couldn't match to any article."
Notice what did the safety work. The refund tickets were protected by your instruction, yes — but also by the tool surface: there is no issue_refund tool, so the failure mode isn't available. The replies were grounded because search_articles existed and was cheap to call. Fifteen minutes of morning triage became one prompt and a review of the summary.
Where this is heading
The near-term trajectory is less about smarter models and more about better surfaces: remote MCP servers you connect with OAuth instead of local processes and pasted keys, richer discovery so assistants can find servers the way browsers find websites, and — most interestingly — tool surfaces designed with review workflows built in, so an assistant's actions queue for approval rather than firing instantly. The protocol is settling into the role good protocols always settle into: invisible.
The practical takeaway today is simpler. If you use AI assistants, the highest-leverage upgrade available is connecting them to the systems you actually work in — the difference between an assistant that talks about your work and one that does some of it. And if you build a product developers use, an MCP server is quickly becoming what a REST API was in 2015: the thing people are surprised you don't have.
Give your assistant a support queue it can work
Helmdesk ships an MCP server with 36 tools across tickets, articles, emails, logs, feedback, and customers — scoped keys, two-minute setup.