deltaops-mcp-server
v1.0.0
Published
MCP server for DeltaOps governance — lets any MCP-compatible AI agent create runs, raise asks, check policies, and log artifacts.
Maintainers
Readme
deltaops-mcp-server
Governance layer for AI agents. One MCP server gives any agent structured runs, human approval gates, policy checks, and a full audit trail.
Works with Claude Desktop, Claude Code, Cursor, Windsurf, and any MCP-compatible client.
Why
AI agents are powerful but opaque. When an agent modifies code, creates PRs, or touches infrastructure, you need:
- Visibility — what is the agent doing right now?
- Control — can it pause and ask before doing something risky?
- Audit — what did it do, and who approved it?
DeltaOps adds a governance loop: the agent creates a run, logs events as it works, raises asks when it needs human approval, and registers artifacts when it produces output. You approve or deny from the DeltaOps dashboard.
Install
{
"mcpServers": {
"deltaops": {
"command": "npx",
"args": ["deltaops-mcp-server"],
"env": {
"DELTAOPS_API_KEY": "delta_your_key_here",
"DELTAOPS_BASE_URL": "https://delta-ops-mvp.vercel.app/api/delta/v1"
}
}
}
}Claude Desktop: Add to ~/Library/Application Support/Claude/claude_desktop_config.json
Claude Code: Add to .claude/settings.json or run claude mcp add
Cursor: Add to .cursor/mcp.json
Get your API key from the DeltaOps dashboard → Agents tab → Generate API Key.
Tools
The server exposes 9 tools:
| Tool | What it does |
|---|---|
| deltaops_create_run | Start a new governed workflow. Every task begins here. |
| deltaops_get_run | Get run details by ID or external reference. |
| deltaops_update_run_status | Transition a run through its lifecycle (executing → completed, etc.). |
| deltaops_list_runs | List recent runs with optional status filter and pagination. |
| deltaops_raise_ask | Request human approval before a risky action. Blocks until decided. |
| deltaops_check_ask_status | Poll whether an ask has been approved or denied. |
| deltaops_log_event | Log progress, warnings, or errors to the run's audit trail. |
| deltaops_log_artifact | Register output (PR, commit, build, document) linked to the run. |
| deltaops_check_policy | Pre-check if an action is allowed under current policies. |
Tool reference
DeltaOps governance — approval gates, policy checks, audit logging — is the feature, not friction. When a tool requires you to poll for approval or check policy before acting, that is the system working as designed.
Error responses
All tools return this shape when an error occurs. The MCP response will have isError: true and the text content will be the error JSON below, not the success response.
Always check isError on the MCP response before reading the data.
{ "error": "Error message here", "status": 401 }deltaops_create_run
Start a new governed workflow. Every governed task should start with a run.
Parameters
| Parameter | Required | Type | Description |
|---|---|---|---|
| title | Yes | string | Short description of what this run will accomplish |
| github_repo_url | No | string | Full GitHub repository URL |
| budget_limit_usd | No | number | Maximum budget in USD (default: 5.0) |
| time_limit_seconds | No | number | Maximum time in seconds (default: 600) |
Success response
{
"id": "uuid",
"user_id": "uuid",
"title": "Fix auth bug",
"status": "pending",
"github_repo_url": "https://github.com/org/repo",
"budget_limit_usd": 5.0,
"time_limit_seconds": 600,
"metadata": {},
"created_at": "2026-03-12T10:00:00Z",
"updated_at": "2026-03-12T10:00:00Z"
}deltaops_get_run
Get details of a specific run by its ID or external reference.
Parameters
| Parameter | Required | Type | Description |
|---|---|---|---|
| id | No | string | The run UUID |
| external_ref | No | string | External reference (e.g., gh-42 for GitHub issue #42) |
Note: Provide exactly one of
idorexternal_ref, not both.
Success response
{
"id": "uuid",
"title": "Fix auth bug",
"status": "executing",
"external_ref": "gh-42",
"github_repo_url": "https://github.com/org/repo",
"metadata": {},
"created_at": "2026-03-12T10:00:00Z",
"updated_at": "2026-03-12T10:05:00Z"
}deltaops_update_run_status
Transition a run through its lifecycle.
Parameters
| Parameter | Required | Type | Description |
|---|---|---|---|
| run_id | Yes | string | The run ID to update |
| status | Yes | string | Lifecycle state: executing | completed | failed | stopped | hibernating |
| message | No | string | Human-readable reason for the status change |
| metadata | No | object | Additional key-value data to attach to this transition |
Success response
{
"run": {
"id": "uuid",
"title": "Fix auth bug",
"status": "completed",
"created_at": "2026-03-12T10:00:00Z",
"updated_at": "2026-03-12T10:30:00Z"
},
"transition": {
"from": "executing",
"to": "completed"
}
}deltaops_list_runs
List recent runs with optional status filter and pagination.
Parameters
| Parameter | Required | Type | Description |
|---|---|---|---|
| status | No | string | Filter by status: pending | executing | hibernating | awaiting_human | completed | failed | stopped |
| limit | No | number | Max runs to return (default: 20, max: 100) |
| cursor | No | string | Pagination cursor from a previous response |
Success response
{
"runs": [
{
"id": "uuid",
"title": "Fix auth bug",
"status": "executing",
"created_at": "2026-03-12T10:00:00Z",
"updated_at": "2026-03-12T10:05:00Z"
}
]
}Note: May include
next_cursorif more results exist. Pass it ascursorto retrieve the next page.
deltaops_raise_ask
Request human approval before proceeding with a risky action.
Parameters
| Parameter | Required | Type | Description |
|---|---|---|---|
| run_id | Yes | string | The run ID this ask belongs to |
| title | Yes | string | Short description of what you need approval for |
| message | Yes | string | Detailed explanation of the action, why it is needed, and potential risks |
| severity | No | string | Risk level: low | medium | high | critical |
| action_type | No | string | Category of action (e.g., merge_pr, deploy, delete) |
| context | No | object | Relevant context to help the reviewer decide |
| options | No | array | Decision options for the reviewer (e.g., [{id: "yes", label: "Approve"}]) |
| is_blocking | No | boolean | UI hint for dashboard urgency. Does NOT cause the API to wait — you must poll check_ask_status regardless. |
| location | No | string | File path or location relevant to this ask |
Success response — normal case
{ "ask_id": "uuid" }Success response — policy-blocked case (ask auto-denied by policy; no human will resolve it)
{
"ask_id": "uuid",
"blocked": true,
"policy_name": "no-deploys",
"message": "Ask blocked by policy: no-deploys"
}deltaops_check_ask_status
Poll whether an ask has been approved, denied, or is still pending.
Parameters
| Parameter | Required | Type | Description |
|---|---|---|---|
| ask_id | Yes | string | The ask ID returned from deltaops_raise_ask |
Success response — pending
{ "status": "pending" }Success response — approved
{
"status": "approved",
"resolver_name": "alice",
"selected_option": "yes"
}Success response — denied
{
"status": "denied",
"resolver_name": "alice"
}deltaops_log_event
Log progress, warnings, or errors to the run's audit trail.
Parameters
| Parameter | Required | Type | Description |
|---|---|---|---|
| run_id | Yes | string | The run ID to log this event against |
| message | Yes | string | Human-readable description of what happened |
| status | No | string | Log level: info | success | warning | error. This is NOT the run lifecycle status. |
| metadata | No | object | Structured data for this event (e.g., file paths changed, test results) |
Success response
{ "success": true }deltaops_log_artifact
Register an output (PR, commit, build, document) linked to the run.
Parameters
| Parameter | Required | Type | Description |
|---|---|---|---|
| run_id | Yes | string | The run ID this artifact belongs to |
| label | Yes | string | Short description of the artifact |
| type | Yes | string | Type: pull_request | commit | merge | deploy | document | build | test_report |
| uri | No | string | URL to the artifact (e.g., GitHub PR URL) |
| checksum | No | string | Optional checksum/hash for integrity verification |
| metadata | No | object | Additional data (e.g., commit SHA, file count) |
| summary | No | string | Brief summary of what this artifact contains |
Success response
{ "success": true, "artifact_id": "uuid" }deltaops_check_policy
Pre-check if an action is allowed under current policies before executing it.
Parameters
| Parameter | Required | Type | Description |
|---|---|---|---|
| action | Yes | string | The type of action to check (e.g., merge_pr, create_pr, deploy) |
| context | No | object | Additional context for policy evaluation (e.g., { "severity": "high" }) |
Success response — action blocked by policy
{
"decision": "block",
"reason": "Blocked by policy: no-deploys",
"policy_snapshot_id": "uuid"
}Success response — action requires human approval
{
"decision": "require_approval",
"reason": "No blocking policy matched. Action requires human approval via an Ask.",
"policy_snapshot_id": "uuid"
}Error reference
| Status | Error | Meaning | What to do |
|--------|-------|---------|------------|
| 401 | Missing API Key | No Authorization: Bearer ... header sent | Check DELTAOPS_API_KEY env var is set. Verify MCP config includes the env block. |
| 403 | Invalid or revoked API Key | Token doesn't exist, was revoked, or expired | Generate a new key from DeltaOps dashboard → Agents tab. |
| 403 | Unauthorized | Token is valid but the run/ask belongs to a different user | Verify you are operating on your own runs. Call deltaops_list_runs to see your runs. |
| 404 | Run not found | No run with that ID, or it belongs to another user | Verify the run_id. Call deltaops_list_runs to confirm the run exists. |
| 404 | Ask not found | No ask with that ID | Verify the ask_id returned from deltaops_raise_ask. |
| 409 | Status update conflict | Run was modified by another process between read and update (optimistic locking) | Safe to retry: call deltaops_get_run to get current state, then retry the status update. |
| 409 | Invalid transition | Cannot transition from current status to requested status (e.g., pending → completed) | NOT retriable as-is. Call deltaops_get_run to read current status. Consult the valid transitions table below and choose the correct next status. |
| 429 | Rate limit exceeded | Too many requests (default: 100 req/min) | Read the Retry-After header for seconds to wait. Back off before retrying. |
Valid transitions
pending -> executing
executing -> completed | failed | stopped | hibernating
hibernating -> executingAny transition not listed above returns 409 Invalid transition. Terminal states (completed, failed, stopped) cannot be changed.
Network timeouts
If a request times out (no HTTP status), the MCP server returns { "error": "Request timed out after 30000ms" }. The operation may or may not have succeeded server-side. For raise_ask, assume the ask was created and use check_ask_status before retrying.
Best practices
These practices work WITH the governance model. Approval gates, policy checks, and audit logging exist to keep agent actions safe and auditable. Following these patterns makes governance seamless rather than frustrating.
Polling
- Poll
deltaops_check_ask_statusevery 3-5 seconds while status ispending. pendingis not a terminal state — keep polling untilapprovedordenied.- On 429 responses during polling, wait the
Retry-Afterheader duration before the next attempt. - Set a maximum poll duration appropriate to the task (e.g., 10 minutes for interactive sessions).
- For
deltaops_list_runswork discovery, poll every 5-10 seconds.
Approval flow
- Always check policy first: Call
deltaops_check_policybeforedeltaops_raise_ask. If decision isblock, do not raise an ask — the action is prohibited. Surface the reason to the user. - If decision is
require_approval, proceed todeltaops_raise_ask. - Set
is_blocking: truefor actions where the agent must wait for a human decision before proceeding. - After
raise_ask, always check theblockedfield in the response. Ifblocked: true, the ask was auto-denied by policy — do not poll for it. - Set
severityaccurately — different severity levels may trigger different policy thresholds. - Include a unique reference in the
contextfield (e.g., PR URL, issue number) to help reviewers and prevent duplicate confusion on retry.
Run lifecycle
- Always call
deltaops_update_run_statusas the LAST step — treat it as afinallyblock. - On success: set status to
completed. - On any unrecoverable error: set status to
failedwith amessageexplaining what went wrong. - Never leave a run in
executingstate — abandoned runs pollute the dashboard and confuse future agents. - Follow the valid transitions:
pending→executing→completed/failed/stopped/hibernating.
Error handling
- Always check
isErroron the MCP tool response before reading data fields. IfisErroristrue, the text content is an error JSON, not the success response. - On 409
Status update conflict: safe to retry after re-fetching current state withdeltaops_get_run. - On 409
Invalid transition: read current status withdeltaops_get_run, then choose the correct next status from the valid transitions table. - On 429: wait the
Retry-Afterduration, then retry. - On 401/403: stop execution — the API key is missing or invalid. Do not retry; fix the configuration.
- On timeout (no status): for
raise_ask, assume it succeeded and pollcheck_ask_statusbefore retrying.
How it works
Agent MCP Server DeltaOps API Dashboard
│ │ │ │
├─ create_run ────────────►├─────────────────────────►│ │
│ │ │ run visible ───────►│
├─ log_event ─────────────►├─────────────────────────►│ │
│ │ │ event in timeline ─►│
├─ raise_ask ─────────────►├─────────────────────────►│ │
│ │ │ ask appears ───────►│
│ (agent waits) │ │ │
│ │ │◄──── human approves ─┤
├─ check_ask_status ──────►├─────────────────────────►│ │
│◄─── approved ────────────┤ │ │
├─ log_artifact ──────────►├─────────────────────────►│ │
├─ update_run_status ─────►├─────────────────────────►│ │
│ (completed) │ │ run complete ──────►│Run lifecycle
Runs follow a state machine enforced server-side:
pending → executing → completed
→ failed
→ stopped
→ hibernating → executing (resumed)Invalid transitions are rejected. Concurrent updates use optimistic locking.
Example: agent workflow
An agent with DeltaOps will naturally:
- Start a run —
deltaops_create_runwith a title describing the task - Log progress —
deltaops_log_eventas it reads code, plans changes, writes tests - Check policy —
deltaops_check_policybefore risky actions - Ask for approval —
deltaops_raise_askbefore merging, deploying, or modifying production - Wait for human —
deltaops_check_ask_statusto poll for the decision - Register output —
deltaops_log_artifactwith the PR URL, build link, etc. - Complete the run —
deltaops_update_run_statusto mark it done
Environment variables
| Variable | Required | Description |
|---|---|---|
| DELTAOPS_API_KEY | Yes | API key from the DeltaOps dashboard (format: delta_<64hex>) |
| DELTAOPS_BASE_URL | No | API base URL (default: https://delta-ops-mvp.vercel.app/api/delta/v1) |
Development
git clone https://github.com/jugbeep/deltaops-mcp-server.git
cd deltaops-mcp-server
npm install
npm run buildTo test locally, point your MCP client at the built binary:
{
"mcpServers": {
"deltaops": {
"command": "node",
"args": ["/path/to/deltaops-mcp-server/dist/index.js"],
"env": {
"DELTAOPS_API_KEY": "delta_your_key_here"
}
}
}
}License
MIT
