Run it locally¶
How to install CORA, bring up its database, and start the dev server.
Sliced from the repo README at build time, so these commands stay the ones a cloner actually runs. For bringing CORA up at a facility rather than on a laptop, see Deployment.
Quick start¶
Requires: Python 3.13.12 (managed via uv), Docker (for Postgres), Atlas (for schema migrations). Node 24 LTS comes later for the frontend.
# Install uv and Atlas (one-time per machine)
curl -LsSf https://astral.sh/uv/install.sh | sh
curl -sSf https://atlasgo.sh | sh
# Install Python deps (runs `uv sync --all-extras` inside apps/api)
make install
# Install pre-commit hooks (one-time per clone)
make precommit
# Start Postgres + pgvector
make db-up
# Apply schema migrations
make migrate-apply
# Run the full test suite
make test
# Start the dev server
make dev
# API at http://localhost:8000
# Health check at http://localhost:8000/health
# REST API: POST /actors (see /docs for OpenAPI)
# MCP server mounted at /mcp (streamable HTTP transport)
Run make help for the full list of dev commands.
See docs/reference/ for commit message conventions and BC layout. See CONTRIBUTING.md for what kinds of collaboration are wanted.
API surfaces¶
CORA exposes every command on two equivalent surfaces backed by the same handler:
REST. OpenAPI docs at http://localhost:8000/docs (Swagger UI) and /redoc. Example:
curl -X POST http://localhost:8000/actors \
-H 'Content-Type: application/json' \
-d '{"name": "Doga"}'
# -> 201 {"actor_id": "01900000-..."}
MCP (Model Context Protocol, the agent surface). Streamable HTTP transport mounted at /mcp. Point an MCP-aware client (Claude Code, etc.) at http://localhost:8000/mcp and tools across every scaffolded BC (access, agent, calibration, campaign, caution, data, decision, enclosure, equipment, federation, operation, recipe, run, safety, subject, supply, trust) appear in the client.
Wire-level: JSON-RPC over POSTs, handshake is initialize (protocol version 2025-11-25) → notifications/initialized → tools/*, with mcp-session-id propagated from the initialize response headers. Example listing tools by hand:
# Initialize, capture session id from response headers
SID=$(curl -si -X POST http://localhost:8000/mcp \
-H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"cli","version":"0.1"}}}' \
| awk -F': ' '/^mcp-session-id/ {print $2}' | tr -d '\r')
# Acknowledge, then list tools
curl -s -X POST http://localhost:8000/mcp -H "mcp-session-id: $SID" \
-H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","method":"notifications/initialized","params":{}}'
curl -s -X POST http://localhost:8000/mcp -H "mcp-session-id: $SID" \
-H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}'
For the full handshake-and-call sequence used by tests, see apps/api/tests/contract/_mcp_helpers.py.