A four-layer semantic index over a source repository, exposed as a FastAPI backend, a Next.js visualization frontend, and an MCP stdio server. Cartographer replaces blind grep-and-read exploration by AI coding agents with structured, conventionally-grounded context bundles: symbols and references, data flows, architectural roles, and implicit invariants.
See SPEC.md for the full design and STRUCTURE.md for a directory map.
backend/— FastAPI service, indexer, agents, MCP server (Python 3.12)frontend/— Next.js UI with Cytoscape graph views and SSE live updatesscripts/— local mongod lifecycle wrapper, MCP launcher, helperstests/— pytest suite (hermetic by default; live-Mongo opt-in).env/.env.local— environment configuration (gitignored)
- Backend: FastAPI, uvicorn, pymongo, tree-sitter, sentence-transformers
(
all-MiniLM-L6-v2, 384-dim), Gemini viagoogle-genai - Storage: MongoDB 7 (local tarball or Atlas) — symbols, refs, flows,
clusters, invariants, embeddings as
BinData.$textindex over qualified names and signatures; cosine similarity computed in-process. - Frontend: Next.js, Cytoscape.js + cytoscape-dagre, SSE event stream
- Auth: JWT in
agentverse_sessioncookie;CARTOGRAPHER_DEV=1accepts the dev secret for local work
Copy .env.example to .env and fill in:
MONGODB_URI(defaultmongodb://localhost:27017)MONGODB_DB_NAME(defaultcartographer)JWT_SECRET(dev-secret-tokenis accepted whenCARTOGRAPHER_DEV=1)GEMINI_API_KEYfor LLM annotation (Layer 3/4)
.env.local overrides .env; OS environment overrides both.
bash scripts/mongo_local.sh start # starts the portable mongod
bash scripts/mongo_local.sh status # check listener
bash scripts/mongo_local.sh stopThe script manages a MongoDB Community 7 tarball under
~/.cartographer/mongo/. Atlas works too — just point MONGODB_URI at the
SRV connection string.
python3 -m venv backend/.venv
source backend/.venv/bin/activate
pip install -r backend/requirements.txt
npm installnpm run backend # FastAPI on :4000
npm run dev # Next.js on :3000Visit http://localhost:3000, log in with the dev credentials, register a
repository path, and watch the four layers populate over SSE.
POST /api/auth/login,POST /api/auth/logoutGET /api/repos,POST /api/repos,GET /api/repos/{hash}POST /api/repos/{hash}/index— kick off indexingGET /api/repos/{hash}/graph— graph snapshot for the FlowViewPOST /api/query/find_relevant_contextPOST /api/query/trace_data_flowPOST /api/query/find_invariantsPOST /api/query/describe_architecturePOST /api/query/find_exemplarsGET /api/stream/{hash}— SSE channel for index + agent eventsGET /health— liveness + Mongo reachability probe
pytest tests/ -q # hermetic suite
MONGODB_URI=mongodb://localhost:27017 \
pytest tests/test_store_live.py -v # live round-tripThe hermetic suite uses the sentinel URI mongodb://localhost:0 and a
MagicMock store; test_store_live.py is module-skipped unless a real URI
is provided. The test DB defaults to cartographer_test so a stray run
never clobbers the developer's main database.
The backend ships an MCP stdio server (backend/mcp/server.py) exposing
six tools: index_directory, find_relevant_context, trace_data_flow,
find_invariants, describe_architecture, find_exemplars. Typical flow:
index_directory(path) → query tools against the returned repo_hash.
scripts/mcp_launcher.sh resolves the repo root, pins the Python
interpreter, and clears MCP_SHARED_SECRET so dev clients aren't rejected.
Use it as the command for any MCP host.
claude mcp add cartographer --scope user -- \
/Users/benjaminhuang/gitssh/LAHacks2026/scripts/mcp_launcher.shVerify with /mcp inside a new claude session — six tools should be listed.
Edit ~/Library/Application Support/Claude/claude_desktop_config.json:
{
"mcpServers": {
"cartographer": {
"command": "/Users/benjaminhuang/gitssh/LAHacks2026/scripts/mcp_launcher.sh"
}
}
}Quit and relaunch Claude Desktop. The hammer/tools menu shows the six tools.
Same command path; no args or env required. Restart the host after adding.
In a fresh session:
Use cartographer to index
/Users/benjaminhuang/gitssh/cart-testapp, then callfind_relevant_contextfor "how does login work" and summarize the top symbols.
The repo also appears at http://localhost:3000/dashboard after indexing
because the MCP tool writes to the same Mongo the website reads from.
mongodrunning locally (bash scripts/mongo_local.sh start) or an Atlas URI.envpopulated (MONGODB_URI,GEMINI_API_KEY, etc.)- Python deps installed in the interpreter the launcher uses
(defaults to
/opt/anaconda3/bin/python— override withCARTOGRAPHER_PYTHON=/path/to/python)
The launcher blanks MCP_SHARED_SECRET so dev clients work. To require a
shared secret in production, export a non-empty value in the host's env
before launching the MCP server; tool calls will then need to pass
__secret__: "<value>" in their arguments.