Skip to main content
Glama

MCP Server + Client

PersonalKB: a real Model Context Protocol (MCP) server, notes search plus a live weather lookup, and a client/agent that talks to it. The MCP protocol layer is never mocked: every test spawns a real server subprocess and does real JSON-RPC over it, either over stdio or over real HTTP. The only thing ever faked offline is the LLM's own tool-choice decision; no API key is needed to run anything here except the final --real flag.

Problem: Wiring a model up to tools with a hand-rolled JSON blob works until you need a second client, a remote server, or someone else's tools. MCP is Anthropic's open standard for how a model discovers and calls tools, reads resources, and uses prompt templates over a real wire protocol instead. This project builds a real server against that protocol, from the decorators up through a working client bridge and agent loop.

Skills demonstrated: building an MCP server (tools, resources, prompts) with FastMCP, both stdio and streamable-HTTP transports, a client bridge that discovers tools live over the protocol, an offline deterministic tool router and a real agentic loop against the Claude API, SQLite full-text search (FTS5), and pytest against real protocol traffic (no mocking).

Tech stack: Python 3.10+, the mcp SDK (FastMCP), SQLite (standard library), the Anthropic SDK for the real agent path, requests for live weather (Open-Meteo), pytest.

What it exposes

Running mcp_kb.server starts an MCP server, PersonalKB, over notes stored in SQLite with full-text search:

  • Tools: search_notes(query, limit), add_note(title, body, tags), list_tags(), get_weather(city).

  • Resources: note://{note_id} (fetch one note), notebook://summary (a summary of the whole notebook).

  • Prompt: research_prompt(topic), a reusable prompt template.

Related MCP server: MCP Apple Notes

Run it

python -m venv .venv ; .\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
python generate_data.py           # seeds data/notes.db with 15 hand-written notes

python -m mcp_kb tools                                  # list tools/resources/prompts
python -m mcp_kb ask "find notes about python"
python -m mcp_kb ask "what's the weather in Paris"
python -m mcp_kb serve                                  # run the server directly (stdio)
python -m mcp_kb serve --http                            # or over streamable-HTTP

pytest -q                          # the full suite, all real protocol traffic, no key needed

ask spawns the real server, discovers its tools live over MCP, and answers your question with an offline deterministic router by default, or the real Claude API with --real (needs ANTHROPIC_API_KEY in .env).

How it fits together

mcp_kb/
├── db.py         SQLite + FTS5 notes store: search, add, tags
├── weather.py     an offline table, or real keyless Open-Meteo data with --live-weather
├── server.py      the actual MCP server (FastMCP-based): tools, resources, a prompt
├── bridge.py       the MCP client wrapper: discovers tools/resources/prompts live
├── llm.py         the offline deterministic tool-choice router
├── agent.py        the agentic loop: offline router, or a real Claude tool-use loop
└── cli.py           python -m mcp_kb tools|ask|serve
tests/                41 tests, all real protocol traffic (stdio and HTTP), no mocking

The design choice that matters: server.py is a thin wrapper around db.py and weather.py; the MCP layer's only job is translating between the protocol and plain Python functions. That split is what makes the underlying logic testable with zero protocol overhead, while the protocol layer itself is still exercised for real in every test.

Connecting a real MCP client

The same server also runs as-is inside the real Claude Desktop app: point its MCP config at python -m mcp_kb serve, and it can search your notes or check the weather in a normal chat, calling the exact tools defined in server.py. See hosting/HOSTING_GUIDE.md for the connection steps and for deploying the HTTP transport somewhere a remote client could reach it.

What I learned

  • MCP separates what a tool does from how a client finds and calls it: the server declares tools, resources, and prompts once, and any compliant client (a hand-rolled bridge, or Claude Desktop) can discover and use them without custom glue.

  • Keeping the protocol layer thin and pushing logic into plain, testable Python functions is what let the test suite run real client/server traffic without it being slow or brittle.

  • stdio and streamable-HTTP are just two transports under the same protocol; the tools, resources, and prompts a server exposes don't change based on how a client reaches it.

F
license - not found
Not graded
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • F
    license
    A
    quality
    C
    maintenance
    Enables seamless interaction with Voicenotes through natural language, allowing users to search, create, edit, tag, and organize their notes via an MCP client like Claude.
    14
    4
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables users to create, link, explore, and synthesize atomic notes using the Zettelkasten method through MCP-compatible clients like Claude.
    MIT

View all related MCP servers

Related MCP Connectors

  • Search, read, and write your Apple Notes from ChatGPT/Claude via a local Mac agent + MCP relay.

  • Markdown-based note-taking with a hosted MCP server. Your notes serve you and your AI.

  • Cross-AI personal memory. Save once in ChatGPT, recall in Claude, Mistral, Grok, or any MCP client.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/K-Divyasri/mcp-server-client'

If you have feedback or need assistance with the MCP directory API, please join our Discord server