For AI agents
The independent verifier coding agents like Codex, Claude Code, and Cursor call before shipping an API change: a deterministic verdict over the CLI, and agent-led Organization onboarding over Dino's hosted MCP server.
Coding agents like Codex, Claude Code, and Cursor change APIs faster than anyone can review by hand. An agent cannot trust its own grade: the check has to come from outside the generation loop. Dino is that check. The agent builds, Dino verifies the running API and returns a deterministic verdict, and the agent branches on it with no human in the middle.
How an agent calls Dino
An agent drives the CLI, which needs no account: run dino scan --format json against any endpoint, read the verdict on stdout and the branch signal from $?. To set up a Dino Organization and its APIs, an agent uses the hosted MCP server (see MCP).
dino scan --endpoint https://your-api.com/graphql --fail-on-high --format json --quietAn agent reads three surfaces, in the order it acts on them:
- Exit code (branch):
0clean ·2usage ·3policy gate failed ·4transient ·5config ·6partial ·70crash. Branch on$?with no parsing. See exit codes. - JSON verdict (understand):
--format jsonemits aDinoResulton stdout (verdict.health.verdict,findings,verdict.coverage); stdout stays pure, so it pipes tojq. See JSON output. - Error envelope (recover): on exit
2/4/5/70, the last stderr line is{"error":{"kind","message","retryable","exitCode"}}.retryablesays retry (transient) or stop (permanent). See error envelopes.
Is the change safe to ship?
dino scan --fail-on-high exits 3 when any HIGH or CRITICAL finding exists and 0 when clean, enough to decide continue-or-stop. Exit 6 (partial) is not a pass: read verdict.reasons to see what could not be verified.
Set up and resume
dino skill --install writes the agent skill (the setup, verify, read, fix, reverify loop) to .claude/skills/dino/SKILL.md, matched to the installed CLI version. dino schema prints every command, flag and exit code as clispec JSON, so an agent can check what the installed version accepts instead of guessing. When dino init is missing an input it exits 2 and puts a nextAction on the stderr envelope: { "type": "ask_user", "inputs": [...], "resume": { "type": "run_command", "bin": "dino", "args": [...] } }. Ask the human for each input (for a secret, ask them to set the named env var), then re-run resume.bin with resume.args, appending each collected input by its flag.
MCP: onboard an Organization from your agent
Dino's MCP server is a remote URL you connect over OAuth, not an npm package (there is no @dino-hq/mcp-server to install). Add it to your agent, for example in Claude Code:
claude mcp add --transport http dino https://api.usedino.dev/mcp
claude mcp login dinoclaude mcp add only saves the server configuration; claude mcp login dino (or /mcp inside Claude Code, then authenticate dino) starts the OAuth sign-in below. Until then the server shows Needs authentication.
The agent leads; the human makes every identity and consent decision in the browser:
- Sign in. Connecting opens Dino sign-in. The human verifies their email with a one-time code, then chooses one of their Organizations or creates a new one. Dino never picks one for them; an existing user can create another Organization with the same email.
- Confirm name and residency (new Organization only). The human confirms the Organization's name and where its data is stored: United States or European Union. Residency cannot change later. The agent may suggest; the human decides.
- Approve access. The human approves the agent's access to that Organization, and the browser returns to the agent. If the agent client cannot resume, reconnect from the agent.
- Onboard the API. Once connected, the agent runs:
bootstrap(admits the API, Environment and Target; no secrets) →create_auth_profile→open_credential_handoffonly when itsnextActioniscredential_required(the human types the credential on Dino's page, never in chat) →get_auth_profile→propose_target_connectionwith the human's answers on where scans run and for which purposes → the human's approval (below) →get_target_connection. - The human approves the Target Connection on Dino's approval page. Authorizing a Target Connection grants Dino authority over the human's system, so only a human signed in to Dino directly can decide it.
get_human_action_requestreturns anapprovalUrl: the agent gives the human that link, the human reviews exactly what the Connection allows (destination, scope, credentials and every limit) and authorizes or declines it there, and the agent pollsget_presentation_requestuntil it is decided. Dino refuses this decision from the agent, even when the agent acts for the human. A changed configuration needs a new approval.
Credential entry is not authorization: the one human approval is the Target Connection, bound to the exact configuration the human reviewed. For a Target whose API signs in with a login, the agent creates the identity with strategy login_flow and proposes the login steps with propose_authentication_flow (secrets only as {{name}} placeholders); the human then enters each named secret on the handoff page. Follow the nextAction in every result, read current state after a reconnect instead of assuming it, and treat a pending, refused, or expired result as not done. New Organizations start on the free plan; get_commercial_state shows the plan and entitlements. To work in a different Organization, clear the stored authorization first, because the client keeps and refreshes its OAuth tokens and reconnecting reuses the current Organization: in Claude Code, run claude mcp logout dino (or choose Clear authentication for dino in /mcp), then claude mcp login dino and choose the other Organization.
Human tasks on Dino's task page
Some work belongs to the human: a secret, an approval, stopping access, a Dino service key. The agent starts it or asks for it, hands the human a link to Dino's task page, and reads the outcome itself. The human does it signed in to Dino directly. A consequential decision needs a sign-in from the last 15 minutes, so the page may ask the human to sign in again first.
- Connect an OAuth2 API on one page.
start_connect_journeytakes the Target, either a name for a new identity or an existingauthProfileId, and the human's answers on where scans run and for which purposes. Give the human the pending step'staskUrl. On that page they configure the OAuth2 client (unless you sent a typed draft), enter the client secret, and approve the exact Connection. Pollget_presentation_requestwith the Request id. The journey endsconnect_proposedand links the approval Request incheckpoint.createdArtifactReferences. An identity that already has its configuration and secret goes straight to the approval. - Ask a human to stop access. You never stop access yourself.
request_operator_actionnames one action and yourwhy:credential.revokewith acredentialReferenceId, orconnection.suspend,connection.revokeorconnection.retirewithtargetId,connectionIdandversion. The human sees what the action affects and confirms once on the page. A human can also stop access with no agent and no link, athttps://api.usedino.dev/task?action=stop-access. - Dino service keys are issued by humans. Issuing, regenerating and revoking a Dino service key happens only on
https://api.usedino.dev/task?action=service-keys.list_service_keysgives you ids, each key's Service Account role, whether it is active, and thattaskUrl, never key material. A key authenticates as its own Service Account, not as the human who issued it. Dino shows a key once; if it was not stored, ask the human to regenerate it. - Read why a Request ended. Every Request carries
statusandstatusReasonCode. For example, FAILED withoperator_action_already_in_effectmeans another action had already stopped that access, so the human's confirmation changed nothing.