npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jnahian/code-notes-mcp

v0.2.0

Published

MCP server for Code Context Notes — gives coding agents read/write access to workspace notes.

Readme

@jnahian/code-notes-mcp

MCP server for Code Context Notes — gives coding agents read/write access to workspace notes over stdio.

Install

Run it straight from npm — no global install needed:

npx -y @jnahian/code-notes-mcp --workspace . --agent claude-code

--workspace <path> is required — no implicit cwd guessing. --agent <name> is required for write access; without it the server starts in read-only mode (only the read tools are listed). --require-existing fails startup (exit 3) if the workspace has no .code-notes/ directory yet; otherwise the server starts in empty mode and creates it on first write. --storage-dir <name> overrides the notes directory (default .code-notes) — pass it if you changed the extension's codeContextNotes.storageDirectory setting.

Configure

Claude Code.mcp.json at the project root (--workspace . resolves against the project directory; for a user-level server in ~/.claude.json, use an absolute path instead):

{
  "mcpServers": {
    "code-notes": {
      "command": "npx",
      "args": ["-y", "@jnahian/code-notes-mcp", "--workspace", ".", "--agent", "claude-code"]
    }
  }
}

Cursor~/.cursor/mcp.json (or .cursor/mcp.json in a project):

{
  "mcpServers": {
    "code-notes": {
      "command": "npx",
      "args": ["-y", "@jnahian/code-notes-mcp", "--workspace", ".", "--agent", "cursor"]
    }
  }
}

Tools

Read tools are always available; write tools appear only when the server was started with --agent.

| Tool | Access | Input | Output | |---|---|---|---| | get_note | read | id | The full note with history and references. | | get_notes_for_file | read | file, includeScopeMatches? | Notes attached to the file, plus directory-scoped notes covering it. | | get_notes_for_changes | read | files? and/or diff? | Notes relevant to changed files or a unified diff, ranked by relevance. | | list_instructions | read | scope? | Active instruction/warning notes, ranked by priority then recency. | | get_handoffs | read | stale? | Handoff notes, most-recently-updated first (excludes expired unless stale). | | search_notes | read | query, type?, tags?, file?, includeExpired? | Full-text matches with optional type/tag/file filters. | | create_note | write | file, lineRange, content, type?, tags?, scope?, references?, priority?, expiresAt? | The created note (authorType: agent). | | edit_note | write | id, content | The updated note (adds a history entry). | | delete_note | write | id | Confirmation of the soft-delete. | | add_handoff | write | file, lineRange, content, references? | A handoff note (expires in 7 days by default). | | add_decision | write | file, lineRange, content, references | A decision note; references required. |

Every tool returns its result as text content whose body is JSON — a note object on success, or { "error": <code>, ... } on failure (see Error convention).

Resources

| URI | MIME | Contents | |---|---|---| | code-notes://digest | text/markdown | The AGENTS.md digest for the workspace. | | code-notes://index | application/json | The INDEX.json note index. | | code-notes://file/{path} | text/markdown | Notes for a single file (path is the workspace-relative path). Not enumerated in resources/list. |

Trust model

Agent writes are governed by agentWriteMode in <storageDir>/config.json — a workspace-owned file, not a server flag. There is deliberately no --write-mode option: an agent that picks its own mode has no rails.

| Mode | Agent writes | Use when | |---|---|---| | direct | Land immediately, attributed authorType: agent. | Solo dev, trusted agent. | | audit (default) | Land immediately, and every op is appended to <storageDir>/_audit.log. The extension's Agent activity view lists them with a Revert action. | Most teams. | | queue | Do not touch live notes. Each write becomes a proposal in <storageDir>/_pending/, surfaced in the extension's Pending agent proposals view for Approve / Reject. | Shared or regulated codebases. |

// .code-notes/config.json
{
  "agentWriteMode": "audit",   // "direct" | "audit" | "queue"
  "agentAllowList": [],         // informational; empty allows any --agent name
  "auditLogRetention": 1000     // ops kept before rotating to _audit.log.1
}

Without --agent, the server is read-only and none of this applies.

What write tools return in queue mode

Not a note, and not an error — retrying will not help:

{ "status": "pending", "proposalId": "prop-xyz", "message": "Awaiting human approval." }

The mode is re-read from disk on every call, so a human changing it takes effect immediately — no server restart.

Troubleshooting

  • { "error": "lock_timeout", "retryable": true } — another writer (the VS Code extension, or a second agent) held the note's lock. Retry the same call once after a short delay; if it times out again, treat it as a real conflict rather than looping.
  • No notes / empty results, and no .code-notes/ in the workspace — the server starts in empty mode when the workspace has no notes yet and creates .code-notes/ on first write. Pass --require-existing if you want startup to fail (exit 3) instead.
  • Write tools return { "status": "pending" } instead of a note — the workspace is in queue mode. This is not a failure and retrying won't change it: a human approves the proposal in the extension's Pending agent proposals view. Check agentWriteMode in <storageDir>/config.json.
  • The agent sees no notes, or writes land somewhere the extension never shows — the server defaults to .code-notes/, but the extension's codeContextNotes.storageDirectory setting can point elsewhere. If you changed it, pass the same value as --storage-dir <name>; otherwise the two sides read different directories and take their locks in different places, so their writes are no longer serialized against each other.
  • Version mismatch with the extension — the MCP server and the VS Code extension share the on-disk note format via @jnahian/code-notes-core. Keep them on compatible versions; a note written by a newer format may not round-trip through an older reader.

Error convention

Tool failures are never thrown as MCP protocol errors — they come back as a normal tool result whose text content is JSON: { "error": "<code>", ...extra fields }. This keeps failure handling uniform for agents: always parse the result text and check for an error key first.

| Code | Meaning | |---|---| | invalid_arguments | Arguments failed schema validation, or the tool name itself is unrecognized; detail describes the issue(s). | | not_found | No note exists with the given id. | | note_deleted | edit_note was called on a note that has since been soft-deleted. | | file_not_found | The target file doesn't exist in the workspace. | | invalid_line_range | The requested line range doesn't fit the file. | | read_only_mode | Server was started without --agent; write tools are unavailable. | | references_required | add_decision requires at least one reference. | | lock_timeout | Another writer holds the note's lock. retryable: true — safe to retry once. | | diff_parse_failed | The supplied unified diff couldn't be parsed; detail has the reason. | | path_escapes_workspace | The target file path resolves outside the workspace root. | | internal_error | Unexpected failure; detail has the underlying message. Not safe to retry blindly. |

lock_timeout is transient: retry the same call once after a short delay. If it times out again, treat it as a real conflict rather than retrying in a loop.

This convention covers tools. The code-notes://file/{path} resource is a different transport shape (contents[0].text is markdown, not JSON) — a path that escapes the workspace returns contents[0].text: "Error: path escapes workspace: <path>" as plain text, not a coded JSON error.