I've been working with MCP servers for a few months now. If you're not familiar, MCP (Model Context Protocol) is Anthropic's open standard for connecting AI models to external tools and data sources. Think of it as the API layer between an LLM and the stuff it can actually do.
There are already a bunch of prebuilt MCP servers out there. Ones that connect to GitHub, Slack, Google Drive, databases, you name it. You can plug them into Claude Desktop or VS Code and start using them immediately. So the obvious question is why would you build your own?
Here's why. Because the prebuilt ones solve general problems. Your problems are specific.
Maybe you have a local SQLite database with project data and you want Claude to query it conversationally. Maybe you have a folder full of markdown files that represent your team's internal documentation and you want an AI that can actually search them. Maybe you have a custom API at work that nobody outside your company will ever build an integration for.
That's the gap. MCP lets you fill it yourself. And the local version is the fastest way to get something running without deploying anything, paying for anything, or asking anyone for permission.
What You Need
Python 3.10 or higher and the fastmcp library. That's it.
shell pip install fastmcp
If you prefer TypeScript, there's an official MCP SDK for that too, but Python is the faster path for a first server.
The Simplest Possible Server
Here's a working MCP server in about 10 lines. This one exposes a single tool that searches through local text files in a directory.
from fastmcp import FastMCP
from pathlib import Path
mcp = FastMCP("Local Notes Search")
NOTES_DIR = Path.home() / "notes"
@mcp.tool()
def search_notes(query: str) -> str:
"""Search through local notes files for a keyword."""
results = []
for f in NOTES_DIR.glob("*.md"):
content = f.read_text()
if query.lower() in content.lower():
results.append(f"**{f.name}**\n{content[:200]}")
if not results:
return f"No notes found matching '{query}'"
return "\n\n".join(results)
That's a complete MCP server. One file. One tool. When connected to Claude Desktop, you can say "search my notes for anything about project deadlines" and it will actually read your local files and respond.
Connecting It to Claude Desktop
Open your Claude Desktop config file.
On Mac:
plaintext ~/Library/Application Support/Claude/claude_desktop_config.json
On Windows:
plaintext %APPDATA%\Claude\claude_desktop_config.json
Add your server to the config:
{
"mcpServers": {
"local-notes": {
"command": "python",
"args": ["/path/to/your/server.py"]
}
}
}
Restart Claude Desktop. Your tool should show up in the tools menu. That's it.
Making It More Useful
Once you've got the pattern down, you can add more tools to the same server. Here's what a slightly more practical version looks like with a few tools on one server.
from fastmcp import FastMCP
from pathlib import Path
import json
mcp = FastMCP("My Local Tools")
NOTES_DIR = Path.home() / "notes"
DATA_DIR = Path.home() / "data"
@mcp.tool()
def search_notes(query: str) -> str:
"""Search local markdown notes for a keyword."""
results = []
for f in NOTES_DIR.glob("*.md"):
content = f.read_text()
if query.lower() in content.lower():
results.append(f"{f.name}: {content[:150]}")
return "\n".join(results) if results else "No matches found."
@mcp.tool()
def list_notes() -> str:
"""List all available notes."""
files = sorted(NOTES_DIR.glob("*.md"))
return "\n".join(f.name for f in files) if files else "No notes found."
@mcp.tool()
def read_note(filename: str) -> str:
"""Read the full content of a specific note."""
path = NOTES_DIR / filename
if not path.exists():
return f"File {filename} not found."
return path.read_text()
@mcp.tool()
def query_json_data(filename: str, key: str) -> str:
"""Look up a key in a local JSON data file."""
path = DATA_DIR / filename
if not path.exists():
return f"File {filename} not found."
data = json.loads(path.read_text())
if key in data:
return json.dumps(data[key], indent=2)
return f"Key '{key}' not found in {filename}."
Four tools, one file, no deployment. You can ask Claude to search your notes, read a specific file, or pull data from local JSON files. Everything runs on your machine. Nothing leaves your network.
When to Go Local vs. Remote
Local MCP servers make sense when you're working with files on your machine, querying local databases, prototyping a tool before deploying it, or connecting to internal APIs that are only accessible from your network.
If you need the server to be available across devices, shared with a team, or triggered by other services, that's when you look at hosting it remotely. But for personal productivity and experimentation, local is the move.
The Bigger Picture
The reason MCP matters isn't the protocol itself. It's that it turns AI from a thing you type questions into to a thing that can actually interact with your environment. Every local tool you expose is one less copy and paste cycle between your terminal and your chat window.
Start with one tool. Make it solve one problem you actually have. You'll find the second and third ones pretty quickly after that.
Top comments (0)