Skip to Content
Quick Start

Quick Start

This guide runs the released gateway and agent against a disposable PostgreSQL database, then calls a capability through REST and MCP. You need no source checkout or Go toolchain. Docker is used only for the example database.

1. Download

Download the binary archive for your host and the Quick Start files from the latest release:

HostDownload
Linux x64⬇ Binary archive 
Linux ARM64⬇ Binary archive 
macOS Intel⬇ Binary archive 
macOS Apple silicon⬇ Binary archive 
Windows x64⬇ Binary archive 
All hosts⬇ Quick Start files 

Extract both into a working directory. Replace linux-amd64 with your host:

mkdir -p onprest/examples cd onprest tar -xzf ../onprest-linux-amd64.tar.gz --strip-components=1 tar -xzf ../onprest-quickstart.tar.gz --strip-components=1 -C examples

On Windows PowerShell:

mkdir onprest\examples cd onprest tar -xf ..\onprest-windows-amd64.zip --strip-components=1 tar -xzf ..\onprest-quickstart.tar.gz --strip-components=1 -C examples

Run every remaining command from this directory. It now holds onprest-gateway, onprest-agent, and the example files under examples/, including a matching agent key pair and API key. These credentials are public: use them only on your own machine.

2. Start the example database

docker compose -f examples/postgres.compose.yml up -d --wait

This starts PostgreSQL on 127.0.0.1:5432 with a legacy database, a customers table, and a capability_user role that can only SELECT from customers and update its name column. If port 5432 is taken, change it in both examples/postgres.compose.yml and examples/capability.postgres.yaml.

Without Docker, create an empty disposable legacy database on an existing PostgreSQL server, run examples/postgres-init.sql against it as an administrator, and adjust sources.databases.primary in examples/capability.postgres.yaml.

3. Validate the agent configuration

./onprest-agent validate --config ./examples/capability.postgres.yaml

validate checks the YAML, connects to the database, and runs EXPLAIN for each capability’s SQL. It does not execute anything or contact the gateway. If it fails, see Troubleshooting.

4. Start the gateway and the agent

Start the gateway:

set -a . ./examples/gateway.env set +a ./onprest-gateway

In a second terminal, start the agent:

./onprest-agent --config ./examples/capability.postgres.yaml

The agent creates private identity and spool directories next to its configuration, so it needs write permission there.

On Windows, the gateway reads its settings from environment variables. Load them and start it, then start the agent in another PowerShell window:

Get-Content .\examples\gateway.env | Where-Object { $_ -match '^GATEWAY_[A-Z_]+=' } | ForEach-Object { $name, $value = $_ -split '=', 2 Set-Item "env:$name" $value.Trim("'") } .\onprest-gateway.exe
.\onprest-agent.exe --config .\examples\capability.postgres.yaml

Use Invoke-RestMethod or another HTTP client for the requests below.

5. Check the connection

curl -s http://localhost:8080/healthz
{ "ok": true, "agent_connected": true }

If agent_connected is false, wait a moment for the agent to finish connecting and try again. If it stays false, read the agent’s terminal output and see Troubleshooting.

6. Call a capability

Set the example API key in the terminal you will call from:

export ONPREST_API_KEY='orjrqqPeX8FXhsECOnrnOr6oa70pOYjyeUWmxTbaZrM'
curl -s \ -X POST http://localhost:8080/api/v1/capabilities/get_customer \ -H "Authorization: Bearer ${ONPREST_API_KEY}" \ -H "Content-Type: application/json" \ -d '{"customer_id":1}'
{ "request_id": "01J5ABCDEF1234567890ABCDEF01", "result": { "data": { "rows": [{ "id": 1, "name": "Ada Lovelace", "email": "ada@example.com" }], "count": 1 }, "files": [] } }

The request body is the capability’s input object itself, not wrapped in {"params": ...}.

On Windows PowerShell:

$env:ONPREST_API_KEY = 'orjrqqPeX8FXhsECOnrnOr6oa70pOYjyeUWmxTbaZrM' Invoke-RestMethod -Method Post -Uri http://localhost:8080/api/v1/capabilities/get_customer ` -Headers @{ Authorization = "Bearer $env:ONPREST_API_KEY" } ` -ContentType 'application/json' -Body '{"customer_id":1}' | ConvertTo-Json -Depth 10

7. Change data and read it back

update_customer is a mutation. Call it through REST:

curl -s \ -X POST http://localhost:8080/api/v1/capabilities/update_customer \ -H "Authorization: Bearer ${ONPREST_API_KEY}" \ -H "Content-Type: application/json" \ -d '{"customer_id":1,"name":"Ada REST"}'
{ "request_id": "01J5ABCDEF1234567890ABCDEF02", "result": { "data": { "count": 1 }, "files": [] } }

Then call the same capability as an MCP tool:

curl -s \ -X POST http://localhost:8080/mcp \ -H "Authorization: Bearer ${ONPREST_API_KEY}" \ -H "Content-Type: application/json" \ -H "MCP-Protocol-Version: 2025-11-25" \ -H "Accept: application/json, text/event-stream" \ -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"update_customer","arguments":{"customer_id":1,"name":"Ada MCP"}}}'

The tool result carries the same envelope in structuredContent. Call get_customer again and the name is now Ada MCP. You can also check the database directly:

docker compose -f examples/postgres.compose.yml exec -T postgres \ psql -U onprest_admin -d legacy -Atc "SELECT name FROM customers WHERE id = 1"

8. Look at the published contract

curl -s -H "Authorization: Bearer ${ONPREST_API_KEY}" http://localhost:8080/openapi.json

The OpenAPI document and the MCP tools/list result are generated from the agent’s capability definitions and filtered to what the API key may call. They contain input and output schemas, not SQL or connection details.

9. Clean up

Stop both binaries with Ctrl+C, then remove the example database:

docker compose -f examples/postgres.compose.yml down -v

What you just ran

examples/capability.postgres.yaml defines the database source primary and two capabilities that use it:

capabilities: get_customer: description: Fetch one customer by ID. executor: type: db source: primary sql: select id, name, email from customers where id = :customer_id input: properties: customer_id: {type: integer, minimum: 1} required: [customer_id] policy: {max_rows: 1} output: data: {} items: properties: id: {type: integer} name: {type: string} email: {type: string} update_customer: description: Update one customer's name. executor: type: db source: primary sql: update customers set name = :name where id = :customer_id input: properties: customer_id: {type: integer, minimum: 1} name: {type: string, minLength: 1, maxLength: 200} required: [customer_id, name] policy: {readonly: false, max_affected_rows: 1} output: {data: {}}

readonly: false is what lets update_customer run an UPDATE; Policy and Limits covers the other settings. The example API key in examples/gateway.env may call only these two capabilities. Capabilities explains each section, and Databases covers the DB executor.

Try without a database

The same two binaries run every other executor. Each example has its own configuration and a README with the commands:

ExecutorExampleWhat it shows
CSVexamples/csv Filter a CSV in a folder or an uploaded CSV, and download the selected rows as a new CSV
Fileexamples/file-output Download a completed report from a folder
Fileexamples/file-input Upload a PDF and save it into a folder
HTTPexamples/http Call an internal API with validated arguments and publish part of its response
Codeexamples/sdk Build a Go module with the SDK, test it locally, and call it through the gateway

Next steps

For a real deployment, generate your own agent key pair and API keys with onprest-gateway create-agent-secret and onprest-gateway create-key, and start from the templates and INSTALL.md in the binary archive. A gateway reachable from other hosts must use wss:// for the agent connection. See Deployment.