Skip to main content

HTTP API

Alongside the MCP tools, the server exposes two HTTP endpoints for triggering indexing from CI/CD or external schedulers. They are served on the same port as MCP (8090 by default).


Endpoints​

EndpointBodyDescription
POST /reindex{"service": "<name>"?, "force": <bool>?, "source": "github"|"gitlab"?, "repo": "<owner/repo>"?, "ref": "<ref>"?, "root": "<path>"?, "exclude": [<glob>, ...]?}Reindex one or all services — returns NDJSON
POST /reindex-history{"service": "<name>"?, "force": <bool>?}Index git commit history — returns NDJSON

All bodies are optional — omit service to act on all services, omit force for incremental indexing. Both endpoints stream newline-delimited JSON (one frame per line) so you can consume progress in real time from CI/CD pipelines or any other client.

# Incremental reindex of every service
curl -N -X POST http://localhost:8090/reindex -H 'Content-Type: application/json'

# Re-embed one service from scratch
curl -N -X POST http://localhost:8090/reindex -H 'Content-Type: application/json' \
-d '{"service": "catalog-service", "force": true}'

The Makefile wraps the no-body forms as make index-code and make index-history.


Registering a repo without config.yaml​

If the POST /reindex body includes repo (or its alias github_repo), the service name is registered with that repo definition before indexing runs — service is required in this case. The registration is persisted, so it survives restarts and behaves like a config.yaml service from then on. ref (alias github_ref) defaults to main and source defaults to github; root and exclude mirror the same fields in config.yaml. A service name already defined in config.yaml always wins over one registered this way.

curl -N -X POST http://localhost:8090/reindex -H 'Content-Type: application/json' \
-d '{"service": "catalog-service", "repo": "my-org/my-repo"}'

See Dynamic Service Registration for how registrations are stored and resolved, and the GitHub Actions example for a drop-in workflow that self-registers a repo and reindexes it on every merge.

No authentication

Neither endpoint is authenticated. An unauthenticated caller can make the server index — and permanently register — any repo GITHUB_TOKEN can read. Put the HTTP API behind your own network boundary or reverse-proxy auth before exposing it.


Frame shapes​

// in-flight progress
{"type": "progress", "phase": "discovery|upserting|cleanup", "current": 12, "total": 200, "percentage": 6.0, "service": "my-service"}
// final summary (one per request)
{"type": "done", "result": {"files": 42, "chunks": 318, "skipped": 5}}
// emitted instead of "done" on failure
{"type": "error", "message": "..."}

For /reindex the upserting frames carry current as a monotonically increasing count of files resolved — indexed, skipped as unchanged, or dropped by a fetch/parse failure — so it always ends at total. Files are indexed concurrently, so frames are emitted per batch rather than per file.

For /reindex-history the phase value is discovery|embedding|upserting and the done result is {"new": int, "skipped": int, "diff_updated": int}.