Skip to main content
Glama
orchestra-hq

Orchestra MCP Server

Official
by orchestra-hq
README.md
# Orchestra MCP Server

A Model Context Protocol (MCP) server for the [Orchestra API](https://docs.getorchestra.io/api/introduction). End users can connect directly to Orchestra's hosted MCP endpoint and authenticate with their Orchestra API key.

## Quick Start

Use Orchestra's hosted MCP endpoint:

- URL: `https://mcp.getorchestra.io/orchestra`
- Required header: `Authorization: Bearer <YOUR_ORCHESTRA_API_KEY>`
- API key location: [Orchestra workspace settings](https://app.getorchestra.io/settings/workspace)

## Available Tools

<!-- The table below is generated by scripts/update_readme.py — do not edit by hand. -->
<!-- available-tools:start -->
| Tool | Auth required | Purpose | Category |
|------|---------------|---------|------|
| `whats_broken` | Yes | Failing and warning pipeline runs in a window, pre-joined to the task runs that failed inside them, with messages, platform links and duration anomalies. | Triage |
| `diagnose` | Yes | Deep dive on one task run: parameters, upstream task statuses, log tail and artifact filenames. | Triage |
| `pipeline_context` | Yes | A pipeline's metadata, full definition, integrations, recent run outcomes and median succeeded duration. | Triage |
| `get_pipeline` | Yes | Fetch a single pipeline. Provide exactly one selector: pipeline_id, alias, or repository together with yaml_path (`GET /pipeline`). | Pipelines |
| `list_pipelines` | Yes | List pipelines (`GET /pipelines`). | Pipelines |
| `create_pipeline` | Yes | Create a pipeline (`POST /pipelines`). | Pipelines |
| `update_pipeline` | Yes | Update a pipeline by selector (`PUT /pipelines`). | Pipelines |
| `delete_pipeline` | Yes | **Disabled by default.** Delete a pipeline. Provide exactly one selector: pipeline_id, alias, or repository together with yaml_path (`DELETE /pipelines`). Set `ORCHESTRA_ENABLE_DELETE` to expose it. | Pipelines |
| `get_pipeline_data` | Yes | Get pipeline data (`GET /pipelines/data`). | Pipelines |
| `start_pipeline` | Yes | Start a pipeline run (`POST /pipelines/{pipeline_id_or_alias}/start`). | Pipelines |
| `pause_pipeline` | Yes | Pause or unpause a pipeline (`PUT /pipelines/{pipeline_id_or_alias}/pause`). | Pipelines |
| `validate_pipeline` | No | Validate pipeline schema (`POST /pipelines/schema`). | Pipelines |
| `migrate_pipeline` | Yes | Migrate an Orchestra-backed pipeline to git-backed storage. Identify it with pipeline_id or alias, and omit working_branch when it equals default_branch (`PATCH /pipelines/storage-settings`). | Pipelines |
| `import_pipeline` | Yes | Import a pipeline (`POST /pipelines/import`). | Pipelines |
| `get_pipeline_run_status` | Yes | Get pipeline run status (`GET /pipeline_runs/{pipeline_run_id}/status`). | Pipeline Runs |
| `list_pipeline_runs` | Yes | List pipeline runs with optional filters. status accepts comma-separated values: CREATED, RUNNING, SUCCEEDED, WARNING, FAILED, CANCELLING, CANCELLED (`GET /pipeline_runs`). | Pipeline Runs |
| `cancel_pipeline_run` | Yes | Cancel a running pipeline run by its ID (`POST /pipeline_runs/{pipeline_run_id}/cancel`). | Pipeline Runs |
| `get_pipeline_run_lineage_url` | No | Build the URL of a pipeline run's lineage graph in the Orchestra UI (derived from `ORCHESTRA_ENV`). | Pipeline Runs |
| `list_task_runs_for_pipeline_run` | Yes | List task runs for a pipeline run (`GET /pipeline_runs/{pipeline_run_id}/task_runs`). | Task Runs |
| `list_task_runs` | Yes | List task runs (`GET /task_runs`). | Task Runs |
| `list_incidents` | Yes | List incidents (`GET /incidents`). | Incidents |
| `get_incident` | Yes | Get an incident (`GET /incidents/{incident_id}`). | Incidents |
| `update_incident` | Yes | Update an incident (`PATCH /incidents/{incident_id}`). | Incidents |
| `list_incident_events` | Yes | List an incident's timeline (`GET /incidents/{incident_id}/events`). | Incidents |
| `get_incident_external_event` | Yes | Get an external event's payload (`GET /incidents/{incident_id}/events/{incident_event_id}/external_event`). | Incidents |
| `merge_incidents` | Yes | Merge incidents (`POST /incidents/{incident_id}/merge`). | Incidents |
| `unmerge_incidents` | Yes | Unmerge incidents (`POST /incidents/{incident_id}/unmerge`). | Incidents |
| `mute_incident` | Yes | Mute an incident (`POST /incidents/{incident_id}/mute`). | Incidents |
| `unmute_incident` | Yes | Unmute an incident (`POST /incidents/{incident_id}/unmute`). | Incidents |
| `create_incident_comment` | Yes | Write to an incident's timeline (`POST /incidents/{incident_id}/comments`). | Incidents |
| `list_operations` | Yes | List operations (`GET /operations`). | Operations |
| `list_assets` | Yes | List assets (`GET /assets`). | Assets |
| `get_asset_by_id` | Yes | Get an asset (`GET /assets/{asset_id}`). | Assets |
| `list_task_run_logs` | Yes | List task run logs (`GET /pipeline_runs/{pipeline_run_id}/task_runs/{task_run_id}/logs`). | Logs |
| `download_task_run_log` | Yes | Download a task run log (`GET /pipeline_runs/{pipeline_run_id}/task_runs/{task_run_id}/logs/download`). | Logs |
| `list_task_run_artifacts` | Yes | List task run artifacts (`GET /pipeline_runs/{pipeline_run_id}/task_runs/{task_run_id}/artifacts`). | Artifacts |
| `download_task_run_artifact` | Yes | Download a task run artifact (`GET /pipeline_runs/{pipeline_run_id}/task_runs/{task_run_id}/artifacts/download`). | Artifacts |
| `list_integration_connections` | Yes | List integration connections (`GET /integrations/connections`). | Integrations |
| `list_environments` | Yes | List environments (`GET /environments`). | Environments |
| `create_environment` | Yes | Create an environment (`POST /environments`). | Environments |
| `get_environment` | Yes | Get an environment (`GET /environments/{environment_id}`). | Environments |
| `update_environment` | Yes | Update an environment (`PATCH /environments/{environment_id}`). | Environments |
| `delete_environment` | Yes | **Disabled by default.** Delete an environment (`DELETE /environments/{environment_id}`). Set `ORCHESTRA_ENABLE_DELETE` to expose it. | Environments |
| `get_integration_state_for_state_aware` | Yes | Get integration state (`GET /state/{integration}`). | State |
| `list_accounts` | Yes | List workspaces (`GET /accounts`). | Accounts |
| `list_agent_avatars` | Yes | List agent avatars (`GET /agents/avatar-catalog`). | Agents |
| `create_agent` | Yes | Create an agent (`POST /agents`). | Agents |
| `list_agents` | Yes | List agents (`GET /agents`). | Agents |
| `get_agent` | Yes | Get an agent (`GET /agents/{agent_id}`). | Agents |
| `update_agent` | Yes | Update an agent (`PATCH /agents/{agent_id}`). | Agents |
| `delete_agent` | Yes | **Disabled by default.** Delete an agent (`DELETE /agents/{agent_id}`). Set `ORCHESTRA_ENABLE_DELETE` to expose it. | Agents |
| `list_agent_skills` | Yes | List an agent's skills (`GET /agents/{agent_id}/skills`). | Agents |
| `set_agent_skills` | Yes | Set an agent's skills (`PUT /agents/{agent_id}/skills`). | Agents |
| `list_agent_integrations` | Yes | List an agent's integrations (`GET /agents/{agent_id}/integrations`). | Agents |
| `set_agent_integrations` | Yes | Set an agent's integrations (`PUT /agents/{agent_id}/integrations`). | Agents |
| `get_agent_usage` | Yes | Get agent token usage (`GET /usage`). | Agents |
| `list_agent_sessions` | Yes | List agent sessions (`GET /sessions`). | Agent Sessions |
| `create_agent_session` | Yes | Start an agent session (`POST /sessions`). | Agent Sessions |
| `get_agent_session` | Yes | Get an agent session (`GET /sessions/{session_id}`). | Agent Sessions |
| `send_agent_session_message` | Yes | Send a message to an agent session (`POST /sessions/{session_id}`). | Agent Sessions |
| `get_agent_session_history_messages` | Yes | Read an agent session's messages (`GET /sessions/{session_id}/history/messages`). | Agent Sessions |
| `cancel_agent_session_prompt` | Yes | Cancel an agent session prompt (`POST /sessions/{session_id}/cancel`). | Agent Sessions |
| `list_skills` | Yes | List skills (`GET /skills`). | Skills |
| `create_skill` | Yes | Create a skill (`POST /skills`). | Skills |
| `get_skill` | Yes | Get a skill (`GET /skills/{skill_id}`). | Skills |
| `update_skill` | Yes | Update a skill (`PATCH /skills/{skill_id}`). | Skills |
| `delete_skill` | Yes | **Disabled by default.** Delete a skill (`DELETE /skills/{skill_id}`). Set `ORCHESTRA_ENABLE_DELETE` to expose it. | Skills |
| `import_skill` | Yes | Import a skill from git (`POST /skills/import`). | Skills |
| `list_audit_events` | Yes | List audit events (`GET /audit_events`). | Audit |
| `get_incident_settings` | Yes | Get incident settings (`GET /incident_settings`). | Incident settings |
| `update_incident_settings` | Yes | Update incident settings (`PATCH /incident_settings`). | Incident settings |
| `list_monitors` | Yes | List monitors (`GET /monitors`). | Monitors |
| `create_monitor` | Yes | Create a monitor (`POST /monitors`). | Monitors |
| `reorder_monitors` | Yes | Reorder monitors (`POST /monitors/reorder`). | Monitors |
| `get_monitor` | Yes | Get a monitor (`GET /monitors/{monitor_id}`). | Monitors |
| `update_monitor` | Yes | Update a monitor (`PUT /monitors/{monitor_id}`). | Monitors |
| `delete_monitor` | Yes | **Disabled by default.** Delete a monitor (`DELETE /monitors/{monitor_id}`). Set `ORCHESTRA_ENABLE_DELETE` to expose it. | Monitors |
<!-- available-tools:end -->

### Cursor

Add this to `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global):

```json
{
  "mcpServers": {
    "orchestra": {
      "url": "https://mcp.getorchestra.io/orchestra",
      "headers": {
        "Authorization": "Bearer <YOUR_ORCHESTRA_API_KEY>"
      }
    }
  }
}
```

### Claude Code

Add the hosted server with:

```bash
claude mcp add --transport http --header "Authorization: Bearer <YOUR_ORCHESTRA_API_KEY>" orchestra https://mcp.getorchestra.io/orchestra
```

### Other MCP clients

Any MCP client that supports remote HTTP/SSE servers can connect with this shape:

```json
{
  "mcpServers": {
    "orchestra": {
      "url": "https://mcp.getorchestra.io/orchestra",
      "headers": {
        "Authorization": "Bearer <YOUR_ORCHESTRA_API_KEY>"
      }
    }
  }
}
```

## Managing Multiple Workspaces

If you need to connect to multiple Orchestra workspaces, you can set up separate MCP server connections with workspace-specific API keys:

```json
{
  "mcpServers": {
    "orchestra-data-quality-tests": {
      "url": "https://mcp.getorchestra.io/orchestra",
      "headers": {
        "Authorization": "Bearer <DATA_QUALITY_WORKSPACE_API_KEY>"
      }
    },
    "orchestra-sales-integrations": {
      "url": "https://mcp.getorchestra.io/orchestra",
      "headers": {
        "Authorization": "Bearer <SALES_WORKSPACE_API_KEY>"
      }
    }
  }
}
```

## Run Locally

This section discusses how to run the MCP server locally, and is mainly intended for contributors.

### Prerequisites

- Python 3.11 or higher
- [uv](https://github.com/astral-sh/uv) package manager
- Orchestra API key

### Install dependencies

```bash
# Install uv if you haven't already
curl -LsSf https://astral.sh/uv/install.sh | sh

# Install project dependencies
uv sync
```

### Set API key

```bash
export ORCHESTRA_API_KEY="your-orchestra-api-key"
```

### (Optional) Select environment for local runs

For local development, the server defaults to `app`. You can override it with `ORCHESTRA_ENV`:

```bash
export ORCHESTRA_ENV="dev"
```

Valid values:

- `app` (default)
- `stage`
- `dev`

### (Optional) Enable destructive deletion

By default, the destructive `delete_pipeline` and `delete_environment` tools are not registered to avoid accidental destructive actions.
To expose them, set `ORCHESTRA_ENABLE_DELETE` before starting the server:

```bash
export ORCHESTRA_ENABLE_DELETE="true"
```

Only the following values are recognized:

- `"true"`
- `"TRUE"`
- `"1"`

### Run the server

```bash
python -m orchestramcp.server
```

The server fetches every Orchestra OpenAPI spec on startup and exposes the operations
each API flags for the MCP. Set `ORCHESTRA_OPENAPI_URL` (Orchestra API),
`ORCHESTRA_PLATFORM_OPENAPI_URL` (Orchestra Platform API) or
`ORCHESTRA_AGENTS_OPENAPI_URL` (Orchestra Agents API) to point at a specific spec
(e.g. a local file) instead of the environment default. Startup fails if any spec
cannot be fetched, rather than serving a partial set of tools.

### (Optional) Accept OAuth access tokens

The hosted Lambda can also accept OAuth 2.1 access tokens issued by Orchestra's
authorization server, alongside API keys. Set all three variables to turn it on —
with any of them unset, every bearer token is treated as an API key:

```bash
export ORCHESTRA_OAUTH_ISSUER="https://app.getorchestra.io"
export ORCHESTRA_OAUTH_JWKS_URI="https://app.getorchestra.io/oauth/jwks.json"
export ORCHESTRA_OAUTH_RESOURCE_URL="https://mcp.getorchestra.io/orchestra"
```

The issuer is per-environment — swap `app` for `stage` or `dev` — and the rest of its
metadata, `jwks_uri` included, is published at
`<issuer>/.well-known/oauth-authorization-server`.

`ORCHESTRA_OAUTH_RESOURCE_URL` must be the MCP URL exactly as a user types it into their
client, path included: it is published as the `resource` of the
[RFC 9728](https://datatracker.ietf.org/doc/html/rfc9728) metadata document, and it is the
audience every token is checked against. The authorization server has to serve that same
identifier — it mints a token only for a resource it is configured for, and stamps `aud`
with its own spelling of it. Verified tokens are forwarded to the Orchestra API unchanged.

### Testing the OAuth flow locally

`scripts/local_resource_server.py` fronts the real Lambda handler with an HTTP socket,
so an MCP client can run the whole flow against the production code path:

```bash
ORCHESTRA_ENV=dev \
ORCHESTRA_OAUTH_ISSUER=https://dev.getorchestra.io \
ORCHESTRA_OAUTH_JWKS_URI=https://dev.getorchestra.io/oauth/jwks.json \
ORCHESTRA_OAUTH_RESOURCE_URL=https://mcp-dev.getorchestra.io/orchestra \
    uv run python scripts/local_resource_server.py
```

```bash
claude mcp add --transport http orchestra-local http://127.0.0.1:8788/orchestra
```

Connecting should take you through discovery, client registration and a consent screen,
after which tool calls run as your user rather than as an account-wide API key.

The resource URL is the deployed dev identifier rather than the local address, because it
has to be one the authorization server serves *and* one the Orchestra API accepts as an
audience — a token minted for `127.0.0.1` is refused by both. The cost is that the
metadata pointer in the 401 names the deployed host, so a client that follows it lands
somewhere this server is not; discovery then depends on the client falling back to
probing the address it connected to. Testing against a deployed environment avoids that,
and is also the only way to exercise the edge routing `/orchestra/.well-known/*`.


## Development

- Run `uv run pytest` to run tests.
- Run `uv run ruff check .` and `uv run ruff format .` to check and format code.

PRs to main will trigger CI checks in GitHub, `main` branch merges release to the dev & stage environments, and Github releases relase to the production environment.

TDQS

B3.4/5.0

Scored across 49 tools

Disambiguation4/5

Most tools have clearly distinct purposes, but the pipeline retrieval trio (get_pipeline, get_pipeline_data, pipeline_context) and the task-run list variants (list_task_runs vs list_task_runs_for_pipeline_run) create some overlap. Descriptions help differentiate, but an agent could still misselect among them.

Naming Consistency4/5

Predominantly consistent verb_noun pattern (get_, list_, create_, update_, etc.), with a few outliers like whats_broken, pipeline_context, and diagnose that break the pattern. Overall the naming is readable and mostly predictable.

Tool Count2/5

49 tools is well above the recommended 3-15 range and is heavy even for a broad orchestration platform. Many tools could be consolidated or omitted, and the sheer count risks overwhelming an agent and increasing selection errors.

Completeness4/5

Covers core CRUD and lifecycle operations for pipelines, incidents, monitors, environments, and task runs, but lacks delete operations for several resources (e.g., delete_pipeline, delete_monitor, delete_environment) and manual incident creation. Agents can work around most gaps.

Maintenance

ActivityMaintained
ResponsivenessNo issues