Skip to main content
Glama

Rabbithole

An infinite canvas for learning. Open a document, ask at any point, and follow each answer into a new document.

Rabbithole branching canvas demo

Open the web app · Explore the offline architecture tour

Rabbithole has two hosts and one canvas:

  • The static web app uses your chosen model endpoint or the coding-agent subscription already signed in on your machine.

  • The MCP server lets Claude Code, Codex, and other MCP clients answer while the canvas, storage, and local transport stay on your machine.

No account, telemetry, or hosted document store. Web documents live in your browser. MCP documents live under ~/.rabbithole/ unless RABBITHOLE_DIR overrides it.

Web

Visit rabbithole.ing, then paste a question or URL, drop Markdown or PDF, or import a Rabbithole file.

The web app supports OpenRouter, local and custom OpenAI-compatible endpoints, and the optional subscription bridge:

npx @shlokkhemani/rabbithole bridge

The bridge prints a private pairing link and connects the page to an installed, signed-in Claude Code or Codex CLI. It binds only to loopback.

Related MCP server: MCP RAG Server

MCP quick start

Requires Node 18+ and a browser.

Claude Code:

claude mcp add rabbithole -- npx -y github:shlokkhemani/rabbithole

Codex:

codex mcp add rabbithole -- npx -y github:shlokkhemani/rabbithole

Then start a fresh agent session and say:

Open this document in Rabbithole.

The tool call stays pending while the agent listens for canvas asks. If a client enforces a short MCP tool timeout, raise that client's timeout; saved asks survive disconnects and resume.

Develop

git clone https://github.com/shlokkhemani/rabbithole.git
cd rabbithole
npm install
npm run build
npm test

Useful references:

The canvas and frozen snapshots remain self-contained HTML. The browser bundles in dist/ are committed so the package can run without an install-time build.

License

MIT. See LICENSE.

Available Tools

4 tools
answer_branchA

Answer one pending branch request from an open Rabbithole. Called after open_rabbithole or answer_branch returns status='branch_request'. Write a focused, well-formatted markdown answer to the human's question about their selection - use selected_text, parent_node_title, and lineage for context (you already hold the documents you authored). If selected_text is empty, answer conversationally about the parent document as a whole. If the request has a 'lens', match that style.

Authoring vocabulary:

  • Base notation: GFM markdown, $...$/$$...$$ and (...)/[...] math, and highlighted language-tagged code fences.

  • If the answer is content fetched from a URL or repo, pass its document URL as base_url so relative images and links resolve.

  • If the answer uses a local image, pass assets: [{ name, file_path }] and reference it as alt; use this for screenshots, generated diagrams, and other non-web images.

  • Use ```show when a concept is spatial or structural: architecture, memory layout, relationships.

  • show dialect: HTML/CSS/inline-SVG only; no scripts. Scripts and unsafe attributes are stripped.

  • show craft: prefer HTML/CSS layout with flexbox/grid over absolute SVG coordinates.

  • Design visuals for about 380px card width; make them fluid and keep labels short.

  • Use theme tokens, never hardcoded colors, so visuals match light and dark themes: --fg, --fg-bold, --fg-dim, --fg-faint, --node-bg, --bar-bg, --border, --border-focus, --accent, --accent-contrast, --code-bg, --hl, --hl-strong, --warn, --font-ui, --font-doc, --font-mono.

  • Example show:

<style>.flow{display:grid;gap:8px}.box{border:1px solid var(--border);padding:8px;border-radius:6px}</style>
<div class='flow'><div class='box'>Parse</div><div class='box' style='background:var(--hl)'>Render</div></div>
  • Streaming choreography: send prose in 1-3 sentence chunks as usual.

  • Emit each visual fence contiguously, ideally in one chunk; readers see a placeholder until the fence closes.

  • Interleave prose -> visual -> prose when useful. Use a visual only when it genuinely carries the explanation.

Finish streaming by sending the remaining final chunk in a normal call with a short 'title'. Partial chunks concatenate verbatim: include your own spacing/newlines and never repeat text already sent. The final call blocks and returns the next event. If it returns status='keep_listening', immediately call open_rabbithole { hole_id }; if the host reports a tool timeout (e.g. timed out awaiting tools/call), do the same. Do not re-send content; asks are saved.

ParametersJSON Schema
NameRequiredDescriptionDefault
titleNoShort label for the new node (a few words; required on the final call)
assetsNoLocal image files to attach to this hole; reference them in markdown as asset:name.png images
contentYesMarkdown chunk (partial) or the remaining markdown (final call)
partialNotrue = stream this chunk into the pending answer and return immediately; omit/false = finish the answer and block for the next event
base_urlNoDocument URL used to resolve relative markdown links/images; absolute http(s) only
request_idYesThe request_id of the branch_request being answered
session_idYesActive session ID from open_rabbithole

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so the description fully discloses behavior: streaming chunks, final blocking call, concatenation rules, authoring vocabulary, asset handling, and timeout recovery. It covers safety (don't re-send content) and formatting expectations comprehensively.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is lengthy but well-structured with clear sections (authoring vocabulary, streaming choreography). It is front-loaded with purpose. Could be slightly more concise, but the detail is warranted given tool complexity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, the description covers all aspects: usage triggers, parameter details, streaming protocol, error handling, formatting rules, and asset management. No gaps for agent execution.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 100% coverage but description adds deep semantics: explains streaming protocol, chunk vs final, asset referencing, title requirement on final call, and content formatting. Goes far beyond schema descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Answer one pending branch request from an open Rabbithole' and specifies the trigger condition. It differentiates from sibling tools (ingest_pdf, list_rabbitholes, open_rabbithole) by focusing on answering branch requests.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to call this tool (after open_rabbithole or answer_branch returns status='branch_request') and provides handling for various scenarios (empty selected_text, lens, keep_listening status, timeout). No ambiguity about usage context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

ingest_pdfA

Extract a local PDF into Rabbithole image assets and per-page text. Produces 2x page render PNGs named page-001.png, page-002.png, etc. plus opportunistic embedded rasters named embed-p001-01.png when the PDF contains extractable images. The agent should compose markdown itself, using page renders as the dependable figure source and embedded rasters when they are cleaner, then call open_rabbithole with the returned ingest_id (or pass hole_id here to attach assets directly to an existing hole). For arXiv links, prefer fetching the HTML version and opening that markdown with base_url instead of ingesting the PDF.

ParametersJSON Schema
NameRequiredDescriptionDefault
pagesNoOptional page or range such as "3" or "1-20"; default processes the first 40 pages
hole_idNoExisting hole id to attach assets to directly; omit to stage assets for open_rabbithole
file_pathYesLocal path to a PDF file
include_textNoWhether to return per-page extracted text; defaults to true

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description explains output formats (PNG naming), opportunistic embedded rasters, and the agent's role in composing markdown. Lacks mention of error handling or prerequisites.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is detailed but each sentence adds value. It front-loads the core purpose and avoids redundancy with the schema. Could be slightly more concise.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers input, output naming, usage patterns, and alternatives. Lacks explicit return value structure (beyond ingest_id), but given no output schema, it is mostly complete for an extraction tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline 3. The description adds context on default pages range, hole_id usage, and includes a note on arXiv preference, enhancing parameter understanding.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool extracts a local PDF into image assets and per-page text, with specific naming conventions. It is distinct from siblings like answer_branch or open_rabbithole.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit guidance on using open_rabbithole with the returned ingest_id or passing hole_id for direct attachment, and advises against PDF ingestion for arXiv links. Does not exhaustively cover all scenarios but is helpful.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_rabbitholesA

List saved Rabbitholes (most recently updated first) so you can resume one by hole_id via open_rabbithole. Returns id, title, last-updated time, and node count for each.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided; description carries full burden. States sorting order and return fields but does not explicitly declare read-only nature or any other behavioral traits. Adequate for a simple list tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with purpose, no wasted words. Efficiently conveys essential information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Sufficient for a zero-parameter tool with no output schema. Mentions return fields and ordering; missing pagination details but likely unnecessary given simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

No parameters exist, so baseline is 4. Description adds no parameter information, but none is needed as schema coverage is 100%.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists saved Rabbitholes sorted by last updated, specifies return fields (id, title, last-updated time, node count), and distinguishes from sibling open_rabbithole by indicating it enables resumption.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear context: use to list rabbitholes for subsequent resume via open_rabbithole. Does not explicitly state when not to use or compare to other siblings, but the purpose is straightforward.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

open_rabbitholeA

Open a document on an infinite canvas so the human can read it and dive down rabbit holes. Start a NEW hole with { title, content } (or { title, file_path }), or RESUME a saved one with { hole_id } (use list_rabbitholes to find it). When opening content fetched from a URL or repo, pass the document's own URL as base_url so relative images and links resolve. For local images that are not on the web, pass assets and reference them as alt. For a PDF already processed with ingest_pdf, pass ingest_id when starting the new hole and reference the returned asset names as page. The canvas opens in the browser and this call BLOCKS until the human acts. It returns status='branch_request' when the human selects text and asks a question — answer it with answer_branch. A branch_request with EMPTY selected_text is a follow-up question about the parent document as a whole (a chat reply beneath it) — answer conversationally in that document's context. A branch_request may carry a 'lens' (explain | eli5 | example | deeper) — the question text spells out the style the human tapped; honor it. One marked saved=true was asked while no agent was listening — answer it like any other. On a resumed hole the first branch_request carries a 'rehydration' field with the whole tree (and any saved_asks); read it to reload your context. Long waits periodically return status='keep_listening' with hole_id; immediately call open_rabbithole { hole_id } to keep listening, and do not re-send content. If the host reports a tool timeout (e.g. timed out awaiting tools/call), also re-call open_rabbithole { hole_id }; nothing is lost and asks are saved. It returns status='session_closed' when the human clicks Done or closes the tab.

ParametersJSON Schema
NameRequiredDescriptionDefault
titleNoDocument title (required for a new hole)
assetsNoLocal image files to attach to this hole; reference them in markdown as asset:name.png images
contentNoRaw markdown for the root document
hole_idNoResume a saved hole instead of starting a new one
base_urlNoDocument URL used to resolve relative markdown links/images; absolute http(s) only
file_pathNoPath to a .md file (alternative to content)
ingest_idNoStaged PDF assets returned by ingest_pdf; only valid when starting a new hole

TDQS

A4.9/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description fully discloses behavior: the tool blocks until human action, returns statuses like branch_request, keep_listening, and session_closed, and explains how to handle timeouts by re-calling with hole_id. It details branch_request semantics including selected_text, lens, and rehydration.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is lengthy but necessary due to the tool's complexity. It is well-structured: starts with purpose, then parameter usage, then return behavior. Every sentence adds value, though a minor trim could improve conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the 7 parameters, no output schema, and complex interaction patterns, the description covers all scenarios: new hole vs resume, branch_request handling, keep_listening, timeout recovery, and rehydration. It is fully complete for an AI agent to use correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, but the description adds significant context beyond parameter names: e.g., base_url resolves relative links, assets are referenced as asset:name.png, and ingest_id is for staged PDF assets. This enriches the schema's baseline descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool opens a document on an infinite canvas for reading and exploration. It distinguishes between starting a new hole (with title and content or file_path) and resuming a saved hole (with hole_id), which differentiates it from sibling tools like list_rabbitholes.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use each parameter combination, such as using base_url for URL-sourced content, assets for local images, and ingest_id for PDFs. It also explains when to use list_rabbitholes to find saved holes and how to handle branch requests and keep_listening responses.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections. Dates show when Glama detected each change.

  1. 4 tool updatesv0.1.0
    • First observedanswer_branch
    • First observedingest_pdf
    • First observedlist_rabbitholes
    • First observedopen_rabbithole

TDQS

A4.5/5.0
Disambiguation5/5

Each tool has a clear, distinct purpose: opening/resuming rabbitholes, answering branch requests, ingesting PDFs, and listing saved ones. No overlap in functionality.

Naming Consistency5/5

All tool names follow the `verb_noun` pattern (e.g., list_rabbitholes, open_rabbithole, answer_branch, ingest_pdf), providing a consistent and predictable interface.

Tool Count5/5

With 4 tools, the set is tightly scoped to the rabbithole interaction domain—opening, answering, ingesting, and listing. No tool feels redundant, and the number is appropriate for the focused purpose.

Completeness4/5

The tools cover core workflows well, but missing explicit update/delete functionality for rabbitholes. However, the blocking nature of open_rabbithole and the branch-answer loop cover most user interactions adequately.

Maintenance

ActivityActive
ResponsivenessSlow

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

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

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    A local MCP server that gives AI coding assistants retrieval access to your personal knowledge base of books, standards, and docs, grounding their answers in sources you trust.
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    A local-first MCP server that ingests PDFs, extracts structure, and provides semantic search and sequential navigation tools for AI clients to query and learn from documents.
    10
    MIT
  • A
    license
    Not graded
    quality
    A
    maintenance
    MCP server for local RAG over personal notes, PDFs, and documents, enabling plain-English querying and hybrid search with multi-hop context expansion.
    MIT

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/shlokkhemani/rabbithole'

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