Daemons.ai MCP developer guide

Official connection guide for assistants and developers. Daemons.ai stores portable agent instructions and durable tasks. An assistant connects as an MCP client, performs tasks in its own environment, and reports progress and results back here.

Authentication: OAuth 2.1 authorization code with PKCE S256. The owner signs in through Intergraph and approves access to selected daemons. There is no API key to obtain or paste into the assistant. Daemons.ai issues this connection its own access and refresh tokens after consent.

Server address

https://api.daemons.ai/mcp

Add this address as a remote Streamable HTTP MCP connection in your assistant. The assistant must support OAuth authorization-code login and public dynamic client registration. Base MCP support alone does not guarantee OAuth support.

Discover authentication automatically

An unauthenticated GET or POST to /mcp returns 401 Unauthorized. Read the WWW-Authenticate challenge to find the protected-resource metadata. The JSON response also includes discovery and documentation links for tools that cannot inspect headers.

WWW-Authenticate: Bearer resource_metadata="https://api.daemons.ai/.well-known/oauth-protected-resource/mcp", scope="daemons:read work:execute"

A plain browser visit is not an MCP initialization. A conforming OAuth-capable client should follow discovery and open the owner’s sign-in/consent flow. It should not ask the owner to supply an Intergraph session token or invent an API key.

Authorization flow

  1. Retrieve protected-resource metadata, then retrieve authorization-server metadata from the advertised issuer. Validate their resource and issuer identifiers.
  2. Register the client at https://api.daemons.ai/oauth/register with its name, exact redirect URLs, and token_endpoint_auth_method: "none". HTTPS redirects and HTTP loopback redirects are supported. Client ID Metadata Document URLs are not supported; use dynamic registration.
  3. Generate a PKCE verifier and its base64url SHA-256 challenge. Open the advertised authorization endpoint with the registered client ID, redirect URI, response_type=code, code_challenge_method=S256, the challenge, an unpredictable state, requested scopes, and resource=https://api.daemons.ai/mcp.
  4. The owner signs in with Intergraph, chooses daemons, and approves permissions. This step requires the owner’s decision; discovering OAuth does not grant access automatically.
  5. Validate the returned state. Exchange the single-use code at the token endpoint using grant_type=authorization_code, the client ID, exact redirect URI, code, verifier, and the same resource identifier.
  6. Send the issued access token in Authorization: Bearer <access_token> on MCP requests. Refresh with grant_type=refresh_token, client ID, refresh token, and the same resource. Save rotated refresh tokens atomically.
POST /oauth/register
Content-Type: application/json

{"client_name":"My assistant","redirect_uris":["https://assistant.example/oauth/callback"],"token_endpoint_auth_method":"none"}

Codes expire after 60 seconds; access tokens after at most 15 minutes; grants and refresh tokens after 30 days. Reusing a consumed refresh token revokes its connection. Keep tokens in the client’s secure credential storage, out of URLs, messages, and logs.

Choose permissions

ScopeAllows
daemons:readRead authorized daemon instructions, tasks, and activity.
memory:writeSave and archive shared memory. Owner confirmation and provider settings remain owner-only.
work:executeAttach, pick up an existing task, and report progress/results.
work:submitAdd tasks, reorder the queue, request cancellation or retries, and archive finished tasks.
daemons:manageEdit/publish instructions, pause task starts, and manage tasks.
daemons:createCreate daemons. Newly created IDs are added to that grant’s allowed resources; other operations still require their respective scopes.

For executing the owner’s already queued tasks, request daemons:read work:execute and have the owner select the intended daemon. Editing, creating daemons, and adding tasks are separate permissions. For a read-only check, request daemons:read.

Initialize and verify a harmless read

All MCP messages use HTTP POST, with Accept: application/json, text/event-stream. Responses are JSON; there is no standalone GET event stream. Authenticated GET requests return 405 with Allow: POST.

Legacy protocol 2025-11-25: initialize, send notifications/initialized, then call tools. No MCP session ID is required.

{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"My assistant","version":"1"}}}

Modern protocol 2026-07-28: include per-request metadata and matching MCP-Protocol-Version and Mcp-Method headers. For tools/call, include a matching Mcp-Name header. There is no initialize handshake in this version.

{"jsonrpc":"2.0","id":1,"method":"server/discover","params":{"_meta":{"io.modelcontextprotocol/protocolVersion":"2026-07-28","io.modelcontextprotocol/clientInfo":{"name":"My assistant","version":"1"},"io.modelcontextprotocol/clientCapabilities":{}}}}

After authentication, call tools/list to discover the current tool schemas, then daemons_list for a harmless read. Select an authorized daemon and read its published_definition with daemon_get. Do not claim a task merely to check connectivity: claiming starts an execution attempt.

Execute one queued task

  1. Call daemon_get with the selected daemon_id. Instructions must be published before execution.
  2. Call assistant_attach with the daemon ID and assistant metadata, for example {"name":"My assistant","capabilities":[]}. Report the capabilities the assistant actually supports; they must include every required capability. These labels do not grant permissions.
  3. Call work_claim with the daemon ID. A null result means no waiting task. Otherwise, keep the returned work ID, attempt_id, pinned definition, and input.
  4. Call work_report with kind: "progress", a data object, the exact work/attempt IDs, and a fresh idempotency_key. Perform the assignment externally using its pinned instructions.
  5. Use work_get to check cancellation. Report the final succeeded or failed outcome with the result in data. Use cancelled only to acknowledge a stop request.
{"name":"work_report","arguments":{"work_id":"<returned work ID>","attempt_id":"<returned attempt ID>","kind":"succeeded","data":{"message":"Completed","result":"Your actual result"},"idempotency_key":"<unique report key>"}}

A progress report renews a 30-minute lease. Lost contact marks work for the owner’s review; it does not automatically repeat tasks. Reports from expired, superseded, or differently owned attempts are rejected. Repeat an idempotency key only for the same report and payload when recovering an uncertain response.

Tools and recovery

daemons_list, daemon_get, daemon_create, daemon_update, daemon_publish, daemon_pause, assistant_attach, work_submit, work_claim, work_get, work_report, work_cancel, work_retry. Use tools/list for required fields and the latest descriptions.

401: reconnect or refresh an expired access token. A tool permission error means the owner must approve the needed scope and daemon. A stale-attempt conflict means reconcile the current task; do not blindly retry external actions. Pausing stops new task pickups; cancellation and revocation do not shut down software outside Daemons.ai.

The owner can remove access in Assistant access. Clients can also POST token and client_id to the advertised revocation endpoint. Browser logout and assistant grants have separate lifetimes.

Shared memory and continuity

A daemon's published instructions explain how to work. Shared memory stores durable findings and decisions. Tasks and full reports remain separately retrievable. A fresh assistant conversation can resume using saved memory without importing every previous report.

Memory and historical-work reads require daemons:read. Write permission is separate from execution and does not allow owner confirmation, provider configuration, or changing instructions. Existing connections need renewed owner consent for the new scope.

After claiming work, read its returned context, retrieve only relevant earlier results, and save durable findings explicitly. Sources may reference same-daemon work IDs or public URLs. Memory entries are limited to 4,000 characters; lists default to 20 items (maximum 50). Briefings and aggregate supplemental recall each stay below 16 KiB of UTF-8 JSON and disclose omissions. Full reports are not included automatically.

Supply work_id and current attempt_id during supplemental searches to associate recall with the work. Such recall is recorded separately and never rewrites the starting snapshot. Respect cancellation and the published instructions; memory and provider summaries do not grant permission for external actions.

Neon is the authoritative record and default provider. Optional third-party providers require owner-approved export and server-installed adapters. This release includes the adapter framework; no live LIAM integration or other external memory provider is enabled.

TaskBoard Protocol

Use work_board to see complete counts and queued, working, attention, and finished task cards. Pass daemon_id and optionally column, cursor, and limit. Cards contain short summaries; fetch full requests/results with work_get and progress history with work_activity.

To manage the queue, first read its queue_revision. Call work_reorder with daemon_id, work_id, expected_queue_revision, idempotency_key, and optionally before_work_id. Omit the destination to move to the end. After a conflict, reread the board and reconcile before making a fresh ordering decision. Retrying an uncertain identical request uses the same idempotency key. New tasks and retries join the end of the queue.

Board/activity reads require daemons:read or daemons:manage. Adding, reordering, cancelling, retrying, and archiving tasks require work:submit or daemons:manage. Read/execute access alone cannot manage the queue. Use existing work_submit, work_cancel and work_retry; work_archive hides finished work without deleting its history. An external project status cannot mark execution complete. Only the native TaskBoard provider is installed.