io.github.vanshulgoyal101/ctx
Turn a GitHub repo or docs site into agent-ready context: pack it or search it, over MCP.
Open source Repository Open in the app JSON README (API)
About
Turn a GitHub repo or docs site into agent-ready context: pack it or search it, over MCP.
Details
- Kind
- MCP servers
- Topic
- Version control
- Publisher
- vanshulgoyal101
- Origin
- official
- Category
- ferramentas
- Transport
- http
- Version
- 1.0.0
- Stars
- 1
- Last push
- 2026-09-04T08:02:01Z
- Repository state
- ativo
- Language
- TypeScript
- License
- MIT
- Added
- 2026-08-29 04:01:37
- Updated
- 2026-08-29 04:01:37
- Origin id
io.github.vanshulgoyal101/ctx
README
# ctx.vanshul.com
[](https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.vanshulgoyal101/ctx)
[](https://ctx.vanshul.com/mcp)
[](./LICENSE)
A public **Model Context Protocol (MCP)** server, running as a Cloudflare
Worker, that turns a **GitHub repository or a documentation site into agent-ready
context**. Point an AI agent at it and it can pack a whole repo (or crawl a docs
site) into one token-counted blob — or search it and get back only the relevant
passages, each with its file/URL and line.
It's the agent-first companion to [`mcp/`](../mcp): where `mcp` reads a single
web page, `ctx` reads whole repos and doc sites. The repo pipeline fetches,
gunzips and parses the tarball in-process; docs extraction reuses Mozilla
Readability + Turndown.
## Endpoint
```
POST https://ctx.vanshul.com/mcp # JSON-RPC 2.0 (MCP)
GET https://ctx.vanshul.com/health # { ok: true, tools: [...] }
```
## Tools
| Tool | Input | Returns |
| --- | --- | --- |
| `pack_repo` | `{ repo, ref?, include?, exclude?, max_tokens? }` | The repo as one context blob with `==== path ====` headers + token estimate |
| `search_context` | `{ repo, query, ref?, include?, exclude?, max_matches?, context_chars? }` | Only the passages matching `query`, each with file, line and score |
| `list_files` | `{ repo, ref?, include?, exclude? }` | JSON: the text files ctx would include, with byte sizes |
| `get_file` | `{ repo, path, ref? }` | The full text of a single file |
| `pack_docs` | `{ url, depth?, max_pages?, max_tokens? }` | A crawled docs site as one context blob (each page → Markdown) |
| `search_docs` | `{ url, query, depth?, max_pages?, max_matches?, context_chars? }` | Only the docs passages matching `query`, each with page URL, line and score |
`repo` is `owner/repo`, `owner/repo/ref`, or a `github.com` URL. `url` (for the
docs tools) is an absolute `http(s)` docs page to start crawling from.
## Connect from an MCP client
```json
{ "mcpServers": { "ctx": { "url": "https://ctx.vanshul.com/mcp" } } }
```
Stdio-only clients bridge with `npx mcp-remote https://ctx.vanshul.com/mcp`.
### Add it to your client
- **Cursor** — Settings → MCP → Add new server, or drop this into `~/.cursor/mcp.json`:
```json
{ "mcpServers": { "ctx": { "url": "https://ctx.vanshul.com/mcp" } } }
```
- **Claude Desktop** — add the same block to `claude_desktop_config.json` (Settings → Developer → Edit Config). If your version is stdio-only, use:
```json
{ "mcpServers": { "ctx": { "command": "npx", "args": ["mcp-remote", "https://ctx.vanshul.com/mcp"] } } }
```
- **Continue / VS Code** — add `ctx` with URL `https://ctx.vanshul.com/mcp` to your MCP servers config.
## Try it with curl
```sh
# Pack a repo, capped to 8000 tokens
curl -s https://ctx.vanshul.com/mcp -H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"pack_repo","arguments":{"repo":"sindresorhus/slugify","max_tokens":8000}}}'
# Search a repo for just the relevant passages
curl -s https://ctx.vanshul.com/mcp -H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call",
"params":{"name":"search_context","arguments":{"repo":"sindresorhus/slugify","query":"replace separator"}}}'
```
## Layout
```
ctx/
├── src/
│ ├── worker.ts # entry: routes /mcp, /health, rate limit, CORS
│ ├── mcp.ts # JSON-RPC dispatch + the six tool definitions
│ ├── github.ts # fetch tarball, gunzip, parse tar, filter files (no deps)
│ ├── pack.ts # assemble the context blob + token estimate
│ ├── search.ts # ranked passage search over files (file + line)
│ ├── docs.ts # crawl a docs site into pages (BFS, same-section)
│ ├── extract.ts # HTML -> Markdown / links (Readability + Turndown)
│ ├── fetcher.ts # bounded fetch with re-validated redirects (SSRF)
│ └── security.ts # SSRF guard (block private/internal addresses)
├── public/
│ ├── index.html # landing page (served for non-API paths)
│ ├── og.png / og.svg
│ ├── robots.txt
│ └── sitemap.xml
├── tests/ # vitest: github (tar parsing), pack, search, mcp, worker
├── docs/ # architecture, tools/API reference, deployment
├── wrangler.toml
├── package.json
└── tsconfig.json
```
## Develop & deploy
```sh
cd ctx
npm install
npm run typecheck
npm test # vitest — full suite
npm run dev # local worker at http://localhost:8787 (POST /mcp)
npm run deploy # wrangler deploy
```
## How it works
```
owner/repo → github.com tarball → DecompressionStream('gzip')
→ in-process tar parse → drop binaries/lockfiles/build dirs
→ pack (concat + token estimate) OR search (ranked passages)
```
The GitHub URL is always constructed from a fixed `owner/repo` slug, so the repo
tools have no SSRF surface. The docs tools fetch caller-supplied URLs, so every
URL and redirect hop is re-validated against the SSRF guard. Downloads are
bounded (timeout, size caps, page/file-count caps) and results are cached
per-isolate for a few minutes.
## Security & limits
- **No SSRF:** input is a repo slug, not an arbitrary URL; only github.com is fetched.
- **Bounded:** 20s download timeout, ~60 MB uncompressed cap, 512 KB/file, ≤3000 files, per-IP rate limit.
- **Stateless & private:** no code stored, no LLM in the loop; public repos by default (private with a token).
## Authentication (optional)
Set a `GITHUB_TOKEN` Worker secret to lift GitHub's rate limit (60 → 5,000/hour) and
read private repos:
```sh
wrangler secret put GITHUB_TOKEN
```
The token is a Worker secret only — never a tool argument — so it can't leak to an agent.
## Documentation
- [docs/architecture.md](docs/architecture.md) — modules, pipeline, tar parsing, limits
- [docs/tools.md](docs/tools.md) — full tool & JSON-RPC API reference
- [docs/deployment.md](docs/deployment.md) — Cloudflare Worker + custom-domain deploy
## License
[MIT](./LICENSE) © Vanshul Goyal