Skip to content
AscendCore
🔌 Integration GuideEarly access

Agent Gateway (MCP)

Give AI agents a sanctioned path into IT operations. Agents connect over the Model Context Protocol and propose runbook actions. A human approves in Slack or Teams, the deterministic runbook executes, and the audit chain records the agent, the approver, and the outcome.

In one sentence

The gateway exposes four MCP tools (plus two read-only setup tools for keys that carry org:read), and the only one that changes anything (propose_action) never executes: it stages the same pending approval card a human request creates, so your existing approval flow and tamper-evident audit chain govern every agent-initiated action.

How a proposal flows

  1. Propose. The agent calls propose_action with a runbook ID and its args. The gateway validates the args, checks the key's runbook allowlist, and stages a pending approval where your org routes API approvals: a card in your Slack or Teams admin channel, or, with no chat channel, your AscendCore approval queue (approvers are emailed). Nothing has executed.
  2. Provenance. A note at the top of the pending approval card (or on its row in the approval queue) names the agent's API key and its stated reason, so approvers know the request came from an agent before they decide.
  3. Decide. A human approves or denies from Slack, Teams, or the dashboard. A denial changes nothing. There is no autonomous path around the gate.
  4. Execute + record. On approval, the runbook runs against your stack and the chain records three linked events: the agent's proposal, the human decision, and the execution outcome. The agent learns the result by polling get_run_status.

Step 1: Create a scoped agent key

In your admin portal under API, create a key with the agent:propose scope. Least privilege applies: this scope can propose and poll, but cannot execute runbooks directly or read audit rows.

Step 2: Connect your MCP client

The gateway is a stateless streamable-HTTP MCP server at POST /api/mcp, authenticated with your key as a bearer header. Claude clients:

# Claude Code (CLI)
claude mcp add --transport http ascendcore https://ascendcore.ai/api/mcp \
  --header "Authorization: Bearer ak_live_YOUR_KEY"

# Claude (web/desktop): Settings -> Connectors -> Add custom connector
#   URL:    https://ascendcore.ai/api/mcp
#   Auth:   Authorization: Bearer ak_live_YOUR_KEY

Microsoft Copilot Studio: add a custom MCP tool/connector pointing at the same URL with an API-key (bearer) authorization header. Any other client that speaks MCP over streamable HTTP works the same way. The raw wire format, if you are building your own client:

POST https://ascendcore.ai/api/mcp
Authorization: Bearer ak_live_YOUR_KEY
Content-Type: application/json

{ "jsonrpc": "2.0", "id": 1, "method": "initialize",
  "params": { "protocolVersion": "2025-06-18", "capabilities": {},
              "clientInfo": { "name": "my-agent", "version": "1.0.0" } } }

The tool surface

ToolWhat it doesExecutes anything?
list_runbooksLists the runbooks this key may propose, with the exact args shape each expects.No. Read-only.
propose_actionStages a pending approval card for a runbook + args + optional reason. Returns a runId.No. It stages; a human decides.
get_run_statusPolls a proposal: pending, approved (a human approved and the runbook ran), or denied.No. Read-only.
search_audit_eventsReads the org's hash-chained audit log. Requires the key to also carry audit:read.No. Read-only.
get_setup_statusReads the org's setup state: sandbox or live, which connectors are connected and verified, and what blocks go-live. Listed only for keys with org:read.No. Read-only.
check_integrationsRuns the read-only connector checks now and returns each result and any missing permissions. Not saved. Listed only for keys with org:read.No. Read-only.

What a proposal looks like

{ "jsonrpc": "2.0", "id": 2, "method": "tools/call",
  "params": {
    "name": "propose_action",
    "arguments": {
      "runbookId": "RB-002",
      "args": { "userEmail": "sarah.chen@acme.com" },
      "reason": "User reported a lost phone in the IT support thread."
    } } }

// Result (the action has NOT run; a human decides in Slack, Teams,
// or the approval queue):
{ "runId": "mfa_1234567890_123456", "status": "pending_approval",
  "runbook": { "id": "RB-002", "name": "MFA Re-enrollment" },
  "approvalSurface": "slack",
  "note": "Staged for human approval in the organization's Slack admin channel. ..." }

Agent-facing contract, stated in the server's own MCP instructions: never represent an action as performed until get_run_status returns approved.

Error codes you will actually see

CodeMeaning
agent_gateway_disabledThe gateway is not enabled for this deployment (early access is enabled per org).
missing_scopeThe key lacks agent:propose (endpoint) or the tool-level audit:read / org:read scope.
runbook_not_allowed_for_keyThe key's rb:* allowlist does not include this runbook.
invalid_argsThe args failed validation. The message names the field; list_runbooks shows the expected shape.
rate_limit_exceededPer-key rate limit hit. Standard API-key limits apply; the response carries Retry-After.

Security model

Early access

The Agent Gateway is in early access and is enabled per organization. Contact us to turn it on for your org. For the story behind the gate, see the Agent Gateway page and Approval-First AI. Ticket-based automation lives in the ServiceNow, Jira, and Freshservice guides.