Oracle Discovery API
Point Claude — or any function-calling LLM — at a running Oracle and let it use C3's cross-project code & memory intelligence as tools. Discover projects, search code and memory across all of them, traverse the memory graph, and surface insights, without ever opening the chat UI.
Overview
The Oracle normally runs the LLM relationship inwards: its own model (Ollama) calls C3 tools to analyze your projects. The Discovery API flips that — it exposes those same capabilities outwards, so an external LLM can use the Oracle as a discovery tool over your whole C3 estate.
Two transports, one tool core. The exact same tool registry is served over both MCP (streamable HTTP/SSE — native for Claude Code / Claude Desktop) and an OpenAPI REST surface (for any function-calling LLM). They run on separate loopback ports because Flask is WSGI and the MCP transport is ASGI, but they dispatch through one definition of each tool — so the two surfaces can never drift apart.
What you get
| Surface | Where | Use it for |
|---|---|---|
| MCP server | http://127.0.0.1:3332/mcp |
Native tool discovery for Claude Code / Desktop and any MCP client |
| REST + OpenAPI | http://127.0.0.1:3331/api/discovery |
Function-calling for any LLM (GPT, Gemini, custom agents) |
c3 oracle api CLI |
Terminal | Get the token + a ready-to-paste .mcp.json snippet; rotate / clear the key |
Safe by construction. Only read and safe-action tools are exposed — there are no code-editing tools on this surface. Both servers bind 127.0.0.1 (loopback) by default and require a Bearer token.
Quick start
Start the Oracle, grab your token, and connect a client.
Start the Oracle
python oracle/oracle_server.py \
--no-browser
Prints the REST + MCP URLs and ensures an API key exists. The MCP server starts in a background thread.
Get the token
c3 oracle api info
Prints the Bearer token, both URLs, and a ready-to-paste Claude .mcp.json entry. Use c3 oracle api key for just the token. You can also generate, rotate, and copy the token visually in the Oracle dashboard under Settings → Discovery API.
Connect
# Claude → paste the snippet
# Any LLM → fetch openapi.json
See the two sections below for the MCP config and the OpenAPI flow.
Connect Claude (MCP)
Add the entry from c3 oracle api info to your .mcp.json (project root) or Claude Desktop config:
{
"mcpServers": {
"c3-oracle": {
"type": "http",
"url": "http://127.0.0.1:3332/mcp",
"headers": { "Authorization": "Bearer <token>" }
}
}
}
Claude lists the c3-oracle tools (list_projects, c3_search_cross, query_memory, read_graph, …). Ask it to "discover what C3 projects exist and search them for X".
Connect any LLM (OpenAPI REST)
Every tool is also a plain REST operation. Point a function-calling LLM at the spec, then call tools with the Bearer header.
# Discover the tools (OpenAPI 3.1)
curl -H "Authorization: Bearer <token>" \
http://127.0.0.1:3331/api/discovery/openapi.json
# Invoke a tool by name
curl -X POST \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"tool":"list_projects","args":{}}' \
http://127.0.0.1:3331/api/discovery/call
# Or use the per-tool path (body = the tool's args)
curl -X POST \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"query":"rate limiter","top_k":5}' \
http://127.0.0.1:3331/api/discovery/tools/c3_search_cross
REST endpoints
All under /api/discovery; every request requires Authorization: Bearer <token>.
| Endpoint | Description |
|---|---|
GET /tools | Available tools, each with a JSON Schema and capability tier |
POST /call | Invoke any tool: body {"tool": name, "args": {…}} |
POST /tools/<name> | Invoke a named tool with the request body as its arguments object |
POST /call/stream | Same as /call but streams start → result|error → [DONE] as SSE |
GET /openapi.json | OpenAPI 3.1 document — one operation per tool |
GET /mcp-info | MCP URL + auth scheme for the streamable-HTTP transport |
Tools & capability tiers
The exposed set is capped by api_max_tier in ~/.c3/oracle/config.json (read or action). Code-editing tools are never registered.
Read tier — discovery
| Tool | Does |
|---|---|
list_projects | All registered C3 projects with paths + fact counts |
search_facts | Search memory facts across ALL projects |
query_memory | Search/list facts within one project |
project_health | Memory health check for a project |
analyze_project | LLM-powered analysis of a project's memory themes |
cross_insights | Cross-project insights |
read_graph | Memory-graph statistics for a project |
c3_search / c3_search_cross | Code-intelligence search (one project / all projects) |
c3_read | Read exact file content (symbols / line ranges) |
c3_compress | Token-efficient structural file map |
c3_validate | Syntax/type validation on a file |
c3_status | Project health / budget / sessions overview |
c3_memory_query | Read-only memory query (recall/list/score/graph/trends) |
c3_edits / c3_edits_cross | Query the edit ledger (one / all projects) |
activity_report | Cross-project daily digest: sessions, tool calls, edits, git mutations, token/cost (optional LLM narration) |
Action tier — safe writes (no code edits)
| Tool | Does |
|---|---|
suggest_action | Create a pending memory suggestion a human approves (not a direct write) |
delegate_task | Run a configured Oracle agent and return its result |
Authentication & security
A single Bearer token guards both transports. The REST surface checks it in a Flask before_request hook; the MCP transport checks it in a pure-ASGI middleware (so streaming responses pass through intact).
Where the token lives
| OS keyring | Token text, under service c3-oracle-api. Backed by Windows Credential Manager, macOS Keychain, or Linux Secret Service. |
C3_ORACLE_API_KEY |
Environment override for headless / CI / containers where no keyring backend exists. When set, it wins and is never persisted to the keyring. |
Exposing on a network. The default bind is 127.0.0.1. To let a remote LLM service reach the Oracle, set bind_host to 0.0.0.0 in ~/.c3/oracle/config.json — and put it behind TLS + a firewall yourself. The token alone is not a substitute for transport security.
Rotate or revoke at any time with c3 oracle api rotate / c3 oracle api clear.
CLI commands
| Command | Description |
|---|---|
c3 oracle api info | Print REST + MCP URLs, the token, and a ready-to-paste .mcp.json snippet |
c3 oracle api key | Print just the token (generating one if needed) |
c3 oracle api rotate | Replace the token with a fresh one |
c3 oracle api clear | Delete the stored token from the keyring |
~/.c3/oracle/config.json keys
bind_host | Interface to bind. Default 127.0.0.1. Use 0.0.0.0 to expose on a network (add TLS/firewall). |
allowed_hosts | Extra hostnames/IPs the Host + Origin guard accepts. Needed when bind_host is non-loopback so legitimate browsers/clients aren't blocked (v2.33.0). |
api_enabled | Serve the /api/discovery/* REST surface. Default true. |
api_require_auth | Require the Bearer token. Default true. |
api_max_tier | Cap exposed tools: read (discovery only) or action (adds suggest_action, delegate_task). Default action. |
mcp_enabled | Start the MCP HTTP/SSE server. Default true. |
mcp_port | MCP transport port. Default 3332. |
Troubleshooting
| Symptom | Cause & fix |
|---|---|
401 unauthorized |
Missing or wrong token. Get the current one with c3 oracle api key and send it as Authorization: Bearer <token>. |
| Claude doesn't list the tools | Confirm the Oracle is running and mcp_enabled is true; check the URL is http://127.0.0.1:3332/mcp and the Authorization header is present in .mcp.json. |
| Tool not found in the catalog | It may be above your api_max_tier (e.g. suggest_action needs action), or it is a code-editing tool — those are never exposed. |
| Need a token without a keyring | Set C3_ORACLE_API_KEY in the environment (CI / containers). It overrides the keyring and is not persisted. |
The 'keyring' package is required |
pip install keyring — a C3 dependency that may be missing if you upgraded without re-installing. |
Full endpoint and schema details live in oracle-guide/api-reference.md and oracle-guide/discovery-api.md.