Built-in MCP tools
The built-in MCP server at /api/mcp builds its tool list per caller from the toolsets below. Each tool calls the listed HTTP route in-process, so it needs that route's permission on top of mcp:read and mcp:execute, and it runs the same FGA and ownership checks as the HTTP request. A tool whose route the caller can't call isn't listed.
Arguments marked with * are required. Routes are relative to the API prefix (/api by default). Tools marked read-only carry the MCP readOnlyHint annotation and stay available with readOnly: true or ?readonly=1.
agentsDirect link to agents
| Tool | Arguments | Route | Permission |
|---|---|---|---|
list_agents | query | GET /agents | agents:read |
get_agent | agentId* | GET /agents/:agentId | agents:read |
call_agent | agentId*, message*, threadId, resourceId | POST /agents/:agentId/generate | agents:execute |
agent_<id> | message*, threadId, resourceId | POST /agents/:agentId/generate | agents:execute |
list_agentsreturns each agent'sid,name, anddescription.querykeeps agents whose id or name contains the text.call_agentreturns the reply text and thethreadIdto pass back to continue the conversation.agent_<id>is added for each agent listed inserver.mcp.featured.agents.- When the caller can see up to
enumLimitagents (25 by default),agentIdlists the allowed ids.
workflowsDirect link to workflows
| Tool | Arguments | Route | Permission |
|---|---|---|---|
list_workflows | query | GET /workflows | workflows:read |
get_workflow | workflowId* | GET /workflows/:workflowId | workflows:read |
start_workflow | workflowId*, inputData, runId | POST /workflows/:workflowId/start-async | workflows:execute |
get_workflow_run | workflowId*, runId*, fields | GET /workflows/:workflowId/runs/:runId | workflows:read |
resume_workflow_run | workflowId*, runId*, step, resumeData | POST /workflows/:workflowId/resume-async | workflows:execute |
cancel_workflow_run | workflowId*, runId* | POST /workflows/:workflowId/runs/:runId/cancel | workflows:execute |
workflow_<id> | The workflow's input schema | POST /workflows/:workflowId/start-async | workflows:execute |
start_workflow,resume_workflow_run, andworkflow_<id>wait for the run to finish or suspend. A suspended run returnsstatus: 'suspended', itsrunId,suspendPayload, andsuspendedSteps.get_workflow_runtakesfieldsas a comma-separated subset ofresult,error,payload,steps, andactiveStepsPath.cancel_workflow_runcarries the MCPdestructiveHintannotation.workflow_<id>is added for each workflow listed inserver.mcp.featured.workflows. When the input schema isn't an object, the tool takes it asinputData.
toolsDirect link to tools
When the caller can see up to enumLimit tools and may call them, each tool gets its own entry:
| Tool | Arguments | Route | Permission |
|---|---|---|---|
tool_<id> | The tool's input schema | POST /tools/:toolId/execute | tools:execute |
Above enumLimit, or when the caller can't call tools (readOnly: true or no tools:execute), operation tools replace them. call_tool is only offered when the caller can call tools:
| Tool | Arguments | Route | Permission |
|---|---|---|---|
list_tools | query | GET /tools | tools:read |
get_tool | toolId* | GET /tools/:toolId | tools:read |
call_tool | toolId*, data | POST /tools/:toolId/execute | tools:execute |
A tool_<id> entry uses the tool's own mcp.annotations when the tool defines them.
memoryDirect link to memory
| Tool | Arguments | Route | Permission |
|---|---|---|---|
list_threads | agentId, resourceId, page, perPage | GET /memory/threads | memory:read |
get_thread | threadId*, agentId | GET /memory/threads/:threadId | memory:read |
list_messages | threadId*, agentId, page, perPage | GET /memory/threads/:threadId/messages | memory:read |
search_memory | agentId*, searchQuery*, resourceId, threadId, limit | GET /memory/search | memory:read |
get_memory_status | agentId*, resourceId, threadId | GET /memory/status, GET /memory/config | memory:read |
get_observations | agentId*, threadId, resourceId, waitForPending | GET /memory/observational-memory | memory:read |
create_thread | agentId*, resourceId, title, metadata, threadId | POST /memory/threads | memory:write |
update_thread | threadId*, agentId*, title, metadata | PATCH /memory/threads/:threadId | memory:write |
clone_thread | threadId*, agentId*, newThreadId, title, metadata, messageLimit | POST /memory/threads/:threadId/clone | memory:execute |
save_messages | agentId*, messages* | POST /memory/save-messages | memory:write |
resourceIddefaults to the caller whenserver.authsetsmapUserToResourceId, and a caller can't read or write another resource's threads, messages, or Observational Memory. WithoutmapUserToResourceId, the tools use theresourceIdthe client sends, so setmapUserToResourceIdto keep memory private. FGA protects threads, butget_observationscalled with only aresourceIdisn't covered by the default FGA routes.get_observationsreads resource-scoped Observational Memory whenthreadIdis left out.waitForPending: truewaits up to 30 seconds for pending observations, and is only offered when the caller may callPOST /memory/observational-memory/buffer-status, which needsmemory:write.search_memoryreturns up to 20 results unlesslimitis set.
observabilityDirect link to observability
| Tool | Arguments | Route | Permission |
|---|---|---|---|
query_traces | timeRange*, where, textSearch, rootSource, group, orderBy, page | POST /observability/traces/query | observability:read |
aggregate_traces | timeRange*, measures*, where, groupBy, interval, having, orderBy, limit | POST /observability/traces/aggregate | observability:read |
query_spans | timeRange*, where, textSearch, orderBy, page | POST /observability/spans/query | observability:read |
aggregate_spans | timeRange*, measures*, where, groupBy, interval, having, orderBy, limit | POST /observability/spans/aggregate | observability:read |
query_threads | timeRange*, where, orderBy, page | POST /observability/threads/query | observability:read |
get_trace_query_fields | timeRange*, predicateScope*, search, limit | POST /observability/traces/query/fields | observability:read |
get_trace_query_values | timeRange*, predicateScope*, path*, search, limit | POST /observability/traces/query/values | observability:read |
list_traces | Filters such as entityType, entityName, status, traceId, threadId, dateRange, plus page, perPage, field, direction | GET /observability/traces | observability:read |
get_trace | traceId*, offset | GET /observability/traces/:traceId/light | observability:read |
get_span | traceId*, spanId* | GET /observability/traces/:traceId/spans/:spanId | observability:read |
get_trace_trajectory | traceId* | GET /observability/traces/:traceId/trajectory | observability:read |
list_logs | Filters such as level, traceId, entityName, threadId, timestamp, plus page, perPage, direction | GET /observability/logs | observability:read |
- A store that supports trace queries serves the query and aggregate tools and not
list_traces. A store without them serveslist_tracesinstead.list_logsis served only when the store implements logs. predicateScopeistrace,spans,scores, orfeedback.intervalis1m,5m,15m,1h, or1d.get_tracereturns light span records. Pass the returnednextOffsetasoffsetto read the rest of a cut trace.
observability_analyticsDirect link to observability_analytics
| Tool | Arguments | Route | Permission |
|---|---|---|---|
list_scores | Filters such as scorerId, traceId, entityName, timestamp, plus page, perPage, field, direction | GET /observability/scores | observability:read |
analyze_scores | op*, scorerId*, scoreSource, aggregation, filters, comparePeriod, groupBy, interval, percentiles | POST /observability/scores/<op> | observability:read |
list_feedback | Filters such as feedbackType, traceId, reviewStatus, timestamp, plus page, perPage, direction | GET /observability/feedback | observability:read |
analyze_feedback | op*, feedbackType*, feedbackSource, aggregation, filters, comparePeriod, groupBy, interval, percentiles | POST /observability/feedback/<op> | observability:read |
analyze_metrics | op*, name*, aggregation, distinctColumn, filters, comparePeriod, groupBy, limit, orderDirection, interval, percentiles | POST /observability/metrics/<op> | observability:read |
list_metric_names | metricName, labelKey, prefix, limit | GET /observability/discovery/metric-names, metric-label-keys, metric-label-values | observability:read |
opisaggregate,breakdown,timeseries, orpercentiles, and selects the route the tool calls.aggregationissum,avg,min,max,count,count_distinct, orlast.comparePeriodisprevious_period,previous_day, orprevious_week.list_metric_nameslists metric names. WithmetricName, it lists that metric's label keys. WithmetricNameandlabelKey, it lists that label's values.- Each tool is served only when the store implements the matching scores, feedback, or metrics queries.
stored_agentsDirect link to stored_agents
| Tool | Arguments | Route | Permission |
|---|---|---|---|
list_available_models | None | GET /editor/builder/models/available | stored-agents:read |
list_stored_agents | status, page, perPage | GET /stored/agents | stored-agents:read |
get_stored_agent | storedAgentId* | GET /stored/agents/:storedAgentId | stored-agents:read |
create_stored_agent | name*, instructions*, model, tools, memory, visibility, autoPublish, id, and the other stored agent fields | POST /stored/agents | stored-agents:write |
update_stored_agent | storedAgentId*, any stored agent field, changeMessage, autoPublish | PATCH /stored/agents/:storedAgentId | stored-agents:write |
list_stored_agentsreturns published agents unlessstatusisdraftorarchived, 100 per page by default.create_stored_agentandupdate_stored_agentpublish the change unlessautoPublishisfalse. A created agent is owned by the caller and private unlessvisibilityispublic. See stored agent visibility.- When the agent builder restricts models, both tools reject models it doesn't allow.
list_available_modelsreturns the allowed models.