Reference
API Reference
The versioned /v1 HTTP API plus the Python, TypeScript and Rust SDKs for LeanCTX — served locally by lean-ctx serve and by the Team Server.
LeanCTX exposes a versioned /v1 HTTP API for programmatic access to tools, events, sessions and knowledge. The same contract is served two ways: locally by lean-ctx serve for your own agent loops, and by the multi-tenant Team Server for shared deployments.
Run the server
Start the local server, it serves REST + SSE + MCP on one port and prints a loopback bearer token:
$ lean-ctx serve # → http://127.0.0.1:8080 Authentication
All API requests require a bearer token in the Authorization header. Create tokens with the CLI:
$ lean-ctx team token create --config team.toml --id ci-bot --role member
→ Token: lctx_t_a3f8c2... Include the token in every request:
Authorization: Bearer lctx_t_a3f8c2... Token Scopes
| Scope | Access |
|---|---|
search | Read tools: ctx_read, ctx_search, ctx_tree, ctx_overview, etc. |
graph | Graph tools: ctx_graph, ctx_impact, ctx_callgraph, etc. |
artifacts | ctx_artifacts, ctx_semantic_search with artifacts |
index | Graph index builds, semantic reindex |
events | Subscribe to SSE event stream |
sessionMutations | ctx_session writes, ctx_handoff, ctx_workflow |
knowledge | ctx_knowledge writes, ctx_knowledge_relations |
audit | Metrics, full-payload events, audit log |
REST Endpoints
Tool Execution
Execute any MCP tool via REST:
POST /v1/tools/call
Request:
{
"name": "ctx_read",
"arguments": {
"path": "src/lib/auth.ts",
"mode": "map"
},
"workspaceId": "my-team",
"channelId": "feat/auth"
}
Response:
{
"content": [{
"type": "text",
"text": "exports: authenticate(), validateToken()\\ndeps: jsonwebtoken, bcrypt\\ncached — 180 tokens (was 4,200)"
}],
"isError": false,
"meta": {
"tokens_saved": 4020,
"cache_hit": false,
"duration_ms": 12
}
} Session Management
GET /v1/session?workspaceId=my-team&channel=feat/auth
POST /v1/session/mutate
GET /v1/session/list?workspaceId=my-team Event Stream (SSE)
Subscribe to real-time events via Server-Sent Events. Events include versioning, causal lineage, and consistency levels:
GET /v1/events?workspaceId=my-team&channelId=feat/auth&since=0
Response (SSE stream):
id: 42
event: tool_call_recorded
data: {"id":42,"workspaceId":"my-team","channelId":"feat/auth","kind":"tool_call_recorded","actor":"cursor","timestamp":"2026-05-05T13:00:00Z","version":42,"parentId":null,"consistencyLevel":"local","payload":{"tool":"ctx_read"}}
id: 43
event: session_mutated
data: {"id":43,"workspaceId":"my-team","channelId":"feat/auth","kind":"session_mutated","actor":"cursor","timestamp":"2026-05-05T13:00:01Z","version":43,"parentId":42,"consistencyLevel":"strong","payload":{"tool":"ctx_session","action":"save","reasoning":"Auth refactor checkpoint"}} Event Types
| Kind | Consistency | Trigger |
|---|---|---|
tool_call_recorded | local | Any tool invocation completes |
session_mutated | strong | Session state modified |
knowledge_remembered | eventual | Knowledge fact written |
artifact_stored | eventual | Artifact persisted |
graph_built | local | Graph index updated |
proof_added | strong | Evidence ledger appended |
Context Summary
GET /v1/context/summary?workspaceId=my-team # Materialized view: agents, decisions, conflicts Event Search & Lineage
GET /v1/events/search?q=auth+strategy&workspaceId=my-team # FTS5 full-text search
GET /v1/events/lineage?id=42&depth=10 # Causal chain traversal Health & Metrics
GET /health # Health check
GET /v1/metrics # JSON metrics snapshot (requires audit scope) Agent Registry
HTTP-backed agent registration and lifecycle management. These endpoints power the Remote Agent Bus.
POST /v1/agents/register
Request:
{
"agent_type": "claude",
"role": "review",
"project_root": "/home/user/my-project"
}
Response:
{
"agent_id": "d4e5f6",
"status": "active",
"registered_at": "2026-05-17T10:00:00Z"
} POST /v1/agents/heartbeat
Request:
{ "agent_id": "d4e5f6" }
Response:
{ "ok": true, "ttl_seconds": 60 } GET /v1/agents/list
Response:
{
"agents": [
{
"agent_id": "d4e5f6",
"agent_type": "claude",
"role": "review",
"status": "active",
"last_heartbeat": "2026-05-17T10:05:00Z"
}
]
} POST /v1/agents/deregister
Request:
{ "agent_id": "d4e5f6" }
Response:
{ "ok": true, "deregistered_at": "2026-05-17T10:10:00Z" } GET /v1/agents/events # SSE stream of agent registry changes
Response (SSE stream):
event: agent_joined
data: {"agent_id":"d4e5f6","agent_type":"claude","role":"review"}
event: agent_left
data: {"agent_id":"a1b2c3","reason":"heartbeat_timeout"} Audit & References
GET /v1/audit/events?limit=50 # Cross-project boundary events + audit trail
Response:
{
"events": [
{
"timestamp": "2026-05-17T10:00:00Z",
"kind": "cross_project_read",
"agent_id": "a1b2c3",
"source_project": "/home/user/api",
"target_path": "/home/user/shared/types.ts",
"action": "blocked"
}
],
"total": 142
} GET /v1/references/{id} # Resolve a reference result by ID
Response:
{
"id": "ref_a7f3c2",
"type": "file_content",
"path": "src/auth.ts",
"content": "export function authenticate() ...",
"created_at": "2026-05-17T09:30:00Z",
"expires_at": "2026-05-17T10:30:00Z"
} Discovery
Branch on facts, not guesses. Two endpoints describe the running server:
GET /v1/capabilities— runtime document: contract version, active persona, transports, presets, the live tool surface and every registered extension.GET /v1/openapi.json— a standard OpenAPI 3.0 schema you can generate a typed client from.
$ curl -s -H "Authorization: Bearer $TOKEN" http://127.0.0.1:8080/v1/capabilities A lightweight MCP Server Card is also published for client auto-configuration:
GET /.well-known/mcp-server.json # MCP Server Card
Response:
{
"name": "lean-ctx",
"version": "3.8.7",
"capabilities": ["tools", "resources", "prompts"],
"tool_categories": ["read", "search", "shell", "knowledge", "agent", "session"],
"security": {
"sandbox": true,
"secret_detection": true,
"shell_allowlist": true,
"signed_handoffs": true
},
"transport": ["stdio", "http"],
"a2a_compatible": true
} Rate Limiting
The Team Server applies per-token rate limits:
| Endpoint | Limit |
|---|---|
/v1/tools/call | 100 req/min per token |
/v1/events | 5 concurrent SSE connections |
/v1/knowledge/* | 60 req/min per token |
Rate limit headers are included in all responses: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset.
SDKs
Three first-party SDKs wrap the /v1 contract with the same surface in every language. They are thin wire clients that never link the engine, so they stay stable as LeanCTX evolves.
# Python
pip install leanctx
# TypeScript
npm install @leanctx/sdk
# Rust
cargo add lean-ctx-client TypeScript
import { LeanCtxClient } from "@leanctx/sdk";
const client = new LeanCtxClient({
baseUrl: "http://127.0.0.1:8080",
bearerToken: process.env.LEANCTX_TOKEN,
});
const caps = await client.capabilities(); // branch on real features
const text = await client.callToolText("ctx_read", { path: "src/lib/auth.ts", mode: "map" });
for await (const ev of client.subscribeEvents({ channelId: "feat/auth" })) {
console.log(ev.kind, ev.payload);
} Python
from leanctx import LeanCtxClient
client = LeanCtxClient("http://127.0.0.1:8080", bearer_token=TOKEN)
caps = client.capabilities()
text = client.call_tool_text("ctx_read", {"path": "src/lib/auth.ts", "mode": "map"})
# Framework adapters — present when the framework is installed
from leanctx.adapters import to_openai_tools, to_langchain_tools SDK Methods
| Method | Description |
|---|---|
capabilities() | Runtime capability document (GET /v1/capabilities) |
openapi() | OpenAPI 3.0 schema (GET /v1/openapi.json) |
listTools() / list_tools() | List the live tool surface |
callToolResult(name, args) | Execute a tool, return the raw result |
callToolText(name, args) | Execute a tool, return text content |
subscribeEvents(opts) | SSE event stream (async iterator) |
health() / manifest() | Liveness check and the full tool manifest |
HTTP MCP Contract
LeanCTX also exposes a small, stable HTTP surface for direct system-to-system access to the tool registry, mirroring MCP semantics over plain HTTP.
Loopback vs Non-Loopback
- Loopback bind (
127.0.0.1/localhost/::1): auth token is optional. - Non-loopback bind (e.g.
0.0.0.0): requires--auth-token. - Host header is checked unless disabled. Use
--allowed-hostto add hostnames.
Error Codes
| Status | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing/invalid Bearer token |
400 | host_denied | Host header not allowed |
429 | rate_limited | RPS guard triggered |
429 | concurrency_limited | In-flight guard triggered |
400 | tool_error | Tool execution rejected/failed |
504 | request_timeout | Tool call exceeded timeout |
Direct curl Examples
# Start server on loopback (no auth required)
lean-ctx serve --host 127.0.0.1 --port 8080
# Health check
curl http://127.0.0.1:8080/health
# Manifest + tool list
curl http://127.0.0.1:8080/v1/manifest
curl "http://127.0.0.1:8080/v1/tools?offset=0&limit=50"
# Call a tool
curl -X POST \
-H "Content-Type: application/json" \
-d '{"name":"ctx_tree","arguments":{"path":".","depth":2}}' \
http://127.0.0.1:8080/v1/tools/call Stability & Versioning Policy
The /v1 surface is governed by a published, CI-enforced stability policy:
all 29 protocol contracts are classified frozen / stable /
experimental. Frozen contracts (HTTP MCP, team server, Context IR, …) are
SHA-256-locked in CI, a change to a frozen surface fails the build; evolution happens in a
new v2 document next to the immutable v1. The public OpenAPI surface
may only grow: removals and auth changes are rejected by a snapshot test.
- CONTRACTS.md — stability matrix, SemVer mapping, deprecation policy (≥ 2 minor releases notice,
lean-ctx doctorwarning, documented replacement) - SDK conformance matrix — Python/TypeScript/Rust SDKs, 14 lockstep checks against a real engine build per commit
- Migration guide 0.x → 1.0 — zero breaking changes, verified locally via
lean-ctx doctor --migrate-check
At runtime, clients can verify compatibility without docs: GET /v1/capabilities
returns both contract_versions and a contract_status map
(frozen/stable/experimental per contract).