Skip to main content
The official Erstan plugin connects Claude and Codex to the hosted Erstan MCP server. It includes maintained Skills for working with agents, runs, Skills, tasks, projects, documents, and files. Each user signs in through browser-based OAuth and chooses exactly which workspace access to grant.
The plugin contains no API key. Erstan remains the source of truth for permissions, resources, expiry, and revocation. Claude or Codex can require additional confirmation, but the host cannot grant access that Erstan denied.

Install the official plugin

The public plugin repository is erstanai/erstan-agent-tools. In both command-line hosts, erstan@erstan means plugin-name@marketplace-name; it is not a secret or an account-specific identifier.
1

Add the Erstan marketplace

Run:
2

Install Erstan

Run:
3

Connect your Erstan account

Start a new Codex session, use /plugins to confirm that Erstan is installed, and complete browser sign-in when prompted.

Choose access in Erstan

The OAuth consent screen asks you to choose a workspace, an access profile, and a resource boundary. The default Build profile supports agent creation and operation without allowing the external host to edit tasks, documents, or files. Custom access can use these server-enforced permissions: For resources, choose All I can access or Selected teams and projects. Erstan always intersects that choice with the connection owner’s live workspace access. Later losing access to a team, project, or agent therefore removes it from the connected app as well.
Read the host’s local confirmation prompt as well as the Erstan consent screen. Erstan sets the maximum allowed access; Claude or Codex may narrow it further or ask for confirmation before an action.

Manage, revoke, and audit access

Open Settings → Connected apps in Erstan to review each connection’s owner, profile, permissions, resources, last use, expiry, and status.
  • Reducing access takes effect immediately.
  • Increasing access requires explicit reauthorization in Claude or Codex; an app cannot expand its own grant.
  • Revoking a connection invalidates it for every host session using that grant.
  • Workspace owners and admins can review all workspace connections and revoke them when required.
For lifecycle evidence, open Admin → Audit → Connected apps. The audit records Connected, Reauthorized, Permissions changed, and Disconnected events, including disconnection by the OAuth provider. Use Admin → Audit → Tools for individual MCP tool calls and their outcomes.

What the MCP server is

The plugin connects to Erstan’s stateless streamable-HTTP MCP endpoint:
  • POST https://api.erstan.com/v1/mcp carries JSON-RPC over HTTP. Each request is independent; there are no SSE sessions in v1 (GET and DELETE return 405).
  • OAuth discovery, authorization, refresh, expiry, and revocation are handled by the host and Erstan.
  • tools/list returns only tools allowed by the grant. tools/call re-checks the grant, the owner’s live permissions, and its resource boundary every time.
  • Tool calls are rate limited per connection and written to the workspace audit trail.

Advanced: direct API-key clients

The recommended Claude and Codex setup is the plugin and OAuth flow above. The advanced API-key option remains available for automation and MCP clients that do not support the plugin or OAuth discovery. Create a key under Settings → API Keys, select only the required scopes, and configure its resource allowlists. Task visibility uses allowedProjectIds and allowedTeamIds; document and file access requires allowed teams. Follow API keys for creation, storage, rotation, and revocation. Never commit a key or paste it into a shared plugin configuration.

Send a task to the external queue

In a task, open the Agent picker and choose Agent → Advanced → External queue. This explicit opt-in makes the task available for external MCP pickup; choosing an internal agent keeps execution inside Erstan. API and MCP callers use the same externalExecution field. Pass externalExecution: true when creating a top-level task or subtask that should enter the external queue. It defaults to false. Opt-in does not grant access. An OAuth connection needs View work to discover tasks and Manage work to claim, comment on, or complete them; its resource boundary must include the task’s project or team. An API-key client needs tasks:execute plus a matching allowedProjectIds or allowedTeamIds entry. The server rechecks permission, resource access, queue eligibility, and task state on every read, claim, and completion call.

Tools

tools/list shows a tool only when the grant holds every required permission. Advanced API-key clients use the equivalent scopes documented in API keys.

Tasks and projects

Creating a task does not send it to the external queue by default. Set externalExecution: true explicitly when the new task should flow through get_next_task. Use list_task_options before setting relationship IDs. Pass taskId when editing an existing Task, or projectId/teamId while constructing a new one. By default it returns all six picker domains; include can select teams, projects, agents, members, labels, and/or parent_tasks. search and limit keep large workspaces bounded. Agent results use the same published-version, task-ingress, marketplace-readiness, team-sharing, and current-user readability rules as the Task editor. Members are restricted to people assignable in the target team. Parent candidates are accessible, non-terminal Tasks in the correct scope; for an existing Task, Erstan excludes the Task and all descendants so the list cannot advertise a cycle. A project-only connection can anchor options through its projectId or an existing visible taskId; that does not silently grant team-wide Task creation. list_agents remains the general runnable-Agent catalog under View agents. list_task_options is the Task-specific relation catalog under View work, so resolving a valid workflowId for update_task does not require a second Agent permission. read_task returns the Task’s scalar properties and stable relationship IDs, including parentTaskId, ordered children, primaryThreadId, currentExecutionId, threadReferences, recent runs, and pendingApprovals. Each run reference carries its runId/execution ID plus threadId and checkpointThreadId. Use those exact IDs with the Task-run tools; never guess a run or thread ID. update_task validates subtask moves end to end. A parent must be an accessible, non-terminal Task in the same workspace/team, and the move must not create a cycle. When parentTaskId changes without an explicit sortOrder, Erstan appends the Task to the new parent’s ordered children. Archive and cancellation use their dedicated lifecycle tools so active runs and descendant Tasks are handled correctly. Parent/child links do not widen the connection’s project/team resource boundary. read_task expands only allowlisted parent/child detail, and an archive/delete cascade fails closed unless every affected descendant remains inside that boundary.

Comment on a task with attachments

attachments is a top-level comment_on_task argument alongside taskId, optional body, and optional teamId. Each attachment needs name, type, and base64-encoded content. body is optional when at least one attachment is present; Erstan generates a short comment such as Attached evidence.txt when it is omitted. An Erstan server cannot read a local filesystem path. The local client must read the file, encode its bytes, and supply them in the tool call:
Files are stored in the Task’s team and linked to the new comment in one tool workflow. For a Team-less Task, Erstan uses an allowlisted workflow default team when available; otherwise pass an allowlisted teamId. When the Task already has a team, any supplied teamId must match it. A call can include up to 10 files, subject to the workspace upload limits, and the complete MCP JSON request is limited to 25 MB, including base64 expansion. Manage work authorizes the task-scoped upload; callers do not also need Edit files. read_task returns each attachment’s teamFileId and its comment activityId. When fileReadable is true, a caller that also has View files can pass the teamFileId to read_file to retrieve the bytes. For a top-level Task attachment/reference, use add_task_attachment with one of:
  • kind: "upload" plus name, type, and base64;
  • kind: "team_file" plus teamFileId;
  • kind: "document" plus documentId; or
  • kind: "external_url" plus an HTTP(S) url.
remove_task_attachment removes only the TaskAttachment link. It never deletes the underlying Team file or document. Inbox attachment references are intentionally not available on this public surface.

Task-linked Agent runs and approvals

There are two deliberate run access paths:
  • General run tools (get_run, get_run_trace, reply_to_run, decide_run_approval) remain bound to the exact OAuth grant or API key that started the run and use View runs / Run agents.
  • Task-run tools first authorize the Task through View work / Manage work, then require the exact persisted Task→execution→thread relationship. They do not require a second Runs or Run agents permission. decide_task_run_approval records the authenticated Task collaborator as the resolver and atomically fences the current interactionId, approval, execution lease, thread interrupt, and resume job.
Reading and tracing remain available for historical/archived Tasks. Reply and approval mutations require an actionable, non-archived Task status. A stale interactionId, mismatched Task/run/thread relationship, or already-accepted decision fails closed; re-read with get_task_run before deciding what to do next.

Documents and files

Documents use a draft-and-publish lifecycle. read_document and search_documents expose publishStatus; draft and published documents are both valid context. Archived documents appear only where a tool explicitly includes historical content.

Agents and runs

General run handles are bound to the exact OAuth grant or API key that started them. Another connection in the same workspace cannot use the general run tools for that run. The Task-linked tools described above are the explicit exception: they derive access from the visible Task and exact persisted relationship. Reply and approval claims are single-use. If a delayed caller addresses an older interaction, Erstan returns run_interaction_changed; call get_run or get_task_run again and use the new interaction. Live token deltas are not persisted; complete messages replay from conversation_item.

Multi-turn conversations

A run belongs to one conversation thread. Which tool advances it depends on the run status from get_run:
  • Terminal (completed, failed, cancelled) → continue_run sends the next user message (optionally with attachments). Always poll get_run with the runId returned by the call: a completed plain chat run usually continues under the same runId, while other cases fork a new runId on the same thread (see below). Retries are safe with idempotencyKey — the same key rejoins the same turn.
  • waiting with a pendingInteraction of type user_inputreply_to_run with the exact interactionId.
  • waiting with a pendingInteraction of type approvaldecide_run_approval with the exact interactionId.
  • running → wait and poll get_run; a concurrent turn returns run_still_active.
How the follow-up executes mirrors the Erstan chat UI exactly:
  • Same-run continuation — a completed chat-lane run of an interactive agent re-queues the same execution with full conversation context.
  • Post-run continuation (new runId) — agents that use post-run continuation (non-interactive agents, and graphs with dedicated human-input nodes such as user-approval, ai-questions, or ai-wait-user-input) fork the one-node conversational shell, pinned to the source run’s version and carrying the source run’s tool and Skill capability envelope. This is how you ask follow-up questions about a completed structured (input-form) run, too — the shell converses about the run; it does not re-execute the authored graph.
  • Thread fork (new runId) — a chat run that ended failed or cancelled continues the conversation on a fresh execution with the prior thread history.
Builder Preview (test_agent) runs are single-turn, and structured runs of interactive agents return run_not_continuable — start a new run_agent run for those.

Run an agent with attachments

attachments is a top-level run_agent argument alongside agentId, input, laneId, and idempotencyKey. Do not nest attachments inside input. Each attachment needs name, type, and either base64-encoded file content or an existing Erstan attachment storageKey. An Erstan server cannot read a local filesystem path. The local client must read the file, encode its bytes, and supply them in the tool call:
The complete MCP JSON request is limited to 25 MB, including base64 expansion. Use list_agents first to confirm the lane supports attachments.

Agent and Skill authoring

See Build agents over MCP for the complete revision, validation, testing, and publication contract.

Included skills

The official plugin keeps its operating guidance versioned with the plugin instead of asking users to paste instructions into each project:
  • erstan-agent-builder — create, revise, validate, test, and publish Agent graphs.
  • erstan-agent-review — review definitions and diagnose runs from durable evidence.
  • erstan-run-operator — launch published Agents and handle waits, approvals, and traces.
  • erstan-skill-manager — manage complete, versioned Erstan Skill packages.
  • erstan-work-manager — work with authorized tasks, projects, documents, folders, and files.
The Erstan MCP server remains the enforcement boundary: it checks the OAuth grant or API-key scope, resource authorization, external-queue opt-in, task eligibility, atomic claims, and allowed state transitions on every call. A Skill or prompt cannot grant access or bypass those checks.

Common error codes

Next steps

Erstan Agent Tools

Review the public plugin, Skills, manifests, and release notes.

Working with tasks

Learn how tasks, external queues, and review work.

Build agents over MCP

Create, inspect, update, validate, test, and publish agent drafts.

API keys

Configure advanced non-OAuth automation clients.