Skip to main content
Glama
poplores

technical-notes-mcp

by poplores
README.md
# technical-notes-mcp

> A [Model Context Protocol](https://modelcontextprotocol.io) server that lets Claude — or any MCP-compatible client — search your local notes directory and check live system resource usage. Built with TypeScript on the official `@modelcontextprotocol/sdk`, talking over stdio.

[![build](https://github.com/poplores/technical-notes-mcp/actions/workflows/build.yml/badge.svg)](https://github.com/poplores/technical-notes-mcp/actions/workflows/build.yml)
[![Node](https://img.shields.io/badge/node-%E2%89%A518-brightgreen)](https://nodejs.org)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
[![MCP](https://img.shields.io/badge/MCP-server-purple)](https://modelcontextprotocol.io)

---

## Demo

![Inspector running both tools](docs/demo.gif)

## Architecture

![Architecture](docs/architecture.svg)

The server is a Node process spoken to over stdio using JSON-RPC 2.0. Each MCP client (Inspector, Claude Desktop, Claude Code) spawns it as a subprocess and exchanges messages on its stdin/stdout. The server exposes two tools that read from the local filesystem and the Node `os` module.

## Tools

### `search_technical_notes`

Searches a local directory of markdown and code files for a keyword and returns the contents of the most relevant file.

| | |
|--|--|
| **Input** | `keyword` (string) — the term to search for, case-insensitive |
| **Output** | Best-matching file's relative path, score, and full contents |
| **Scoring** | filename matches × 10, plus content occurrence count |

Supported extensions: `.md`, `.mdx`, `.txt`, `.ts`, `.tsx`, `.js`, `.jsx`, `.py`, `.go`, `.rs`, `.java`, `.c`, `.cpp`, `.h`, `.hpp`, `.rb`, `.sh`, `.json`, `.yaml`, `.yml`. Files over 1 MB are skipped; `node_modules`, `.git`, `dist`, `build`, `.venv`, `__pycache__`, `.cache`, `.next` are pruned during the walk.

### `get_system_resource_usage`

Returns a live snapshot of the host's CPU and memory.

| | |
|--|--|
| **Input** | none |
| **Output** | platform, CPU%, memory used/free/total, uptime, ISO timestamp |
| **Method** | samples `os.cpus()` twice over 500 ms and computes busy-time delta |

This is more accurate than `os.loadavg()` (which is Unix-only) and works on every platform Node supports.

---

## Quick start

### Requirements

- Node.js 18 or later
- An MCP client — the [MCP Inspector](https://modelcontextprotocol.io/legacy/tools/inspector) for testing, or [Claude Code](https://docs.claude.com/en/docs/claude-code/overview) for daily use

### Install and build

```bash
git clone https://github.com/poplores/technical-notes-mcp.git
cd technical-notes-mcp
npm install
npm run build
```

The build produces `build/index.js` — the entry point an MCP client will spawn.

### Configure your notes directory

The search tool reads from `NOTES_DIR`. Set this in your MCP client config (examples below) — never hardcode it in the source.

### Verify it works

Run the official Inspector against the build:

```bash
NOTES_DIR=/path/to/your/notes npm run inspector
```

**Windows (Command Prompt):**

```cmd
set NOTES_DIR=C:\path\to\your\notes
npm run inspector
```

Open the URL the Inspector prints, click **Connect**, then the **Tools** tab. Both tools should appear. Run `search_technical_notes` with a keyword you know is in your notes — it should return the matching file. Run `get_system_resource_usage` twice in a row — the timestamp and uptime should change, confirming live data.

---

## Use it with an MCP client

### Claude Code (recommended)

```bash
claude mcp add technical-notes \
  --env NOTES_DIR=/absolute/path/to/your/notes \
  -- node /absolute/path/to/technical-notes-mcp/build/index.js
```

Then in any Claude Code session: *"Search my technical notes for X"* or *"What's my CPU usage?"*

### Claude Desktop

> ⚠️ The current MSIX/Microsoft Store builds of Claude Desktop on Windows have a [known bug](https://github.com/anthropics/claude-code/issues/29100) where they silently ignore `mcpServers` in `claude_desktop_config.json`. The macOS build is unaffected. If you're on Windows, use Claude Code for now.

On macOS, edit `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "technical-notes": {
      "command": "node",
      "args": ["/absolute/path/to/technical-notes-mcp/build/index.js"],
      "env": {
        "NOTES_DIR": "/absolute/path/to/your/notes"
      }
    }
  }
}
```

Restart Claude Desktop fully.

---

## Project structure

```
technical-notes-mcp/
├── src/
│   └── index.ts            # Server setup + both tool handlers
├── docs/
│   ├── architecture.svg    # Diagram embedded above
│   └── demo.gif            # Demo embedded above
├── .github/workflows/
│   └── build.yml           # CI: typecheck + build on Node 18/20/22
├── package.json            # ESM, bin entry, build/inspector scripts
├── tsconfig.json           # ES2022 / Node16 module resolution
├── LICENSE                 # MIT
└── README.md
```

## How it works (under the hood)

This is a stdio MCP server: a Node process that reads JSON-RPC requests on stdin and writes responses on stdout. Each MCP client spawns it as a subprocess; there's no network, no port, no shared state.

**Don't `console.log` from a stdio MCP server.** stdout is reserved for the protocol. The server uses `console.error` (stderr) for its startup message. Any stray write to stdout will break the JSON-RPC stream.

The `get_system_resource_usage` tool samples CPU counters twice over 500 ms and computes the busy-time delta across all cores — see the `getCpuUsagePercent` function in [`src/index.ts`](src/index.ts) if you want to tune the sample window.

The `search_technical_notes` tool walks the directory with an async generator that yields one file path at a time, scoring each file with a simple weighted match count (`filename_hits × 10 + content_hits`). For a smarter scoring strategy, edit `scoreFile` — e.g. weight matches in markdown headers higher, or plug in a real tokenizer.

## Extending it

- **Different scoring** — edit `scoreFile` in `src/index.ts`.
- **More extensions** — add to the `ALLOWED_EXTENSIONS` set.
- **More tools** — call `server.registerTool(...)` again with the same shape as the existing two. The SDK handles schema validation via Zod.

## Troubleshooting

| Symptom | Cause | Fix |
|--|--|--|
| `Notes directory does not exist` | `NOTES_DIR` not set or wrong path | Set it in the client config or env |
| Inspector "Disconnected" on connect | Build failed or path wrong | Re-run `npm run build`; check `build/index.js` exists |
| Tools don't appear in Claude Desktop on Windows | MSIX build ignores config | Use Claude Code instead |
| `'chmod' is not recognized` on Windows during build | Old build script | The current `package.json` uses just `tsc` |

## License

MIT — see [LICENSE](./LICENSE).

TDQS

A3.8/5.0

Scored across 2 tools

Disambiguation5/5

The two tools serve completely different purposes: one monitors system resources, the other searches technical notes. There is no risk of confusion.

Naming Consistency5/5

Both tool names follow the 'verb_noun' pattern in snake_case, which is consistent and clear.

Tool Count2/5

With only 2 tools, the server feels very thin. Moreover, the tools cover two unrelated domains (system monitoring and note searching), which is odd for a server named 'technical-notes-mcp'.

Completeness1/5

For a technical notes server, only a single search tool exists, lacking create, update, delete, or list operations. The system resource tool is out of place and does not address note management needs.

Maintenance

ActivityInactive
ResponsivenessNo issues