Skip to main content
Glama
techsaurabh-394

mcp-notes-server

mcp-notes-server

Stars License: MIT Last commit Issues Buy Me A Coffee

A complete reference Model Context Protocol (MCP) server in TypeScript: 6 tools, resources and a prompt, backed by a persistent, searchable notes file. Small enough to read in one sitting, and tested end to end over real stdio.

What is MCP?

The Model Context Protocol is an open standard that lets AI apps (like Claude) talk to outside programs in one uniform way, a bit like USB-C for AI. Instead of custom glue for every assistant, you write one MCP server that offers tools (actions the AI can run), resources (data it can read) and prompts (reusable templates), and any MCP client can discover and use them.

Learn MCP step by step: ai-engineer-roadmap / 06-mcp

Related MCP server: mcp-server-example

Architecture

flowchart LR
    C["MCP client<br/>(Claude Desktop, Claude Code, Inspector)"] -- "JSON-RPC over stdio" --> S["mcp-notes-server<br/>(dist/index.js)"]
    S --> N[("notes.json")]

Tools

Tool

What it does

Hints

add_note

Save a note with title, content and optional tags

Writes

get_note

Fetch one note by id

Read-only

list_notes

List notes newest first, optionally by tag

Read-only

search_notes

Keyword search over titles, tags and bodies (title matches rank highest)

Read-only

update_note

Edit title, content and/or tags (tags replace existing ones)

Writes, idempotent

delete_note

Permanently delete a note by id

Destructive

Errors (unknown id, malformed id, empty update) come back as isError results with a clear message, never as crashes.

Resources and prompts

Type

Name / URI

Description

Resource

notes://all

Every note, newest first, as plain text

Resource template

notes://{id}

One note by id; each note is also listed individually

Prompt

review_notes (optional tag)

Asks the model to summarise your notes, flag duplicates and suggest better tags

Notes are stored in a JSON file (~/.mcp-notes/notes.json by default, override with NOTES_FILE). Writes are atomic (temp file + rename).

Quick start

git clone https://github.com/techsaurabh-394/mcp-notes-server.git
cd mcp-notes-server
npm install
npm run build
npm test

Use with Claude Desktop

Add this to your Claude Desktop config (claude_desktop_config.json), using the absolute path to your clone:

{
  "mcpServers": {
    "notes": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-notes-server/dist/index.js"],
      "env": { "NOTES_FILE": "/absolute/path/to/notes.json" }
    }
  }
}

Restart Claude Desktop, then try:

  • "Save a note titled RAG chunking with the content use 800-char chunks with overlap, tag it rag."

  • "Search my notes for chunking."

  • "Change the tags on that note to rag and search."

Use with Claude Code

claude mcp add notes -- node /absolute/path/to/mcp-notes-server/dist/index.js
# optional: custom storage file
claude mcp add notes --env NOTES_FILE=/absolute/path/to/notes.json -- node /absolute/path/to/mcp-notes-server/dist/index.js

Run claude mcp list to confirm. Other MCP clients (Cursor, etc.) work the same way: point them at node dist/index.js over stdio.

Test with the MCP Inspector

npm run build
npx @modelcontextprotocol/inspector node dist/index.js

Open the printed URL to browse and call the tools, resources and prompt interactively.

Testing

npm test builds and runs the node:test suite: store unit tests plus an end-to-end test that spawns the built server over stdio with the SDK client and exercises initialize, every tool, resources and prompts. CI runs it on Node 22.

Security design

  • No shell, no SQL, no network: the server only reads and writes one JSON file.

  • Path handling: the file path comes from the operator (NOTES_FILE), never from tool input. Note ids are validated (^[a-f0-9]{8}$) and only compared against stored ids, never used as paths.

  • stdout is the protocol channel: all logging goes to stderr.

  • Validation: every tool input is checked with zod (length and count limits); bad input returns an error result.

  • Annotations: read-only tools are marked readOnlyHint, delete_note is destructiveHint, so clients can show the right confirmation UI.

  • Atomic writes avoid a half-written notes file.

Project layout

src/index.ts             MCP server: tools, resources, prompt
src/store.ts             NoteStore: JSON-file persistence and search
src/test/store.test.ts   unit tests
src/test/e2e.test.ts     end-to-end test over stdio
.github/workflows/ci.yml GitHub Actions CI

License

MIT, built by Saurabh Pathak.

Roadmap (contributions welcome)

  • update_note tool (edit title, content, tags)

  • Resources (notes://all, notes://{id}) and a review_notes prompt

  • Optional SQLite backend for large note collections

  • Semantic search using embeddings

  • Publish to npm so it runs with npx mcp-notes-server

  • Streamable HTTP transport for remote clients

If this is useful, a star helps others find it.

Support this project

If this is useful, a star helps others find it, and you can support more free open-source work:


Available Tools

4 tools
add_noteAdd noteB

Save a new note. Returns the note id. Use tags to group related notes.

NameRequiredDescriptionDefault
tagsNoOptional tags
titleYesShort title
contentYesBody of the note

TDQS

B3.4/5.0
Behavior3/5

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

With no annotations the description carries the full behavioral burden. It usefully discloses that the call returns the note id (compensating for the missing output schema), but says nothing about permissions, persistence, failure behavior, or the 10-tag cap enforced by the schema.

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?

Three short, front-loaded sentences with no filler: the action, the return value, and the tag tip. Every sentence earns its place.

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

Completeness4/5

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

For a simple additive create tool with a fully documented schema, the description covers the essentials and even compensates for the absent output schema by naming the returned id. It stops short of stating any permissions or error behavior, which is a minor gap given the tool's simplicity.

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%, so title and content are already documented in the schema and the baseline is 3. The tag sentence adds a small amount of intent ('group related notes') but does not explain format, syntax, or interaction with other fields.

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?

States a specific verb and resource ('Save a new note') plus the return value, so the agent immediately knows this is a creation tool. It does not differentiate itself from siblings like list_notes or search_notes, though the verb makes the distinction obvious.

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?

'Use tags to group related notes' is advice about a parameter, not about when to invoke this tool versus its siblings. There is no stated precondition, no exclusion, and no alternative named, so an agent gets no routing guidance beyond the obvious verb.

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

delete_noteDelete noteA
Destructive

Permanently delete one note by id. This cannot be undone.

NameRequiredDescriptionDefault
idYesNote id from list_notes or search_notes

TDQS

A3.8/5.0
Behavior4/5

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

The destructiveHint=true annotation already signals a write operation, but the description adds useful specificity: the deletion is permanent and irreversible. It stops short of mentioning permission requirements, error behavior for missing ids, or cascading effects.

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?

Two short sentences, zero filler, with the permanence warning front-loaded. Every sentence earns its place.

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

Completeness4/5

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

For a single-parameter destructive tool, the description plus annotations and schema cover the essentials. It could be slightly richer by noting what happens when the id does not exist, but nothing critical is missing.

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%, with the 'id' parameter already documented as coming from list_notes or search_notes. The description's 'by id' adds no new meaning beyond the schema, so the baseline 3 applies.

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

Purpose5/5

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

States a specific verb ('delete'), resource ('note'), scope ('one'), and identifier ('by id'), which cleanly distinguishes it from add_note, list_notes, and search_notes. An agent can identify the operation without opening the schema.

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?

The description gives no when-to-use guidance, no alternatives, and no prerequisites. It only implies that the tool deletes, leaving the agent to infer the appropriate context from the name alone.

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

list_notesList notesA
Read-only

List notes, newest first. Optionally filter by a single tag.

NameRequiredDescriptionDefault
tagNoOnly notes with this tag

TDQS

A3.6/5.0
Behavior3/5

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

readOnlyHint=true already tells the agent this is a safe read. The description adds genuinely useful traits beyond that: the default sort order ('newest first') and the constraint that only one tag can be supplied. It does not mention pagination, result limits, or ordering controls, which matters for a list endpoint.

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?

Two short sentences, zero waste, with the ordering behavior front-loaded and the filter constraint second. Nothing is repeated from the name or title.

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

Completeness4/5

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

For a zero-required-parameter read tool with an annotated safety profile and no output schema, the description covers what is needed to invoke it. The only real gap is the absence of any hint about result size or pagination for a potentially unbounded list.

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% for the single 'tag' parameter, so the baseline is 3. The description adds a small nuance the schema does not convey: only a single tag is accepted, not a set.

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?

States a specific verb and resource ('List notes') plus ordering ('newest first') and an optional filter. It is clear on its own, but it never differentiates itself from the sibling search_notes, which an agent could easily confuse with a filtered list.

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?

'Optionally filter by a single tag' implies the intended usage, but there is no explicit guidance on when to use this versus search_notes or when a tag filter is preferable to a search query. Usage must be inferred.

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

search_notesSearch notesA
Read-only

Keyword search across note titles, tags and bodies. Returns the best matches with full content.

NameRequiredDescriptionDefault
limitNoMax results (default 5)
queryYesSpace-separated keywords

TDQS

A3.5/5.0
Behavior3/5

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

readOnlyHint=true already tells the agent this is a safe read. The description adds genuine value beyond annotations by disclosing that results are relevance-ranked ('best matches') and returned with full content rather than snippets, but it says nothing about result-count behavior or what happens when the query matches nothing.

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?

Two tight sentences, front-loaded with the search scope and then the return shape. No filler, though the second sentence is thin relative to the room available.

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

Completeness4/5

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

With no output schema, the description usefully compensates by stating that matches come back ranked with full content. Combined with the fully documented input schema and readOnly annotation, an agent has enough to call this correctly.

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 100%, so both parameters (query, limit) are already documented in structured form. The description only echoes the query semantics ('keyword') and adds nothing about the limit or the interaction between limit and result ranking, so 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?

States a specific verb and resource ('Keyword search across note titles, tags and bodies'), making it immediately distinguishable from the CRUD siblings add_note/list_notes/delete_note. It does not explicitly name a sibling, but the search-vs-mutate distinction is unmistakable.

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?

Keyword search implies when to use it, but the description never addresses the obvious overlap with list_notes (browse vs. query) nor states any prerequisite. Usage context is left to inference rather than made 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. 4 tool updatesv1.0.0
    • First observedadd_note
    • First observeddelete_note
    • First observedlist_notes
    • First observedsearch_notes

TDQS

A3.6/5.0

Scored across 4 tools

Disambiguation5/5

Each tool maps to a clearly distinct operation: create, enumerate, keyword-search, and delete. There is no overlap between search_notes and list_notes since one is keyword-based and the other is enumerative with tag filtering, and descriptions make the boundaries explicit.

Naming Consistency4/5

All tools follow a verb_noun snake_case pattern (add_note, list_notes, search_notes, delete_note), which is highly predictable. The only minor deviation is singular 'note' in add/delete versus plural 'notes' in list/search, but this reflects natural object plurality rather than a convention break.

Tool Count4/5

Four tools is a tight, well-scoped surface for a simple notes server, with each tool earning its place. It sits at the low end of the typical 3-15 range, and the absence of any modification tool makes it feel slightly under-provisioned rather than bloated.

Completeness3/5

The surface covers create, read/list, search, and delete, but there is no update/edit tool, so an agent cannot modify an existing note's title, body, or tags without deleting and recreating it. Retrieval by id is also only implicitly available via search, leaving a notable lifecycle gap.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables AI assistants to manage in-memory notes by listing, fetching, and creating notes through MCP tools over stdio.
    64 npm
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables managing plain-text notes on disk through MCP resources, tools, and prompts, so natural-language requests can create, read, search, delete, and summarize notes via an interactive client.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI assistants to read, search, create, update, and remove locally stored personal notes organized by themes and subt themes, with backlink navigation, all through MCP tools.
    MIT