Skip to main content
ClaudeWave

MCP server that saves your Claude Code, Cursor, and Codex sessions as versioned Markdown reports — with human-in-the-loop review and Apple Pencil / S Pen annotation.

MCP ServersOfficial Registry3 stars0 forksTypeScriptMITUpdated today
Install in Claude Code / Claude Desktop
Method: NPX · md-log-mcp
Claude Code CLI
claude mcp add md-log-mcp -- npx -y md-log-mcp
claude_desktop_config.json (Claude Desktop)
{
  "mcpServers": {
    "md-log-mcp": {
      "command": "npx",
      "args": ["-y", "md-log-mcp"],
      "env": {
        "MDLOG_API_BASE_URL": "<mdlog_api_base_url>"
      }
    }
  }
}
1. Run the command above in your terminal (Claude Code), or paste the JSON config into claude_desktop_config.json (Claude Desktop).
2. Replace any <placeholder> values with your API keys or paths.
3. Restart Claude. The MCP server and its tools appear automatically.
Detected environment variables
MDLOG_API_BASE_URL
Use cases

MCP Servers overview

# md-log-mcp

[![npm version](https://img.shields.io/npm/v/md-log-mcp)](https://www.npmjs.com/package/md-log-mcp)
[![MCP Registry](https://img.shields.io/badge/MCP%20Registry-com.md--log%2Fmd--log--mcp-1f6feb)](https://registry.modelcontextprotocol.io/v0/servers?search=md-log)
[![License: MIT](https://img.shields.io/npm/l/md-log-mcp)](./LICENSE)
[![Node](https://img.shields.io/node/v/md-log-mcp)](https://nodejs.org)

> **Review the report, not the diff.** An MCP server that lets your AI coding agent — **Claude Code, Claude Desktop, Codex, Cursor** — save its work and analysis as immutable, versioned **Markdown reports** into [**md-log**](https://md-log.com), a human-in-the-loop review & archive layer for **"vibe coding."** You then read and **stylus-annotate** (S-Pen / Apple Pencil) those reports on web, phone, and tablet — every save a new immutable version.

A [Model Context Protocol](https://modelcontextprotocol.io) server — **two transports, one tool set** —
that lets **Claude Code** (and other agents) save `.md` files — text **and** embedded screenshots
together — straight into **md-log**, a human-in-the-loop review & archive layer for vibe coding. The
**recommended** way to connect is the **hosted remote endpoint** (`https://mcp.md-log.com/mcp`, a URL +
your key — no install); a local **stdio** (`npx -y md-log-mcp`) transport is the alternative. The agent writes a report
**by path** (`my-project/2026-07-07-error-report.md`); missing folders are auto-created, images are
uploaded and their references rewritten to `asset://` links, and every save becomes an immutable new
version. The same report is then readable, editable, and stylus-annotatable (S-Pen / Apple Pencil
where supported) on a phone or tablet, and on the web.

md-log is a **hosted service** at **https://app.md-log.com** — you don't run any server yourself.
This package is just the connector: a **thin authenticated HTTP client** that validates POSIX paths,
orchestrates asset uploads, maps errors to stable agent codes, and forwards everything to the hosted
md-log service — the single authority for auth, storage, versioning and quota. All you need is a
Personal Access Token from the web app.

## Stack

- **@modelcontextprotocol/sdk** (TypeScript) — one `McpServer` (15 tools), two transports.
- **stdio transport** (`md-log-mcp`) — JSON-RPC over stdin/stdout; the default local mode (so stdout
  is reserved for the protocol; logs go to stderr). PAT from env.
- **Streamable HTTP transport** (`md-log-mcp-http`) — the remote mode: agents connect by URL with no
  local install; the PAT is taken **per request** from the `Authorization` header. See
  [Remote (Streamable HTTP) mode](#remote-streamable-http-mode).
- **TypeScript**, bundled with **tsup** to ESM `dist/server.js` (stdio) + `dist/http.js` (HTTP).
  Runtime deps: the MCP SDK and **zod** (input schemas). Node's built-in `fetch`/`http` are the only
  network layers — no web framework.
- **PAT auth** — a md-log Personal Access Token sent to the backend as `Authorization: Bearer`.

## Requirements

- Node **22+**
- A **Personal Access Token** (PAT) minted in the md-log web app (**Settings → Tokens**; shown once)

That's it — the md-log service itself is hosted at `https://app.md-log.com`; there is nothing to
install or self-host.

## Tools (15)

Every tool returns dual output — a human-readable `content[].text` and a machine-readable
`structuredContent` — and validates the POSIX path (NFC-normalize; reject `..`/`.`, control chars,
empty/whitespace segments, backslashes, reserved names; enforce 255-byte name / 1024-byte path
limits; require `.md` for files) **before** any backend call. All requests hit the base URL in
`MDLOG_API_BASE_URL` (which already includes `/api/v1`).

| Tool | What it does |
| ---- | ------------ |
| **`save_markdown`** ⭐ | The headline tool. Create or overwrite a `.md` by path (force last-writer-wins); missing folders auto-created. Optionally uploads embedded images first (each given as `data_base64` **or** a local `file_path`) and rewrites each `placeholder` in the content to an `asset://<key>` link. Accepts `commit_message` — a recommended 1-2 line change summary shown in the version history. |
| `upload_asset` | Upload one image (reserve → presigned PUT → complete) and return an `asset://<key>` reference to embed as `![alt](asset://<key>)`. Provide the image as **either** `data_base64` (inline base64) **or** `file_path` (a local file the server reads) — exactly one; with `file_path`, `filename` defaults to the basename and `content_type` is inferred from the extension (png/jpg/jpeg/gif/webp/avif). |
| `append_to_markdown` | Append to an existing file with optimistic concurrency (GET current → concat → conditional PUT with `base_version_no`). Auto-retries once on conflict, then surfaces `CONFLICT`. Accepts `commit_message` — a recommended 1-2 line change summary shown in the version history. |
| `update_markdown` | Replace a file's content. Pass `expected_version` for optimistic concurrency (mismatch → `CONFLICT`); omit it to force LWW. Accepts `commit_message` — a recommended 1-2 line change summary shown in the version history. |
| `get_markdown` | Read a file's content by path (materializes inline content or a presigned content URL for large docs). Pass `version` (a `version_no` from `list_versions`) to read an old immutable version. |
| `list_versions` | List a file's immutable version history, newest first (`version_no`, `commit_message`, author, `registered_at`, size). |
| `delete_markdown` | Soft-delete a file. Requires `confirm:true` (otherwise `VALIDATION`); resolves the path to a document key first. |
| `create_folder` | `mkdir -p` — create every missing segment; already-existing folders count as success. |
| `list_folders` | Return the full folder tree. |
| `list_files` | List the documents and immediate subfolders inside a folder path. |
| `search_markdown` | Search by TITLE (substring) + BODY full-text (current versions; whole-word match, ranked, body hits include a snippet). |
| `move_markdown` | Move and/or rename a `.md` by path (`from_path` → `to_path`); destination folders auto-created; the document KEEPS its key, so version history and reviewers' annotations survive. |
| `move_folder` | Move a folder (whole subtree) under a new parent (`new_parent_path` empty/omitted = root); parent auto-created; cyclic moves rejected server-side. |
| `rename_folder` | Rename a folder in place (descendant paths rewritten server-side). |
| `delete_folder` | Delete a folder. Requires `confirm:true`; by default only an EMPTY folder is deleted — pass `cascade:true` to soft-delete the whole subtree (`rm -r`). |

### Error codes surfaced to the agent

Backend failures return `{ isError: true, content:[{type:"text", ...}] }` with a mapped code in
`structuredContent.error.code`:

`NOT_FOUND` · `CONFLICT` (carries the server head `{server_version_no, server_checksum, …}` in
`detail`) · `UNAUTHORIZED` · `RATE_LIMITED` · `QUOTA_EXCEEDED` · `BACKEND_UNAVAILABLE` ·
`VALIDATION` · `FOLDER_EXISTS` (swallowed as success by `create_folder`) · `ERROR`.

## Authentication

The MCP/PC lane authenticates with a **Personal Access Token** (`mdlog_pat_…`) — minted once in the
web app's **Settings** and supplied via env. The client attaches it as `Authorization: Bearer <PAT>`
(plus `X-API-Token` for compatibility) on every request. The backend is the single source of truth
for auth and quota.

| Variable | Required | Example | Notes |
| -------- | -------- | ------- | ----- |
| `MDLOG_API_BASE_URL` | yes | `https://app.md-log.com/api/v1` | The hosted service base, **including** `/api/v1`. No version suffix is appended; a trailing slash is stripped. |
| `MDLOG_PAT` | yes | `mdlog_pat_xxxxxxxxxxxxxxxxxxxxxxxx` | Bearer PAT. **Store it securely (OS keychain) — never commit it.** |

The server fails fast at startup with a clear message if either var is missing or the base URL is
malformed.

## Build

```bash
npm install
npm run build      # tsup → dist/server.js (ESM, Node 22)
npm run typecheck  # tsc --noEmit (optional)
```

## Smoke test

`scripts/smoke.mjs` spawns the **built** server over stdio (MCP SDK `Client` +
`StdioClientTransport`), then runs `initialize` → `tools/list` → `save_markdown` (a small report
embedding a tiny `data:` PNG) → `get_markdown` (reads it back, checks the marker) →
`search_markdown` — printing PASS/FAIL per step and exiting non-zero on any failure. Run it against
a **live** backend with a real PAT:

```bash
npm run build
MDLOG_API_BASE_URL="http://localhost:8080/api/v1" \
MDLOG_PAT="mdlog_pat_xxxx" \
node scripts/smoke.mjs        # or: npm run smoke
```

## Connect a client

Mint the PAT in the web app's **Settings → Tokens**, store it securely, then add md-log to your MCP
client. **Never commit a PAT.**

> 📄 **연결 가이드 (HTML)** — [md-log.com/guides/customer-guide.html](https://www.md-log.com/guides/customer-guide.html): 웹 앱에서 발급받은 **MCP 키(PAT)** 로 URL 연결(권장) 또는 `npx` 로컬 연결 (Claude Code · Desktop · Codex · Cursor).

### Recommended — remote (URL), no install

Point your client at the **hosted endpoint** and pass the PAT as a Bearer header. **Nothing to
install — no Node.js, no `npx`.** (You don't even need this package for the hosted connection.)

```bash
# Claude Code
claude mcp add --transport http md-log https://mcp.md-log.com/mcp \
  --header "Authorization: Bearer mdlog_pat_xxxxxxxxxxxxxxxxxxxxxxxx"
```

```jsonc
// Cursor / Claude Desktop / any client that takes JSON — the `type` field MUST be "http"
{
  "mcpServers": {
    "md-log": {
      "type": "http",
      "url": "https://mcp.md-log.com/mcp",
      "headers": { "Authorization": "Bearer mdlog_pat_xxxxxxxxxxxxxxxxxxxxxxxx" }
    }
  }
}
```

Over the remote endpoint, embed images inline (base64); uploading a local image **by path**
(`file_path`) works only with the local method below.

### Alternative — local (stdio via `npx`)

Runs this connector as a local subprocess (needs Node 22+; `npx` fetches the publish
aiannotationclaudeclaude-codecode-reviewcodexcursordeveloper-toolsdocumentationhuman-in-the-loopllmmarkdownmcpmodel-context-protocolvibe-coding

What people ask about md-log-mcp

What is md-log/md-log-mcp?

+

md-log/md-log-mcp is mcp servers for the Claude AI ecosystem. MCP server that saves your Claude Code, Cursor, and Codex sessions as versioned Markdown reports — with human-in-the-loop review and Apple Pencil / S Pen annotation. It has 3 GitHub stars and was last updated today.

How do I install md-log-mcp?

+

You can install md-log-mcp by cloning the repository (https://github.com/md-log/md-log-mcp) or following the README instructions on GitHub. ClaudeWave also provides quick install blocks on this page.

Is md-log/md-log-mcp safe to use?

+

md-log/md-log-mcp has not been audited yet by our security agent. Review the original repository on GitHub before using it in production.

Who maintains md-log/md-log-mcp?

+

md-log/md-log-mcp is maintained by md-log. The last recorded GitHub activity is from today, with 0 open issues.

Are there alternatives to md-log-mcp?

+

Yes. On ClaudeWave you can browse similar mcp servers at /categories/mcp, sorted by popularity or recent activity.

Deploy md-log-mcp to your cloud

Ship this repo to production in minutes. Each platform spins up its own environment with editable env vars.

Maintain this repo? Add a badge to your README

Drop the badge into your GitHub README to show it's tracked on ClaudeWave. Each badge links back to this page and reflects the live Trust Score.

Featured on ClaudeWave: md-log/md-log-mcp
[![Featured on ClaudeWave](https://claudewave.com/api/badge/md-log-md-log-mcp)](https://claudewave.com/repo/md-log-md-log-mcp)
<a href="https://claudewave.com/repo/md-log-md-log-mcp"><img src="https://claudewave.com/api/badge/md-log-md-log-mcp" alt="Featured on ClaudeWave: md-log/md-log-mcp" width="320" height="64" /></a>

More MCP Servers

md-log-mcp alternatives