BYOA MCP Facade
Dispatch autonomous Rensei agents from any MCP-capable host via the /api/cli/mcp JSON-RPC facade - list workflows, dispatch, poll receipts, and verify audit signatures.
The Rensei BYOA (Bring-Your-Own-Agent) MCP facade (/api/cli/mcp) is a Model Context Protocol server that lets any MCP-capable host - Hermes, Claude Desktop, an IDE plugin, or CI - dispatch autonomous Rensei agents, poll for audit receipts, and enumerate available workflows. It is a stateless JSON-RPC 2.0 endpoint: every request carries a bearer rsk_* key, and the server enforces your org's full Cedar policy on each call. Tokens never leave your environment.
This is the org-wide dispatch facade. For the per-session MCP endpoint used by a running agent (memory, knowledge graph, A2A tools) see MCP Session Tools. For the formal request/response contract see the API reference.
Prerequisites
- A project with BYOA workflows provisioned. You need at least one published BYOA workflow in your org. Confirm with the
list_workflowstool (see Connectivity check) - there is no CLI subcommand that lists workflows. - An
rsk_*API key withdispatch:invokescope. Create one in the Dashboard (Settings > API Keys) or with the CLI:rensei org api-keys create --name byoa --scope dispatch:invoke. The--scopeflag is repeatable. See API Key Authentication for the full flow and scoping rules. - An MCP host that supports Streamable HTTP transport with bearer auth headers.
Never commit an rsk_* token to source control. Inject it from your secret manager or an environment variable at runtime.
Wiring your host
Any MCP host that speaks Streamable HTTP with bearer auth can use this facade. Point it at https://app.rensei.ai/api/cli/mcp with an Authorization: Bearer <rsk_*> header. For a worked, host-specific example, see Hermes Integration.
Connectivity check
Verify the connection with two raw JSON-RPC calls before committing to a workflow. Shell expands $RENSEI_API_KEY in these examples; export it first.
1. Handshake
curl -s -X POST https://app.rensei.ai/api/cli/mcp \
-H "Authorization: Bearer $RENSEI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"clientInfo": { "name": "my-host", "version": "1.0.0" }
}
}'Expected response (the server always reports its own protocolVersion):
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2024-11-05",
"capabilities": { "tools": {} },
"serverInfo": { "name": "rensei-byoa-mcp", "version": "0.1.0" }
}
}If you get 401 Unauthorized, the key is missing, invalid, or expired. If you get 403 Forbidden, the key is valid but lacks the dispatch:invoke scope - re-create it with that scope.
2. List available workflows
curl -s -X POST https://app.rensei.ai/api/cli/mcp \
-H "Authorization: Bearer $RENSEI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "list_workflows",
"arguments": {}
}
}'Every tool result is JSON-stringified into result.content[0].text, so parse that string:
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [{
"type": "text",
"text": "{\"workflows\":[{\"id\":\"wf_abc\",\"projectId\":\"prj_123\",\"templateSlug\":\"byoa-research-request\",\"status\":\"published\",\"workType\":\"research\"}]}"
}]
}
}Each workflow row carries id, projectId, templateSlug, status, and workType (the field is templateSlug, not slug). An empty workflows array means your org has no published BYOA templates yet.
Dispatching an agent
Use the dispatch tool to enqueue a run. The arguments are project (slug or id), goal (free text), and an optional workType. The call returns immediately.
curl -s -X POST https://app.rensei.ai/api/cli/mcp \
-H "Authorization: Bearer $RENSEI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "dispatch",
"arguments": {
"project": "my-project",
"goal": "Research the tradeoffs between vector-only and hybrid BM25+vector search for our use case.",
"workType": "research"
}
}
}'The result payload (inside content[0].text) is { instanceId, sessionId, receiptUrl, streamUrl }:
{
"jsonrpc": "2.0",
"id": 3,
"result": {
"content": [{
"type": "text",
"text": "{\"instanceId\":\"inst_abc123\",\"sessionId\":\"sess_xyz\",\"receiptUrl\":\"https://app.rensei.ai/...\",\"streamUrl\":\"https://app.rensei.ai/...\"}"
}]
}
}Keep the instanceId - you pass it to get_receipt.
workType values
workType | Workflow template | Use for |
|---|---|---|
research (default) | byoa-research-request | Analysis, investigation, spike |
implement | byoa-implement-request | Code changes, feature work |
review | byoa-review-request | PR/diff review, audit |
Polling for the receipt
Poll get_receipt with the instanceId from dispatch. The tool returns { receipt } (again JSON-stringified into content[0].text). The run's state lives in the sessionStatus field, which moves pending -> running -> a terminal value. Poll until sessionStatus is one of the four terminal values: completed, failed, stopped, or cancelled. (A running run whose heartbeat goes stale is flagged stuck, which is not terminal; sessionStatus is null only before the session row has resolved.) There is no top-level status field.
curl -s -X POST https://app.rensei.ai/api/cli/mcp \
-H "Authorization: Bearer $RENSEI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "get_receipt",
"arguments": { "instanceId": "inst_abc123" }
}
}'While running, the parsed receipt looks like {"receipt":{"version":"v1","sessionStatus":"running", ...}}; once settled, sessionStatus is a terminal value such as "completed".
Recommended polling back-off: 5 s, 10 s, 30 s, 60 s (cap). Most research runs complete in 2-8 minutes; implement runs may take longer depending on scope and capacity-pool size.
Receipt verification
When a recorded audit decision is present, the receipt carries the current-path signature material needed for an explicit check. decision is null until that record exists, and retained audit history can include legacy unsigned entries. Do not treat receipt or signature presence as a verified result:
receipt.decision.signature- the Ed25519 signature over the audit entry (present once a decision is recorded;decisionisnulluntil then).receipt.decision.signingKeyId- thekidof the public key in your workspace JWKS.receipt.decision.entryHash- the hex-encoded audit entry the signature covers.receipt.links.jwksVerifyUrl- the ready-made JWKS endpoint for your workspace. Use this value directly.receipt.receiptIntegrity.receiptHash- a SHA-256 digest of the whole receipt for tamper-evidence. This is a hash, not a signature: recomputing it proves integrity in transit, not authenticity.
The CLI provides an explicit signature check: it reads the supplied entryHash, fetches the referenced JWKS, and checks the Ed25519 signature over that hash offline. It does not recompute the receipt hash or reconstruct the audit entry that produced entryHash:
rensei receipt verify --url "$RECEIPT_URL"
# or against a saved receipt:
rensei receipt verify --file receipt.jsonTo run the same signature check manually: fetch receipt.links.jwksVerifyUrl, select the JWK whose kid equals receipt.decision.signingKeyId, and verify receipt.decision.signature (Ed25519) over the raw bytes represented by receipt.decision.entryHash. Recomputing the receipt hash or the audit entry hash is a separate check and requires the corresponding canonical input fields. See Audit Keys JWKS for the key format and rotation rules.
A successful rensei receipt verify result authenticates the signature over the supplied entryHash; it does not establish whole-receipt integrity or recompute the entry hash from canonical event fields. It also does not establish event capture, full-history completeness, retention outside the supplied artifact, truth at capture, or external timestamp anchoring.
The JWKS endpoint is keyed by workspace id, not org id, and returns an empty { "keys": [] } with HTTP 200 for an unknown id (it never reveals whether a workspace exists). Always use the jwksVerifyUrl from the receipt rather than assembling the URL from an org id yourself.
Rate limits
The facade applies the byoaMcp rate-limit bucket server-side. The exact limits are not publicly enumerated. A throttled request returns HTTP 429 with a Retry-After header and a JSON-RPC error body (code -32005):
- Retry with exponential back-off: 1 s, 2 s, 4 s, 8 s, 16 s (max 5 attempts).
- Honor the
Retry-Afterheader.
Heavy batch usage (dozens of concurrent dispatches) should be coordinated with Rensei support to avoid hitting the bucket ceiling.
Troubleshooting
Transport and auth failures arrive as real HTTP status codes. Tool-level denials and validation errors arrive as a JSON-RPC error object inside an HTTP 200 response - inspect error.code, not the HTTP status, for those.
| Symptom | Likely cause | Fix |
|---|---|---|
HTTP 401 Unauthorized | Bearer key missing, invalid, revoked, or expired (or an inbound-handshake signature failure) | Confirm RENSEI_API_KEY is exported and the key is active |
HTTP 403 Forbidden | Key is valid but lacks the dispatch:invoke scope | Re-create the key with --scope dispatch:invoke |
HTTP 429 Too Many Requests | byoaMcp rate bucket exceeded (JSON-RPC error code -32005) | Honor Retry-After and back off (see Rate limits) |
HTTP 200 with a JSON-RPC error code -32003 | Project/workflow not allowed for this key, or Cedar policy denies | Run list_workflows to confirm availability; check the key's project scope; contact your org admin |
HTTP 200 with a JSON-RPC error code -32602 | Invalid params: missing project/goal/instanceId, or project/instance not found in your org | Check the arguments against the tool schema |
list_workflows returns an empty workflows array | No published BYOA templates in your org | Provision BYOA workflows via Dashboard > Workflows or contact your org admin |
dispatch succeeds but sessionStatus never becomes terminal | Run stuck in the capacity-pool queue | Check Dashboard > Sessions for the run; may be a capacity-pool configuration issue |
Related
- Hermes Integration - host-specific wiring for Hermes
- BYOA MCP Facade API reference - the generated request/response contract
- MCP Session Tools - the per-session MCP endpoint (memory, knowledge graph, A2A tools)
- API Key Authentication - creating and scoping
rsk_*keys - Audit Keys JWKS - Ed25519 public keys for receipt verification
- Audit Overview - audit event schema and retention policy