The Engineering of Intent, Chapter 4: The Model Context Protocol (MCP)

This is Part 4 of a series walking through my book The Engineering of Intent. In the previous chapter, we looked at project momentum and path dependence — why early prompts and conventions shape everything that follows. Chapter 4 opens Part II of the book: the agent’s side of the triad, and the infrastructure that makes it possible at all.


MCP Is to Agents What HTTP Was to the Early Web

The Model Context Protocol, or MCP, is the single most important infrastructural development in AI-native software since the rise of the agentic editor. It is the lingua franca between the model and the outside world.

Before MCP, every integration was bespoke. Every IDE had its own tool-calling format. Every agent framework had its own function-definition schema. Every company wrote its own adapters. After MCP, a tool implemented once is usable by any compliant client. That shift is the reason agentic development is starting to feel like a serious discipline instead of a demo trick.


The Problem MCP Solves

Think about one of your team’s internal tools — a “check deployment status” command your engineers run a hundred times a day. Before MCP, you had three options for letting an agent call it:

  • Wrap it in a custom plugin for whatever assistant your team uses — and lock yourself in.
  • Expose it via a local HTTP endpoint and train the agent to talk to it — careful prompt engineering forever.
  • Give the agent shell access and hope — the infrastructural equivalent of handing over the master key to your house.

None of these scaled. A mid-sized company with fifty internal tools could not afford to write fifty plugins per assistant, nor absorb the security liability of broad shell access. MCP collapses the problem. You write one server. Any compliant client consumes it with zero additional work.

💡 Key idea: MCP defines three roles — host, client, server — and three capability types: tools (functions the model can call), resources (content it can read), and prompts (named templates). Transport is JSON-RPC 2.0 over stdio or streamable HTTP. The schema is self-describing, so clients discover what a server does without prior registration. That last point is what makes it interoperable in a way earlier tool-calling formats weren’t.

Your First MCP Server in Fifteen Lines

The chapter walks through a minimum viable server in TypeScript that exposes one tool — a deploy-status check. Stripped to essentials, it’s about fifteen lines of real code. The value compounds: the next engineer adds a trigger_rollback tool to the same server, and every agent gets richer without the client needing any update.

The book has the full code with production-grade authentication, logging, and error handling. But the starter is short enough to sketch on a napkin, and that’s the point. MCP’s low activation energy is precisely what makes it spread.


Security Is Where Most Teams Break

Because MCP makes integration easy, it makes misconfiguration easy. The chapter catalogs the three most common security failures I see in the wild:

  1. Overbroad tool surface. A server is written to expose “one little thing,” grows to dozens, and an agent that should only read deployment status can now trigger rollbacks, mutate the database, and send all-hands emails. Principle of least privilege has never been more important.
  2. Credential leakage. Agents try to be helpful. If they see credentials in a resource, they may paste them into a later message. Never expose raw credentials. Use short-lived scoped tokens. Resolve credentials server-side.
  3. Prompt injection through tool outputs. A tool that fetches a web page may return attacker-controlled text containing instructions for the agent. The agent, trying to be helpful, follows them. This is not hypothetical. It has already been exploited in the wild. Treat every tool output as untrusted input.

What a Good Tool Looks Like

Not every function in your codebase should become an MCP tool. The tools that work best share a recognizable shape. The chapter’s checklist, compressed:

  • A narrow, verb-shaped name. get_customer beats customer_utilities. Tools ending in handler or manager are almost always too broad to be useful.
  • A precise input schema. JSON Schema with enums, required fields, and descriptions is non-optional. “Any string” inputs invite hallucinated parameters.
  • A typed, structured output. Named fields, not free-text blobs. Every re-parse the agent has to do is an opportunity for misinterpretation.
  • Idempotent semantics where possible. Retries should not produce different side effects.
  • Fails loudly. “Customer not found” is useful; an empty array is ambiguous.
  • Short, example-laden description. The description is the single most important piece of prose in your MCP server. Invest time in it.
  • Read-only by default. Separate list_customers from create_customer. The read tool is low-risk; the write tool requires higher-privilege invocation.

“MCP servers do not need to be comprehensive. They need to be right about the things that matter. Three perfect tools beat a hundred mediocre ones.”


The Anti-Patterns That Bite

The chapter’s anti-pattern list is the part I get quoted on most:

  • The “do anything” tool. A single database_query that accepts raw SQL. Equivalent to giving the agent root on your database. Don’t ship it.
  • The unversioned tool. Changing semantics without bumping the name or version. Tool contracts are public APIs.
  • The leaky tool. Returning the full customer record when only the email was requested.
  • The side-effectful read. get_report that quietly logs to an analytics system. Reads should be reads.
  • The unauthenticated gateway. Fine for local dev. Catastrophic anywhere near production.
  • The ambiguous scope. A tool that operates on “the current project” without saying what that means. Cross-contamination is the inevitable consequence.
⚠ Warning: Every MCP server you run should emit traces — every tool call, every input, every output, every error. This is not optional. Agents do weird things, and when you cannot reproduce the weird thing, the trace is your only evidence. Structured logs, OpenTelemetry spans, one-week retention for production. Tools that are called a lot and fail a lot are the tools to fix first.

The Legacy ERP Case Study

The chapter closes with a pattern I helped implement at a manufacturing company. Their 20-year-old Oracle-based ERP was the source of truth for inventory, and engineers spent an inordinate amount of time extracting data from it. We built an MCP server in front of it.

We didn’t expose the full ERP. We identified the three queries engineers actually used — get_inventory_level, get_reorder_forecast, get_supplier_contact — and built three tools, each backed by a pre-optimized read-only view, cached for 30 seconds, scoped per user, logged on every call.

The server was 300 lines of code. It replaced a twenty-page internal wiki. The time-to-productivity metric for new engineers on that team dropped from two weeks to one day.


Next up — Chapter 5: Agentic Editors and Flow States. If MCP is the wiring, the editor is where the wiring meets your hands. Chapter 5 walks through the three generations of editor, what semantic codebase search actually changes about your day, and the design patterns that protect flow from the constant interruption of modern AI tooling.


📖 Want the full picture?

The chapter covers the full TypeScript starter server, the complete security decomposition (including prompt-injection defenses), the good-tool checklist with concrete examples, the six anti-patterns with concrete fixes, the enterprise MCP rollout case study (insurance company; seven systems in six months; time-to-productivity from two weeks to three days), and the tool-versioning pattern that saves you four-hour outages.

Get The Engineering of Intent on Amazon →

2026-04-20

Sho Shimoda

I share and organize what I’ve learned and experienced.