RepoMicrosoftMicrosoftpublished Mar 9, 2026seen 5d

microsoft/tscodesearch

Python

Open original ↗

Captured source

source ↗
published Mar 9, 2026seen 5dcaptured 5dhttp 200method plain

microsoft/tscodesearch

Description: Code search MCP wrapper for Typesense

Language: Python

License: MIT

Stars: 5

Forks: 2

Open issues: 11

Created: 2026-03-09T11:09:10Z

Pushed: 2026-06-20T16:06:44Z

Default branch: main

Fork: no

Archived: no

README:

codesearch

Full-text and structural code search for a large monorepo. Runs an in-process Tantivy index (via tantivy-py) and exposes results as MCP tools so Claude can query the codebase directly without copy-pasting.

> Early alpha. Expect rough edges.

Installation

git clone https://github.com/microsoft/tscodesearch
cd tscodesearch
setup.cmd
ts start

setup.cmd creates a Python venv (via uv), registers the MCP server with Claude Code and VS Code (GitHub Copilot), prompts for a source directory to index, creates config.json, and installs the VS Code extension.

To uninstall: setup.cmd --uninstall

Prerequisites

  • Windows 11 (or Linux/macOS for the daemon, with caveats)
  • Python 3.10+
  • Node.js 20+
  • uv is installed automatically by setup.mjs if missing

There is no Docker, WSL, or Typesense dependency. The whole index is in-process.

One-time setup

From a Windows command prompt or PowerShell:

setup.cmd

setup.cmd checks for Node.js then calls node setup.mjs, which: 1. Registers the MCP server with Claude Code and VS Code (GitHub Copilot mcp.servers) 2. Creates .client-venv and installs Python dependencies 3. Creates config.json -- prompts for a source directory to index (can be added later) 4. Installs the VS Code extension

After setup, start the daemon:

ts start

To uninstall: setup.cmd --uninstall

Adding roots

ts root --add NAME C:\path\to\source
ts restart

Or use the VS Code extension command TsCodeSearch: Add Root.

Each root gets its own on-disk Tantivy index at /.tantivy/codesearch_NAME/. Multi-root config in config.json:

{
"api_key": "...",
"port": 8108,
"roots": {
"default": { "path": "C:/myproject/src" },
"other": { "path": "D:/other/src" }
}
}

Each root entry can be either an object ({"path": "...", "extensions": [".cs", ".py"]}) or a bare string ("C:/myproject/src"). The object form is what setup.mjs writes and what ts root --add produces; the string form is accepted for backwards compatibility.

Use the MCP root= parameter to search a specific collection:

query_codebase("implements", "IRepository", root="other")
query_single_file("methods", file="path/to/Widget.cs", root="other")

Daemon management

All daemon commands go through ts.cmd (Windows CMD/PowerShell):

ts status show daemon health, doc count, watcher state
ts start start the daemon (auto-indexes on first run)
ts stop stop the daemon
ts restart stop then start
ts verify scan FS + repair index: add missing, re-index stale, remove orphans
ts verify --root verify a specific named root
ts verify --no-delete-orphans repair without removing deleted-file entries
ts recreate stop daemon, wipe the on-disk index, restart (full reindex)
ts recreate --root recreate a specific named root's index
ts log [-n N] tail the daemon log (default: last 40 lines)

Keeping the index up to date

The watcher picks up changes automatically within a couple of seconds (~1 s ReadDirectoryChangesW latency + 2 s debounce). For large repos, or after bulk operations like a git pull or branch switch, use the MCP tools or ts verify to confirm everything is in sync.

From Claude (MCP tools)

ready() # check index readiness (calls /check-ready)
verify_index(action="start") # launch background sync/repair scan
verify_index(action="status") # monitor sync progress (reads from GET /status)
verify_index(action="stop") # cancel a running scan
wait_for_sync(timeout_s=30) # poll until queue drained; pass 0 for instant status

ready() returns a summary with poll_ok (FS walk completed), index_ok (zero missing/stale/orphaned), and timing. If not ready, verify_index(action="start") triggers the syncer to repair the index without resetting it.

wait_for_sync sleeps up to 1 s (watcher warm-up) then polls /status every 0.5 s until the queue is empty. Reports "Index synced in {N}s" with a "was: queue={N}" note if work was observed, or a timeout message with recovery hints.

From the command line

ts verify # foreground repair scan (missing + stale + orphans)
ts verify --no-delete-orphans # repair without removing deleted-file entries
ts verify --root other # verify a specific named root

Running tests

.client-venv\Scripts\python.exe -m pytest tests/ query/tests/ -v # full Python suite
node run_tests.mjs # VS Code extension tests

The integration tests open a fresh Tantivy index in /.tantivy/test_* for each class and clean up afterwards. No external service needs to be running.

| File / dir | What it tests | |------------|---------------| | query/tests/ | All language AST query modes against synthetic fixtures | | tests/unit/ | Indexer, queue, watcher, verifier, MCP server helpers -- all use _FakeBackend | | tests/integration/ | Indexer, verifier, watcher, search modes, sample E2E -- open real Tantivy indexes |

Direct CLI usage

Management API via curl

# Read key/port from config.json -- never hard-code
API_KEY=$(node -e "const c=require('./config.json'); process.stdout.write(c.api_key)")
API_PORT=$(node -e "const c=require('./config.json'); process.stdout.write(String(c.port??8108))")
curl -s -X POST http://localhost:$API_PORT/query-codebase \
-H "Content-Type: application/json" -H "X-API-KEY: $API_KEY" \
-d '{"mode":"declarations","pattern":"SaveChanges","root":""}' | python -m json.tool

The daemon authenticates every request by matching the X-API-KEY header against config.json's api_key. The HTTP server binds localhost only, but the key still matters: any process on the same machine -- a browser background page, another dev tool, a malicious dependency -- can reach localhost:PORT. Requiring a shared secret means a random local process can't query or mutate the index without first reading config.json.

Standalone search CLI (scripts/search.py)

.client-venv\Scripts\python.exe scripts\search.py "BlobStore" --ext cs --limit 5
.client-venv\Scripts\python.exe scripts\search.py "IRepository" --implements

This opens the on-disk...

Excerpt shown — open the source for the full document.

Notability

notability 3.0/10

Routine code search repo, low stars.