MCP Development June 16, 2026 ~22 min read Model Context Protocol AI Tool Calling

Build an MCP Server from Scratch:
Hands-On AI Tool Calling

Protocol basics · Tools / Resources / Prompts · Debug & deploy · Personal knowledge base

Build MCP Server from scratch for AI tool calling

Backend and AI developers with Python or TypeScript experience keep hitting the same wall: Claude and GPT are smart, but they cannot query your database, call internal APIs, or read local files—because models lack a standard channel to external tools. The Model Context Protocol (MCP), open-sourced by Anthropic, lets AI Clients (Cursor, Claude Desktop) talk to your Server over JSON-RPC. By the end of this guide you will build and deploy a production-ready MCP Server, covering: protocol architecture → environment setup → Hello World → Tools / Resources / Prompts → HTTP remote transport → debug and test → Docker deployment → a personal knowledge-base project → the 2026 ecosystem outlook.

01

Introduction: Why AI Needs MCP

Even the strongest models have training cutoffs. They cannot magically know your CRM customers, last night's logs, or the live state of an internal API. The industry path is clear: Function Calling → Plugins → MCP. The first two are mostly vendor-specific formats—switch models and you rewrite the integration layer. MCP standardizes how AI discovers and invokes tools, so you write once and reuse across Clients.

  1. 01

    Pain point: You want Claude or GPT to query databases, call APIs, and manipulate files—but every vendor speaks a different format.

  2. 02

    Scenario: In Cursor, have AI read your Markdown notes; in Claude Desktop, pull GitHub Issues on demand.

  3. 03

    Promise: This guide takes you from an empty directory to a deployable Server, with complete code and a troubleshooting table.

02

What Is MCP? Understand the Protocol Before You Code

2.1 Background

Anthropic released MCP in November 2024 to standardize AI-to-tool communication, replacing N models × M tools = N×M custom adapters with one open protocol. For the broader protocol narrative, see our MCP and HTTP analogy article.

2.2 Architecture Overview

MCP uses a Client ↔ Server model: the Client lives on the AI side (Claude Desktop, Cursor); the Server is what you build, exposing three core capabilities over JSON-RPC:

  • T

    Tools: Functions the AI can call—search, calculate, query databases.

  • R

    Resources: Data the AI can read—files, URLs, config streams.

  • P

    Prompts: Predefined, parameterizable prompt templates.

2.3 Communication Mechanism

Built on JSON-RPC 2.0. Transport options: stdio (local subprocess—default for Cursor and Claude Desktop) and HTTP + SSE / Streamable HTTP (remote services). Lifecycle: initialization handshake → capability negotiation (initialize) → request/response → shutdown.

2.4 Comparison with Other Approaches

DimensionMCPOpenAI Function CallingLangChain Tools
StandardizationOpen protocolVendor-specificFramework-bound
Transportstdio / HTTPHTTPHTTP
Cross-modelYesNoPartial
Resources / PromptsNative supportNot supportedNot supported
Ecosystem10,000+ Servers in 2026MatureMature
03

Development Environment Setup

3.1 Choose a Language

Python (official mcp SDK with FastMCP decorators) is the best starting point for newcomers. TypeScript (@modelcontextprotocol/sdk) suits frontend and full-stack teams. This guide uses Python as the primary example, with TypeScript noted where relevant.

Environment setup
# Python
python -m venv .venv && source .venv/bin/activate
pip install mcp httpx pydantic

# TypeScript (reference)
npm init -y && npm install @modelcontextprotocol/sdk

3.2 Project Structure

my-mcp-server/
my-mcp-server/
├── server.py            # Main entry point
├── tools/               # calculator.py, web_search.py
├── resources/           # file_reader.py
├── prompts/             # templates.py
├── tests/test_tools.py
├── pyproject.toml
└── README.md

3.3 Debugging Tools

  1. 1

    MCP Inspector: npx @modelcontextprotocol/inspector python server.py

  2. 2

    Claude Desktop: Edit claude_desktop_config.json to register your Server.

  3. 3

    Cursor: Settings → MCP → add command + args.

04

Your First MCP Server: Hello World

server.py · Minimal working Server
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("my-first-server")

@mcp.tool()
def say_hello(name: str) -> str:
    """Greet a person by name"""
    return f"Hello, {name}! This is your first MCP tool."

if __name__ == "__main__":
    mcp.run()

Run python server.py, then in Inspector or Cursor MCP settings enter {"command":"python","args":["/path/to/server.py"]}. Refresh the tool list—you should see say_hello.

Cursor / Claude Desktop Integration Tips

  • Use absolute paths for server.py and your virtualenv Python binary.

  • After code changes, restart the MCP connection or reopen the Cursor window.

  • Explicitly ask the model to call the tool in chat to confirm registration.

05

Tools: Building Functions the AI Can Call

5.1 Basic Structure

Your function signature is the documentation: parameter types, return types, and docstrings are exposed to the model for tool selection. Use snake_case with verb prefixes (search_web, read_file). Return structured JSON on errors instead of raw exceptions so the model can self-correct.

5.2 Complex Parameters (Pydantic)

Search tool with schema
from pydantic import BaseModel, Field

class SearchInput(BaseModel):
    query: str = Field(description="Search keywords")
    max_results: int = Field(default=5, description="Maximum results to return")
    language: str = Field(default="en", description="Result language")

@mcp.tool()
def web_search(input: SearchInput) -> list[dict]:
    """Run a web search and return matching results"""
    ...

5.3 Five Practical Tools to Build

ToolPurposeCaveats
CalculatorEvaluate math expressionsUse ast.literal_eval or a safe parser—never eval
File I/ORead/write local filesWhitelist directories; normalize paths to prevent traversal
HTTP requestsCall external APIsTimeouts, retries, response size limits
Database queriesRead-only SQLParameterized queries; block DDL
Time utilitiesCurrent time, timezone conversionReturn ISO 8601 for easy parsing

5.4 Async Tools

async fetch_url
@mcp.tool()
async def fetch_url(url: str) -> str:
    """Fetch content from a URL"""
    async with httpx.AsyncClient(timeout=30.0) as client:
        response = await client.get(url)
        return response.text

5.5 Error Handling Best Practices

  • !

    Set timeouts on network and I/O operations (15–30s recommended).

  • !

    Apply permission checks on sensitive operations (API keys, allowed paths).

  • !

    Return {"error": "...", "hint": "..."} so the model can retry intelligently.

06

Resources: Let AI Read Dynamic Content

Resource vs Tool: A Resource is a data provider (mostly read-only); a Tool is an action executor. Resources are addressed by URI: file://, http://, custom://.

Static and dynamic resources
@mcp.resource("config://app-settings")
def get_app_settings() -> str:
    """Return application configuration"""
    return json.dumps({"version": "1.0", "env": "production"})

@mcp.resource("user://{user_id}/profile")
def get_user_profile(user_id: str) -> str:
    """Return user profile by ID"""
    return json.dumps(db.query_user(user_id))

Resource types include: text (text/plain, application/json), binary (images, PDFs), and streaming (live market data). A practical project: a filesystem Server that lists directories, reads files, and optionally subscribes to file changes.

07

Prompts: Reusable Prompt Templates

MCP Prompts are predefined prompt fragments with dynamic parameter injection, improving team consistency and maintainability.

Code review prompt template
from mcp.types import PromptMessage, TextContent

@mcp.prompt()
def code_review_prompt(language: str, code: str) -> list[PromptMessage]:
    """Code review prompt template"""
    return [PromptMessage(
        role="user",
        content=TextContent(type="text", text=f"""Review the following {language} code:
1. Quality and readability  2. Bugs and security  3. Performance

```{language}
{code}
```""")
    )]

You can define multi-turn templates with user + assistant roles for interview simulations, debugging assistants, and more. Clients call prompts/get to retrieve the filled message chain.

08

Advanced: HTTP Transport (Remote MCP Server)

FeaturestdioHTTP + SSE
DeploymentLocal processRemote server
LatencyVery lowNetwork-dependent
Multi-clientNot supportedSupported
Use caseLocal IDE toolsSaaS / team sharing
Streamable HTTP mode
mcp = FastMCP("remote-server", transport="streamable-http")

if __name__ == "__main__":
    mcp.run(host="0.0.0.0", port=8000)

Production requirements: Bearer Token / API Key middleware, CORS allowlists, and rate limiting. Never expose an unauthenticated HTTP MCP Server to the public internet.

09

Debugging and Testing

9.1 MCP Inspector

Inspector provides a GUI to test tools/list, tools/call, inspect JSON-RPC logs, and simulate error scenarios.

9.2 Unit Tests (pytest + ClientSession)

test_calculator_tool
@pytest.mark.asyncio
async def test_calculator_tool():
    server_params = StdioServerParameters(command="python", args=["server.py"])
    async with stdio_client(server_params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            result = await session.call_tool("calculate", {"expression": "2 + 2"})
            assert result.content[0].text == "4"

9.3 Common Errors

ErrorCauseFix
Tool not listedWrong config pathVerify absolute paths in config.json
JSON serialization failureUnsupported return typeConvert to str or dict
Timeout disconnectSlow tool executionUse async + timeout controls
Permission deniedRestricted file pathConfigure allowed directories / use VNC for TCC
10

Production Deployment

10.1 Docker Containerization

Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 8000
CMD ["python", "server.py"]

10.2 Cloud Hosting Options

  • Railway / Render: One-click deploy for personal projects.

  • AWS Lambda / Cloud Run: Serverless—watch cold starts and stdio limitations.

  • Self-hosted VPS + Nginx: Reverse proxy, TLS, and rate limiting.

10.3 Observability

Structured request logs, Prometheus metrics for tool calls, Sentry error alerts, and a /health endpoint. Declare your MCP protocol version and keep tool upgrades backward compatible.

11

Project: Personal Knowledge Base MCP Server

Goal: Let AI search local Markdown notes, run semantic retrieval, and create or update notes. In Cursor, ask: "What did I write about MCP last week?"

Tech Stack

ComponentRecommendation
Vector storeChromaDB / Qdrant (local)
Embedding modeltext-embedding-3-small
File watcherwatchfiles for incremental indexing

Core Tools

  1. 1

    index_notes: Scan a directory and build a vector index.

  2. 2

    semantic_search: Return relevant snippets by meaning.

  3. 3

    write_note: Create or append Markdown files.

  4. 4

    Resource: notes://{path} to read a single note directly.

The AI calls semantic_search, synthesizes answers from retrieved snippets, and saves tokens compared to stuffing your entire note library into context.

12

MCP Ecosystem and 2026 Outlook

Recommended Open-Source Servers

  • mcp-server-filesystem — Filesystem operations

  • mcp-server-github — GitHub repositories

  • mcp-server-brave-search — Web search

  • mcp-server-postgres — Database queries

  • mcp-server-slack — Slack messaging

In 2026, Cursor, Claude Desktop, OpenAI, Google Gemini, and Microsoft all support or have completed MCP integration. The MCP Marketplace and enterprise security standards (OAuth 2.1, audit trails) continue to mature. Official docs: modelcontextprotocol.io; Python SDK: github.com/modelcontextprotocol/python-sdk.

Five-Step Rollout (Including Remote Mac Validation)

  1. 1

    Pick a Host (Cursor / Claude Desktop) and confirm 2026 builds have native MCP support.

  2. 2

    Develop locally over stdio; validate tools/list in Inspector.

  3. 3

    Register in Cursor MCP config; smoke-test with the Hello World tool.

  4. 4

    For Servers touching browsers, Keychain, or screen recording, complete TCC authorization in a macOS graphical session—SSH alone cannot click Allow.

  5. 5

    Deploy HTTP mode in Docker with auth and monitoring; cross-link with our Agent Skill guide and browser MCP checklist.

13

FAQ

Python (mcp + FastMCP) is the fastest on-ramp; TypeScript (@modelcontextprotocol/sdk) fits teams already on Node. The protocol layer is equivalent.

Prefer stdio for local IDE development; choose HTTP + SSE / Streamable HTTP when you need multi-user sharing or SaaS delivery—and always add authentication.

Tools execute actions (write to DB, send requests); Resources provide read-only data (config, file contents) addressed by URI templates.

Browser DevTools MCP, high-privilege file access, Keychain, and screen recording trigger macOS TCC dialogs. SSH cannot click Always Allow—you need a VNC graphical session on the same machine as the Host.

Closing

MCP is the standard protocol for AI tool integration—mastering the full path from Hello World to production deployment is a core skill for AI engineers in 2026. What tool will you build first? Share your Server design after you ship it.

Hidden cost rarely lives in writing code—it lives in the runtime environment. Windows-primary workflows plus a cloud Mac running Cursor MCP mean TCC dialogs, Python virtualenvs, and Inspector logs must be cross-checked in a graphical session on the same machine. Buying a Mac mini adds sleep, OS updates, and depreciation; 8 GB RAM chokes under vector indexing plus concurrent Servers.

To validate your MCP toolchain hourly with on-machine GUI checks for TCC and Inspector, rent a remote Mac through VNCMac: use the primary button below for the pricing page, or browse plans on the homepage first.