On this page

MCP server

The Model Context Protocol interface gives external AI clients scoped access to the same platform. It is opt-in, and its limits are enforced structurally rather than by prompt instructions.

AspectDetail
TransportStreamable HTTP at /mcp
IdentityExactly one authenticated account per call; user_id is never a tool argument
Default stateOff — MCP_ENABLED=true mounts it, read at boot
Live governanceAn admin can disable it, force read-only, or restrict token minting without a redeploy
Resourcesmate://docs/usage, mate://processes, mate://process/{log_id}/module/{module_id}
Discoveryget_server_info reports the live toolset and scope set; mate://docs/usage is the agent's starting document

Enabling the server#

.env on the server
MCP_ENABLED=true
API_BASE_URL=https://mate.example.org     # required for OAuth discovery
MCP_TOOLSETS=                             # empty = everything except admin
MCP_REQUIRE_EGRESS_CONSENT=true
Terminal
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d   # recreate, not restart

The proxy already routes /mcp and /.well-known/oauth-protected-resource to the API.

Authentication#

MethodHow it works
Personal access tokenA mate_pat_… token minted in Settings → API & MCP. It acts as its owner, on that owner's data only, and can never carry admin. An empty scope grant means all read scopes.
OAuth 2.1The client discovers Keycloak from the 401 challenge (RFC 9728), runs auth-code with PKCE, then retries with the JWT. The admin scope additionally needs the admin realm role on the same token.

Independently of the credential, each user opts in once to external data access; without it, tools answer [consent_required]. That makes consent a per-user switch rather than a per-token one, so a stolen token cannot silently widen egress.

Scopes and toolsets#

ScopeGrants
processes:read / processes:writeLog metadata and aggregates / import, rename, filter, delete, folders
modules:read / modules:write / modules:manageModule outputs and datasets / per-module configuration / install lifecycle
dashboards:read / dashboards:writeRead boards (own and shared) / create, edit, share, delete
jobs:read / jobs:controlList, get, wait / cancel, retry, queue pause and resume
watched:read / watched:writeRead watched folders / create, update, scan, delete
account:read / account:writeUsage summary and token list / revoke your own tokens
adminThe admin toolset — OAuth plus the admin realm role only
ToolsetCovers
meta (always on)get_server_info, whoami
processesLog listing and detail, activities, variants, data quality, OCEL views, folders, import, remap, re-import, duplicate, delete
analysisModule inventory and availability, curated module outputs, dataset catalogue, cached guidance, module configuration, plus the convenience readers get_bottlenecks, get_conformance, get_process_model, get_drifts
dashboardsBoard CRUD, card catalogue, export and import, shares, share targets
jobsList, get, wait, cancel, retry, queue control
watchedWatched-folder CRUD and scan
accountUsage summary, token list, revoke
adminCross-user jobs, users, teams, insights, MCP governance, token oversight — module policy stays REST-only

Conventions#

ConventionBehaviour
Dry runsDestructive tools take confirm: bool; without it they return a preview and mutate nothing.
Long operationsAnswer with { job_id }; follow up with get_job or block on wait_for_job, where a timeout returns the current state with timed_out: true rather than an error.
Paginationcursor and limit (max 200), returning { items, next_cursor, total }.
Output capAbout 200 KB per result, truncated with a preview — narrow the query instead.
Rate limits120 requests/min per user (burst 40), writes 30/min (burst 10), 4 concurrent calls, 30 s per call.
ErrorsA stable prefix: [not_found], [forbidden], [conflict], [invalid], [rate_limited], [timeout], [read_only], [consent_required], [scope_missing], [confirm_required], [internal].

The data wall#

Client setup#

MCP client configuration (PAT)
{
  "mcpServers": {
    "mate": {
      "type": "http",
      "url": "https://mate.example.org/mcp",
      "headers": {
        "Authorization": "Bearer mate_pat_…"
      }
    }
  }
}
Claude Code
claude mcp add --transport http mate https://mate.example.org/mcp \
  --header "Authorization: Bearer $MATE_PAT"

For an OAuth-capable client, omit the header and point it at the same URL: the first unauthenticated call answers 401 with the Keycloak authorization server, and the client runs auth-code with PKCE.

Common workflows#

TaskTools behind it
Orientget_server_info, whoami, list_processes
Import and waitimport_process_from_url → wait_for_job
Understand a processget_process, get_process_overview, then get_bottlenecks / get_drifts / get_conformance
Drill into detailget_variants → get_variant → get_variant_cases
Explain a numberget_cached_guidance, get_module_output (cache-only, never triggers a model call)
Build a boardget_dashboard_card_catalog → create_dashboard → share_dashboard
Recover a failurelist_jobs(status="failed") → get_job → retry_job

Failure modes#

SymptomCause
503 "MCP is disabled"The boot flag is off, or the live admin kill switch is on.
401 on every callToken missing, expired, revoked, or wrong OAuth audience.
[consent_required]The user has not enabled external data access.
[scope_missing]The token lacks the scope; scopes are fixed at mint time.
[read_only] on a writeServer-wide read-only, from the boot flag or the live toggle.
404 on /mcpThe flag never reached the container, or the proxy route is missing.
403 "Origin not allowed"A browser-based client on a foreign origin — use a native or server-side client.