Part 4 of Claude Code, Beyond the Prompt — patterns from running a live automated trading system on Claude Code. Part 3: slash commands and skills.
Here's a workflow you've definitely done:
You ask Claude what's wrong with production. It can't see production. So you SSH in, run a command, copy the output, paste it back into the chat. Claude reads it, asks for another command. You run that, copy, paste. Twenty minutes of you being a very expensive copy-paste buffer between Claude and your own systems.
There's a better way, and it's the single biggest capability jump in this series. It's called MCP — the Model Context Protocol — and it lets you give Claude its own tools: functions it can call directly to reach your systems, on your terms.
This is where "chat in a terminal" becomes "operational interface." Let me show you the smallest possible version, then how I scaled it to run real infrastructure.
What MCP actually is
Strip away the acronym. An MCP server is a small program that exposes a set of tools — named functions with typed inputs — that Claude can call. You write the functions. You decide exactly what they do and, more importantly, what they can't do. Claude calls them like any other tool; the results come back as structured data, not a wall of pasted text.
That's the whole model. Instead of you being the bridge between Claude and your database, you build a query_database tool once, and Claude uses it directly — but only in the ways you allowed.
The smallest useful MCP server
Here's a read-only tool that lets Claude run safe SELECT queries against a database. In Python, using the official SDK's FastMCP helper (check the current MCP docs for exact syntax — the shape is what matters):
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-tools")
@mcp.tool()
def db_query_ro(sql: str) -> str:
"""Run a read-only SQL query. SELECT statements only."""
stripped = sql.strip().lower()
if not stripped.startswith("select"):
return "Error: only SELECT queries are allowed."
# ... connect, execute with a row limit and a timeout, return rows ...
return run_readonly(sql, row_limit=500, timeout_s=5)
if __name__ == "__main__":
mcp.run()
Register it with Claude Code (via claude mcp add or your settings file), and now Claude has a db_query_ro tool. Ask "how many users signed up yesterday?" and it writes the query, calls the tool, and reads back 500 rows max — no SSH, no psql, no copy-paste, and no way for it to run a DELETE.
That guard — SELECT only, row limit, timeout — is not incidental. It's the reason the tool is safe to hand over.
Why this beats pasting output
- No lossy human relay. You stop being the buffer. Claude gets the real data, structured, and can chain three queries in the time it took you to alt-tab once.
- You define the blast radius. The tool can only do what you coded. A read-only query tool cannot drop a table no matter how the conversation goes. Compare that to handing over shell access and hoping.
- It's auditable. Every tool call goes through your code, so you can log every single one. I know exactly what was run against my systems and when, because the server writes it down.
- It's fast and cheap. A tool returns 500 tidy rows instead of you pasting a 5,000-line log. Fewer tokens, faster turns (Part 7 puts numbers on this).
How I scaled it
My main MCP server exposes around thirty tools, and the story of how it got there is the story of this whole series.
It started exactly like the pain at the top: I was the copy-paste bridge between Claude and my servers. So I built one tool — read-only database queries. Then another — tail a service's logs. Then: check if a service is alive. Search the code. Read a file (with path-traversal blocked so it can't wander off into /etc). List and comment on GitHub issues. Eventually: deploy a file, with the deploy tool itself enforcing backup-first, checksum-verify, restart, health-check.
Every tool is narrow, sandboxed, and logged. Read-only by default; the few tools that write are the ones I deliberately hardened. The result is that Claude can operate my infrastructure — triage a down service, check overnight state, ship a fix — through an interface where the interface itself enforces the safety rules. I'm not trusting the model to be careful. I'm trusting my code to not let it be careless.
That's a very different feeling from ssh root@server and hoping.
The design lessons that matter
If you build one MCP server, internalize these:
Read-only by default. Most of what you want is observation — query, read, check status, tail logs. Ship those first. They're safe, they're 80% of the value, and nothing they do can hurt you. Add write/deploy tools later, one at a time, each hardened on purpose.
The tool enforces the rules, not the prompt. Never rely on "I told Claude not to." Rely on the tool physically being unable to.
SELECT-only is a code check, not a polite request. This is the difference between a safety rule and a safety feature.Narrow beats general. A
db_query_rotool with a row limit is better than arun_shelltool that can do anything. Every capability you don't expose is an incident you can't have. Resist the urge to build one god-tool.Log everything. An audited interface turns "I hope nothing weird happened" into "here's the exact list of what ran." When Claude has hands on real systems, that ledger is what lets you sleep.
Return small, structured results. Cap rows. Truncate logs. Return the 20 lines that matter, not the 5,000 that don't. Your tools are also your token budget.
Don't reinvent what exists
You don't have to build everything. There's a growing ecosystem of ready-made MCP servers — for Postgres administration, for GitHub, for filesystems, for dozens of SaaS tools. I run an off-the-shelf Postgres-monitoring server alongside my custom one, because someone already built those 30 DBA tools better than I would have.
The pattern that scales: compose ready-made servers for the generic stuff, build custom servers for what's specific to you. Your custom server is where your system's unique shape lives — the tools that know your deploy recipe, your services, your conventions.
What you're really getting
The honest version: MCP is where Claude stops being an advisor you relay for and becomes something that can act on your systems directly — inside a fence you built. On a good setup, "check whether the payment service is healthy and show me the last errors" is one sentence, and Claude just does it, safely, in seconds.
It's also the most over-buildable thing in this series. So don't over-build. One read-only tool that removes your most annoying copy-paste loop is a complete, valuable first MCP server. Ship that. Add the next tool when a real task demands it.
Next
Your MCP tools let Claude reach your systems. But there's still one place it's oddly clumsy: finding the right code in your own repository. It falls back to grep, guesses keywords, and burns tokens spelunking through files. Part 5: semantic code search — why I stopped letting Claude grep, and the RAG setup I gave it instead.
Part 4 of a series on running real systems on Claude Code. The deeper retrieval research is open source — see RE-call. Part 5 is next.
Top comments (3)
Great tutorial. Building an MCP server is a great way to move from simple prompt interactions to structured, tool-enabled AI workflows. Giving models controlled access to your own services through well-defined interfaces is much more scalable than embedding everything in prompts.
I also like the emphasis on safe tool access. Clear permissions, validation, and predictable interfaces are what make MCP practical for production systems—not just more powerful. As the ecosystem grows, well-designed MCP servers will likely become as important as APIs are today. Great walkthrough!
Thanks — and you've put your finger on the real bet: a well-designed MCP server is basically an API whose caller happens to be a model instead of another program. Same discipline — clear contracts, validation, least privilege — except the caller is creative in ways an API client never is. That's exactly why "the tool enforces the rule, not the prompt" matters more here than in a normal API: you're not defending against bugs, you're defending against improvisation.
Completely agree on the "APIs of the AI era" framing. Worth being upfront about where the series is, though: this piece is deliberately the on-ramp — concepts for new and intermediate readers building their first server. I kept the depth out on purpose so it doesn't scare off the people who most need to ship tool #1. It gets more detailed as the series advances.
One teaser since you clearly get it: my setup isn't only Claude calling tools. I run a fine-tuned Qwen-13B as Claude's assistant, reachable over the same MCP layer — so Claude can hand the cheap, high-volume work down to a local model instead of doing everything itself. More on that later in the series.
Some comments may only be visible to logged-in visitors. Sign in to view all comments.