soup-chop
v1.0.5
Published
A JIT Documentation Proxy for the Model Context Protocol
Maintainers
Readme
The Problem
You're using an AI coding assistant. You ask it to help you with [email protected].
It confidently writes code using the v1 API — because that's what was in its
training data. You correct it. It apologizes. It does it again.
soupChop fixes this.
It gives your AI agent a live, on-demand window into the actual documentation for the exact version of the library you're working with. No pre-training required. No stale knowledge. No hallucinated function signatures.
Why soupChop?
| Without soupChop | With soupChop | | :--- | :--- | | AI guesses API from training data | AI reads the real docs for your exact version | | You paste READMEs into chat manually | Docs are fetched and structured automatically | | Full READMEs flood the context window | Only the relevant section is delivered | | Every library needs its own MCP server | One server handles every NPM package |
Quick Start
Option 1 — Run directly with npx
npx soup-chop serveThat's it. The MCP server starts on stdio and is ready for your AI client to connect.
Option 2 — Install globally
npm install -g soup-chop
soup-chop serveOption 2.5 — Use as a library
The published package also exposes a library entry point alongside the CLI. MCP server providers can use it to register their server with any supported AI client programmatically.
ESM:
import { setupClient, installMcp } from 'soup-chop';CommonJS:
const { setupClient, installMcp } = require('soup-chop');Bundled TypeScript declarations are included, so editors and consumers resolve types without needing internal dist/ paths.
Option 3 — Inspect the supported clients
npx soup-chop clientsThis prints the currently documented client list and highlights which clients support automatic file-based configuration on your current platform.
Option 4 — Auto-configure a supported client
npx soup-chop configure windsurf
npx soup-chop configure cursor
npx soup-chop configure cursor --project
npx soup-chop configure vscode-copilot
npx soup-chop configure firebase-studio
npx soup-chop configure claude-code
npx soup-chop configure cursor --project --dry-run
npx soup-chop configure cursor --print
npx soup-chop configure cursor --project --local-build --dry-runFor clients that register via their own CLI (like Claude Code), soup-chop configure runs the appropriate command automatically — no manual file editing needed. Use --dry-run to preview the command that would be executed, or --print to emit the command line for use in scripts.
Use --project or --global when a client supports more than one writable scope. Without a flag, soup-chop uses that client's default writable scope.
On Linux today, the exact auto-config targets exposed by soup-chop help depend on the current platform and writable config paths.
On macOS and Windows, Claude Desktop is also documented and may become auto-configurable when its stable config path is available on that platform.
For a non-mutating preview, use:
npx soup-chop configure cursor --project --dry-run
npx soup-chop configure vscode-copilot --dry-runTo print only the config snippet for copy-paste workflows, use:
npx soup-chop configure cursor --print
npx soup-chop configure vscode-copilot --printTo generate config for an unpublished local build instead of npx soup-chop serve, use:
npx soup-chop configure cursor --project --local-build --dry-run
npx soup-chop configure cursor --local-buildThis emits node /abs/path/to/dist/index.js serve using the current working directory as the local build root.
If you're unsure what the current build supports on your machine, run:
npx soup-chop help
npx soup-chop clients --jsonThe help output includes the exact auto-config client IDs available on the current platform. clients --json emits the same client matrix as structured JSON for setup scripts and tooling.
Option 5 — Manual configuration matrix
The ecosystem is moving quickly, so soupChop documents both implemented auto-config targets and UI/manual targets that are officially supported by their clients.
| Client | Status | Scope | Verified config path / flow | Notes |
| :----- | :----- | :---- | :-------------------------- | :---- |
| Claude Desktop | Auto-config on macOS and Windows | Global | macOS: ~/Library/Application Support/Claude/claude_desktop_config.jsonWindows: %APPDATA%\Claude\claude_desktop_config.json | Official MCP docs expose this file via Claude > Settings > Developer > Edit Config; Linux remains documented-only in CLI output |
| Claude Code | Auto-configure (CLI) | Project / user | claude mcp add <name> npx -- soup-chop serve | soup-chop configure claude-code runs the claude mcp add command automatically |
| Cursor | Auto-config | Global / project | Global: ~/.cursor/mcp.jsonProject: .cursor/mcp.json | Use npx soup-chop configure cursor for the global file or npx soup-chop configure cursor --project for the project file |
| Windsurf | Auto-config | Global | ~/.codeium/windsurf/mcp_config.json | Official docs also expose MCP management from the MCP Marketplace / Settings UI |
| Antigravity | Documented | UI-managed | Agent pane → MCP Servers / MCP Store / View raw config | Official docs describe the flow but do not publish a stable file path |
| Cline | Documented | UI-managed | MCP Servers icon → Configure MCP Servers → cline_mcp_settings.json | Official docs expose the config file through the UI |
| VS Code Copilot | Auto-config | Project / user | Project: .vscode/mcp.jsonUser: VS Code user settings under mcp.servers | soup-chop writes the project file today; the user-settings path remains manual. Uses servers rather than mcpServers |
| Gemini CLI | Documented | Project / user | Project: .gemini/settings.jsonUser: ~/.gemini/settings.json | Same JSON shape as other mcpServers clients |
| Gemini Code Assist | Documented | Project / user | Project: .gemini/settings.jsonUser: ~/.gemini/settings.json | Shares Gemini CLI config format |
| Firebase Studio | Auto-config | Project | .idx/mcp.json | soup-chop writes the project-local MCP config directly |
Option 6 — Manual snippets by client
The configure command accepts a few convenience aliases, for example claude, copilot, and firebase, and it supports explicit --project / --global scope selection when a client exposes more than one writable file target. Use --dry-run to preview the resolved file and merged JSON, --print to emit just the minimal snippet, or --local-build to point the config at the local built dist/index.js entrypoint.
When configure cannot write a client automatically, it now reports the documented target and points you back to soup-chop clients for the full matrix instead of failing with a generic message.
In the examples below, soup-chop is just the default registered server name. For manual JSON edits or client-specific CLI registration, you can replace that key with any local name you prefer. The public soup-chop configure CLI currently writes the default soup-chop name.
Claude Desktop / Cursor / Windsurf / Gemini / Firebase Studio
{
"mcpServers": {
"soup-chop": {
"command": "npx",
"args": ["soup-chop", "serve"]
}
}
}VS Code Copilot project config
{
"servers": {
"soup-chop": {
"type": "stdio",
"command": "npx",
"args": ["soup-chop", "serve"]
}
}
}Claude Code manual registration
claude mcp add soup-chop npx -- soup-chop serveThe first soup-chop token is the registered MCP server name inside Claude Code.
You can replace it with another local label if you want, for example:
claude mcp add my-docs npx -- soup-chop serveAntigravity manual registration
Open the Agent pane, then go to MCP Servers or MCP Store, add a custom stdio server, and point it to:
npx soup-chop serveIf Antigravity exposes raw JSON editing in your current build, use the same mcpServers JSON shown above.
Available Tools
The server is primarily tool-oriented, but it also exposes a small capability
resource at soup-chop://capabilities so MCP clients that inspect resources
have a useful entry point.
Target selection is explicit:
- use
packageplusversionfor published npm docs - use
local_pathfor a direct local package checkout - use
workspace_pathpluspackagefor a package resolved from a local monorepo
soupChop does not merge local and published corpora implicitly. When you
select a local target, the server stays on that filesystem corpus only.
Source discovery is broader than package-shipped markdown alone:
README.md- package-local markdown under
doc/anddocs/ - a small allowlist of top-level markdown docs such as
API.md,FAQ.md,MIGRATING.md,UPGRADING.md,CHANGELOG.md, andCONTRIBUTING.md - synthetic
source_jsdocentries generated from exported TypeScript JSDoc/TSDoc discovered from local packages, published npm tarballs, and GitHub/GitLab repositories - same-origin website docs crawled from an explicit
docs_url, or auto-detected from README links when a package is website-first - repository-derived wiki pages indexed as
wiki_docwhen a GitHub / GitLab wiki is discoverable - one-hop local workspace dependency docs when resolving a package through
workspace_path
Website pages are indexed as website_doc sources and use origin values such as website/dockview.dev/docs/core/overview.
Synthetic JSDoc pages use origins like jsdoc/createstableclient. Wiki pages use wiki/... origins.
For website ingestion, soup-chop currently stays Node-only: it supports static HTML crawling plus manifest-aware discovery such as VitePress hashmap.json and sitemap-backed doc sites, but intentionally does not require Playwright or a browser runtime for JS-rendered SPA fallback.
compare_versions and get_upgrade_guide currently remain npm-only.
get_capabilities
Get a concise overview of the server surface.
Returns the current tool inventory, the recommended usage flow, and the current source-selection policy in a short text response.
Use it when a client needs a quick MCP entry point before choosing a more specific tool.
list_sources
Inspect the exact markdown corpus that was indexed.
Returns the exact markdown files indexed for a target together with corpus debug metadata such as source precedence, cache freshness, and the resolved local package root.
This is the best tool to call when you want to verify which files were actually
analyzed before following up with search_docs, get_toc, or the Mincer tools. For website-first packages, this can include website_doc entries in addition to packaged markdown.
Parameters:
| Name | Type | Required | Description |
| :-------- | :------- | :------- | :---------------------------------------------------------------------- |
| package | string | No | NPM package name, or workspace package name when using workspace_path |
| version | string | No | NPM version string for remote usage, or optional exact local-version check |
| docs_url | string | No | Optional docs website entry URL; when provided, soup-chop crawls this website as an additional documentation source |
| local_path | string | No | Local package directory or local package.json path |
| workspace_path | string | No | Local monorepo / workspace root; requires package |
Example call using a local package path:
{
"name": "list_sources",
"arguments": {
"local_path": "/home/me/dev/acme/packages/docs-pkg"
}
}Example response:
{
"package": "dockview",
"version": "5.1.0",
"sources": [
{
"sourceId": "readme__md",
"sourceKind": "readme",
"origin": "README.md",
"title": "README.md",
"lineCount": 81
},
{
"sourceId": "website__dockview__dev__docs__core__overview",
"sourceKind": "website_doc",
"origin": "website/dockview.dev/docs/core/overview",
"title": "Overview | Dockview",
"lineCount": 3
},
{
"sourceId": "website__dockview__dev__docs__core__panels__register",
"sourceKind": "website_doc",
"origin": "website/dockview.dev/docs/core/panels/register",
"title": "Registering Panels | Dockview",
"lineCount": 5
}
],
"debug": {
"precedence": "explicit_target_only",
"targetMode": "npm",
"freshness": "immutable_published_version",
"cacheEnabled": true,
"cacheReason": "Exact published npm versions are immutable, so manifest and search caches are safe.",
"cachePaths": {
"manifest": "/home/me/.cache/soup-chop/dockview/5.1.0/sources-manifest.json",
"searchIndex": "/home/me/.cache/soup-chop/dockview/5.1.0/search-index.json"
},
"sourceOrigins": [
"README.md",
"website/dockview.dev/docs/core/overview",
"website/dockview.dev/docs/core/panels/register"
]
}
}get_toc
Discover what's in the documentation.
Returns a structured table of contents for a package's markdown docs.
Without origin, it returns a package-wide multi-document TOC that includes
synthetic file-root entries such as README.md, CHANGELOG.md, docs/faq.md, or website origins such as website/dockview.dev/docs/core/overview.
With origin, it returns the TOC for a single markdown document.
For README.md, soup-chop also adds direct synthetic entries for common top-level sections such as Installation, API, Usage, and FAQ so callers can jump straight to those sections without the full hierarchical path.
Parameters:
| Name | Type | Required | Description |
| :-------- | :------- | :------- | :------------------------------------- |
| package | string | No | NPM package name, or workspace package name when using workspace_path |
| version | string | No | NPM version string for remote usage, or optional exact local-version check |
| docs_url | string | No | Optional docs website entry URL; when provided, soup-chop crawls this website as an additional documentation source |
| local_path | string | No | Local package directory or local package.json path |
| workspace_path | string | No | Local monorepo / workspace root; requires package |
| origin | string | No | Source path from search_docs such as "docs/faq.md", "CHANGELOG.md", or "website/dockview.dev/docs/core/overview" |
Example call:
{
"name": "get_toc",
"arguments": {
"package": "zod",
"version": "3.23.8"
}
}Example call using a local workspace package:
{
"name": "get_toc",
"arguments": {
"package": "@acme/docs-pkg",
"workspace_path": "/home/me/dev/acme-monorepo"
}
}Example response:
{
"package": "axios",
"version": "1.6.7",
"entries": [
{
"depth": 0,
"title": "README.md",
"path": "README.md",
"startLine": 1,
"endLine": 1648,
"origin": "README.md",
"topicId": "README.md"
},
{
"depth": 2,
"title": "Request Config",
"path": "Request Config",
"startLine": 386,
"endLine": 634,
"origin": "README.md",
"topicId": "README.md#Request Config"
},
{
"depth": 0,
"title": "CHANGELOG.md",
"path": "CHANGELOG.md",
"startLine": 1,
"endLine": 205,
"origin": "CHANGELOG.md",
"topicId": "CHANGELOG.md"
}
]
}When you already know the document you want, pass origin to get just that
document's headings.
get_topic
Read a specific section.
Fetches the raw Markdown content for a specific section or whole markdown document.
You can identify the target either with topic_id, or with path plus an
optional origin.
For website docs, origin and topic_id use the normalized website source path returned by search_docs and get_toc.
The same applies to synthetic README section shortcuts such as README.md#Installation.
Parameters:
| Name | Type | Required | Description |
| :-------- | :------- | :------- | :------------------------------------------------------- |
| package | string | No | NPM package name, or workspace package name when using workspace_path |
| version | string | No | NPM version string for remote usage, or optional exact local-version check |
| docs_url | string | No | Optional docs website entry URL; when provided, soup-chop crawls this website as an additional documentation source |
| local_path | string | No | Local package directory or local package.json path |
| workspace_path | string | No | Local monorepo / workspace root; requires package |
| path | string | No | Section path from get_toc (e.g., "Zod/Installation") |
| origin | string | No | Source path from search_docs such as "docs/faq.md", "CHANGELOG.md", or "website/dockview.dev/docs/core/panels/register" |
| topic_id| string | No | Stable topic identifier from search_docs or aggregated get_toc |
Example call using topic_id:
{
"name": "get_topic",
"arguments": {
"package": "zod",
"version": "3.23.8",
"topic_id": "README.md#Coercion for primitives"
}
}Example call using a direct local package path:
{
"name": "get_topic",
"arguments": {
"local_path": "/home/me/dev/acme/packages/docs-pkg",
"topic_id": "docs/guide.md#Workspace Guide"
}
}get_examples
Extract fenced code examples from a whole doc or one section.
Returns the fenced code blocks found in a markdown document or a selected
section. Use topic_id, or path plus optional origin, to narrow the
extraction scope.
Parameters:
| Name | Type | Required | Description |
| :-------- | :------- | :------- | :---------------------------------------------------------------------- |
| package | string | No | NPM package name, or workspace package name when using workspace_path |
| version | string | No | NPM version string for remote usage, or optional exact local-version check |
| docs_url | string | No | Optional docs website entry URL; when provided, soup-chop crawls this website as an additional documentation source |
| local_path | string | No | Local package directory or local package.json path |
| workspace_path | string | No | Local monorepo / workspace root; requires package |
| path | string | No | Optional section path from get_toc |
| origin | string | No | Optional source path such as "docs/faq.md", "CHANGELOG.md", or "website/dockview.dev/docs/core/panels/add" |
| topic_id| string | No | Stable topic identifier from search_docs or aggregated get_toc |
Example call:
{
"name": "get_examples",
"arguments": {
"package": "zod",
"version": "3.23.8",
"topic_id": "README.md#Coercion for primitives"
}
}find_symbol_in_docs
Find documentation that mentions a known identifier.
Searches the indexed markdown corpus for an exact exported identifier or literal
symbol name such as createClient, z.object, or parseAsync.
This is especially useful after get_api_ref when you know the symbol and want
the documentation sections that mention it.
Parameters:
| Name | Type | Required | Description |
| :-------- | :------- | :------- | :---------------------------------------------------------------------- |
| package | string | No | NPM package name, or workspace package name when using workspace_path |
| version | string | No | NPM version string for remote usage, or optional exact local-version check |
| docs_url | string | No | Optional docs website entry URL; when provided, soup-chop crawls this website as an additional documentation source |
| local_path | string | No | Local package directory or local package.json path |
| workspace_path | string | No | Local monorepo / workspace root; requires package |
| name | string | Yes | Identifier or literal symbol to locate |
| limit | number | No | Maximum ranked results to return, from 1 to 20, default 10 |
Example call:
{
"name": "find_symbol_in_docs",
"arguments": {
"package": "zod",
"version": "3.23.8",
"name": "z.object",
"limit": 5
}
}search_docs
Search package docs when you do not know the exact section yet.
Searches README.md, package-local markdown under doc/ and docs/, and a
small allowlist of top-level markdown docs such as API.md, FAQ.md,
MIGRATING.md, UPGRADING.md, CHANGELOG.md, and CONTRIBUTING.md. For website-first packages, soup-chop can also crawl same-origin website docs and index them as website_doc sources.
Results are ranked lexically and return the source origin, section path, line
ranges, a stable topicId, a short preview, and lightweight example metadata
such as hasExamples, exampleCount, and exampleLanguages so the caller can
pick sections that are more likely to contain runnable snippets.
Current language support: search is currently optimized for English tokenization and ranking.
TODO: add better Chinese / broader CJK tokenization and ranking support.
Parameters:
| Name | Type | Required | Description |
| :-------- | :------- | :------- | :---------------------------------------------------------------------- |
| package | string | No | NPM package name, or workspace package name when using workspace_path |
| version | string | No | NPM version string for remote usage, or optional exact local-version check |
| docs_url | string | No | Optional docs website entry URL; when provided, soup-chop crawls this website as an additional documentation source |
| local_path | string | No | Local package directory or local package.json path |
| workspace_path | string | No | Local monorepo / workspace root; requires package |
| query | string | Yes | Keyword query or natural-language question |
| limit | number | No | Maximum number of ranked results to return, from 1 to 20, default 5 |
Example call:
{
"name": "search_docs",
"arguments": {
"package": "zod",
"version": "3.23.8",
"query": "coercion schema parsing",
"limit": 3
}
}Example call using a local package path:
{
"name": "search_docs",
"arguments": {
"local_path": "/home/me/dev/acme/packages/docs-pkg",
"query": "workspace guide",
"limit": 3
}
}Example follow-up flow:
- Call
search_docsto find likely sections. - If needed, call
get_tocwith the returnedoriginto inspect that doc's structure. - Call
get_topicwith the returnedtopicId, or with the returnedpathandorigin, to fetch the exact section.
search_examples
Search for explanation plus nearby examples in one response.
Searches the same markdown corpus as search_docs, but returns section-centered
results that keep the prose preview and attach the nearest fenced examples from
that matching section.
Use this when the user intent is closer to "keywords -> paragraph + example" than to raw document navigation.
Parameters:
| Name | Type | Required | Description |
| :-------- | :------- | :------- | :---------------------------------------------------------------------- |
| package | string | No | NPM package name, or workspace package name when using workspace_path |
| version | string | No | NPM version string for remote usage, or optional exact local-version check |
| docs_url | string | No | Optional docs website entry URL; when provided, soup-chop crawls this website as an additional documentation source |
| local_path | string | No | Local package directory or local package.json path |
| workspace_path | string | No | Local monorepo / workspace root; requires package |
| query | string | Yes | Keyword query or natural-language question |
| limit | number | No | Maximum number of ranked results to return, from 1 to 20, default 5 |
Example call:
{
"name": "search_examples",
"arguments": {
"package": "zod",
"version": "3.23.8",
"query": "coercion example",
"limit": 3
}
}Example usage pattern:
- Call
search_exampleswhen the user asks for a concrete usage example. - If the attached examples are enough, answer directly from that response.
- If more context is needed, pivot to
get_topicwith the returnedtopicId.
get_traps
Surface warnings, caveats, and operational gotchas.
Returns compact, evidence-backed trap findings extracted deterministically from
the same markdown corpus used by search_docs.
Each finding includes:
packageversionkindseverityconfidencetitlesummaryevidence
Each evidence item includes the source document, section path, exact line
range, snippet, and detector names so the caller can pivot back into
get_topic without losing traceability.
Parameters:
| Name | Type | Required | Description |
| :-------- | :------- | :------- | :----------------------------------------------------------------------- |
| package | string | No | NPM package name, or workspace package name when using workspace_path |
| version | string | No | NPM version string for remote usage, or optional exact local-version check |
| docs_url | string | No | Optional docs website entry URL; when provided, soup-chop crawls this website as an additional documentation source |
| local_path | string | No | Local package directory or local package.json path |
| workspace_path | string | No | Local monorepo / workspace root; requires package |
| limit | number | No | Maximum number of ranked trap findings to return, from 1 to 50, default 10 |
Example call:
{
"name": "get_traps",
"arguments": {
"package": "zod",
"version": "3.23.8",
"limit": 2
}
}Example response:
{
"package": "zod",
"version": "3.23.8",
"kind": "traps",
"findings": [
{
"package": "zod",
"version": "3.23.8",
"kind": "traps",
"severity": "warning",
"confidence": "high",
"title": "Important caveat noted in documentation",
"summary": "> IMPORTANT: The value returned by .parse is a deep clone of the variable you passed in.",
"evidence": [
{
"sourceId": "readme__md",
"sourceKind": "readme",
"sourceTitle": "README.md",
"origin": "README.md",
"path": "Schema methods/.parse",
"startLine": 1930,
"endLine": 1930,
"snippet": "> IMPORTANT: The value returned by .parse is a deep clone of the variable you passed in.",
"detectors": ["trap.important"]
}
]
}
]
}get_deprecations
Surface deprecated APIs, legacy guidance, and replacements.
Returns compact, evidence-backed deprecation findings extracted deterministically
from the same markdown corpus used by search_docs.
Deprecation findings are surfaced at warning severity because they usually
indicate migration work, compatibility edge-cases, or removal risk rather than
neutral reference material.
Use it when you want focused migration and replacement guidance instead of the
broader caveat-oriented get_traps view.
Parameters:
| Name | Type | Required | Description |
| :-------- | :------- | :------- | :----------------------------------------------------------------------------- |
| package | string | No | NPM package name, or workspace package name when using workspace_path |
| version | string | No | NPM version string for remote usage, or optional exact local-version check |
| docs_url | string | No | Optional docs website entry URL; when provided, soup-chop crawls this website as an additional documentation source |
| local_path | string | No | Local package directory or local package.json path |
| workspace_path | string | No | Local monorepo / workspace root; requires package |
| limit | number | No | Maximum number of ranked deprecation findings to return, from 1 to 50, default 10 |
Example call:
{
"name": "get_deprecations",
"arguments": {
"package": "zod",
"version": "3.23.8",
"limit": 2
}
}Example response:
{
"package": "demo",
"version": "1.0.0",
"kind": "deprecations",
"findings": [
{
"package": "demo",
"version": "1.0.0",
"kind": "deprecations",
"severity": "warning",
"confidence": "high",
"title": "Deprecation or replacement guidance",
"summary": "This API is deprecated; use createClient instead.",
"evidence": [
{
"sourceId": "migration",
"sourceKind": "package_doc",
"sourceTitle": "migration.md",
"origin": "docs/migration.md",
"path": "Migration",
"startLine": 8,
"endLine": 8,
"snippet": "This API is deprecated; use createClient instead.",
"detectors": ["deprecation.deprecated", "deprecation.use_instead"]
}
]
}
]
}get_constraints
Surface prerequisites, ordering requirements, and unsupported scenarios.
Returns compact, evidence-backed constraint findings extracted deterministically
from the same markdown corpus used by search_docs.
Use it when you want integration requirements and support boundaries rather than general caveats.
Parameters:
| Name | Type | Required | Description |
| :-------- | :------- | :------- | :--------------------------------------------------------------------------- |
| package | string | No | NPM package name, or workspace package name when using workspace_path |
| version | string | No | NPM version string for remote usage, or optional exact local-version check |
| docs_url | string | No | Optional docs website entry URL; when provided, soup-chop crawls this website as an additional documentation source |
| local_path | string | No | Local package directory or local package.json path |
| workspace_path | string | No | Local monorepo / workspace root; requires package |
| limit | number | No | Maximum number of ranked constraint findings to return, from 1 to 50, default 10 |
Example call:
{
"name": "get_constraints",
"arguments": {
"package": "demo",
"version": "1.0.0",
"limit": 2
}
}Example response:
{
"package": "demo",
"version": "1.0.0",
"kind": "constraints",
"findings": [
{
"package": "demo",
"version": "1.0.0",
"kind": "constraints",
"severity": "warning",
"confidence": "high",
"title": "Operational constraint",
"summary": "This only works after setup and requires a token.",
"evidence": [
{
"sourceId": "guide",
"sourceKind": "package_doc",
"sourceTitle": "guide.md",
"origin": "docs/guide.md",
"path": "Setup",
"startLine": 4,
"endLine": 4,
"snippet": "This only works after setup and requires a token.",
"detectors": ["constraint.after_setup", "constraint.only_works", "constraint.requires"]
}
]
}
]
}get_performance_notes
Surface complexity notes, expensive operations, and hot paths.
Returns compact, evidence-backed performance findings extracted deterministically
from the same markdown corpus used by search_docs.
Use it when you want cost and scaling signals rather than functional or operational caveats.
Parameters:
| Name | Type | Required | Description |
| :-------- | :------- | :------- | :----------------------------------------------------------------------------- |
| package | string | No | NPM package name, or workspace package name when using workspace_path |
| version | string | No | NPM version string for remote usage, or optional exact local-version check |
| docs_url | string | No | Optional docs website entry URL; when provided, soup-chop crawls this website as an additional documentation source |
| local_path | string | No | Local package directory or local package.json path |
| workspace_path | string | No | Local monorepo / workspace root; requires package |
| limit | number | No | Maximum number of ranked performance findings to return, from 1 to 50, default 10 |
Example call:
{
"name": "get_performance_notes",
"arguments": {
"package": "demo",
"version": "1.0.0",
"limit": 2
}
}Example response:
{
"package": "demo",
"version": "1.0.0",
"kind": "performance",
"findings": [
{
"package": "demo",
"version": "1.0.0",
"kind": "performance",
"severity": "warning",
"confidence": "high",
"title": "Performance-sensitive behavior",
"summary": "This operation is expensive on the hot path.",
"evidence": [
{
"sourceId": "perf",
"sourceKind": "package_doc",
"sourceTitle": "performance.md",
"origin": "docs/performance.md",
"path": "Performance",
"startLine": 12,
"endLine": 12,
"snippet": "This operation is expensive on the hot path.",
"detectors": ["performance.expensive", "performance.hot_path"]
}
]
}
]
}get_security_notes
Surface authentication, authorization, token, and attack-surface guidance.
Returns evidence-backed security findings extracted deterministically from the
same markdown corpus used by search_docs.
Use it when you want package docs filtered specifically for security-relevant guidance rather than general caveats or performance notes.
Parameters:
| Name | Type | Required | Description |
| :-------- | :------- | :------- | :----------------------------------------------------------------------------- |
| package | string | No | NPM package name, or workspace package name when using workspace_path |
| version | string | No | NPM version string for remote usage, or optional exact local-version check |
| docs_url | string | No | Optional docs website entry URL; when provided, soup-chop crawls this website as an additional documentation source |
| local_path | string | No | Local package directory or local package.json path |
| workspace_path | string | No | Local monorepo / workspace root; requires package |
| limit | number | No | Maximum number of ranked security findings to return, from 1 to 50, default 10 |
Example call:
{
"name": "get_security_notes",
"arguments": {
"package": "demo",
"version": "1.0.0",
"limit": 2
}
}soup-chop://capabilities
Quick MCP entry point for resource-oriented clients.
If your client starts by listing resources, soup-chop://capabilities explains
the server surface and points you toward the recommended tool-first flow.
Use it to discover:
- the main tools
- the recommended
search_docs->get_toc/get_topicflow - the current English-first search behavior
get_api_ref
Index the published API surface.
Returns a compact index of exported identifiers from published or local .d.ts files.
Each entry is grouped by identifier name and lists its associated runtime and
compile-time kinds.
Parameters:
| Name | Type | Required | Description |
| :-------- | :------- | :------- | :------------------------------------------------------------------------------------- |
| package | string | No | NPM package name, or workspace package name when using workspace_path |
| version | string | No | NPM version string for remote usage, or optional exact local-version check |
| local_path | string | No | Local package directory or local package.json path |
| workspace_path | string | No | Local monorepo / workspace root; requires package |
Example call using a local package path:
{
"name": "get_api_ref",
"arguments": {
"local_path": "/home/me/dev/acme/packages/docs-pkg"
}
}get_declaration
Read the exact declaration body.
Returns the explicit TypeScript declaration text for an exported identifier.
Use get_api_ref to discover names first, then fetch the full declaration body
only when needed.
Parameters:
| Name | Type | Required | Description |
| :-------- | :------- | :------- | :------------------------------------------------------------------------------------- |
| package | string | No | NPM package name, or workspace package name when using workspace_path |
| version | string | No | NPM version string for remote usage, or optional exact local-version check |
| local_path | string | No | Local package directory or local package.json path |
| workspace_path | string | No | Local monorepo / workspace root; requires package |
| name | string | Yes | Exported identifier name (e.g., "ZodType") |
compare_versions
See what changed between versions.
Diffs the documentation structure between two published npm versions of a package, showing added, removed, and unchanged sections.
Parameters:
| Name | Type | Required | Description |
| :-------- | :------- | :------- | :------------------------------------------------------------------------------------- |
| package | string | Yes | NPM package name |
| v_old | string | Yes | NPM version string: exact version or published dist-tag (e.g., "3.22.0", "oldest") (jk) |
| v_new | string | Yes | NPM version string: exact version or published dist-tag (e.g., "3.23.8", "latest") |
get_upgrade_guide
Get a migration-focused upgrade bundle for two published npm versions.
Composes compare_versions, changelog extraction, and deprecations from the
target version into a single response that is easier for agents to consume as
an upgrade guide.
Parameters:
| Name | Type | Required | Description |
| :-------- | :------- | :------- | :------------------------------------------------------------------------------------- |
| package | string | Yes | NPM package name |
| v_old | string | Yes | Older version to compare from |
| v_new | string | Yes | Newer version to compare to |
| limit | number | No | Maximum number of deprecation findings to include from the target version, default 10 |
Example call:
{
"name": "get_upgrade_guide",
"arguments": {
"package": "express",
"v_old": "4.18.2",
"v_new": "5.0.0",
"limit": 5
}
}How It Works
You ask about [email protected]
│
▼
┌─────────────────┐
│ Your AI Agent │ "What middleware options are available?"
│ (Claude, etc.) │
└────────┬─────────┘
│ calls get_toc("express", "4.18.2")
▼
┌─────────────────┐
│ soupChop │ MCP Server (runs locally on stdio)
└────────┬─────────┘
│
┌────┴─────────────────────────┐
│ Is it cached on disk? │
│ │
│ YES → read from │
│ ~/.cache/soup-chop/ │
│ express/4.18.2/README.md │
│ │
│ NO → fetch from │
│ unpkg.com/[email protected]/ │
│ README.md │
│ then cache it. │
└────┬─────────────────────────┘
│
▼
┌─────────────────┐
│ Remark AST │ Parses Markdown into a heading tree
│ Parser │ with line ranges for each section
└────────┬─────────┘
│
▼
Structured TOC returned to the AI
(only metadata — not the full README)Key design decisions:
- Version-scoped caching — Each
package@versionpair is cached independently. Since published NPM versions are immutable, packaged markdown, website-source manifests, search indexes, and findings caches can be reused safely. - No API keys required — Everything runs locally. No LLM calls, no embeddings
API, no external services beyond UNPKG (a public CDN) and the target documentation website when
docs_urlor README-based website detection is used. - Surgical delivery — The AI gets a table of contents, not the full README. It can then request only the section it needs, keeping context windows lean.
- Website-first docs support — Packages whose real docs live on a website can be indexed through bounded same-origin crawling and HTML-to-Markdown normalization.
Configuration
Cache Location
soupChop uses env-paths to store
cached documentation in the standard OS-specific cache directory:
| OS | Path |
| :------ | :---------------------------------------- |
| Linux | ~/.cache/soup-chop/ |
| macOS | ~/Library/Caches/soup-chop/ |
| Windows | %LOCALAPPDATA%\soup-chop\Cache\ |
Cache is organized as:
~/.cache/soup-chop/
├── express/
│ └── 4.18.2/
│ ├── README.md
│ ├── sources-manifest.json
│ ├── search-index.json
│ └── mincer-findings.json
├── zod/
│ └── 3.23.8/
│ ├── README.md
│ ├── sources-manifest.json
│ ├── search-index.json
│ └── mincer-findings.json
└── ...To clear the cache, simply delete the directory.
For MCP Providers
If you are building an MCP server and want to help your users register it with their AI client, soup-chop exports a library API for exactly this purpose.
setupClient(clientId, options)
Registers an MCP server with a named AI client. Handles both file-based clients (Cursor, Windsurf, VS Code Copilot, …) and CLI-based clients (Claude Code) transparently.
import { setupClient } from 'soup-chop';
// stdio server — file-based client
await setupClient('cursor', {
name: 'my-mcp-server',
server: { command: 'npx', args: ['my-mcp-server', 'serve'] },
scope: 'project',
cwd: process.cwd(),
});
// stdio server — CLI-based client (runs: claude mcp add my-mcp-server npx -- my-mcp-server serve)
await setupClient('claude-code', {
name: 'my-mcp-server',
server: { command: 'npx', args: ['my-mcp-server', 'serve'] },
});
// URL server — VS Code Copilot project config
await setupClient('vscode-copilot', {
name: 'my-mcp-server',
server: { type: 'http', url: 'https://my-server.example.com/mcp' },
scope: 'project',
cwd: process.cwd(),
});Returns a SetupOutcome discriminated union:
type SetupOutcome =
| { mode: 'auto-config'; path: string; created: boolean } // wrote/merged a JSON config file
| { mode: 'cli-install'; command: string; args: string[] }; // ran an external CLI commandSetupOptions:
| Field | Type | Required | Description |
| :---- | :--- | :------- | :---------- |
| name | string | Yes | Key used in the client config JSON or as the CLI registration name |
| server | McpServer | Yes | stdio or URL transport descriptor |
| scope | 'global' \| 'project' | No | Config scope for file-based clients |
| cwd | string | No | Base directory for project-scoped path resolution |
| spawnImpl | SpawnLike | No | Injectable spawn function for testing |
McpServer union:
// stdio transport
type McpStdioServer = { type?: 'stdio'; command: string; args: string[]; env?: Record<string, string> };
// HTTP or SSE transport
type McpUrlServer = { type: 'http' | 'sse'; url: string; headers?: Record<string, string> };
type McpServer = McpStdioServer | McpUrlServer;installMcp(command, args, options?)
Low-level helper that spawns an external command (e.g. claude mcp add …) and collects its output. Rejects with an InstallMcpError on non-zero exit.
import { installMcp } from 'soup-chop';
const result = await installMcp('claude', ['mcp', 'add', 'my-server', 'npx', '--', 'my-server', 'serve']);
console.log(result.stdout);getSupportedSetupClientIds()
Returns the list of client IDs that setupClient can handle automatically on the current platform.
import { getSupportedSetupClientIds } from 'soup-chop';
console.log(getSupportedSetupClientIds());
// e.g. ['cursor', 'windsurf', 'claude-code', 'vscode-copilot', 'firebase-studio']For Library Authors
soupChop is designed to work with ordinary package docs. You do not need a special integration, custom metadata, or an MCP-specific format.
That said, some documentation patterns make retrieval much more reliable for both humans and AI agents:
For declaration inspection, soupChop uses the types entry from package.json when resolving a package's TypeScript declarations, so publishing an accurate types path helps get_api_ref and get_declaration target the right .d.ts surface.
Best Practices for Library Authors
Use Clear, Specific Headings
Prefer headings like Authentication, Error Handling, Transactions, or React Integration over vague titles like Advanced or More. Section-based retrieval works best when the heading already says what problem the section solves.
Keep Sections Focused
One section should usually answer one question well. Very large umbrella sections are harder to retrieve precisely than several smaller, well-named sections.
Document Important Concepts in Prose, Not Only in Examples
Short narrative explanations help retrieval and ranking much more than code alone. Keep examples, but explain what they demonstrate and when to use them.
Use Stable Terminology Consistently
If the product uses terms like schema, resolver, adapter, or provider, prefer one canonical term and reuse it throughout the docs. Synonym drift makes both human search and automated retrieval weaker.
Publish Package-Local Markdown When It Matters
README.md is a strong default, but additional docs such as docs/*.md, API.md, FAQ.md, or MIGRATING.md make specialized topics easier to isolate. Migration guides, upgrade notes, and troubleshooting docs are especially valuable.
Separate Version-Sensitive Material Clearly
If behavior changed in v2, say so explicitly in the relevant section. Dedicated upgrade or breaking-change sections are easier to retrieve than scattered notes.
Include Exact Names and Signatures Where Possible
Mention real option names, config keys, CLI flags, and exported identifiers. Precise tokens help users, search, and AI agents converge on the right section faster.
Prefer Descriptive Links and Filenames
docs/authentication.md and docs/error-handling.md are more useful than opaque file names. Good filenames also make multi-document corpora easier to navigate.
A good rule of thumb is simple: write docs so that a person can jump straight to the answer from the table of contents alone. If that works well for a human, it usually works well for soupChop too.
Examples
Example 1 — Exploring a new library
You: "I want to use
zodfor form validation. What does it offer?"AI (calls
get_toc("zod", "3.23.8")): "Here's what Zod's documentation covers: Introduction, Installation, Basic Usage, Primitives, Coercion, Literals, Strings, Numbers, ..."You: "Tell me about coercion."
AI (calls
get_topic("zod", "3.23.8", "Zod/Coercion")): "Zod provides coercion methods that automatically transform input data..."
Example 2 — Debugging a version mismatch
You: "This code worked in express 4 but breaks in express 5."
AI (calls
compare_versions("express", "4.18.2", "5.0.0")): "Several sections have changed between these versions. The 'Middleware' section was reorganized and 'Error Handling' has new subsections..."
Example 3 — Getting accurate type information
You: "What's the actual type signature for
z.object?"AI (calls
get_api_ref("zod", "3.23.8")): "I foundobjectin the published API index. It is exported as a function."AI (calls
get_declaration("zod", "3.23.8", "object")): "Here is the explicit declaration from the published type definitions..."
Example 4 — Verifying a local workspace corpus
You: "Search my local package docs, but first show me exactly what files you indexed."
AI (calls
list_sources({"package":"@acme/docs-pkg","workspace_path":"/home/me/dev/acme-monorepo"})): "I indexedREADME.md,API.md, anddocs/guide.md. This target is local, so caches are intentionally disabled and the resolved package root is/home/me/dev/acme-monorepo/packages/docs-pkg."AI (calls
search_docs({"package":"@acme/docs-pkg","workspace_path":"/home/me/dev/acme-monorepo","query":"workspace guide"})): "The best match isdocs/guide.md#Workspace Guide."
Example 5 — Building an upgrade guide
You: "Summarize the risky migration points between
[email protected]and[email protected]."AI (calls
get_upgrade_guide("express", "4.18.2", "5.0.0")): "The documentation gained several new sections, the changelog includes the relevant release notes, and the target version docs contain deprecation guidance you should address during the upgrade."
Requirements
- Node.js 20 or later
- An MCP-compatible AI client (Claude Desktop, Cursor, Windsurf, etc.)
FAQ
Why not just paste the README into the chat?
Three reasons:
- Context window waste. A typical README is 5,000–50,000 tokens. soupChop delivers only the section the AI needs — often under 500 tokens.
- Version accuracy. You'd have to find and paste the README for the exact version you're using. soupChop does this automatically.
- Automation. The AI can explore documentation on its own, without you acting as a copy-paste intermediary.
Why UNPKG instead of the npm registry API?
UNPKG serves individual files from published packages via a simple URL scheme
(unpkg.com/pkg@version/file). The npm registry API returns package metadata
but not file contents directly. UNPKG gives us exactly what we need with a
single HTTP request.
Does this work with private packages?
Not yet. The current version only supports packages published to the public npm registry via UNPKG. Private registry support is on the roadmap.
What if the package has no README?
soupChop returns a clear error message indicating that no README was found for the requested package and version. The AI can then inform you and suggest alternative documentation sources.
Is my data sent anywhere?
No. soupChop runs entirely on your machine. The only external request is to
unpkg.com to fetch package files — the same CDN used by millions of
developers daily. No telemetry, no analytics, no API keys.
