Skip to main content
Glama
dasanjaneyuludarla

servicenow-docs

README.md
# servicenow-docs-mcp

MCP server that searches a local clone of [ServiceNow/ServiceNowDocs](https://github.com/ServiceNow/ServiceNowDocs) via two tools:

- `search_docs(query, max_results?)` — keyword/regex search across all docs, returns file + line + snippet.
- `read_doc(path)` — reads the full content of a doc by the relative path returned from `search_docs`.

No vector DB, no API keys. Search runs against a flat pre-built text index using `grep`, so it works fully offline.

See [ARCHITECTURE.md](ARCHITECTURE.md) for how it works, why grep over a vector DB, measured benchmarks, and known limitations.

## Prerequisites

- Node.js 18+
- `grep` (preinstalled on macOS/Linux)
- A local clone of the docs repo

## Setup

```bash
# 1. Clone the docs repo, as a sibling of this project's parent dir
#    (default DOCS_ROOT expects ../ServiceNowDocs/markdown relative to this folder)
git clone --depth 1 https://github.com/ServiceNow/ServiceNowDocs.git

# 2. Install dependencies
cd servicenow-docs-mcp
npm install

# 3. Build the search index (one-time; re-run after pulling doc updates)
node build-index.mjs
```

Directory layout expected:

```
ServiceNowKB/
├── ServiceNowDocs/          # cloned docs repo
│   └── markdown/            # DOCS_ROOT
└── servicenow-docs-mcp/     # this project
    ├── index.js
    ├── build-index.mjs
    └── index.txt            # generated by build-index.mjs
```

To point at docs cloned elsewhere, set `DOCS_ROOT` when running the server or the index builder:

```bash
DOCS_ROOT=/path/to/ServiceNowDocs/markdown node build-index.mjs
```

### Why the index build step

`search_docs` doesn't grep the 49k individual markdown files directly — walking that many small files takes minutes. `build-index.mjs` flattens every file into one `index.txt` (`path:line:content` per line), so a query becomes a single-file grep (~1-5s). Rebuild it whenever the docs repo is updated:

```bash
cd ServiceNowDocs && git pull
cd ../servicenow-docs-mcp && node build-index.mjs
```

## Register with a Claude environment

### Claude Code (any project)

Add to that project's `.mcp.json` (create it if missing) — path is relative to wherever you run Claude Code, adjust as needed:

```json
{
  "mcpServers": {
    "servicenow-docs": {
      "command": "node",
      "args": ["/absolute/path/to/servicenow-docs-mcp/index.js"]
    }
  }
}
```

Restart the Claude Code session in that directory to load it — MCP servers are only picked up at session start.

### Claude Desktop

Edit `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows):

```json
{
  "mcpServers": {
    "servicenow-docs": {
      "command": "node",
      "args": ["/absolute/path/to/servicenow-docs-mcp/index.js"]
    }
  }
}
```

Restart Claude Desktop to load it.

## Usage

Once loaded, just ask questions naturally — Claude calls `search_docs` / `read_doc` on its own. Example:

> "Is there a system property to debug OAuth issues?"

To search directly yourself, call the tool with a keyword or grep-style regex:

```
search_docs(query: "oauth.*debug", max_results: 15)
```

Regex special characters are passed through to `grep -i`, so patterns like `glide\.oauth\..*` work.

## Token usage per query

Measured directly from `index.txt` (per-file content size, single pass over all 48,975 indexed files — not sampled), converted at ~4 characters/token.

**File size distribution (this corpus):**

| Percentile | Size | Approx tokens |
|---|---|---|
| min | 348 B | ~90 |
| median | 3.3 KB | ~825 |
| average | 5.4 KB | ~1,360 |
| p90 | 8.9 KB | ~2,215 |
| p99 | 31.4 KB | ~7,850 |
| max (outlier) | 2.2 MB | ~557,000 |

**Per-call cost:**

| Call | What's returned | Approx tokens |
|---|---|---|
| `search_docs`, small (5 results) | 5× `{file, line, snippet≤300 chars}` JSON | ~500 |
| `search_docs`, default (20 results) | 20× same | ~1,900 |
| `search_docs`, max (50 results) | 50× same | ~4,800 |
| `read_doc`, median file (3.3 KB) | full markdown file | ~825 |
| `read_doc`, p90 file (8.9 KB) | full markdown file | ~2,215 |
| `read_doc`, p99 file (31 KB) | full markdown file | ~7,850 |

A typical question costs one `search_docs` call plus one or two `read_doc` calls — so roughly **1,500-10,000 tokens** for most docs, more if it lands on a p99+ outlier page. Lower `max_results` or read fewer docs to cut cost; the server has no chunking/summarization, so `read_doc` always returns the entire file.

## Response token usage with caveman mode

This session ran with the [caveman](https://github.com/anthropics/claude-code) skill active (terse, no filler). Measured on an actual response from this session (the "how this works / best practices" answer above) against a normal-verbosity rewrite of the same content:

| Version | Characters | Approx tokens |
|---|---|---|
| Normal mode (rewritten, same content) | 5,223 | ~1,306 |
| Caveman mode (actual) | 1,762 | ~441 |
| **Savings** | **66%** | **66%** |

Matches caveman's own documented ~65% output-token reduction. Applies to Claude's *response* text only — doesn't change `search_docs`/`read_doc` tool-result token cost above, which is fixed by doc size regardless of response style.

## Troubleshooting

- **No results for an obvious term**: rebuild the index — it may predate a `git pull`.
- **`Search index missing` error**: run `node build-index.mjs` (step 3 above).
- **Server doesn't appear after editing `.mcp.json` / Desktop config**: restart the Claude session — config is only read at startup, not hot-reloaded.