Skip to main content
Glama
JackieNonSense

Notes MCP Server

inktrace-mcp-template

A minimal remote MCP (Model Context Protocol) server you can run in ten minutes: Hono, the official MCP SDK over streamable HTTP, token auth with a constant-time comparison, Zod-validated tools, and Postgres via Drizzle. The domain is a toy notes table, but the structure is the one I run in production for InkTrace — this repo is a clean-room extraction of that pattern, written for reading. The full design write-up is in the inktrace-showcase repo.

What it demonstrates

  • Stateless streamable HTTP. A fresh McpServer + transport per request, so the same code runs on a laptop, a container, or a serverless function with nothing to desynchronize. See src/index.ts — the whole transport dance is five lines.

  • Token auth done carefully. SHA-256 both sides, then timingSafeEqual (src/auth.ts). Hashing first equalizes buffer lengths so a wrong-length guess can't throw. The secret is accepted as a Bearer header (preferred) or a URL path segment for connector UIs that can't send headers — with a comment explaining why the header variant is preferred (URLs end up in logs).

  • Policy in the protocol. Write tools carry a "requires prior explicit user approval" prefix and the server instructions state the rules of engagement, so a well-behaved client asks the user before mutating anything (src/mcp/server.ts, src/mcp/tools.ts).

  • Snapshot before destructive writes. write_note versions the current content before overwriting it and prunes history to the newest 20 (snapshotBeforeEdit in src/mcp/tools.ts). Undo is a data-model feature, not a support ticket.

  • Zod on every tool input, and a safe() wrapper that turns thrown exceptions into MCP tool errors instead of protocol crashes.

  • No delete tool. The worst realistic failure of a confused model is an unwanted addition — visible and reversible — not silent destruction.

Related MCP server: Snackbar MCP Server

Quickstart

You need Node 20+ and a Postgres database.

npm install
cp .env.example .env        # fill in DATABASE_URL and MCP_SECRET
npm run db:push             # create the notes / note_versions tables
npm run dev                 # http://localhost:3001/mcp

Connect from Claude Code:

claude mcp add --transport http notes http://localhost:3001/mcp \
  --header "Authorization: Bearer <your MCP_SECRET>"

Then ask Claude to list_notes, have it draft something, approve it, and watch write_note create the row — and snapshot before any edit.

Layout

src/
├── index.ts        # Hono app, health check, MCP mount, stateless transport
├── auth.ts         # timing-safe token middleware (Bearer or path segment)
├── db.ts           # postgres.js + Drizzle, serverless-friendly pool size
├── schema.ts       # notes + note_versions
└── mcp/
    ├── server.ts   # server identity + usage-policy instructions
    └── tools.ts    # 3 read tools + 1 write tool with pre-write snapshot

What the production version adds

Since this template is deliberately single-file-per-concern, it's worth naming what the real InkTrace server layers on top: per-tool project-ownership checks, Postgres row-level security pinned per request as a second authorization layer, HTML sanitization on rich-text input, batch caps on bulk operations, and rate limiting inherited from the surrounding API. The auth gate here is single-tenant by design; the multi-user path is OAuth, which replaces tokenAuth without touching any tool.

License

MIT — take the structure, replace the notes.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    A personal note store exposed as an MCP server. Enables any MCP-speaking assistant to create, search, list, and categorize notes, with per-client bearer tokens for author attribution.
    259 npm
    MIT