DEV Community

MxGuru
MxGuru

Posted on

I Built a 127-Tool MCP Server From Scratch — Here's What I Learned

The Model Context Protocol (MCP) is how AI agents talk to tools. Claude Code, Cursor, Windsurf — they all use it. But most MCP servers have 5-10 tools.

I built one with 127.

Why?

I run a local AI operations platform called The Sovereign Hive. It coordinates multi-agent swarms, runs security scans, manages a knowledge graph, and serves as the backbone for everything I build. Every agent needs tools — and I got tired of wiring up 8 different MCP servers.

So I consolidated everything into one server, one port, one health endpoint.

The Tool Categories

Category Count Examples
File I/O 11 read, write, copy, move, delete, head, tail, wc
Search 6 grep, glob, find_symbol, find_references, search_replace
Git 10 status, diff, log, blame, commit, branch, stash, tag
Code Analysis 6 lint, complexity, dead_code, dependency_graph
Browser Automation 7 navigate, screenshot, click, fill, evaluate, snapshot
Docker 8 ps, logs, exec, images, inspect, run, stop, stats
Semantic Memory 7 store, search, relate, observe, get, list, delete
Monitoring 4 health_probe, logs_tail, service_status, uptime_check
HTTP/Web 5 fetch, request, dns_lookup, url_encode, curl_equivalent
Web Search 1 DuckDuckGo via ddgs (no API key)
System 7 system_info, process_list, env_vars, port_check, disk_usage
Data Parsing 7 json_query, csv, yaml, toml, ini, xml, json_format
Database 3 sqlite_query, sqlite_schema, sqlite_tables
Archive 5 zip/tar create, extract, list
Text/Transform 8 diff, regex, base64, hash, token_estimate, string_transform
Crypto 4 generate_secret, uuid, hmac, password_hash
Notebook 3 read, create, add_cell
Task/Todo 4 create, list, update, complete
Prompt Engineering 4 build, chain, message_format, library
Thinking/Reasoning 4 sequential_think, decision_matrix, assumption_check, pros_cons
API Testing 4 graphql_query, websocket_send, api_test, openapi_parse
Comms Hub 3 post, read, channels
Ollama 2 list models, generate

Architecture Decisions

Every tool is an async function with the same signature:

async def tool_name(args: dict) -> dict:
Enter fullscreen mode Exit fullscreen mode

Input is always a dict. Output is always a dict. No exceptions in the signature — errors go in {"error": "..."}.

Every tool carries MCP metadata:

TOOL_META = {
    "name": "grep_recursive",
    "description": "Search for a regex pattern across files in a directory tree.",
    "inputSchema": { ... }  # JSON Schema
}
Enter fullscreen mode Exit fullscreen mode

This means any MCP client can discover the tool, see its parameters, and call it — without reading the source code.

The registry supports both stdio and HTTP/SSE transport:

  • mcp_server.py — JSON-RPC over stdin/stdout (for Claude Code direct integration)
  • mcp_server_sse.py — FastAPI with /tools, /tools/call, /mcp, /sse, /health endpoints

No mandatory external dependencies. Every tool uses Python stdlib where possible. Browser tools need Playwright. Docker tools need Docker. But the other 112 tools work with zero pip installs beyond FastAPI/uvicorn.

The Semantic Memory System

This was the most interesting piece to build. It's a knowledge graph stored in SQLite with TF-IDF similarity search — no vector database, no embeddings model required.

await memory_store({"name": "project-x", "content": "FastAPI backend with Redis caching", "type": "project"})
await memory_relate({"from": "duayne", "relation": "builds", "to": "project-x"})
await memory_observe({"entity": "project-x", "content": "Deployed to production"})
results = await memory_search({"query": "FastAPI caching backend"})
Enter fullscreen mode Exit fullscreen mode

Entities, relationships, and observations — all queryable. Agents can build up persistent knowledge across sessions without needing a GPU or external service.

What I'd Do Differently

  1. Start with MCP metadata from day one. I retrofitted it onto 15 existing tools. Building it in from the start is much cleaner.
  2. Group tools by file, not one-per-file. Related tools (like all git operations) belong together.
  3. The DDG HTML scraper approach failed. DuckDuckGo now serves CAPTCHAs to scrapers. Use the ddgs library or pay for a search API.

Try It

The entire stack is open source: Repo is private during development — DM me for early access.

Top comments (0)