Skip to content

MCP Apps

The server ships four browser-based views that MCP clients supporting the MCP Apps protocol can render inline or in fullscreen. They are delivered as a single HTML resource at ui://vault/app.html and use visibility="app" so they appear only in supporting clients.

Views

Context Card

Displays a note dossier for the note currently in focus. Includes:

  • Backlinks: other notes that link to this note
  • Outlinks: notes this document links to, with existence check
  • Similar notes: semantically similar documents (requires embeddings)
  • Tags: frontmatter tag values
  • Folder peers: other notes in the same folder
  • Modification time: last modified timestamp

Click any linked note to open its context card.

Graph Explorer

Interactive force-directed link graph of the vault, powered by vis-network. Two modes:

  • Neighborhood: shows a note and its direct connections (configurable depth, soft-capped at max_nodes=200 by default; the response carries truncated=true when the BFS hit the cap so the SPA can warn the user)
  • Hubs: shows the most-linked notes in the vault and their connections

Click a node to view that note's context card. Toggle semantic similarity edges when embeddings are available (semantic edges render as dashed accent-colored lines, distinct from the solid wikilink edges).

Node labels follow a level-of-detail rule. The focus note, its direct neighbors, and hub notes keep their labels; other farther-out notes render as unlabelled dots (their names appear on hover, or once you zoom in past a threshold). A separate hover text with the note's title and backlink count is always available, regardless of zoom level. A count chip in the top-right corner of the canvas reports how many notes are currently visible, next to zoom-in and zoom-out buttons. A legend below the canvas explains the edge and node styles; on a narrow panel it collapses behind an "ⓘ legend" chip to save space.

Vault Browser

Searchable, filterable file tree for browsing the vault without issuing tool calls. Features:

  • Expandable folder tree
  • Real-time search filtering
  • Click a note to preview it in the Note tab

Note Preview

Full-width markdown preview with:

  • Rendered markdown (via marked.js, sanitized with DOMPurify), with the leading frontmatter block stripped so it renders only once
  • A Contents popover: an on-this-page table of contents built from the note's headings
  • Collapsible frontmatter properties (first few shown, the rest behind a toggle) and collapsible tags
  • Copy markdown (the full note, frontmatter included) and Copy vault link (the note's path) buttons
  • Send to Claude button: sends the note content to the LLM conversation
  • Navigation to Context Card or Graph Explorer for the same note

Tools

Two primary tools are exposed to MCP clients:

Tool Description
browse_vault Opens the vault explorer SPA; optionally focuses a specific note and view. Returns a text summary for non-Apps clients.
show_context Opens the Context Card for a given note path.

browse_vault accepts an optional path parameter to focus on a specific note, and a view parameter (context, graph, browse, or note). show_context requires a path parameter.

Six additional app-only tools (prefixed with _vault_) handle data fetching for the SPA views. These are hidden from the LLM and only callable from within the app itself.

Configuration

Variable Default Description
MARKDOWN_VAULT_MCP_BASE_URL (none) Public base URL of the server. Required for auto-computing the app domain.
MARKDOWN_VAULT_MCP_APP_DOMAIN (auto) Override the Claude app domain used for iframe sandboxing. Auto-computed from BASE_URL when not set.

Domain auto-computation

When APP_DOMAIN is not set, the server computes it from BASE_URL and HTTP_PATH:

  1. Concatenate: mcp_url = f"{BASE_URL}{HTTP_PATH}"
  2. SHA-256 hash the URL and take the first 32 hex characters
  3. Result: {hash_prefix}.claudemcpcontent.com

Override APP_DOMAIN if your deployment is behind a proxy that changes the apparent hostname.

Architecture

The SPA is a self-contained HTML file with its JavaScript dependencies vendored at build time (no runtime CDN requests for libraries; web fonts are the one exception, see Visual identity):

Library Purpose
vis-network Force-directed graph rendering
marked.js Markdown to HTML rendering
DOMPurify XSS sanitization
@modelcontextprotocol/ext-apps MCP Apps lifecycle, messaging, and theming

The app integrates with the host client via the ext-apps SDK:

  • app.callServerTool(): calls app-only tools to fetch data
  • app.sendMessage(): sends note content to the LLM conversation
  • app.updateModelContext(): keeps the LLM aware of which note the user is viewing
  • app.requestDisplayMode(): requests fullscreen or inline display (auto-expands to fullscreen on first load on desktop and web, but stays inline on mobile)
  • Adaptive sizing: honors the host's reported container dimensions and safe-area insets. It fills a fixed-height frame with internal scrolling, or, when the host reports a flexible or unbounded frame (as mobile inline hosts and sidebars typically do), grows to its content and reports its height so the host can size the view
  • Theme sync: automatically adapts to the host's light/dark theme and CSS variables

Visual identity ("Paper")

The views use a warm, editorial "Paper" theme (serif headings, a single warm accent, light and dark). The Paper palette is expressed as CSS custom properties that map onto the host's --color-* variables: a host that pushes its own theme overrides Paper, otherwise the Paper values show. Three font families load from Google Fonts and are exposed as --font-head / --font-body / --font-mono: Newsreader styles headings, Public Sans the body and UI, and IBM Plex Mono the code, property keys, and tags. (As each view is restyled, these families also reach the remaining mono metadata such as paths and scores.) The fonts are the one runtime network dependency the app keeps (the vendored libraries are embedded); if they fail to load, the app falls back to system fonts with no loss of function.

Source layout and build

The SPA source is authored as small partials under src/markdown_vault_mcp/static/spa/:

File Contents
shell.html The HTML document: head, tab bar, view panels, toast
styles.css All styles
core.js App setup, theming, tab navigation, cross-view routing, shared helpers
views/context.js, views/graph.js, views/browser.js, views/note.js One file per view

Two build steps turn the partials into the served resource:

spa/*  ->  build_spa.py  ->  app.src.html  ->  vendor_spa.py  ->  app.html
  1. python scripts/build_spa.py assembles the partials into static/app.src.html. Assembly is a recursive /*@@FILE:path@@*/ include, a valid comment in both CSS and JavaScript, so each partial stays independently readable.
  2. python scripts/vendor_spa.py embeds the vendored libraries into the self-contained static/app.html that the server serves.

app.src.html and app.html are both generated, committed artifacts: edit the files under static/spa/, then run both scripts. Never hand-edit the generated files. build_spa.py --check and vendor_spa.py --check fail the build if either artifact is stale; both run in CI and as pre-commit hooks.

Client support

MCP Apps views require a client that supports the MCP Apps protocol. Currently supported by Claude on claude.ai. Clients without Apps support receive a text-only fallback from browse_vault and show_context.

To hide browse_vault and show_context from the tool listing entirely (for clients that never render Apps panels), set MARKDOWN_VAULT_MCP_DISABLE_APPS_UI=true. See Configuration.

Firing prompts from Claude.ai's + menu

MCP Apps surface interactive views, but this server also ships MCP prompts (summarize, research, propose-links, and the workflow prompts from the PARA and Zettelkasten packs). On Claude.ai, every prompt appears in the compose area's + menu once the server is added as a connector. Click +, select connectors, pick the server, pick a prompt, and Claude opens with the invocation scaffolded. See How to invoke prompts.