MCP Setup Overview
Connect AI agents to HeadlessOps via the Model Context Protocol. Full reference for MCP tools, OAuth 2.1 authentication, workspace resolution, push-run execution modes, and synchronous run output.
MCP Setup (AI Agents)
HeadlessOps provides a native Model Context Protocol (MCP) server that lets AI agents (Claude Desktop, Cursor, Roo Code, and others) interact with the platform directly — reading, writing, deploying, and running integrations without leaving the IDE.
What Is MCP?
The Model Context Protocol is an open standard for connecting AI assistants to external tools and data sources. HeadlessOps implements an MCP server that exposes platform operations as typed tools callable by any MCP-compatible AI client.
With MCP connected, your AI agent can:
- List, create, and deploy integrations
- Push code files and trigger test runs
- Read run logs and debug failures
- Manage credentials and data stores
- Browse the workspace knowledge base
- List labels accessible to the caller
Authentication: OAuth 2.1 + PKCE
The MCP server uses OAuth 2.1 with PKCE (Proof Key for Code Exchange) for authentication. This is the recommended flow for public clients without a client secret.
OAuth is user-level — each user authenticates with their own HeadlessOps account and receives an individual access token. This design supports multiple users connecting their own AI clients independently, each acting under their own identity and permissions.
AI Client HeadlessOps MCP
│ │
│─── OAuth authorize ─────▶│
│◀── redirect to browser ──│
│ │
│ [User logs in + approves scopes in browser]
│ │
│─── code + verifier ─────▶│
│◀── access token ─────────│
│ │
│─── tool calls (Bearer) ─▶│
│◀── tool results ─────────│Steps
- The AI client initiates an OAuth authorization request with a code challenge
- The user logs in to HeadlessOps in the browser and grants the requested scopes
- The authorization code is exchanged for an access token
- The access token is included in all subsequent MCP tool calls
MCP Server URL
https://app.headlessops.ai/mcpAll MCP-compatible clients connect to this single endpoint. There is no separate configuration per workspace — workspace selection happens at the tool call level (see below).
MCP Tool Scopes
| Scope | Description |
|---|---|
mcp:tools | Core tools: workspaces, knowledge base, data stores, labels |
integrations:read | List and read integrations and their files |
integrations:write | Create, update, push, deploy, and run integrations |
runs:read | List runs and read step logs |
runs:write | Trigger manual runs |
credentials:use | List, create, and manage credentials |
Label-Based Access and MCP
MCP tool calls respect the caller's label grants, the same way direct API calls do.
integrations_listreturns only integrations the caller has a label grant for (or all integrations for ADMINs)credentials_listreturns only credentials the caller has a label grant forknowledge_docs_listreturns only docs the caller has a label grant forlabels_listreturns all labels in the workspace the caller has access to
Important for integration builders: An integration or credential must be labeled before non-admin members or AI agents (using non-admin API keys) can access it. Unlabeled resources are admin-only. See Labels & Permissions for the full guide.
OAuth for Multiple Users
OAuth is user-level authentication — each user who connects an AI client via MCP authenticates independently with their own HeadlessOps account. This makes OAuth the right choice when multiple users need to connect: every user gets their own token, their own identity, and their own permission scope.
How Each User Connects
- The user configures their AI client with the MCP server URL
- On first use, their client opens a browser window for login
- The user logs in to their HeadlessOps account and grants access
- An access token is issued to that user's session — no sharing required
Because tokens are tied to individual users, each person's AI client acts under their own role and label grants automatically.
Workspace Resolution
When using the MCP via OAuth, your token grants access to all workspaces you are a member of.
Always call workspaces_list first to discover available workspaces and their IDs:
Tool: workspaces_list
Args: {}Response example:
[
{ "id": "ws_abc123", "name": "Client A", "slug": "client-a", "description": "Production CRM automation for Client A" },
{ "id": "ws_def456", "name": "Client B", "slug": "client-b", "description": "Staging environment for Client B integrations" }
]Resolve workspaceId in this priority order:
- Config file — if
iterator/iterator.config.jsonexists in the repo with aworkspaceIdfield, use that value. - Repo name match — match the current repo/folder name against workspace slugs.
- Explicit user input — ask the user to specify if ambiguous.
- Error — if resolution fails, return:
"workspaceId is required — call workspaces_list to find your workspace ID"
Never rely on alphabetical order. Workspace IDs are CUIDs — alphabetical fallback will silently target the wrong workspace.
iterator.config.json Convention
Create this file at iterator/iterator.config.json in your repository to pin a workspace:
{
"workspaceId": "ws_abc123"
}This is the canonical source of truth for workspaceId in the repo. All MCP tool calls automatically resolve to this workspace when this file is present.
Push-Run Execution Modes
integration_files_push_run supports two execution modes controlled by the optional mode parameter. Choosing the right mode lets agents balance responsiveness against the need for immediate output.
Default — Fire-and-Forget (Asynchronous)
Omit mode (or leave it unset) to trigger an asynchronous run. The server pushes the files, creates a run, and returns the runId immediately. The run executes in the background and the agent polls for completion separately.
{
"name": "my-automation",
"files": {
"integration.yaml": "...",
"step.ts": "..."
},
"payload": {}
}Response (201 Created):
{ "runId": "run_abc123", "status": "RUNNING" }After receiving the runId, poll for the result using runs_list_get or GET /api/runs/:runId.
Use fire-and-forget when:
- The run is long-running or its output is large.
- You want non-blocking execution.
- You plan to inspect logs afterward via
runs_list_getorruns_steps.
mode=sync — Synchronous Execution (Wait for Result)
Pass "mode": "sync" to wait for the run to complete and receive the output directly in the response body. The connection is held open until the run finishes, then the full result is returned in a single response.
{
"name": "my-automation",
"files": {
"integration.yaml": "...",
"step.ts": "..."
},
"payload": {},
"mode": "sync"
}Successful response (200 OK):
{
"runId": "run_abc123",
"status": "SUCCEEDED",
"output": { "result": "ok", "records_processed": 42 }
}outputcontains the value passed toctx.output()in the final step, ornullifctx.output()was never called.statusreflects the final run status:SUCCEEDED,FAILED,CANCELLED, etc.
Use mode=sync when:
- The run is short (seconds, not minutes) and you need the output immediately.
- You want to avoid a separate polling loop.
- The output payload is small (under 50 KB).
50 KB Output Guard — Truncation Handling
When the run output exceeds 50 KB, the server does not return the full payload inline to avoid flooding the agent's context window. Instead, the response contains a truncation notice:
{
"runId": "run_abc123",
"status": "SUCCEEDED",
"output": null,
"truncated": true,
"warning": "Run output exceeds 50KB size limit (73KB). Use runs_steps with outputPath to download full logs instead."
}When you receive truncated: true, download the full output using runs_steps with an outputPath to save logs to a local file:
Tool: runs_steps
Args: { "runId": "run_abc123", "outputPath": "/tmp/run-abc123-logs.json" }This keeps the agent context clean and prevents token overflow on large automations.
Available MCP Tools Reference
All workspace-scoped tools accept an optional workspaceId argument. Always pass it explicitly.
Workspace Tools
| Tool | Operation | Scope |
|---|---|---|
workspaces_list | List all workspaces the user has access to | mcp:tools |
workspaces_create | Create a new workspace | mcp:tools |
workspace_members_list | List members and pending invites | mcp:tools |
workspace_members_invite | Invite a user by email and role | mcp:tools |
Label Tools
| Tool | Operation | Scope |
|---|---|---|
labels_list | List all labels in the workspace the caller has access to | mcp:tools |
label_grants_list | List all label grants for a specific workspace member, including any expiresAt value (ADMIN only) | mcp:tools |
label_grants_create | Grant a workspace member access to a label (read or write). Accepts an optional expiresAt for a temporary, time-boxed grant. Auto-creates the label if it does not exist. (ADMIN only) | mcp:tools |
label_grants_delete | Revoke a label grant from a workspace member by grant ID (ADMIN only) | mcp:tools |
Integration Tools
| Tool | Operation | Scope |
|---|---|---|
integrations_list | List integrations (supports search, filter by trigger/label). Results are scoped to the caller's label grants and automatically returned in a compact form (core metadata only, no code/deployed files) to keep responses small for AI agents. | integrations:read |
integrations_get | Get a single integration by name | integrations:read |
integrations_create | Create a new integration | integrations:write |
integrations_update | Update integration settings (trigger, schedule, webhook, requirements) | integrations:write |
integrations_delete | Delete an integration | integrations:write |
integrations_activate | Activate an integration | integrations:write |
integrations_deactivate | Deactivate an integration | integrations:write |
integrations_clone | Clone an integration | integrations:write |
integrations_labels | Set labels on an integration | integrations:write |
File & Deployment Tools
| Tool | Operation | Scope |
|---|---|---|
integration_files_list | List files (read mode: snippets; download mode: full content) | integrations:read |
integration_files_push | Push files without running (syncs packages → requirements from YAML) | integrations:write |
integration_files_push_run | Push files and trigger a run atomically. Supports mode=sync for synchronous output. | integrations:write |
integration_files_deploy | Snapshot current files as a versioned deployment | integrations:write |
Run Tools
| Tool | Operation | Scope |
|---|---|---|
runs_list_get | List runs for an integration (with step logs) | runs:read |
runs_create | Trigger a manual run with an optional payload | runs:write |
runs_cancel | Cancel a running run | runs:write |
Credential Tools
| Tool | Operation | Scope |
|---|---|---|
credentials_list | List credentials the caller has access to (scoped by label grants for non-admins) | credentials:use |
credentials_create | Create a new API key or OAuth2 credential | credentials:use |
credentials_update | Update a credential's value or metadata | credentials:use |
credentials_delete | Delete a credential | credentials:use |
credentials_apps_list | List available credential app templates | credentials:use |
credentials_app_create | Create a credential from an app template | credentials:use |
credentials_invite_create | Generate a public invite link for external credential fill | credentials:use |
Data Store Tools
| Tool | Operation | Scope |
|---|---|---|
data_stores_list | List all data stores | mcp:tools |
data_stores_create | Create a new data store with column schema | mcp:tools |
data_stores_delete | Delete a data store (permanent) | mcp:tools |
Knowledge Base Tools
| Tool | Operation | Scope |
|---|---|---|
knowledge_docs_list | List documents the caller has access to (scoped by label grants for non-admins) | mcp:tools |
knowledge_docs_get | Get the full content of a document | mcp:tools |
knowledge_docs_create | Create a new Markdown document | mcp:tools |
knowledge_docs_update | Update an existing document | mcp:tools |
knowledge_docs_delete | Delete a document | mcp:tools |
Local MCP Proxy (Required for folderPath)
The @headlessops-ai/mcp npm package provides a local proxy that:
- Sits between the AI client (stdio) and the remote
/mcpendpoint - Handles OAuth 2.1 + PKCE authentication via
mcp-remote - Resolves
folderPathparameters to inline file contents from the local filesystem
Install the Proxy
npm install -g @headlessops-ai/mcpThis installs the headlessops-mcp binary globally.
Configure Your MCP Client
Instead of pointing directly at the remote MCP URL, use the headlessops-mcp command:
{
"command": "headlessops-mcp",
"args": ["--mcp-url", "https://app.headlessops.ai/mcp"]
}Once the proxy is running, folderPath works transparently — the proxy reads files locally and forwards them to the remote server via OAuth.
Notes
- macOS Homebrew Node: If you installed Node via Homebrew, the binary lands at
/opt/homebrew/bin/headlessops-mcp. Use the absolute path if your client doesn't inherit the shell PATH. - Authentication: Auth is handled automatically on first run via browser OAuth flow. No manual token management is needed.
folderPathrequirement:folderPathsupport requires the local proxy. Plain URL connections directly tohttps://app.headlessops.ai/mcpcannot resolve local filesystem paths.
If you do not have the proxy set up, use the
filesinline mode instead. Pass the file content directly in the tool call payload.
Next Steps
- Connect Claude Desktop
- Connect Cursor & Roo Code
- Labels & Permissions — understand how label grants affect MCP tool results
- Scripting Guide — integration.yaml
- TypeScript ctx API Reference
- npm Packages
Connect VS Code / GitHub Copilot
Connect VS Code with GitHub Copilot to HeadlessOps via MCP
integration.yaml Schema
Complete reference for the integration.yaml manifest format used in HeadlessOps automations. Covers trigger types, step routing, npm package dependencies, webhook authentication, HTML responses, and synchronous response modes.