Chapter 19: Model Context Protocol (MCP)
Learning Objectives
By the end of this chapter, you will be able to:
- Explain what the Model Context Protocol (MCP) is and why it matters for AI-native engineering
- Distinguish between MCP resources, prompts, and tools
- Build a minimal MCP server in TypeScript
- Verify that server locally with MCP Inspector
- Configure an AI client to launch the server and call its tool
- See how MCP supports spec-driven workflows by making external context queryable
What is the Model Context Protocol?
The Model Context Protocol (MCP) is an open protocol for connecting AI clients to external context and executable capabilities. Instead of stuffing every requirement, contract, and reference doc directly into a prompt, MCP lets a client ask a server for exactly the resource or tool it needs.
At a high level:
- MCP client: the AI runtime or editor that can call MCP servers
- MCP server: a local or remote process that exposes resources, prompts, and tools
In an SDD workflow, that means your agent can fetch only the contract, issue, schema, or checklist it needs instead of working from stale pasted snapshots.
Why MCP is Useful in SDD
In Spec-Driven Development, the specification is the source of truth, but that truth is often spread across multiple systems:
- feature specs in
specs/ - work items in Jira or Linear
- API contracts in OpenAPI or AsyncAPI files
- architecture decisions in ADRs
- internal docs in a wiki or portal
MCP helps in three practical ways:
1. Live context instead of copied context
Instead of copying a Jira ticket into chat, the agent can query a tool like get_issue("PROJ-123").
2. Smaller, more relevant context windows
Instead of pasting an entire API reference, the agent can ask for just the endpoint or schema it needs.
3. Better automation boundaries
Instead of writing one-off shell scripts for every lookup, you expose stable, named tools and resources that multiple agents can share.
MCP Building Blocks
An MCP server typically exposes three categories of capability:
- Resources: read-oriented context such as docs, schemas, contracts, and files
- Prompts: reusable prompt templates the client can invoke
- Tools: executable functions such as "fetch issue," "query schema," or "trigger validation"
For SDD, tools and resources are usually the most important:
- Resources hold durable context
- Tools fetch or transform context on demand
Tutorial: Build and Verify a Minimal MCP Server
This tutorial creates a tiny local MCP server that exposes one tool, get_contract, which returns contract metadata for a named service.
Prerequisites
- Node.js 20 or newer
- npm
- A terminal
- An MCP-capable client or MCP Inspector for verification
Step 1: Create the Project
mkdir mcp-contract-server
cd mcp-contract-server
npm init -y
npm install @modelcontextprotocol/sdk zod
npm install -D typescript tsx @types/node
npx tsc --init
This gives you a minimal TypeScript project plus the MCP SDK.
Step 2: Create the Server File
Create src/index.ts:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { z } from "zod";
const contracts = {
billing: { version: "1.2.0", path: "contracts/billing.yaml" },
auth: { version: "2.0.1", path: "contracts/auth.yaml" },
};
const server = new McpServer({
name: "contract-server",
version: "1.0.0",
});
server.tool(
"get_contract",
"Fetch contract metadata for a service name",
{ service: z.string() },
async ({ service }) => {
const result = contracts[service as keyof typeof contracts];
if (!result) {
return {
content: [
{ type: "text", text: `Unknown service: ${service}` },
],
};
}
return {
content: [
{ type: "text", text: JSON.stringify(result, null, 2) },
],
};
}
);
const transport = new StdioServerTransport();
await server.connect(transport);
This example is intentionally small. The point is to verify the protocol flow before you connect real systems.
Step 3: Run the Server Locally
npx tsx src/index.ts
If the process starts and waits silently, that is expected. A stdio MCP server usually stays quiet until a client connects.
Step 4: Verify with MCP Inspector
Use Inspector to confirm the server launches and exposes the expected tool:
npx @modelcontextprotocol/inspector node --loader tsx/esm src/index.ts
In Inspector:
- Connect to the server
- Confirm
get_contractappears in the tool list - Invoke it with
billing
Expected result: You receive JSON text containing the billing contract metadata.
Step 5: Configure an MCP Client
Point your MCP-capable client at the server. A minimal config looks like:
{
"mcpServers": {
"contract-server": {
"command": "node",
"args": ["--loader", "tsx/esm", "/ABSOLUTE/PATH/src/index.ts"]
}
}
}
Use an absolute path. Relative paths are a common source of launch failures.
Step 6: Use the Tool from the Client
Once the client is configured, prompt it with something like:
"Use the
get_contractMCP tool to fetch the auth service contract metadata and summarize what file I should read next."
Expected result: The client calls get_contract("auth") and returns the path and version information.
Applying MCP to an SDD Workflow
Once the minimal server works, the next step is replacing the hard-coded contracts object with a real backing system. Typical patterns:
get_issue(issueId)-> pull requirements from Jira or Linearget_contract(service)-> return the latest contract location or contentssearch_docs(query)-> return relevant internal docslist_feature_specs()-> expose availablespecs/[branch-name]/folders
That changes the agent workflow from:
- Human copies context into chat
- Agent works from a static snapshot
to:
- Agent discovers the latest source of truth
- Agent fetches only the needed context
- Agent works from live, queryable inputs
Common Mistakes
Logging to stdout
Stdout is used for protocol traffic. Extra logs there can break the session. Log to stderr instead.
Treating examples as production-ready
The tutorial server is deliberately minimal. Add auth, validation, and real data access before using MCP for sensitive systems.
Returning unstable shapes
If a tool response changes shape frequently, agents become unreliable. Keep tool outputs consistent and documented.
Skipping local verification
Always test with Inspector before debugging client configuration. That isolates protocol problems from client-specific problems.
Troubleshooting
"Server does not appear in Inspector"
- Confirm
npx tsx src/index.tsstarts without syntax errors - Confirm the file path in the Inspector command is correct
- Confirm Node.js version is recent enough for your setup
"Tool is missing"
- Check the
server.tool(...)registration name - Restart the server after edits
- Make sure the client is connecting to the file you just changed
"Client cannot launch the server"
- Use an absolute path in the client config
- Verify the
commandandargswork directly in the terminal - Check whether your client expects a different config location
"The server launches but returns bad data"
- Start with a hard-coded response like the tutorial example
- Only add external integrations after the minimal flow is working
- Validate the returned shape before wiring the next system
Try With AI
Prompt 1: Design a Real MCP Tool
"I have API contracts in
specs/[branch-name]/contracts/. Design an MCP tool calledget_contractthat returns the contract file path and the latest version metadata. Show the response shape and the validation rules."
Prompt 2: Map MCP to SDD
"For a spec-driven workflow that uses Jira, OpenAPI contracts, and ADRs, list the 5 highest-value MCP tools or resources to implement first. Explain what each one replaces in a manual workflow."
Practice Exercises
Exercise 1: Replace the Hard-Coded Data
Change the tutorial server so get_contract reads from a local JSON file instead of a hard-coded object.
Expected outcome: The server still works, but contract metadata now comes from a file you can edit without changing code.
Exercise 2: Add a Second Tool
Add list_contracts so the client can discover available services before calling get_contract.
Expected outcome: The server exposes at least two tools, and Inspector shows both.
Exercise 3: Sketch an MCP Adoption Plan
Choose one real project and list the first external systems you would expose through MCP. For each one, specify whether it should be a resource, a prompt, or a tool.
Expected outcome: A short MCP adoption plan tied to a real SDD workflow.
Key Takeaways
- MCP turns external context into queryable context. Agents do not need every document pasted into chat.
- Tools and resources are the practical core for SDD. They let agents fetch the exact spec, contract, or issue they need.
- Start with a minimal server. Verify the protocol and tool shape locally before integrating real systems.
- Inspector-first debugging saves time. Validate the server independently before debugging client config.
Chapter Quiz
- What problem does MCP solve in an AI-native workflow?
- What is the difference between an MCP client and an MCP server?
- Name the three major capability categories an MCP server can expose.
- Why should you verify a server with Inspector before debugging the client?
- Give one SDD use case where an MCP tool is better than copying context into chat.
Back to: Part VI Overview | Next: Chapter 20 - /speckit.specify - Feature Specification