Repo docs

Per-repo documentation — each repo's docs/ and README, ingested and associated with the repo. Rendered through the <<<RepoDocs>>> tag.

← testmonkeyalpha__notes_db_mcp docs · README.md

jazz-notes-db-mcp

MCP (Model Context Protocol) adapter for jazz-notes-db. Proxies the notes_db HTTP API as MCP tools, allowing AI assistants and agents to manage notes via the MCP protocol.

Install

pip install jazz-notes-db-mcp --index-url https://gitlab.com/api/v4/projects/83824314/packages/pypi

Then run:

jazz-notes-db-mcp

Or with a custom upstream URL:

NOTES_DB_URL=http://my-notes-server:8001 jazz-notes-db-mcp

Docker

docker run -e NOTES_DB_URL=http://notes_db:8001 registry.gitlab.com/testmonkeyalpha/notes_db_mcp:4.0.0

Available tags: - registry.gitlab.com/testmonkeyalpha/notes_db_mcp:4.0.0 - registry.gitlab.com/testmonkeyalpha/notes_db_mcp:latest

Configuration

Configuration is via environment variables. There is no config file — all values can be set at launch time.

| Variable | Default | Description | |----------|---------|-------------| | NOTES_DB_URL | http://notes_db:8001 | Base URL of the upstream notes_db HTTP API. Use the Docker service name in containerized deployments; use http://127.0.0.1:8001 for local dev. |

> Note on client.py: The bundled client.py module (used by integration tests and other tools) defaults NOTES_DB_URL to http://127.0.0.1:8765 — a different port from the server default. Set NOTES_DB_URL explicitly in both contexts to avoid confusion.

Proposed future config schema (JSON)

A conf/config.json file is planned to replace hardcoded values. Draft schema:

{
  "notes_db_url": "http://notes_db:8001",
  "timeout": 30,
  "host": "0.0.0.0",
  "port": 8002,
  "log_level": "info"
}

Priority order: env vars > config.json > built-in defaults.

MCP Tools Exposed

| Tool | Description | |------|-------------| | add_note | Add a note (title, text, collection, tags) | | get_notes | List notes, optionally filtered by collection or tag | | get_note | Get a single note by ID | | update_note | Update an existing note by ID | | delete_note | Delete a note by ID | | search_notes | Search notes by tag match (see note below) |

> search_notes limitation: The current implementation filters by tag match (passes the query string as a tag filter to GET /notes). It does not perform full-text search against note titles or bodies. A future version should wire to the upstream /search?q= endpoint.

Endpoints

- GET /health — Health check (returns {"status": "ok"}) - GET /tools — List available MCP tools with input schemas - POST /tools/{name} — Call a tool by name with a JSON body

Architecture

AI agent / Claude
      │
      │  HTTP POST /tools/{name}  (MCP protocol over HTTP)
      ▼
jazz-notes-db-mcp  (this service, FastAPI)
      │
      │  HTTP GET/POST/PUT/DELETE  (notes_db REST API)
      ▼
jazz-notes-db  (upstream, port 8001)
      │
      ▼
SQLite / storage

The MCP server is a thin proxy: each POST /tools/{name} call translates directly to one upstream HTTP request to notes_db. There is no caching, no local state, and no authentication layer.

Key files

| File | Purpose | |------|---------| | notes_db_mcp/server.py | FastAPI app, tool definitions, proxy logic | | notes_db_mcp/client.py | Synchronous HTTP client for notes_db (used by tests and other tools) | | notes_db_mcp/__main__.py | Entry point, runs uvicorn |

Error Handling and Retry Behavior

Current behavior

- HTTP errors from upstream (4xx/5xx) are forwarded as-is to the caller with the upstream status code and body. - Network errors (connection refused, timeout) are not caught — they surface as unhandled 500 errors from FastAPI. - The timeout for upstream calls is hardcoded to 30 seconds per request. - Each tool call creates a new httpx.AsyncClient (no connection pooling).

Known gaps

- No retry logic. Transient upstream failures (brief restart, network blip) fail immediately. - Health check does not verify upstream. GET /health returns {"status": "ok"} even if notes_db is unreachable. - No circuit breaker. Sustained upstream unavailability causes every tool call to wait the full 30s timeout before failing.

Recommended mitigations (not yet implemented)

- Add 1-2 retries with exponential backoff for idempotent read operations (get_note, get_notes, search_notes). - Do not retry write operations (add_note, update_note, delete_note) — they are not idempotent. - Add upstream health-check to /health endpoint (with short timeout, e.g. 2s). - Use a module-level httpx.AsyncClient with connection pool limits.

Development

Prerequisites

- Python 3.11+ - A running jazz-notes-db service (for integration tests)

Setup

cd services/notes_db_mcp
python -m venv .venv
source .venv/bin/activate
pip install -e ".[test]"

Run locally

NOTES_DB_URL=http://127.0.0.1:8001 jazz-notes-db-mcp

Run tests

Unit tests (no upstream required):

pytest tests/

Integration tests (requires notes_db running at http://127.0.0.1:8765):

NOTES_DB_URL=http://127.0.0.1:8765 pytest notes_db_mcp/tests/

Build and package

pip install build
python -m build

The version is derived from the git tag via setuptools-scm. Tag a commit with vX.Y.Z to produce a clean version.

CI / CD

See .gitlab-ci.yml. On tag push, the pipeline: 1. Runs tests 2. Builds the wheel 3. Publishes to the GitLab PyPI registry 4. Builds and pushes the Docker image