Skip to main content
Glama
kschroeder

MarkdownMCP

by kschroeder

MarkdownMCP

Live markdown preview for LLM agents. The agent calls one tool when a markdown file comes into scope; a shared hub watches the file, opens your OS default browser (managed profile) on the first create/change, and streams updates into a multi-tab Vue UI (unread dots, toggleable change marks, history).

Features

  • One MCP tool: scope_markdown — call once before the first write (path may not exist yet)

  • Singleton hub shared by all MCP clients; exits when no clients remain

  • Sticky high port — hub reuses a preferred port from settings.json so preview tabs reconnect after restarts

  • Managed browser profile — system default browser with an isolated profile under the app data dir; left open when the hub exits

  • Reconnect-first — does not spawn a new window if a managed browser session is already running

  • In-app tabs with subtle unread indicators

  • Toggleable change highlights + snapshot history

  • First-run settings (theme, bind host, preferred port, allowed path roots)

  • Cross-platform (Windows, macOS, Linux)

Related MCP server: MCP Docs Server

Quick install (Grok)

From this repo (after build), or once published:

# From monorepo root
npm install
npm run build

# User-level MCP (Grok)
grok mcp add markdown-mcp -- node /absolute/path/to/live-markdown-mcp/packages/mcp/dist/cli.js

Or with a global/workspace link:

npm link -w markdown-mcp
grok mcp add markdown-mcp -- markdown-mcp

~/.grok/config.toml equivalent:

[mcp_servers.markdown-mcp]
command = "node"
args = ["/absolute/path/to/live-markdown-mcp/packages/mcp/dist/cli.js"]
enabled = true
startup_timeout_sec = 60

Copy the skill so the model knows when to call the tool:

# Windows PowerShell
Copy-Item -Recurse .grok/skills/markdown-scope $HOME/.grok/skills/markdown-scope

Other clients

Claude Code

claude mcp add markdown-mcp -- node /absolute/path/to/live-markdown-mcp/packages/mcp/dist/cli.js

Or project .mcp.json:

{
  "mcpServers": {
    "markdown-mcp": {
      "command": "node",
      "args": ["/absolute/path/to/live-markdown-mcp/packages/mcp/dist/cli.js"]
    }
  }
}

Cursor

.cursor/mcp.json:

{
  "mcpServers": {
    "markdown-mcp": {
      "command": "node",
      "args": ["/absolute/path/to/live-markdown-mcp/packages/mcp/dist/cli.js"]
    }
  }
}

Agent usage

1. Decide you will create or edit a markdown doc the user should see rendered.
2. Call scope_markdown once with the path (absolute preferred).
3. Write/edit the file freely — do not call the tool again for edits.

Tool:

Tool

Args

Purpose

scope_markdown

path: string

Watch + preview this file

Architecture

MCP client(s)  --stdio-->  markdown-mcp bridge
                              |
                              +--> ensure hub up (singleton)
                              +--> register client
                              +--> scope_markdown → hub API

Hub  --chokidar--> disk
Hub  --WebSocket--> Vue UI (tabs, diffs, history)
Hub  --spawn--> system default browser + managed profile (first file event, if none running)

State lives under:

Platform

Directory

Windows

%LOCALAPPDATA%\markdown-mcp\

macOS

~/Library/Application Support/markdown-mcp/

Linux

${XDG_CONFIG_HOME:-~/.config}/markdown-mcp/

File / dir

Role

hub.json

Live hub URL/port/pid (cleared when hub stops)

settings.json

Theme, bind host, preferredPort, browser prefs

hub.lock

Singleton lock

browser-profile/

Managed browser user-data / profile

browser.pid

Last launched browser pid (reconnect-first)

Development

npm install
npm run build
npm run start:hub          # hub only (stays up until Ctrl+C; no MCP client timeout if you register manually)
npm run start:mcp          # MCP stdio server (spawns hub as needed)
npm run dev:web            # Vite UI against a hub on :7420 (optional proxy)
npm run test:unit          # shared + hub unit tests
npm run test:local         # unit + sticky-port + browser policy + default-browser
npm run test:sticky-port   # sticky port integration (uses real app data dir)
npm run test:default-browser  # OS default product → binary (skips if browser missing)

Install-dependent checks (Brave/Chrome/Edge/Firefox present on disk, OS default detection) skip with a clear message when the browser is not installed — they do not fail CI machines without that browser.

Packages:

Package

Role

@markdown-mcp/shared

Types + defaults

@markdown-mcp/hub

HTTP/WS hub, watchers, browser

@markdown-mcp/web

Vue UI

markdown-mcp

MCP stdio entry (scope_markdown)

Settings

First browser open shows a short wizard. Later: Settings in the UI.

Setting

Default

Theme

System / Light / Dark

Bind host

127.0.0.1

Preferred port

auto (high port 49152–65535, then sticky)

Allowed path roots

empty = allow any

Open browser on first file event

on

Preserve scroll

on

Show changes by default

on

Changing bind host or preferred port requires a hub restart. Non-loopback binds ask for confirmation.

Sticky port & browser profile

  1. On first start (or empty preferred port), the hub binds a free high port and writes it to settings.json as preferredPort.

  2. Later starts try that port first. If it is taken, the hub picks another free high port and updates preferredPort.

  3. On the first scoped file create/change (when enabled), the hub launches the system default browser with a dedicated profile under browser-profile/. Common engines are supported (Chrome/Edge/Brave/Chromium via --user-data-dir, Firefox via -profile). Safari and unknown browsers fall back to a normal URL open with limited isolation.

  4. If a managed browser session is already running, the hub does not open another window (the open tab reconnects over WebSocket).

  5. Stopping the hub does not close the browser.

Troubleshooting

Issue

Fix

Hub won't start

Delete %LOCALAPPDATA%\markdown-mcp\hub.lock and hub.json if stale

Browser never opens

Scope a file and write it; browser waits for first create/change. Confirm “Open browser on first file event” is on.

Extra browser windows

Hub skips launch when browser.pid / profile locks show a live session; close the preview browser if you need a clean relaunch

Tab won’t reconnect after restart

Ensure sticky preferredPort is free; check Settings → Preferred port and hub.json

Path denied

Add root under Settings → Allowed path roots

UI is fallback HTML

Run npm run build so packages/hub/dist/public is populated

Port unknown

Read hub.json (live) or preferredPort in settings.json (sticky)

License

MIT

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity
Issues opened vs closed

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

View all related MCP servers

Related MCP Connectors

  • Give your agent live data from Twitter, Reddit, the web and GitHub. No API keys, no scraping stack.

  • Read a URL as clean markdown, screenshot a website, url to PDF. Web access for agents, no signup.

  • Human feedback for AI agents: share HTML, get a live review link, read anchored notes as markdown.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kschroeder/live-markdown-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server