# StackAI MCP Server

## Connecting to and Using the StackAI MCP Server

The StackAI MCP server exposes Stack AI workflows (projects, runs, knowledge bases, integrations) over the [Model Context Protocol](https://modelcontextprotocol.io) so any MCP-aware client (Claude Desktop, Claude Code, Claude.ai, the MCP Inspector, Cursor, etc.) can read and operate on your account.

### 1. Connection URL

| Environment    | URL                        |
| -------------- | -------------------------- |
| **Production** | `https://mcp.stack.ai/mcp` |

Authentication is via StackAI. There are no API keys to paste — the client redirects you to Stack AI's login page.

### 2. Connect from a client

#### Claude Code (CLI)

```bash
# Production
claude mcp add --transport http stack-ai-prod https://mcp.stack.ai/mcp
```

#### Claude.ai (web)

1. Settings → **Integrations** → **Add More**
2. Paste `https://mcp.stack.ai/mcp`
3. Sign in with your Stack AI / Supabase credentials.

#### Claude Desktop / Cursor / MCP Inspector

Use the same URL with HTTP transport. The client will trigger the OAuth flow on first call.

### 3. Session bootstrap (do this once per session)

The server is **stateless HTTP** with a per-token active-org cache, so every tool resolves your org context from the upstream Stack AI API. The first two calls in a new session should always be:

1. **`whoami`** — returns your email, current org, and a paginated list of orgs you belong to.
2. **`switch_org`** — sets the active org for org-scoped tools. Pass an `org_id` from `whoami`. Without this, org-scoped tools (`get_project`, `run_project`, `edit_project`, etc.) error out and direct you back to `whoami`.

### 4. Tool reference

All tools accept keyword-only args. Most reads paginate with `cursor` / `page_size` (default 50, max 200). Every response carries a top-level `summary` string and, where relevant, a `pagination` object with `next_cursor` and `has_more`.

#### Identity & org context

| Tool         | Purpose                                                            |
| ------------ | ------------------------------------------------------------------ |
| `whoami`     | Email, plan, current org, and paginated org membership.            |
| `switch_org` | Activate an org\_id for all subsequent calls (membership-checked). |

#### Discovery (read-only)

| Tool                         | Purpose                                                                                                                                                                                                                                                                                         |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`list_projects`**          | Cursor-paginated projects, split into `owned` vs `accessible`. Pass `owned_only=true` to limit.                                                                                                                                                                                                 |
| **`list_connections`**       | OAuth/API-key credentials the user has authorized. Filter by `provider_id`.                                                                                                                                                                                                                     |
| **`list_knowledge_bases`**   | Compact KB list (id, name, file count, last sync). `verbose=true` for full metadata.                                                                                                                                                                                                            |
| **`list_providers_actions`** | Integration catalog. Three modes: `null` → catalog summary; single `provider_id` → that provider's actions/triggers in compact form; `provider_id` + `actions=[...]` → full input/output schemas for those specific action ids. Cached server-side (`CATALOG_CACHE_TTL_SECONDS`, default 300s). |
| **`list_triggers`**          | Project-scoped trigger configurations (cron / webhook / polling). `verbose=true` for full metadata.                                                                                                                                                                                             |

#### Project inspection (read-only)

| Tool                          | Purpose                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
| ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`get_project`**             | Node-centric **paginated subgraph** of a flow. Each page is self-contained — it carries a window of nodes, every edge incident to those nodes, and `referenced_node_ids` for endpoints outside the window. Boundary edges appear in two adjacent pages — dedupe by `edge.id`. Pass `include_flow_json=true` only when you need the raw upstream blob (refused with `flow_too_large` past the inline cap).                                                                                                                  |
| **`get_project_corrections`** | Re-validates a draft and returns paginated correction entries (each with `node_id`, `provider_id`, `action_id`, `param`, reason `unknown_param` / `wrong_type` / `invalid_select_value`, expected type, dropped-value preview). Use this as the follow-up when `create_project` / `edit_project` returned `corrections_truncated=true`.                                                                                                                                                                                    |
| **`validate_workflow`**       | Runs every pre-flight check against the **draft** (cycles, dangling edges, missing I/O nodes, unknown providers/actions, unresolved connections, action-param shape, plus warnings for orphans, unconnected I/O, LLM nodes without a system message). Top-level `is_runnable` is the one-bit blocker answer; `error_count` / `warning_count` are run-wide so they survive pagination. `severity_filter="errors_only"` drops warnings. Each finding has a stable `code`, a `locator`, a `detail` dict, and a `next_action`. |
| **`get_run`**                 | Per-node execution trace, filtered for debugging by default (`severity_filter="failed_or_slow"`, inputs/outputs stripped). Use `node_ids=[...]` to expand specific nodes, `severity_filter="all"` to see everything. `failed_nodes` is global across pages.                                                                                                                                                                                                                                                                |
| **`search_kb`**               | Semantic / keyword / hybrid search over an indexed KB. Returns chunks with `text_preview` only — call again with `expand_chunk_ids=[...]` (up to 20) to get full `text` for specific chunks.                                                                                                                                                                                                                                                                                                                               |

#### Mutating tools (suppressed when `READ_ONLY_MODE=1`)

| Tool                 | Purpose                                                                                                                                                                                                                                                                                      |
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **`create_project`** | LLM generates nodes/edges from a natural-language `description`, saves the draft, and auto-publishes.                                                                                                                                                                                        |
| **`edit_project`**   | Two modes on the same tool: pass `description` for an LLM-driven rewrite, OR pass `direct_patch=[...]` with structured ops (`add_node`, `remove_node`, `update_node`, `add_edge`, `remove_edge`). Pass `publish=true` to also publish the draft (destructive — overwrites the live version). |
| **`run_project`**    | Execute a published project with typed `inputs`. Each call creates a new run and may hit external services.                                                                                                                                                                                  |

### 5. Recommended workflows

#### "Build me a new workflow"

1. `whoami` → `switch_org`
2. `list_providers_actions` (no args) → see what integrations exist
3. `list_connections` → check what's already authorized
4. `create_project` with a description
5. If response carries `corrections_truncated=true` → `get_project_corrections` to see every dropped param
6. `validate_workflow` → confirm `is_runnable`
7. `run_project`

#### "Debug this run"

1. `get_run` with the failing run\_id (default filter shows failed-or-slow)
2. Pick failing `node_id` → `get_run` again with `node_ids=[...]` to read full inputs/outputs
3. `validate_workflow` to see if it's a draft-shape issue
4. `edit_project` with `direct_patch` to fix the offending node, or `description` to rewrite

#### "Fix the contract of an action"

1. `list_providers_actions` with `provider_id="<id>"` → see compact action list
2. `list_providers_actions` with `provider_id="<id>"` + `actions=["<action_id>"]` → get full input/output schema
3. `edit_project` with a `direct_patch` `update_node` op

### 6. Gotchas

* **Always `switch_org` first if you are in multiple tenants.** Org-scoped tools fail closed with a `MissingOrgError` pointing back at `whoami`.
* **`get_project` paginates by node, not by edge.** Cross-page edges are duplicated — dedupe by `edge.id`.
* **`validate_workflow` reads the draft, not the published version.** Call it after `edit_project` (with `publish=false`) and before `run_project`.
* **`search_kb` text is truncated.** Use `expand_chunk_ids` for full text on the few chunks that matter.
* **Stateless HTTP transport.** No `Mcp-Session-Id` handshake; every request re-authenticates via its bearer token. `switch_org` on one pod propagates to others within `ACTIVE_ORG_CACHE_TTL_SECONDS` (default 60s).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.stackai.com/interface-and-deployment/mcp-reference/stackai-mcp-server.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
