Skip to main content
Glama
README.md
# Wiki Explorer MCP Server

A generic MCP (Model Context Protocol) server that exposes any project wiki to AI assistants, enabling contextual wiki lookups during development sessions.

## Features

- **Lazy loading** — indexes headings once, loads content on-demand via byte positions
- **Auto-reload** — watches the wiki file or markdown directory for changes with debouncing
- **Fuzzy search** — handles typos and partial matches via levenshtein distance
- **Content search** — searches within section content, not just headings
- **Custom anchors** — use `{#anchor}` syntax in headings for stable TOC links
- **Directory mode** — index entire markdown directory trees with file-prefixed keys
- **Legacy key support** — backward-compatible lookup of heading-only keys
- **Heading hierarchy** — tracks full breadcrumb path for nested sections
- **Batch fetch** — retrieve multiple sections in one call (max 20)
- **Smart suggestions** — returns similar keys when a section isn't found
- **Path safety** — validates markdown sources and safe path resolution
- **Graceful shutdown** — handles SIGINT/SIGTERM, cleans up watchers
- **Structured logging** — configurable log levels for debugging

## Setup

```bash
# 1. Install dependencies
npm install

# 2. Configure wiki path
cp .env.example .env

# 3. Run tests
npm test
```

### .env

```env
WIKI_PATH=path/to/your/wiki-source  # file (.md/.markdown) or directory
LOG_LEVEL=info  # debug, info, warn, error
```

## MCP Tools

| Tool | Description | Parameters |
|---|---|---|
| `list_wiki` | List all available wiki sections | none |
| `browse_wiki` | Browse sections by topic/parent | `topic` (string, optional) |
| `search_wiki` | Search sections by keyword | `query` (string), `fuzzy` (boolean) |
| `get_wiki_section` | Get a single section's content | `key` (string), `offset` (number), `limit` (number) |
| `get_wiki_sections` | Get multiple sections at once | `keys` (string[], max 20) |

## Connecting to AI Assistants

### Claude Desktop

Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS, `%APPDATA%\Claude\claude_desktop_config.json` on Windows):

```json
{
  "mcpServers": {
    "wiki-explorer": {
      "command": "node",
      "args": ["/path/to/wiki-explorer/index.js"],
      "env": {
        "WIKI_PATH": "/path/to/your/docs/wiki"
      }
      }
  }
}
```

### Cursor

Add to Cursor MCP settings:

```json
{
  "mcpServers": {
    "wiki-explorer": {
      "command": "node",
      "args": ["/path/to/wiki-explorer/index.js"],
      "env": {
        "WIKI_PATH": "/path/to/your/docs/wiki"
      }
      }
  }
}
```

### VS Code (GitHub Copilot)

Add to `.vscode/mcp.json`:

```json
{
  "servers": {
    "wiki-explorer": {
      "command": "node",
      "args": ["/path/to/wiki-explorer/index.js"],
      "env": {
        "WIKI_PATH": "/path/to/your/docs/wiki"
      }
      }
  }
}
```

## Running

```bash
# Start MCP server (stdio transport)
npm start

# Debug mode
LOG_LEVEL=debug npm start
```

## Architecture

```
index.js          → MCP server + tool registration + signal handlers
utils.js          → WikiParser class (indexing, search, content extraction)
logger.js         → Structured logging with configurable levels
test.js           → 67 assertions covering all functionality
.env              → WIKI_PATH, LOG_LEVEL configuration
```

### WikiParser Class

- **Constructor** — validates file/directory source, loads markdown docs, builds heading index with byte positions
- **`search(query, { fuzzy, limit })`** — find sections by keyword
- **`findSimilar(key)`** — get similar keys via levenshtein distance
- **`getSection(key)`** — retrieve content for a single section
- **`getSections(keys)`** — batch retrieve multiple sections
- **`reload()`** — re-read file and rebuild index
- **`close()`** — stop file watcher

### Key Compatibility

- Canonical keys in directory mode are prefixed by file slug (e.g. `user-wiki-approval-workflow-deep-dive`)
- Legacy heading-only keys are still accepted in `getMeta`/`getSection` for backward compatibility
- Ambiguous legacy keys require suffixed form (`-1`, `-2`) to resolve deterministically
- Search accepts legacy key queries but returns canonical keys

### Custom Anchors

Headings can include a custom anchor using `{#anchor-name}` syntax at the end of the heading text:

```markdown
## Backend Architecture {#portage-backend-architecture}
```

This creates a stable anchor that can be used in table of contents or direct links. The anchor is stripped from the displayed title but registered as a legacy alias for lookup.

### Content Search

Search matches both heading text and section content. Results are prioritized:
1. **Header matches** — exact or fuzzy match in heading text
2. **Content matches** — keyword found within section body

This ensures the most relevant sections appear first.

### Security

- Source validation (`.md`/`.markdown` file or directory)
- Safe path resolution via `path.resolve` + fs stat checks
- File size cap (50MB default)
- Key format validation (lowercase alphanumeric + hyphens)
- Batch request limits (max 20 keys)

### Graceful Shutdown

Handles `SIGINT`, `SIGTERM`, `uncaughtException`, and `unhandledRejection`. Cleans up file watchers and exits cleanly.

## Testing

```bash
npm test
```

Covers: initialization, path validation, directory mode, search (headers + content), fuzzy search, findSimilar, meta, sections, batch fetch, boundaries, reload, file watcher, key format validation, custom anchors, legacy key resolution, and cleanup.

## CI/CD

GitHub Actions runs tests on Node 20 and 22 for every push/PR to `main`. See `.github/workflows/ci.yml`.

TDQS

A4.1/5.0

Scored across 6 tools

Disambiguation4/5

Most tools have clear distinct purposes: search, browse, get single, get multiple, and info are unambiguous. However, list_wiki and browse_wiki overlap significantly since both return section keys, though browse offers topic filtering.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case: list_, browse_, search_, get_wiki_section(s), get_wiki_info. The verbs are descriptive and predictable.

Tool Count5/5

Six tools is well-scoped for a wiki server. Each tool covers a distinct aspect of reading wiki content, and the count feels neither sparse nor bloated.

Completeness4/5

The surface covers all read-related workflows: discovery (list/browse/search), retrieval (single/multiple sections), and metadata. Missing write operations (create/update/delete) but likely outside the apparent read-only scope.

Maintenance

ActivityInactive
ResponsivenessNo issues