Generic MCP stdio server that exposes a local repository checkout (docs + code) to any MCP host.
Designed for the “one codebase, many instances” workflow:
- you run the same server binary multiple times,
- each instance points at a different repo via env,
- each instance gets its own tool prefix + URI scheme.
Given MCP_TOOL_PREFIX=telegraph, tools are:
telegraph_read_repo_file— read any text file from the repo checkouttelegraph_list_docs— list doc pages asslug -> docs/...(slug is inferred from the docs file path)telegraph_get_doc— read a doc page by slugtelegraph_search_docs— search inside the docs directorytelegraph_search_code— search inside common code directoriestelegraph_refresh_index— rebuild the docs indextelegraph_git_fetch—git fetch --prune --tagsfor the repo (optional helper)telegraph_info— print server settings (paths, prefixes, etc.)
Given MCP_URI_SCHEME=telegraph, resources are:
telegraph://readmetelegraph://contributingtelegraph://doc/{slug}
{prefix}_doc_writer— starter workflow for “write a guide / answer about this repo”.
bun install
bun run buildMCP_REPO_ROOT=/ABS/PATH/to/repo \
MCP_TOOL_PREFIX=myrepo \
MCP_URI_SCHEME=myrepo \
bun run startIn stdio mode, logs go to stderr on purpose (stdout is reserved for MCP JSON-RPC).
Required:
MCP_REPO_ROOT— absolute path to the local repo checkout
Optional:
MCP_TOOL_PREFIX— tool name prefix (default:repo)MCP_URI_SCHEME— resource URI scheme (default: derived from tool prefix)MCP_REPO_LABEL— text label used in the prompt (default: basename of repo root)MCP_DOCS_DIR— docs directory relative to repo root (default:docs)MCP_DOCS_DISCOVERY_DEPTH— if> 0andMCP_DOCS_DIRis a plain folder name, auto-discovers matching docs dirs up to this depth (default:3)MCP_DOCS_EXTS— comma-separated docs extensions (default:.md,.mdx)MCP_CODE_DIRS— comma-separated dirs to search for code (default:src,config,routes,database,resources,tests)MCP_CODE_EXTS— comma-separated extensions for code search (default:.php,.md,.json,.yml,.yaml,.xml,.ts,.js)
Limits:
MCP_MAX_FILE_BYTES(default: 512KB)MCP_DEFAULT_MAX_CHARS(default: 50k chars)
Git helper:
MCP_GIT_AUTO_FETCH=1— rungit fetch --prune --tagsonce at server start (default: off)MCP_GIT_FETCH_TIMEOUT_MS— timeout for the fetch command (default: 30000)
Compatibility:
- If
MCP_REPO_ROOTis not set, the server will fall back toMCP_TELEGRAPH_ROOT(legacy name).
Add this to ~/.codex/config.toml:
[mcp_servers.telegraph_docs]
command = "/ABS/PATH/TO/bun"
cwd = "/ABS/PATH/TO/mcp"
args = ["run", "build/index.js"]
[mcp_servers.telegraph_docs.env]
MCP_REPO_ROOT = "/ABS/PATH/TO/telegraph"
MCP_TOOL_PREFIX = "telegraph"
MCP_URI_SCHEME = "telegraph"
MCP_REPO_LABEL = "defstudio/telegraph"
[mcp_servers.laravel_data_docs]
command = "/ABS/PATH/TO/bun"
cwd = "/ABS/PATH/TO/mcp"
args = ["run", "build/index.js"]
[mcp_servers.laravel_data_docs.env]
MCP_REPO_ROOT = "/ABS/PATH/TO/laravel-data"
MCP_TOOL_PREFIX = "laravel_data"
MCP_URI_SCHEME = "laravel-data"
MCP_REPO_LABEL = "spatie/laravel-data"See claude_desktop_config.example.json.
- Docs slugs are inferred from file paths (ordering prefixes like
01.,01-,01_are stripped). - If a doc file is
index.mdinside a folder, the slug is the folder name (e.g.guide/index.md→guide). - With
MCP_DOCS_DISCOVERY_DEPTH > 0, nested docs likepackages/*/docsare indexed too, and their slugs get a prefix (e.g.packages/actions/...).