Skip to main content
Glama
team-humaki

notes-lite

by team-humaki

MCP Server Starter Lite

A minimal, tested Model Context Protocol server in Python. It's built on the official MCP Python SDK v2 and is small enough to read in two minutes. It is one stdio server with two typed tools over an in-memory notes list, plus tests that call it in-process and as a real subprocess.

src/mcp_server_lite/server.py   the server: add_note, search_notes
tests/test_server.py            in-process tests through the SDK's Client (fast)
tests/test_stdio.py             launches the server as a subprocess, like a host does

Quick start

Requires uv and Python 3.10+.

git clone https://github.com/team-humaki/mcp-server-starter-lite
cd mcp-server-starter-lite
uv run pytest            # 5 passed
uv run mcp-server-lite   # starts on stdio and waits silently: that is correct (Ctrl+C to stop)

Use it from Claude Code

claude mcp add notes-lite -- uv --directory /ABSOLUTE/PATH/TO/mcp-server-starter-lite run mcp-server-lite
claude mcp list          # notes-lite: ... ✔ Connected

Then ask Claude to "save a note titled X". The tools appear as mcp__notes-lite__add_note and mcp__notes-lite__search_notes.

Other hosts

Any MCP host that launches stdio servers can use the same command and args: uv --directory /ABSOLUTE/PATH/TO/mcp-server-starter-lite run mcp-server-lite. (Only Claude Code was tested; see below.)

Related MCP server: Notes MCP

What it shows

  • Typed inputs. Annotated[..., Field(min_length=..., le=...)] becomes the JSON Schema the model sees, and bad input comes back as a tool error instead of a crash.

  • Structured output. Return a Pydantic model or a list of them and the client gets both text and structured_content.

  • Model-facing errors. ToolError("...") reaches the model as is_error: true, so write it as an instruction.

  • stdio hygiene. Log to stderr and never print(), because stdout is the protocol wire.

  • Testing without a host. async with Client(mcp) as client: runs the real protocol in-process.

Make it yours

  1. Rename the server (MCPServer("notes-lite")) and the package.

  2. Replace NOTES with your database or API client.

  3. Replace the two tools. Keep the docstrings specific, because they're what the model reads to decide when to call a tool.

  4. Update the tests, then uv run pytest.

Tested

  • uv run pytest: 5 passed on Python 3.13 and 3.10, with mcp 2.3.0 (pinned in uv.lock).

  • Claude Code 2.1.310 (Linux): claude mcp add (the command above) and claude mcp list showed it as ✔ Connected. A session called add_note and got {"id":1,"title":"Hello from Claude Code","body":""} back. The model side was a scripted local API, not a real model.

  • Not tested: Cursor, Claude Desktop, VS Code, macOS, Windows.

What the full version adds

Python MCP Server Starter (paid, $12) adds:

  • A full "notes" server showing every building block: resources and URI templates, prompts, a Pydantic model as tool input, tool annotations (read-only/destructive), Context, and error handling for each type.

  • Streamable HTTP with OAuth 2.1 bearer auth as a resource server. It covers Protected Resource Metadata, 401/403 challenges, per-tool scopes, a JWT/JWKS verifier and DNS-rebinding protection, with a dev-key script for local testing.

  • A Dockerfile, and config snippets for Claude Code, Cursor, Claude Desktop and VS Code.

  • 32 tests: in-process, stdio subprocess, a real uvicorn HTTP server with auth, and the JWT verifier. Plus documented SDK and spec gaps and an upgrade guide.

License

MIT. See LICENSE.

Available Tools

2 tools
add_noteB

Save a note and return it with its id.

NameRequiredDescriptionDefault
bodyNoNote text.
titleYesShort title.

Output Schema

NameRequiredDescription
idYesServer-assigned id.
bodyNo
titleYes

TDQS

B3.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description does carry the burden, but it does disclose that this is a write ("save") and that the response is the stored note including its id. It says nothing about duplicate titles, permission requirements, or whether an existing note is overwritten — gaps that matter for a mutation, even a simple one.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single short sentence with zero filler and the operation front-loaded. Efficient, though the "return it with its id" clause partly restates what the output schema already covers.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter create tool with a full schema and an output schema, the core purpose is covered and return values need not be spelled out. What's missing is the surrounding context an agent needs to choose this tool confidently — durability, uniqueness handling, or any prerequisite — leaving it minimally adequate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% — both title ("Short title.") and body ("Note text.") plus length bounds are documented in the schema. The description adds no meaning beyond that, so the baseline 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

"Save a note" gives a specific verb and resource, and the second clause states what comes back (the note with its id). It is clear against the only sibling, search_notes (a read), though it never states the contrast explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no guidance on when to use this vs. search_notes or any other alternative, and no preconditions. The agent must infer that this is the write path for creating new notes.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_notesA

Find notes whose title or body contains the query.

NameRequiredDescriptionDefault
limitNo
queryYesCase-insensitive text to look for in titles and bodies.

Output Schema

NameRequiredDescription
resultYes

TDQS

A3.5/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It does disclose the matching semantics (substring containment across title AND body, not just one field), which is genuinely useful behavior beyond the name; but it says nothing about result ordering, whether the limit truncates silently, or scope/permission behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler; the matching scope is stated before any caveat would be needed. Nothing is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Output schema exists, so return values needn't be explained, and there are only two parameters. Still, for a tool with zero annotations, the description omits ordering, truncation behavior at 'limit', and any scope constraints — leaving the agent to guess at result semantics.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 50%: 'query' is documented in the schema as case-insensitive, and the description reinforces it by tying matching to title/body. The 'limit' parameter has no description in either place, only a default of 10 and a max of 50, so the description fails to compensate for the uncovered half.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Clear verb ('Find') plus resource ('notes') and even the matching scope (title or body). It does not explicitly name the sibling add_note, but the read-vs-write distinction is obvious from the verb, so an agent can differentiate without more.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied by the verb 'Find' — the description never states when to reach for this over add_note or any other lookup path, nor any exclusions. For a two-tool sibling set where the alternative is a write, the implication is strong enough to be workable but not explicit.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 2 tool updatesv0.1.0
    • First observedadd_note
    • First observedsearch_notes

TDQS

B3.4/5.0

Scored across 2 tools

Disambiguation5/5

The two tools serve clearly distinct purposes: one writes a note, the other queries existing notes. There is no overlap or risk of misselection.

Naming Consistency5/5

Both names follow a consistent verb_noun snake_case pattern (add_note, search_notes). The convention is predictable and readable.

Tool Count3/5

Two tools is thin for a notes server; creation and search alone leave little room for a full workflow. The count itself is not excessive, but it feels under-scoped.

Completeness2/5

The surface covers only create and search; there is no way to fetch a note by id, list all notes, update content, or delete a note. These significant gaps will block common agent tasks like editing or cleanup.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers