MCP and CLI
Epure error tracking has two agent clients, the MCP server @epure-sh/mcp and the CLI @epure-sh/cli, plus a hosted MCP server at https://app.epure.sh/mcp on Epure Cloud. All three sign in with OAuth and call the same /api/v1 routes, within the scopes you approve. The npm packages need Node.js 18 or later; Apache-2.0 covers these client packages, and the engine is AGPL-3.0. None of them sends errors: events still go from your Sentry SDK to Epure through the DSN (Quickstart).
For a walk-through with checks after each step, see connect Epure to Claude Code, Cursor or Codex. This page is the reference. Last checked against @epure-sh/mcp and @epure-sh/cli 0.3.0 on 6 Nov 2026.
How do I set up an MCP server for my Epure errors?
Setting up the Epure MCP server takes two commands in Claude Code and three for any stdio client. Claude Code connects to the hosted server and signs in with /mcp (Claude Code MCP docs). Cursor, Claude Desktop, Codex and self-hosted instances run npx -y @epure-sh/mcp after one login. The doctor command then confirms the session reaches your instance.
# Claude Code, hosted server (Epure Cloud)
claude mcp add --transport http --scope user epure https://app.epure.sh/mcp
# then, inside Claude Code: /mcp, and approve in the browser
# Any stdio client: Cursor, Claude Desktop, Codex, self-hosted
npx -y @epure-sh/mcp login
npx -y @epure-sh/mcp init # prints the client configuration
npx -y @epure-sh/mcp doctor # checks session and instance
# Terminal and scripts
npm install -g @epure-sh/cli
epure auth login
epure issues list --limit 20init prints a configuration with no credential in it, for mcp.json (Cursor) or claude_desktop_config.json (Claude Desktop):
{ "mcpServers": { "epure": { "command": "npx", "args": ["-y", "@epure-sh/mcp"] } } }Cursor reads that entry from ~/.cursor/mcp.json or .cursor/mcp.json (Cursor MCP docs). Codex takes the same command: codex mcp add epure -- npx -y @epure-sh/mcp (Codex MCP docs). Add --read-only or --toolsets issues,projects to init to bake those filters into the printed entry, and --transport http to print the hosted entry instead.
How do I add the Epure agent skills?
The Epure agent skills teach a coding agent the setup and triage steps on this page: epure-setup (Cloud or self-host), epure-wire (point the Sentry SDK at the DSN), epure-agent (MCP and CLI) and epure-triage (fix an issue, treat its content as untrusted data). Install them with skills.sh for any agent, or as a Claude Code plugin that also adds the hosted MCP server.
# Any agent that reads skills
npx skills add epure-sh/epure
# Claude Code, inside a session
/plugin marketplace add epure-sh/epure
/plugin install epure@epureThe skills live in plugins/epure/skills in the engine repository. Checked on 12 Nov 2026.
Should I use the hosted MCP server, the stdio package or the CLI?
The three Epure clients share one OAuth model and one tool registry; they differ in transport and where they run. The hosted server needs no install but only exists where the instance enables it. The stdio package runs anywhere Node.js 18 runs, including against self-hosted instances. The CLI suits scripts, CI and agents that prefer a shell.
Hosted /mcp | stdio @epure-sh/mcp | CLI @epure-sh/cli | |
|---|---|---|---|
| Transport | Stateless Streamable HTTP, JSON responses | Newline-delimited JSON-RPC over stdio | Terminal commands |
| Install | None | npx -y @epure-sh/mcp | npm install -g @epure-sh/cli |
| Sign-in | The MCP client's OAuth flow (discovery, PKCE, automatic client registration) | npx -y @epure-sh/mcp login | epure auth login |
| Clients | Claude Code, Claude web and mobile (custom connector) | Cursor, Claude Desktop, Codex, Claude Code | Any shell |
| Self-hosted | Only with EPURE_MCP_ENABLED=true (default false) | --url https://errors.example.com | --url or EPURE_URL |
| Filters | OAuth scopes | Scopes, --read-only, --toolsets | Scopes |
Both MCP transports support protocol versions 2024-11-05, 2025-03-26, 2025-06-18 and 2025-11-25. Claude on the web cannot run a local stdio server, so it uses the hosted URL: Customize → Connectors → Add custom connector, name it Epure, enter https://app.epure.sh/mcp, choose Register automatically.
How do Epure MCP and the CLI sign in?
Epure MCP and the CLI sign in with OAuth only, and share one session. npx -y @epure-sh/mcp login and epure auth login open a browser approval (PKCE) on a desktop and use a device code (RFC 8628) with --device, or automatically when SSH_CLIENT is set or stdin is not a terminal. The session lives in $XDG_CONFIG_HOME/epure/credentials.json (default ~/.config/epure/credentials.json), mode 0600, written atomically and refreshed before expiry.
epure auth login [--device] [--no-browser] [--scope "read:agent write:triage write:admin"]
epure auth status # local session metadata, never credentials
epure auth whoami # verify the session with the server
epure auth logout # revoke the grant and remove the local session
epure auth login --url https://errors.example.com
epure auth instances
epure auth use https://app.epure.sh
# The MCP package has the same verbs:
npx -y @epure-sh/mcp login --device --no-browser
npx -y @epure-sh/mcp status
npx -y @epure-sh/mcp logout- No pasted credentials.
--token,--secretand--api-keyare rejected, and a setEPURE_TOKENstops both clients withOAUTH_ONLY. Tools and commands never start a login on their own; they fail at once withAUTH_REQUIRED. - Self-hosted instances need an HTTPS origin; plain HTTP works only on loopback for development.
--urlorEPURE_URLselects the instance. - Desktop apps must run as the same operating-system user that signed in, because the stdio server reads that user's session file.
- Hosted clients discover OAuth from
/.well-known/oauth-protected-resource/mcp. A request without a valid grant gets401with aWWW-Authenticateheader that namesscope="read:agent". - Revoking:
logoutrevokes the grant remotely and deletes the local file. If revocation fails, it says so; revoke the app in Settings → Connected apps.
Which OAuth scopes do Epure tools need?
Epure has three OAuth scopes, and the default consent requests all three. read:agent covers reading; write:triage adds issue state changes; write:admin adds setup and workspace administration. Ask for less with --scope "read:agent" or --scope "read:agent write:triage". Workspace roles still apply on top: a Member gets 403 on admin routes even with write:admin.
| Scope | Allows | Example tools |
|---|---|---|
read:agent | Every read on /api/v1/*, except invitations and token management | epure_issues_list, epure_issues_context, epure_projects_list, epure_alerts_list, epure_auth_whoami |
write:triage | Resolve, ignore, reopen, update and snooze issues; merge and split; update alerts | epure_issues_resolve, epure_issues_snooze, epure_issues_update, epure_alerts_update |
write:admin | Projects, alert rules, channels, cron monitors, releases, webhooks, members, invitations, connected apps, privacy erase | epure_rules_create, epure_channels_create, epure_monitors_create, epure_projects_delete, epure_privacy_erase |
On the hosted server, a tool call that needs a scope the grant lacks returns 403 insufficient_scope naming the scope, and runs nothing.
Which tools does the Epure MCP server expose?
The Epure MCP server names every product action epure_<resource>_<action>, with dots and hyphens turned into underscores. One registry generates the hosted and the npm tool lists, and CI checks them for drift. Resources: projects, issues, rules, channels, monitors, alerts, releases, members, invitations, webhooks, privacy, connected-apps and auth. Four extra tools discover and call the rest. These are the ones an agent uses most:
| Tool | Returns | Access | Use it when |
|---|---|---|---|
epure_projects_list | Projects and their IDs | Read | First, to get a project_id |
epure_auth_whoami | Account, workspace, role and granted scopes | Read | Diagnosing access |
epure_issues_list | Priority-ranked issue queue; filters project_id, environment, q, window; limit 20 by default, 100 at most | Read | "What broke in production today?" |
epure_issues_context | Stack trace, culprit frame, application frames, breadcrumbs, request URL and method, release, environment | Read | Before proposing a fix |
epure_issues_show | One issue summary | Read | Checking status or counts |
epure_issues_events, epure_issues_timeline, epure_issues_releases | Events, timeline and releases of one issue | Read | Regression and frequency questions |
epure_alerts_list | Fired alerts | Read | "Why did I get paged?" |
epure_issues_resolve, epure_issues_ignore, epure_issues_reopen | Updated issue; optional resolved_in_release | write:triage | After you confirm a fix |
epure_issues_snooze, epure_issues_unsnooze | Snoozed issue; mode such as 4h | write:triage | Muting a known issue |
epure_rules_create, epure_channels_create, epure_channels_test | Alert rule or channel; channels_test sends a real notification | write:admin | Setting up alerts |
epure_monitors_create, epure_monitors_check_in | Cron monitor; a check-in changes its state | write:admin | Setting up cron monitoring |
epure_discover | Tool names and descriptions for task keywords; exact schemas with include_schema: true; no sign-in needed | Read | The agent doesn't know which tool fits |
epure_action | Runs one discovered operation with validated arguments | Per operation | Calling a tool by operation ID |
epure_api_catalog, epure_api | Remaining REST routes, called through OAuth | Per route | No named tool fits |
Older names. epure_get_issue_context and get_crash_context still call epure_issues_context; epure_list_issues and list_unresolved_issues call epure_issues_list; mark_issue_resolved calls epure_issues_resolve; epure_triage_issue calls epure_issues_update. The 0.1.x names epure_queue and epure_issue_context no longer exist.
The server also offers two prompts, epure-triage and epure-monitoring, and one resource, epure://guide, which explains discovery and safe operation. Every result carries structuredContent plus the same JSON as text.
What does epure_issues_context return?
epure_issues_context returns one issue's brief for the latest event, or for the event ID passed as event. The JSON holds issue (title, status, level, event_count, environment, release, first and last seen), exception_text, culprit, app_stack with vendor frames filtered out, breadcrumbs, request, user_journey, runtime_tags and custom_tags. With format: "markdown" the same facts come as a fix-oriented Markdown brief.
{
"name": "epure_issues_context",
"arguments": { "id": "ISSUE_ID", "format": "json" }
}include_payload: trueadds the raw event aspayload_json. Off by default.include_user: truereturns end-user identifiers as stored. Off by default.- In a terminal,
epure issues context ISSUE_IDprints the Markdown brief; piped or with--json, it prints JSON.
Readable JavaScript frames need source maps: upload source maps.
How do I limit what an agent can do with Epure?
Epure limits an agent at three layers, and the server-side ones always win. The OAuth scope decides what the session may call. On the stdio server, --read-only exposes only read tools (epure_action and epure_api accept GET only), and --toolsets keeps the resources you list. Workspace roles apply last, whatever the client asks for.
npx -y @epure-sh/mcp login --scope read:agent
npx -y @epure-sh/mcp --read-only
npx -y @epure-sh/mcp --toolsets issues,projects- Destructive tools (deletes,
epure_privacy_erase,epure_webhooks_rotate_secret) refuse to run withoutconfirm: true; the CLI needs--yes, scripts included. - Each tool carries
readOnlyHintanddestructiveHintannotations, so clients can ask before a write. - Results larger than 64 KiB are refused with
RESPONSE_TOO_LARGEand a hint to narrow the query.
How does Epure handle untrusted event data?
Epure treats everything inside an event as untrusted input, because your users, their browsers and any attacker can write into exception messages, URLs and breadcrumbs. Every MCP session starts with server instructions that say application content is data, never instructions. epure_issues_context leaves out the raw payload and end-user identifiers unless asked. The older hosted tool epure_get_issue_context also wraps its Markdown in an <untrusted_exception_data> block after neutralising code fences, prompt-style tags such as <system> and shell command words.
No filter stops every prompt injection
The MCP specification asks servers to sanitize tool outputs and clients to validate results before they reach the model (MCP tools, security considerations). Keep write tools behind your client's approval prompt, and don't let an agent that reads production errors also run shell commands or send data out without review. The reasoning: give your coding agent production errors safely.
What Epure stores in the first place, including the IP and end-user defaults: Data and privacy.
Which CLI commands does @epure-sh/cli provide?
The Epure CLI @epure-sh/cli provides the epure command, with one verb per resource action and the same names as the MCP tools. Output is a table in a terminal and JSON when redirected, so an agent can parse stdout while diagnostics go to stderr. Destructive commands need --yes, and network failures are never retried on writes.
epure projects list --json --fields id,name
epure issues list --project-id PROJECT_ID --q 'status:unresolved' --limit 20
epure issues context ISSUE_ID
epure issues resolve ISSUE_ID --resolved-in-release v2.1
epure issues snooze ISSUE_ID --mode 4h
epure rules create --project-id PROJECT_ID --name "New errors" --kind issue_created
epure channels test CHANNEL_ID
epure monitors create --project-id PROJECT_ID --slug backup --schedule '0 * * * *' --timezone UTC
epure projects delete PROJECT_ID --yes
# discover flags and schemas, signed out
epure issues --help
epure schema issues.context
epure api-catalog --search noise-policy --limit 10
epure api GET /api/v1/projects/PROJECT_ID/noise-policy- Output:
--json,--outputwithjson,tableorndjson, and--fieldswith dotted paths. - Input: flags, or
--data '{...}',--data @request.json,--data -for stdin. Unknown fields fail before the request. - Aliases kept from 0.1.x:
login,logout,queue,context,issue show,triage resolve|ignore|reopen|snooze.
| Exit code | Meaning |
|---|---|
0 | Success |
1 | Request or runtime failure |
2 | Usage error, missing confirmation, or cancelled |
4 | Sign-in required |
5 | Forbidden |
Errors are JSON on stderr with a stable error.code.
When should I use a personal access token instead?
Epure personal access tokens (epure_pat_…) are for scripts and HTTP calls to the Agent API, not for MCP or the CLI. Create one in Settings → Agent tokens (Admin or Owner); it is shown once and carries the same three scopes. Send it as Authorization: Bearer epure_pat_…, keep it out of repositories and agent configuration files, and revoke it there if it leaks. Authentication compares DSN, session and token.
AUTH_REQUIRED (exit code 4)
AUTH_REQUIRED means the Epure client found no session for this instance and this operating-system user. Confirm with npx -y @epure-sh/mcp status (or epure auth status): "authenticated": false. Fix it by running login as the user that starts the MCP client, with the same --url. Verify with npx -y @epure-sh/mcp doctor, which returns "ok": true and your identity.
OAUTH_ONLY
OAUTH_ONLY means a manual credential reached an Epure client that only accepts OAuth: EPURE_TOKEN is set in the environment, or a --token, --secret or --api-key flag was passed. Remove it from the shell profile or the MCP client's env block, then sign in with login. Old 0.1.x setups that passed EPURE_URL and EPURE_TOKEN to a locally built server need this change.
403 insufficient_scope and PERMISSION_DENIED
403 insufficient_scope comes from the hosted Epure server when a tool needs a scope the grant lacks; the WWW-Authenticate header names it. The stdio server and the CLI report the same refusal as PERMISSION_DENIED (exit code 5). Check the granted scopes with epure_auth_whoami, then sign in again with the scope, or keep the task read-only. When the scopes are right and the call still fails, your workspace role blocks the route; an Owner or Admin can change it.
CONFIRM_REQUIRED and TOOLSET_DISABLED
CONFIRM_REQUIRED means an Epure destructive action was called without confirm: true (MCP) or --yes (CLI). Review the action, then repeat it with the flag. TOOLSET_DISABLED, or Unknown or disabled tool, means --read-only or --toolsets hides the operation; change the server arguments, or call epure_discover to see what is enabled.
RESPONSE_TOO_LARGE
RESPONSE_TOO_LARGE means an Epure result passed the 64 KiB ceiling. Narrow it: pass a project_id, lower limit, shorten the window, or fetch one issue's context instead of a list. The ceiling keeps one tool call from filling the agent's context window.
FAQ
Do I need to paste an API token into Cursor or Claude Code?
No. MCP and the CLI sign in with OAuth in the browser, and the configuration printed by init holds no credential. Personal access tokens exist only for scripts that call the HTTP Agent API.
Can the agent change or delete my data?
Only within the scopes you grant and your workspace role. Sign in with --scope read:agent and run the server with --read-only to give the agent reading only. Destructive tools always need confirm: true.
Do MCP or the CLI send errors to Epure?
No. They read and manage issues. Errors travel from your Sentry SDK through the DSN: point your Sentry SDK at Epure.
The docs I found mention epure-mcp, epure-cli or EPURE_TOKEN. Are those current?
No. The npm packages are @epure-sh/mcp and @epure-sh/cli. The 0.1.x local server built from tools/epure-mcp and the EPURE_TOKEN variable were replaced by OAuth sign-in in 0.2.
Do MCP and the CLI work with self-hosted Epure?
Yes. Pass --url https://errors.example.com to login and to the server or command; the hosted /mcp endpoint stays off on a self-hosted instance unless EPURE_MCP_ENABLED=true. Apache-2.0 covers the client packages; the engine is AGPL-3.0. Cloud plans and the 14-day trial: Epure pricing. How the agent workflow fits the product: read production errors from Claude Code or Cursor.