Content
# Pear Docs MCP Server
A [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server that exposes the
complete **Pear by Holepunch** documentation ([docs.pears.com](https://docs.pears.com))
to AI agents and MCP-compatible clients.
It lets an assistant browse, search, and read the Pear documentation directly while helping
you design or build a Pear-based peer-to-peer application. The entire documentation set is
snapshotted into a local JSON file, so the server runs fully offline and answers every
request without a network round trip.
---
## Table of Contents
- [Overview](#overview)
- [Why This Exists](#why-this-exists)
- [Architecture](#architecture)
- [How It Works](#how-it-works)
- [Tools](#tools)
- [Installation](#installation)
- [Registering With an MCP Client](#registering-with-an-mcp-client)
- [Usage Examples](#usage-examples)
- [Updating the Documentation Snapshot](#updating-the-documentation-snapshot)
- [Project Structure](#project-structure)
- [Development and Testing](#development-and-testing)
- [Data Snapshot Format](#data-snapshot-format)
- [Troubleshooting](#troubleshooting)
- [License](#license)
---
## Overview
Pear is Holepunch's peer-to-peer runtime and deployment platform, built on the Bare runtime
and the Hypercore ecosystem (Hyperswarm, HyperDHT, Hyperbee, Hyperdrive, Autobase, and more).
Its documentation spans well over a hundred pages of conceptual explanations, how-to guides,
and API references.
This project packages that documentation as an MCP server. Once registered with a client
such as Claude Code or Claude Desktop, an assistant can call three tools to explore the docs
on demand instead of relying on memorized or outdated information.
| Property | Value |
| ------------------- | ------------------------------------------------- |
| Documentation pages | 123 |
| Sections | overview, explanation, getting-started, how-to, reference |
| Snapshot size | approximately 1.2 MB of markdown |
| Transport | stdio (standard input/output) |
| Runtime | Node.js 18 or newer |
| Network at runtime | None; content is served from a local snapshot |
---
## Why This Exists
- **Accuracy.** Answers come from the current, authoritative documentation rather than model
recall, which reduces hallucinated APIs and outdated guidance.
- **Speed.** The documentation is bundled locally, so lookups are instant and work offline.
- **Focus.** An agent can retrieve only the relevant pages instead of loading the entire
documentation set into its context window.
- **Reproducibility.** The snapshot is a committed artifact, so every user of the repository
queries the exact same content until it is deliberately refreshed.
---
## Architecture
The system has two independent halves: an offline **build pipeline** that produces a
documentation snapshot, and a **runtime server** that serves that snapshot over MCP.
```mermaid
flowchart TB
subgraph Build["Build pipeline (run occasionally)"]
direction TB
SITE["docs.pears.com"]
FETCH["scripts/fetch-docs.mjs"]
SNAP["data/docs.json<br/>(committed snapshot)"]
SITE -->|sitemap.xml, per-page .md, llms.txt| FETCH
FETCH -->|normalize and bundle| SNAP
end
subgraph Runtime["Runtime server (per session)"]
direction TB
SERVER["src/index.js<br/>MCP server"]
TOOLS["list_docs / search_docs / get_doc"]
SERVER --> TOOLS
end
subgraph Clients["MCP clients"]
direction TB
CC["Claude Code"]
CD["Claude Desktop"]
OTHER["Any MCP-compatible client"]
end
SNAP -->|loaded at startup| SERVER
CC -->|stdio| SERVER
CD -->|stdio| SERVER
OTHER -->|stdio| SERVER
```
---
## How It Works
### Build pipeline
The docs site is unusually friendly to machine consumption, and the fetch script relies on
three of its endpoints:
1. `sitemap.xml` provides the canonical list of every documentation URL.
2. Each page exposes a clean markdown version by appending `.md` to its path
(for example, `/explanation/workers` is available at `/explanation/workers.md`).
3. `llms.txt` provides a one-line description for each page.
The script merges these sources into a single normalized `data/docs.json` file.
```mermaid
sequenceDiagram
participant S as fetch-docs.mjs
participant D as docs.pears.com
S->>D: GET /sitemap.xml
D-->>S: list of 123 page URLs
S->>D: GET /llms.txt
D-->>S: one-line description per page
loop for each page (6 concurrent)
S->>D: GET {page}.md
D-->>S: clean markdown content
end
S->>S: normalize paths, attach titles<br/>and descriptions, group by section
S->>S: write data/docs.json
```
### Runtime server
At startup the server loads `data/docs.json` into memory, builds a path index and a section
list, and registers three tools on an MCP `stdio` transport. From then on it answers tool
calls entirely from memory.
```mermaid
sequenceDiagram
participant C as MCP client
participant S as Pear Docs MCP server
participant M as In-memory snapshot
Note over S,M: On startup, load data/docs.json into memory
C->>S: initialize
S-->>C: server info and capabilities
C->>S: tools/list
S-->>C: list_docs, search_docs, get_doc
C->>S: tools/call search_docs { query: "hyperswarm topic" }
S->>M: score and rank pages
M-->>S: top matches with snippets
S-->>C: ranked results and paths
C->>S: tools/call get_doc { path: "/reference/building-blocks/hyperswarm" }
S->>M: resolve path
M-->>S: full page markdown
S-->>C: page content
```
### Search ranking
`search_docs` uses a lightweight weighted scoring model rather than a full search engine.
Each query term contributes to a page's score based on where it appears:
| Match location | Weight per term |
| ------------------------- | ------------------------ |
| Title | 10 |
| Path | 6 |
| Description | 4 |
| Body | 1 per occurrence, capped at 8 |
| Exact phrase in title | 15 (bonus) |
| Exact phrase in body | 5 (bonus) |
Pages with a score of zero are excluded, and the remainder are returned in descending order
of relevance. This keeps the server dependency-light while still surfacing the most relevant
pages first.
---
## Tools
The server exposes three tools. A typical workflow is to `search_docs` to locate relevant
pages, then `get_doc` to read one in full. Use `list_docs` to browse a section systematically.
### `list_docs`
Browse the documentation catalog.
| Parameter | Type | Required | Description |
| --------- | ------ | -------- | --------------------------------------------------------------------------- |
| `section` | enum | No | Restrict to one section: `overview`, `explanation`, `getting-started`, `how-to`, `reference`. |
| `filter` | string | No | Case-insensitive substring matched against title, path, and description. |
Returns the matching pages grouped by section, each with its path, title, and description.
### `search_docs`
Full-text, relevance-ranked search across every page.
| Parameter | Type | Required | Description |
| --------- | ------- | -------- | ------------------------------------------------------------------ |
| `query` | string | Yes | Search terms, for example `hyperswarm topic discovery` or `OTA update`. |
| `section` | enum | No | Restrict results to a single section. |
| `limit` | integer | No | Maximum number of results (1 to 25, default 8). |
Returns ranked results, each with the page title, path, section, relevance score, and a
snippet showing the matched context.
### `get_doc`
Retrieve the full markdown content of a single page.
| Parameter | Type | Required | Description |
| --------- | ------ | -------- | --------------------------------------------------------------------------------- |
| `path` | string | Yes | A page path (`/explanation/workers`), a bare slug (`workers`), or a full docs URL. |
Path resolution accepts exact paths, bare slugs with a unique suffix match, and full
`docs.pears.com` URLs. When a page cannot be found, the tool suggests close matches.
---
## Installation
### Prerequisites
- Node.js 18 or newer
- npm
### Steps
```bash
# 1. Install dependencies
npm install
# 2. Generate the documentation snapshot (data/docs.json).
# The repository already includes a snapshot, so this step is only
# required if the file is missing or you want the latest content.
npm run fetch
# 3. (Optional) Run the server directly to confirm it starts
npm start
```
When started, the server prints a readiness line to standard error and then waits for MCP
messages on standard input. This is expected; the server communicates over stdio and is
normally launched by an MCP client rather than run interactively.
---
## Registering With an MCP Client
Replace the path below with the absolute path to `src/index.js` on your machine.
### Claude Code
Register the server for the current project:
```bash
claude mcp add pear-docs -- node /absolute/path/to/pear_tool/src/index.js
```
Register it globally so it is available in every project:
```bash
claude mcp add -s user pear-docs -- node /absolute/path/to/pear_tool/src/index.js
```
Verify the registration and health:
```bash
claude mcp list
```
The server should appear as `pear-docs` with a `Connected` status. Tools are loaded when a
session starts, so open a new Claude Code session after registering.
### Claude Desktop and other clients
Add an entry to the client's `mcpServers` configuration:
```json
{
"mcpServers": {
"pear-docs": {
"command": "node",
"args": ["/absolute/path/to/pear_tool/src/index.js"]
}
}
}
```
---
## Usage Examples
Once registered, an assistant can call the tools naturally. The following examples show the
tool name and arguments alongside a description of the result.
Browse the reference section for Hypercore-related modules:
```json
list_docs { "section": "reference", "filter": "hyper" }
```
Search for guidance on connecting peers:
```json
search_docs { "query": "connect two peers by public key hole punching", "limit": 3 }
```
Read a specific page in full using a bare slug:
```json
get_doc { "path": "workers" }
```
Read a page using its full path:
```json
get_doc { "path": "/reference/building-blocks/hyperswarm" }
```
---
## Updating the Documentation Snapshot
The upstream documentation changes over time. To refresh the local snapshot:
```bash
npm run refresh
```
This re-runs the fetch pipeline and overwrites `data/docs.json` with the latest content.
Commit the updated file to publish the new snapshot to anyone using the repository. The
snapshot records a `generatedAt` timestamp so you can tell when it was last updated.
---
## Project Structure
```
pear_tool/
├── src/
│ └── index.js MCP server: loads the snapshot and registers the three tools
├── scripts/
│ ├── fetch-docs.mjs Build pipeline: snapshots docs.pears.com into data/docs.json
│ └── smoke-test.mjs Minimal stdio MCP client that exercises all three tools
├── data/
│ └── docs.json Committed documentation snapshot (generated)
├── package.json Package metadata, dependencies, and scripts
├── README.md This document
└── .gitignore
```
---
## Development and Testing
A self-contained smoke test performs a full MCP handshake and calls every tool, which is the
quickest way to confirm the server works after a change:
```bash
node scripts/smoke-test.mjs
```
The script spawns the server, sends `initialize` and `tools/list`, then invokes `list_docs`,
`search_docs`, and `get_doc` (including an intentional miss to verify error handling), and
prints a summary of each response.
### npm scripts
| Script | Description |
| ----------------- | ------------------------------------------------------- |
| `npm start` | Run the MCP server on stdio. |
| `npm run fetch` | Build the documentation snapshot into `data/docs.json`. |
| `npm run refresh` | Alias for `fetch`; regenerate the snapshot. |
### Dependencies
- [`@modelcontextprotocol/sdk`](https://www.npmjs.com/package/@modelcontextprotocol/sdk):
the official MCP server implementation and stdio transport.
- [`zod`](https://www.npmjs.com/package/zod): schema definitions for tool input validation.
---
## Data Snapshot Format
`data/docs.json` is a single JSON object with top-level metadata and a `pages` array:
```json
{
"source": "https://docs.pears.com",
"generatedAt": "2026-07-03T18:23:42.524Z",
"count": 123,
"pages": [
{
"path": "/explanation/workers",
"url": "https://docs.pears.com/explanation/workers/",
"title": "Workers",
"section": "explanation",
"description": "Why a Pear app's peer-to-peer logic lives in a Bare worker...",
"content": "# Workers\n\n...full markdown...",
"chars": 13048,
"ok": true
}
]
}
```
| Field | Description |
| ------------- | ------------------------------------------------------- |
| `source` | Origin the snapshot was fetched from. |
| `generatedAt` | ISO 8601 timestamp of when the snapshot was produced. |
| `count` | Number of pages included. |
| `path` | Normalized page path, used as the primary identifier. |
| `url` | Canonical documentation URL for the page. |
| `title` | Page title, taken from `llms.txt` or the first heading. |
| `section` | Top-level section derived from the path. |
| `description` | One-line summary from `llms.txt`. |
| `content` | Full page content as markdown. |
| `chars` | Character count of the content. |
---
## Troubleshooting
**The server exits immediately with a message about `data/docs.json`.**
The snapshot is missing. Run `npm run fetch` to generate it.
**The client shows the server as failed or not connected.**
Confirm the path in the client configuration is absolute and points to `src/index.js`, and
that `npm install` has been run so dependencies are present. Run
`node scripts/smoke-test.mjs` to test the server in isolation.
**The tools are registered but not available in the assistant.**
MCP tools are loaded when a session starts. Start a new session after registering the server.
**Search returns no results.**
Try broader or fewer terms, or use `list_docs` to browse a section directly. Search matches
whole terms against titles, paths, descriptions, and page bodies.
---
## Attribution and Content Source
This project is an independent, unofficial tool. It is not affiliated with,
endorsed by, or sponsored by Holepunch or the Pear project.
The documentation content bundled in `data/docs.json` is retrieved from the
official Pear documentation at [docs.pears.com](https://docs.pears.com) and
remains the property of its respective owners (Holepunch). That content is
redistributed here solely to make the documentation queryable through the Model
Context Protocol, and its copyright and terms are those of the original
publisher. Refer to [pears.com](https://pears.com) and
[holepunch.to](https://holepunch.to) for the authoritative sources.
The MIT license below applies only to the original code in this repository
(the server, scripts, and configuration), not to the bundled documentation
content. If you intend to redistribute the snapshot, review the upstream
documentation's terms first, or regenerate it from source with `npm run fetch`.
## License
The source code in this repository is released under the MIT License. See
[LICENSE.md](LICENSE.md) for the full text.
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available