Model Context Protocol (MCP): a practical intro
MCP (Model Context Protocol) is a way for an LLM app (the client) to connect to external capabilities exposed by one or more MCP servers—things like reading a repo, querying a database, calling an internal API, or running safe automations.
The value is standardization: instead of building custom integrations per tool, your client speaks MCP to many servers.
The moving parts
- MCP Client: your app/IDE/agent that decides when to call tools.
- MCP Server: exposes capabilities (often “tools”) in a consistent format.
- Tools / Resources: the actual operations and data sources behind the server.
Typical request flow
When MCP is a good fit
- You want one client to talk to many internal tools safely.
- You want tool schemas and consistent calling patterns.
- You want to keep credentials + network access on the server side, not inside the LLM client.
Practical tips
- Keep tools small and composable (one job per tool).
- Return structured output (JSON-ish) when possible.
- Treat servers as "capability boundaries" (auth, audit logs, rate limits).
Example: App MCP Server Implementation
Let's walk through a concrete example—building an MCP server that exposes a tool to query the App API info endpoint. The server uses stdio transport, runs in Docker, and integrates with Cursor's agent window.
Architecture
Files to Create
1. MCP Server (mcp/server.py)
Main MCP server implementation using the mcp Python SDK:
from mcp.server import Server
from mcp.server.stdio import stdio_server
import requests
app = Server("app-mcp-server")
@app.tool()
async def get_app_info() -> dict:
"""Query the App API info endpoint."""
response = requests.get(
"https://api-dv2.app-usw2.dev.aligntech.com/app/info"
)
response.raise_for_status()
return response.json()
async def main():
async with stdio_server() as (read_stream, write_stream):
await app.run(read_stream, write_stream)
if __name__ == "__main__":
import asyncio
asyncio.run(main())
2. Dependencies (mcp/requirements.txt)
mcp>=1.0.0
requests>=2.28.0
3. Dockerfile (mcp/Dockerfile)
FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY server.py .
CMD ["python", "server.py"]
4. Docker Compose (optional) (mcp/docker-compose.yml)
For easier container management during development:
version: "3.8"
services:
app-mcp:
build: .
image: app-mcp-server
stdin_open: true
tty: true
5. README (mcp/README.md)
Documentation with Cursor configuration instructions.
Cursor Configuration
After building the Docker image, add to .cursor/mcp.json:
{
"mcpServers": {
"app": {
"command": "docker",
"args": ["run", "-i", "--rm", "app-mcp-server"]
}
}
}
Build and Run Steps
- Build Docker image:
docker build -t app-mcp-server ./mcp - Restart Cursor to pick up the MCP configuration
- Use the agent window to ask about App API status
Tool Specification
The MCP server exposes one tool:
| Tool | Description | Parameters |
|---|---|---|
get_app_info | Query the App API info endpoint | None |