---
slug: mcp
title: MCP
---

# MCP

The **Elaras Ask MCP server** exposes your agent workspace as
[Model Context Protocol](https://modelcontextprotocol.io) tools so any
MCP client — Claude Desktop, Claude Code, Cursor, Zed — can build,
version, test, and manage agents programmatically.

**Public endpoint:** `https://ask-api.elaras.ai/mcp` (Streamable HTTP transport)

## What it's for

- **Automate agent construction** — script agent creation, knowledge ingestion, personality versioning, skill/flow wiring
- **Test conversations in a loop** — send preview messages, read the full trace (which skills fired, with what inputs and outputs, flow transitions, token counts), and iterate
- **Regression-test with scenarios** — declarative multi-turn test cases with an AI judge for `required_facts`; run one or all, get pass/fail per turn

---

## Install

Two auth modes. Pick one per client.

### Option A — OAuth via browser (recommended for interactive clients)

Best for Claude Desktop, Cursor, Zed. No API key to paste anywhere.

**Claude Desktop:** Settings → Connectors → **Add custom connector**
```
Name: Elaras Ask
URL:  https://ask-api.elaras.ai/mcp
```
Click Connect. A browser opens ElarasAuth → sign in → consent to `chat:read chat:write` → tokens are stored by Claude Desktop. Tools appear in the tool picker.

**Claude Code CLI:**
```bash
claude mcp add --transport http elaras-chat https://ask-api.elaras.ai/mcp
```
First tool invocation triggers the OAuth browser flow. Subsequent calls reuse the stored token.

**Cursor / Zed:** same as Claude Desktop pattern — check each client's MCP config docs. All follow the [RFC 9728 protected-resource discovery](https://datatracker.ietf.org/doc/html/rfc9728) pointer we emit on 401.

### Option B — Personal Access Token (recommended for CI + automation)

Best when you want a long-lived key without a browser, e.g. GitHub Actions.

**1.** Sign in to your Elaras dashboard.  
**2.** Go to **Developer** → **New Key**.  
**3.** Give it a name (e.g. `ci-github-actions`) and click **Create Key**.  
**4.** Copy the `sk_...` value — shown once.  
**5.** Add to your MCP client's config file:

```json
{
  "mcpServers": {
    "elaras-chat": {
      "transport": "http",
      "url":       "https://ask-api.elaras.ai/mcp",
      "headers":   { "Authorization": "Bearer sk_..." }
    }
  }
}
```

Rotate anytime from Developer → API Keys. Old key is invalidated instantly.

---

## Tool catalog

**54 tools across 7 domains.** Every call is scoped to the team owning the bearer token.

### Agents (5)
| Tool | Purpose |
|---|---|
| `list_chatbots` | List every agent in your workspace |
| `get_chatbot` | Fetch one agent's config |
| `create_chatbot` | Create a new agent |
| `update_chatbot` | Change name, description, status, or assigned personality |
| `delete_chatbot` | Permanently remove an agent (destructive; ask before running) |

### Personalities + Versions (12)
Personalities are reusable AI configurations (system prompt, greeting, Anthropic model choice). Agents reference a **published** personality version — never a draft. See [Personality](/docs/ask/personality).

| Tool | Purpose |
|---|---|
| `list_models` | All models in workspace |
| `get_model` | One model + its versions |
| `create_model` | New model — accepts optional inline `system_prompt`, `greeting`, `underlying_model` |
| `update_model` | Rename or change model settings |
| `delete_model` | Remove a model and all its versions |
| `list_model_versions` | Versions of one model (draft + published) |
| `create_model_version` | New draft version of a model |
| `update_model_version` | Edit a draft (published versions are immutable) |
| `publish_model_version` | Freeze a draft as published; gated on ≥1 passing scenario |
| `clone_model_version` | Copy a version as a new draft (fork for experimentation) |
| `delete_model_version` | Remove a version |
| `assign_model_to_chatbot` | Point an agent at a specific published personality version |

### Scenarios + Scenario Runs (17)
Multi-turn test cases with pass/fail per turn. AI judge scores `required_facts` in each expected assistant reply. See [Scenarios](/scenarios).

| Tool | Purpose |
|---|---|
| `list_model_scenarios` | Scenarios owned by a model |
| `add_model_scenario` | New scenario against a model |
| `update_model_scenario` | Edit an existing scenario |
| `delete_model_scenario` | Remove a scenario |
| `draft_model_scenarios` | AI-drafts candidate scenarios from your model's system prompt |
| `list_chatbot_scenarios` | Scenarios owned by an agent (rarer; usually personality-scoped) |
| `add_chatbot_scenario` | New scenario against an agent |
| `start_model_scenario_run` | Kick off a run against a model version |
| `get_model_scenario_run` | Fetch results for a run |
| `list_model_scenario_runs` | All runs for a model |
| `cancel_model_scenario_run` | Stop a running run |
| `compare_model_scenario_runs` | Side-by-side diff between two runs (e.g. before/after a prompt change) |
| `start_chatbot_scenario_run` | Same for agent-scoped scenarios |
| `get_chatbot_scenario_run` | " |
| `list_chatbot_scenario_runs` | " |
| `cancel_chatbot_scenario_run` | " |
| `wait_for_scenario_run` | Blocking helper — poll until a run completes, then return results |

### Skills (5)
Skills let the AI call your HTTP endpoints during a conversation. See [Skills](/skills).

| Tool | Purpose |
|---|---|
| `list_skills` | All skills in workspace |
| `create_skill` | Register a new skill (name, description, endpoint URL, input_schema, output_schema) |
| `update_skill` | Edit skill config |
| `delete_skill` | Remove a skill |
| `test_skill` | Fire a test invocation with arbitrary inputs and inspect the response |

### Flows (5)
Deterministic conversation flows — set of states with transitions triggered by user intent or a skill result.

| Tool | Purpose |
|---|---|
| `list_flows` | All flows in workspace |
| `create_flow_via_ai` | Describe a flow in natural language; AI generates the flow spec |
| `update_flow` | Edit an existing flow |
| `delete_flow` | Remove a flow |
| `attach_flow_to_chatbot` | Link a flow to an agent |

### Preview (2)
Send test messages against any agent and get the full trace back.

| Tool | Purpose |
|---|---|
| `send_preview_message` | Send one message; response includes the assistant text + full trace |
| `clear_preview_session` | Reset a preview session's history |

### Knowledge (8)
Documents your agent can retrieve for RAG. Chunk text is never exposed via MCP — only document metadata.

| Tool | Purpose |
|---|---|
| `list_knowledge` | All documents in workspace |
| `get_knowledge` | One document's metadata + indexing status |
| `add_knowledge_url` | Fetch a URL, extract text, embed, index |
| `add_knowledge_crawl` | Crawl a website, add every page as a document |
| `add_knowledge_qa` | Add a Q&A pair (fastest path — no scraping) |
| `wait_for_knowledge_indexing` | Blocking poll until a document is `indexed` or `failed` |
| `delete_knowledge` | Remove a document (permanent) |
| `resync_knowledge` | Refetch + re-embed an existing URL-sourced document |

---

## Preview response

`send_preview_message` returns a full trace alongside the assistant's reply so you can see exactly what happened during the turn:

```json
{
  "session_token": "01HXYZ...",
  "response":      "It is 12:00 UTC.",
  "credits_used":  2,
  "enrichment":    null,
  "trace": {
    "skills_called": [
      {
        "name":       "get_time",
        "input":      { "tz": "UTC" },
        "output":     "{\"time\":\"12:00\"}",
        "latency_ms": 42
      }
    ],
    "flow_transitions": [
      { "from": "greeting", "to": "asking_purpose", "trigger": "user_provided_name" }
    ],
    "model_used":     "claude-sonnet-4-6",
    "input_tokens":   150,
    "output_tokens":  30
  }
}
```

Fields:
- **`skills_called`** — every skill invoked this turn, with the AI-generated input, your endpoint's output (truncated to 4KB), and wall-clock latency. Assert that the agent called the right skill with the right args.
- **`flow_transitions`** — flow state changes triggered by this turn.
- **`model_used`** — the underlying Anthropic model that answered.
- **`input_tokens` / `output_tokens`** — for cost accounting.

---

## Example workflows

### Build an agent from scratch, publish, verify

Prompt Claude Desktop / Code:

> Build an agent for a small vet clinic:
> - Add knowledge for hours (Mon-Fri 8am-6pm, Sat 9am-1pm), phone (555-0123), and services (routine checkups, vaccinations, emergencies).
> - Create a personality with a friendly, concise tone.
> - Add three scenarios covering hours, phone number, and emergency handling.
> - Run the scenarios; publish the personality version once they pass.
> - Assign the published version to the agent.
> - Send a preview message "when are you open on saturday?" and confirm 9am to 1pm appears.

### Iterate a scenario until it passes

> Test scenario `scn_abc123` against model version `mv_xyz789`. If any turn fails, tell me which required_facts were missing and suggest a system-prompt tweak that would fix it. Loop until it passes.

### Regression-test after a prompt change

> Clone the currently-published version of personality `Concierge` as a new draft. Update the greeting to say "Welcome to the Blue Room." Run every existing scenario against the draft. Compare pass rates between the draft run and the last published run. If the draft doesn't regress, publish it and reassign the agent.

---

## Tool safety annotations

Every write tool carries [MCP tool annotations](https://modelcontextprotocol.io/specification/server/tools#tool-annotations) so client UIs can decide whether to auto-run or ask for confirmation:

| Annotation | Meaning | Example tools |
|---|---|---|
| `readOnlyHint: true` | Never mutates state. Safe to auto-run. | `list_*`, `get_*`, `wait_for_*`, `compare_*`, `test_skill`, `send_preview_message` |
| `destructiveHint: true` | Removes data or does something hard to reverse. Clients should confirm. | `delete_*`, `publish_model_version` (irreversibly freezes a version) |
| `idempotentHint: true` | Calling twice with the same args has the same effect as once. Safe to retry. | `update_*`, `assign_model_to_chatbot`, `attach_flow_to_chatbot`, `resync_knowledge` |

Claude Desktop, Cursor and Claude Code all honour these — you'll see a confirmation prompt before any `destructiveHint` tool runs. `test_skill` and `send_preview_message` are marked read-only despite hitting your endpoints, because they don't mutate Elaras state.

---

## Scope enforcement

sk_ PATs and OAuth tokens carry scopes. Requests without the right scope return `403 insufficient_scope`.

| Scope | Grants |
|---|---|
| `read` (or `chat:read`) | `list_*`, `get_*`, `wait_for_*`, `compare_*` |
| `write` (or `chat:write`) | Everything else (`create_*`, `update_*`, `delete_*`, `publish_*`, `add_*`, `test_*`, `send_preview_message`, `start_*_run`, etc.) |

For OAuth clients the scopes are namespaced (`chat:read`, `chat:write`) so consent screens can group them by product. Both forms are accepted.

---

## Rate limits

`60 requests/minute per team`. Applies across sk_ PAT and OAuth tokens for the same team.

Bulk workflows (e.g. seeding 50 scenarios) should space calls with a short delay or split across multiple keys.

---

## Support

Email support@elaras.ai for any issue — bug reports, integration questions, or urgent production incidents. Please include the MCP tool name, the arguments you called it with, and the response you received.
