# The Rabbithole MCP tool call stays pending while you work in the canvas

> Rabbithole is an infinite canvas where selecting text and asking branches a new document, delivered two ways: a static web app that talks to a model endpoint you choose, and an MCP server that lets a coding agent answer while your documents stay on your machine. The design choice that shapes everything else is a tool call that stays open.

**shlokkhemani/rabbithole** — An infinite canvas for learning — select text, ask, and answers branch out as documents. MCP server for Claude Code, Codex, and any agent.

- Repository: https://github.com/shlokkhemani/rabbithole
- Website: https://rabbithole.ing
- Stars: 315 · Forks: 44
- Language: JavaScript
- License: MIT
- Published: 2026-09-18 · Updated: 2026-09-18 · Language: en
- Canonical page: https://hysenlabs.com/projects/shlokkhemani-rabbithole

## Two hosts and one canvas, with documents in two different places

The architecture statement is two sentences long and everything else follows from it.

There are two hosts and one canvas. The static web app uses either a model endpoint you choose or a coding-agent subscription already signed in on your machine. The MCP server lets Claude Code, Codex, and other clients answer while the canvas, storage, and local transport stay local.

That means there are two document stores, not one. Web documents live in the browser. MCP documents live under a directory in your home folder, and an environment variable overrides the location.

The privacy claims are stated as absolutes rather than settings: no account, no telemetry, no hosted document store. There is no server holding your text.

The web path is a paste, a drop, or an import: paste a question or a URL, drop a Markdown or PDF file, or import a file this tool produced earlier.

The MCP path is a different interaction entirely. There, a document is opened in an agent session and the human asks from the canvas, so the split is not just storage, it is who drives the conversation.

## The tool call blocks, so a short client timeout breaks it

One sentence in the MCP quick start describes the whole interaction model, and it is a design choice rather than a limitation.

The tool call stays pending while the agent listens for asks coming from the canvas. In other words, the agent calls a tool and then waits, for as long as the human takes to select text, type a question, and read the answer.

The consequence is stated immediately: if your client enforces a short tool timeout, raise it.

That is a compatibility requirement rather than a suggestion, and it rules out a class of clients. An agent harness that assumes tool calls return in seconds cannot use this, and there is no fallback path offered.

The other half of the design is what happens when the connection drops. Saved asks survive disconnects and resume, so the failure mode is a reconnect rather than a lost question.

The setup itself is two commands that differ only in the client name, both registering the server through the package runner against the repository rather than against a published version.

```bash
claude mcp add rabbithole -- npx -y github:shlokkhemani/rabbithole
codex mcp add rabbithole -- npx -y github:shlokkhemani/rabbithole
```

Node 18 or newer and a browser are both required, and you start a fresh agent session after adding it.

## The bridge reuses a signed-in CLI and binds only to loopback

The web app lists three ways to reach a model, and the third is the interesting one.

First, an aggregator service. Second, local and custom endpoints speaking the same protocol. Third, an optional subscription bridge, started by running the package through the package runner.

What the bridge does is print a private pairing link and connect the page to an installed, signed-in coding agent CLI. So instead of a model key, the page borrows a subscription you have already authenticated, using the credentials that CLI already holds.

The security detail worth noting is that it binds only to loopback. The bridge is reachable from your own machine and not from the network, which is what makes a pairing link safe to hand to a web page.

The pairing link is described as private, which means it is the credential. Anyone holding it and able to reach the loopback port could drive the session, so it is worth treating as a secret rather than as a shareable link.

That is the whole mechanism, and it is why the web app needs no account of its own.

## Registry installs need no build because packaging builds the bundle

The distribution note is one sentence and it removes a whole class of setup problem.

The canvas and frozen snapshots remain self-contained HTML, and package tarballs include the browser bundles built during packaging, so an install from a registry needs no build step on the consumer side.

Two things make that work. The HTML is self-contained, so a frozen snapshot can be opened without a server or a network fetch. And the packaging pipeline runs the same build script into a distribution directory, wired as the prepare step so it happens automatically when the package is built.

For an MCP server installed through a package runner, that matters more than it would for a library. The runner does not run a build, it extracts files, so anything not committed or pre-built into the tarball simply would not be there.

The canvas being plain HTML also explains the offline architecture tour being a page you can open rather than a documentation site you have to serve.

## Six specs sit at the root and a version bump stages the docs

The root of the repository has six files whose names all begin with the same prefix and none of which are documentation in the usual sense.

They are specifications: one for automatic tidying, one for images, one for an images setting, one for MCP efficiency, one for preference persistence, and one for reactions. They sit beside an architecture document and a changelog rather than inside a documentation folder.

So the project is specified before it is built, in writing, with each behaviour named after its own file. That is a different discipline from documenting behaviour after the fact, and it explains why a design-system document and a compatibility contract are also first-class.

The release script is where that discipline shows up operationally. The version step runs the documentation build and then stages the documentation directory into the index. So every version bump regenerates documentation and includes it, which means a stale document cannot ship because the regeneration is part of the bump.

The same script also has a publish variant, separate from the plain build and the package build, which suggests documentation, package, and publication are three separate outputs of one toolchain.

## Half the scripts are checks and five of them are live

The package manifest is mostly build and check scripts, and the check half is unusually dense.

Some checks are static. There is one for type checking, one for the interface layer with a single linter invocation, one for interface architecture, one for style-sheet integrity, one for design-system conformance, one that generates and verifies a design document, one that generates and verifies icons, and one named for purity that checks the interface source.

Five more are named as live checks, and their subjects say what the project considers worth testing against a running system: the bridge, the install journey, vision, image generation, and isolation.

An install journey check is unusual and valuable: it means the documented commands for adding the server to an agent client are tested rather than asserted.

The isolation check is the one to look at first if you are evaluating this for anything sensitive. Two of the project's central claims are that documents stay on your machine and that the bridge binds only to loopback, and a test named for isolation is the natural place to verify them.

The presence of live checks for vision and image generation also tells you the canvas is not only text, which the specification files at the root corroborate.

## An ESM package at 0.1.0 with three separate type configurations

The version is 0.1.0 and there are no tagged releases, so the published surface is whatever the registry currently holds.

The package is scoped and marked as an ES module, with the repository URL, homepage, author, and MIT licence all declared. Every registration example in the documentation runs through the package runner against the GitHub repository rather than a versioned tarball, which sidesteps the versioning question entirely and means you are always on the tip.

Type configuration is split three ways, with a base configuration, a strict one, and one for tests. Three files rather than one is a deliberate choice, since the strict and test configurations exist because tests and production code fail different checks for different reasons.

Linting and formatting are handled by one tool, invoked through its own configuration file and through a JSON file. Nothing here suggests a second formatter.

The tree also carries a deploy document, a release document, a third-party notices file, and directories for the workers, the website, a policy set, tooling, scripts, and reference screenshots.

The last recorded push is 2026-09-16.

## Conclusion

Rabbithole suits someone who learns by interrogating a text and wants the answer to become a document rather than a message, and who would rather reuse a subscription their coding agent already has than manage model keys. It does not suit an MCP client with a short tool timeout, because the interaction is built around a call that stays pending until you finish asking. Before you wire it into an agent, check your client's timeout setting, decide whether your documents belong in the browser or under a home directory, and read the compatibility contract before depending on it.

## FAQ

### How do I install the Rabbithole MCP server?

Register it with your client: `claude mcp add rabbithole -- npx -y github:shlokkhemani/rabbithole` for Claude Code, or the same command with `codex mcp add` for Codex. It requires Node 18 or newer and a browser, and documents live under `~/.rabbithole/` unless `RABBITHOLE_DIR` overrides that location.

### Does Rabbithole need an account or send telemetry?

No account, no telemetry, and no hosted document store. Web documents live in your browser and MCP documents live on your machine, with the canvas, storage, and local transport staying local in both cases.

### What happens if my MCP client times out on a Rabbithole tool call?

The call will be cut off. The tool call stays pending while the agent listens for asks from the canvas, so a client that enforces a short tool timeout needs that timeout raised. Saved asks survive disconnects and resume, so a dropped connection costs you a reconnect rather than a question.

### How do I use Rabbithole without a model provider key?

With the optional bridge: run `npx @shlokkhemani/rabbithole bridge`. It prints a private pairing link and connects the page to an installed, signed-in Claude Code or Codex CLI, borrowing that subscription, and it binds only to loopback. The web app also supports an aggregator service and local or custom endpoints.

### Does installing the Rabbithole package require a build step?

No. Package tarballs include the browser bundles built during packaging, so registry installs need no consumer-side build, and the canvas plus its frozen snapshots are self-contained HTML that opens without a server. Registration runs the package through the package runner against the repository rather than a pinned version.

## Sources

- [Issues](https://github.com/shlokkhemani/rabbithole/issues)
- [License: MIT](https://github.com/shlokkhemani/rabbithole/blob/main/LICENSE)
- [Project website](https://rabbithole.ing)
- [README](https://github.com/shlokkhemani/rabbithole/blob/main/README.md)
- [shlokkhemani/rabbithole on GitHub](https://github.com/shlokkhemani/rabbithole)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/shlokkhemani-rabbithole
