MCP Tools Reference
Parameters, responses, and errors for the default 26-tool Neatlogs MCP catalog, from trace search to detection authoring and incident fixes.
Complete reference for the tools the hosted Neatlogs MCP server exposes to a session authenticated with a project API key. To connect a client, see MCP Server or the MCP Integration guide.
Every tool returns one text content item containing JSON. The Response examples below show that parsed JSON. A tool failure is returned as a normal tool result with isError: true and a JSON body of { "error": "<message>", "errorCode": "<code>" }. See Errors.
Legacy names. In the dashboard, the investigation record with a root cause, evidence, and recommended action is a fix attached to an incident on the Incidents page. The MCP tools that read and update it keep the legacy triage_ prefix: IDs are passed as triage_id, triage_list returns triage_cards, and tool descriptions and error messages say "fix".
Tool categories
This reference covers the default 26-tool project-key catalog. Deployments enable tools individually, and authentication scope can change the list. Initialize an authenticated session and call tools/list to see exactly what it can call; use ping to check connectivity. The hosted /mcp/health endpoint requires authentication.
| Category | Tools | Purpose |
|---|---|---|
| Connection | ping, whoami | Verify connectivity and the project the session is bound to |
| Traces | search_traces, get_trace_context, get_trace_evaluations, log_trace | Find runs, read a run's spans and evaluations, push a run into Neatlogs |
| Analytics | get_project_analytics | Dashboard aggregates over an explicit time window |
| Detections | list_detections, get_detection_trend, get_detection_status, get_detection_capabilities | See what the project monitors, how often it fires, and detection state |
| Detection authoring | list_detection_groups, create_detection_group, preview_detection, create_detection | Dry-run and create detections from your editor |
| Incident fixes | triage_list, triage_get, triage_get_investigation, triage_list_steps, triage_list_versions, triage_get_version, triage_accept, triage_dismiss, triage_update_status, triage_update, triage_restore_version | Read and manage fixes; names keep the legacy triage_ prefix |
Connection tools
Call these first to confirm the connection before using data tools.
ping
Health check. Takes no parameters and doesn't count toward the rate limit.
Response:
{
"pong": true,
"timestamp": "2026-10-13T14:32:10.000Z"
}whoami
Identifies the project this session is bound to. Takes no parameters.
Response:
{
"project_id": "8f14e45f-ceea-467a-9575-4c1d2b3a6f10",
"project_name": "checkout-assistant",
"org_id": "c9f0f895-fb98-4b91-a6d2-2f5e1a7c9e33",
"project_repo": "",
"is_archived": false,
"tier": "free"
}Trace tools
search_traces
Searches the project's traces by free-text query. Defaults to BM25 keyword search over span text; mode: "semantic" uses vector search.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
query | string | Yes | Free-text search query |
mode | keyword | semantic | No | Default keyword |
limit | integer 1-100 | No | Default 20 |
offset | integer ≥ 0 | No | Pagination offset, default 0 |
workflow_name | string | No | Filter by workflow name |
date_from, date_to | string | No | ISO 8601 start and end |
model | string | No | Filter by LLM model |
framework | string | No | Filter by framework |
detection_name | string | No | Filter by detection, for example hallucination |
min_tokens | integer | No | Minimum total tokens |
min_duration | integer | No | Minimum trace duration in ms |
min_errored_spans | integer | No | Minimum number of errored spans |
min_cost_usd | number | No | Minimum cost in USD |
preview_chars | integer 1-2000 | No | Characters kept in input and output previews, default 500 |
The schema also advertises fields for summary projection. It currently returns not_enabled; omit it.
Response:
{
"total": 37,
"totalRelation": "eq",
"mode": "keyword",
"results": [
{
"score": 12.4,
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"workflow_name": "checkout-assistant",
"start_ts": "2026-10-13T09:14:02.118Z",
"total_duration": 5234,
"span_count": 12,
"trace_input": "Where is my refund for order 1182?",
"trace_output": "Your payment failed. Please try again.",
"span_names": ["checkout-assistant", "process_payment", "compose_answer"],
"matched_spans": [
{
"span_id": "00f067aa0ba902b7",
"span_name": "process_payment",
"span_type": "TOOL",
"snippet": "...gateway timeout after 30s..."
}
],
"detections": ["Task Failure"]
}
]
}Results can also carry summary fields such as status, cost_usd, total_tokens, environment, session_id, input_preview, and output_preview. totalRelation is gte when total is a lower bound.
get_trace_context
Returns a trace's metrics, flat span list, detections, and a first page of evaluations. Pass exactly one selector.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
trace_id | string | One selector | 32-character hex or UUID trace ID |
created_after | string | One selector | ISO timestamp; returns the latest project trace after it |
verification_marker | string | One selector | Returns a trace carrying this process-scoped runtime marker |
candidate_offset | integer 0-100 | No | Which distinct marker match to return; only with verification_marker |
limit | integer 1-200 | No | Spans per page, default 50 |
offset | integer | No | Span offset for the next page |
include_evaluations | boolean | No | Include a bounded evaluation page, default true |
The schema also advertises span_types, span_names, fields, max_chars_per_field, and context_revision for selective context. They currently return not_enabled; omit them.
Response:
{
"trace_context_contract_version": 2,
"trace_id": "4bf92f3577b34da6a3ce929d0e0e4736",
"name": "checkout-assistant",
"workflow": "checkout-assistant",
"framework": "langchain",
"status": "finalized",
"finalization_status": "finalized",
"latency_ms": 5234,
"span_count": 12,
"root_span_count": 1,
"span_payload_complete": true,
"span_tree_complete": true,
"verification_ready": true,
"returned_span_count": 12,
"offset": 0,
"next_offset": null,
"llm_calls": 3,
"tool_calls": 2,
"retrieval_calls": 1,
"has_error": true,
"error_count": 1,
"total_tokens": 4120,
"prompt_tokens": 3700,
"completion_tokens": 420,
"total_cost": 0.0234,
"created_at": "2026-10-13T09:14:02.118Z",
"detections": ["Task Failure"],
"spans": [
{
"span_id": "00f067aa0ba902b7",
"name": "process_payment",
"type": "TOOL",
"status": "ERROR",
"duration_ms": 3000,
"parent_span_id": "a3ce929d0e0e4736",
"is_root": false,
"input_value": "{\"order_id\": \"1182\"}",
"output_value": "",
"code_filepath": "app/tools/payments.py",
"code_function": "process_payment",
"code_lineno": 88
}
],
"evaluations": { "status": "available", "complete": true, "evaluations": [] }
}Spans are a flat list; rebuild the tree from parent_span_id. When next_offset is not null, call again with offset set to it. A trace that is still being processed reports status: "processing" or finalization_status: "pending".
get_trace_evaluations
Reads the evaluation questions linked to a trace or span, their human and AI answers, and every related judge run, including pending, failed, and repeated runs. Missing data is not a passing evaluation.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
trace_id | string | Yes | Trace ID |
evaluation_id | UUID | No | One evaluation; use it when paging its responses or runs |
span_id | string | No | Limit to evaluations on one span |
offset | integer | No | Evaluation offset, default 0 |
limit | integer 1-10 | No | Evaluations per page, default 3 |
response_page | integer ≥ 1 | No | Response page, default 1 |
response_limit | integer 1-50 | No | Responses per page, default 10 |
run_offset | integer | No | Judge-run offset, default 0 |
run_limit | integer 1-50 | No | Judge runs per page, default 10 |
Response: { "status": "available", "complete": <boolean>, ... } with the evaluations, each carrying responses, runs, and separate response_counts and run_counts. complete is true only when the first page holds everything.
log_trace
Pushes an execution trace from your agent into Neatlogs. It creates a root workflow span from workflow_name, a child agent span, and one span per entry in spans. The trace appears in the dashboard like one sent by an SDK.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
workflow_name | string | Yes | Workflow name shown in the dashboard |
agent_name | string | No | Name of the child agent span |
framework | string | No | For example langchain |
input, output | string | No | Top-level agent input and output |
latency_ms | number | No | Total execution time |
token_usage | object | No | prompt_tokens, completion_tokens, total_tokens; adds an LLM span so counts appear in the dashboard |
cost_usd | number | No | Kept as metadata; dashboard cost is computed from tokens and model pricing |
metadata | object | No | Custom context such as git_sha or environment |
timestamp | string | No | Trace start (ISO 8601), default now |
spans | array | No | Child spans, ordered parent before child |
Each spans entry takes name and start_time (ISO 8601, required), plus optional span_id, parent_span_id (omit to attach to the agent span), kind (LLM, TOOL, AGENT, CHAIN, RETRIEVER, EMBEDDING, WORKFLOW, TASK, MCP_TOOL), status_code (UNSET, OK, ERROR), status_message, end_time, attributes, and events. A tool call's parent_span_id should be the LLM span that requested it.
Response:
{
"trace_id": "9a1c3e5f7b2d4f6a8c0e1b3d5f7a9c2e",
"span_count": 5,
"status": "queued",
"workflow_name": "code-review-agent"
}Payloads over about 700 KB return invalid_argument; split them across calls.
Analytics tools
get_project_analytics
Reads dashboard aggregates over an explicit [from, to) window of at most 30 days.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
from, to | string | Yes | ISO 8601 date-times with offset |
workflow_name | string | No | Limit to one workflow |
view | string | No | kpis (default), cost, errors, time, tools, detections, waste, or workflows |
kpis returns exact persisted trace and error counts with their denominator, latency percentiles, cost and tokens, and the preceding equal-length baseline.
Response:
{
"project_id": "8f14e45f-ceea-467a-9575-4c1d2b3a6f10",
"workflow_name": null,
"view": "kpis",
"entity_level": "trace",
"interval": "[from,to)",
"observed_at": "2026-10-13T14:40:00.000Z",
"ingestion_complete": null,
"ingestion_watermark": null,
"readiness": "persisted_records_only",
"data": {}
}Results count only persisted records; an error from this tool is not zero traffic.
Detection tools
list_detections
Lists the project's detections, for example Hallucination, Jailbreak Attempt, Task Failure, and User Frustration.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
group_id | string | No | Limit to one detection group |
Response:
{
"total": 1,
"detections": [
{
"id": "1f0e3dad-9990-4f8a-b1c2-7d6e5f4a3b21",
"slug": "task_failure",
"display_name": "Task Failure",
"description": "The agent did not complete the user's task",
"type": "classifier",
"group_name": "Quality",
"is_active": true,
"threshold": 0.5,
"run_on": { "frequency": "trace" },
"created_at": "2026-09-02T10:00:00Z",
"updated_at": "2026-10-01T08:12:00Z"
}
]
}get_detection_trend
Returns occurrence counts over time for one detection.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
detection_name | string | Yes | Slug or display name; case-insensitive, and suffixes such as "Detector" are ignored |
period | 24h | 7d | 30d | No | Default 7d |
granularity | hour | day | week | No | Default hour for 24h, day otherwise |
Response:
{
"detection_id": "1f0e3dad-9990-4f8a-b1c2-7d6e5f4a3b21",
"detection_name": "task_failure",
"period": "7d",
"granularity": "day",
"start_date": "2026-10-06T14:40:00.000Z",
"end_date": "2026-10-13T14:40:00.000Z",
"total_occurrences": 89,
"data_points": [
{ "date": "2026-10-12", "count": 14 },
{ "date": "2026-10-13", "count": 21 }
]
}get_detection_status
Reads one detection's saved configuration, activation, and backfill state.
Input: detection_id (UUID, required).
Response: the detection's id, type, isActive, config, runOn, threshold, backfillStatus, backfillProgress, updatedAt, and configFingerprint, plus processing_complete (true only when the backfill completed) and quality_verified (always null). A finished backfill does not prove the detection is accurate.
get_detection_capabilities
Describes the detection engines, their configuration schemas, authoring guidance, and the project's existing monitoring. It grants no write permission.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
engine | string | No | classifier, regex, conditional, pii, custom_trained, code, trace_rules, or decision |
target | span | trace | session | No | Default trace |
Detection authoring tools
Create a detection in four steps: find a group, dry-run the rule, then create it. Creating starts a 14-day backfill so the detection scores recent traces right away. See Create a detection for choosing what to detect.
list_detection_groups
Lists the project's detection groups. Every detection belongs to a group. Takes no parameters.
Response: { "total": 2, "groups": [{ "id": "<uuid>", "name": "Quality" }] }
create_detection_group
Creates a group when none fits.
Input: name (string, 1-255 characters, required).
Response: { "id": "<uuid>", "name": "Payments", "message": "Group 'Payments' created" }
preview_detection
Dry-runs a regex or conditional detection against recent spans without saving it. Run it before create_detection for those types, and create only if it flags something.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
type | regex | conditional | Yes | classifier and pii can't be previewed |
config | object | Yes | regex: input_pattern and/or output_pattern, optional operator (default OR) and case_sensitive (default false). conditional: { "root": { "type": "group", "logic": "AND", "children": [ ... ] } } |
run_on | object | No | frequency: trace (default), span_type (with span_types), or span_name (with span_names) |
timeframe_days | integer 1-365 | No | How far back to scan |
limit | integer 1-500 | No | Sample spans to return, default 50 |
Response:
{
"total_count": 6,
"samples": [
{
"span_id": "00f067aa0ba902b7",
"span_name": "compose_answer",
"span_type": "LLM",
"matched_input": "",
"matched_output": "Your payment failed. Please try again."
}
]
}create_detection
Creates the detection and starts a 14-day backfill.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
display_name | string | Yes | Name shown in the dashboard |
group_id | UUID | Yes | From list_detection_groups or create_detection_group |
type | classifier | regex | conditional | pii | Yes | Detection type |
config | object | Yes | classifier: { "classifier_slug": "jailbreaking" } (or nsfw, hate, refusals). regex and conditional: as in preview_detection. pii: optional entities, for example ["EMAIL_ADDRESS", "PHONE_NUMBER"] (omit for all) |
description | string | No | What the detection flags |
threshold | number 0-1 | No | Default 0.5 |
run_on | object | No | As in preview_detection |
Response:
{
"id": "6512bd43-d9ca-4e1a-9b5c-2f3e4d5a6b7c",
"slug": "payment_failed_answer",
"display_name": "Payment failed answer",
"group_name": "Payments",
"type": "regex",
"backfill_status": "pending",
"message": "Detection created. A 14-day backfill is running to score recent traces; it will appear scoring in the dashboard shortly."
}Use get_detection_status to follow the backfill.
Incident fix tools
These tools read and update fixes: the investigation records, with root cause, evidence, and recommended action, that appear as incidents on the Incidents page. They don't list every incident on that page; incidents that Neatlogs groups from production activity without a fix are read in the dashboard.
A typical flow is triage_list → triage_get → triage_accept → triage_update_status (in_progress, then resolved after you ship the change).
Every write tool requires user_email, the email of an active member of the project's organization, and records that person as the actor. Ask the user before calling a write tool.
triage_list
Lists fixes for the project, up to 50.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
status | string | No | draft (awaiting review), open (default), in_progress, resolved, or archived |
severity | string | No | critical, high, medium, or low |
category | string | No | Layer to change: prompt, tool, model, config, or cost |
triage_label | string | No | Failure pattern: prompt_regression, hallucination, tool_contract_misuse, retrieval_miss, latency_anomaly, cost_anomaly, orchestration_inefficiency, guardrail_bypass, user_frustration_signal, or silent_degradation |
Response:
{
"total": 1,
"triage_cards": [
{
"triage_id": "a87ff679-a2f3-41c9-8e7d-6b5a4c3d2e1f",
"title": "Answer reports payment failure after successful charge",
"root_cause": "The answer prompt reads the first gateway response, not the retry result.",
"status": "open",
"severity": "high",
"category": "prompt",
"triage_label": "prompt_regression",
"workflow_name": "checkout-assistant",
"source": "neatlogs_agent",
"thread_id": "e4da3b7f-bbce-4345-9d77-7c5b2a1f0e9d",
"linked_trace_ids": ["4bf92f3577b34da6a3ce929d0e0e4736"],
"confidence": 0.86,
"created_at": "2026-10-13T10:30:00Z"
}
]
}triage_get
Returns one fix in full.
Input: triage_id (UUID, required).
Response: triage_id, title, status, severity, category, triage_label, workflow_name, source, thread_id, root_cause, evidence_reasoning, recommended_action (title, steps, verification, risk_assessment, rollback_plan), recommended_action_md, confidence, confidence_factors, linked_trace_ids, cloud_agent_runs (each with status, provider, and pr_url), accepted_by, accepted_at, resolved_by, resolved_at, resolution_note, created_at, and updated_at.
triage_get_investigation
Reloads the investigation that produced a fix: its steps, the resulting fix, and the linked traces.
Input: thread_id (UUID, required). Use the thread_id from triage_list or triage_get, not the triage_id.
Response: { "thread_id": "<uuid>", "status": "...", "steps": [ ... ], "triage_card": { ... }, "linked_traces": [ ... ] }
triage_list_steps
Lists the investigation steps (each tool call or model hop) behind a fix.
Input: triage_id (UUID, required).
Response: { "triage_id": "<uuid>", "steps": [ ... ] }
triage_list_versions
Lists saved versions of a fix's editable sections: root cause, evidence, and recommended action. Every edit, from the dashboard, an agent, or MCP, adds a version.
Input: triage_id (UUID, required).
Response: { "triage_id": "<uuid>", "count": 3, "latest_version_no": 3, "versions": [ ... ] }
triage_get_version
Reads one saved version.
Input: triage_id (UUID, required) and version_no (positive integer, required).
triage_accept
Accepts a draft fix so it moves onto the team's board (draft → open).
Input: triage_id (UUID, required) and user_email (required).
Response: { "id": "<uuid>", "status": "open", "message": "Fix accepted" }
triage_dismiss
Dismisses a fix that is no longer relevant, a false positive, or fixed elsewhere. Its status becomes archived.
Input: triage_id and user_email (required), and resolution_note (optional, shown to future readers).
Response: { "id": "<uuid>", "status": "archived", "message": "..." }
triage_update_status
Moves a fix to in_progress, resolved, or archived. Setting resolved opens the verification watch window.
Input:
| Parameter | Type | Required | Description |
|---|---|---|---|
triage_id | UUID | Yes | Fix to move |
user_email | string | Yes | Acting member's email |
status | in_progress | resolved | archived | Yes | Target status |
resolution_note | string | For resolved and archived | What shipped, or why it is closed |
Response: { "id": "<uuid>", "status": "resolved", "message": "Fix status set to 'resolved'" }
triage_update
Edits a fix without changing its status. Pass at least one field. Editing root_cause, evidence_reasoning, or recommended_action_md adds a version.
Input: triage_id and user_email (required), plus any of title, severity (critical, high, medium, low), triage_label, resolution_note, root_cause, evidence_reasoning, and recommended_action_md (Markdown).
Response: { "id": "<uuid>", "status": "open", "message": "Fix updated", "updated_fields": ["severity", "root_cause"] }
triage_restore_version
Restores an earlier version of root cause, evidence, and recommended action as current. Title, severity, status, and notes are unchanged, and other versions stay in history.
Input: triage_id and user_email (required), and version_no (positive integer, required).
Response: { "id": "<uuid>", "version_no": 4, "restored_from": 2, "message": "..." }
Service-account sessions
An organization service-account token (nlsa_ prefix) can also open an MCP session. Send the project ID in the x-project-id header. These sessions expose only read tools, and each call is checked against the account's permissions and scopes: ping, whoami, search_traces, get_trace_context, get_trace_evaluations, get_project_analytics, list_detections, get_detection_trend, list_detection_groups, get_detection_capabilities, and get_detection_status. They also add incident read tools: list_incidents, get_incident, list_incident_traces, list_incident_spans, and get_incident_span_payload. See Public API authentication for service accounts.
Errors
A tool error looks like this inside the JSON-RPC result:
{
"isError": true,
"content": [
{
"type": "text",
"text": "{\"error\":\"Trace not found: 4bf92f3577b34da6a3ce929d0e0e4736\",\"errorCode\":\"not_found\"}"
}
]
}errorCode | Meaning |
|---|---|
invalid_argument | A parameter is missing or invalid, or the result is too large |
not_found | The trace, detection, fix, or user email doesn't exist in this project |
conflict | The change conflicts with the current state |
forbidden | The credential isn't allowed to do this |
not_enabled | The feature or parameter isn't enabled on this deployment |
rate_limited | Capacity is exhausted; retry with backoff |
timeout | The call exceeded its time limit |
upstream_unavailable | A dependent service failed; retry |
internal_error | Unexpected server failure |
Transport errors (missing or invalid key, unknown session, rate limit) are plain HTTP responses. See Error handling.
Limits
| Limit | Value | Notes |
|---|---|---|
| Request body | 1 MB | POST requests must use Content-Type: application/json |
| Tool result | 2 MB | Larger results return invalid_argument; narrow the query or paginate |
| Tool time limit | 15 seconds | Per call |
log_trace payload | About 700 KB | Split larger traces across calls |
| Search results | 100 per call | Default 20; page with offset |
| Trace spans | 200 per call | Default 50; page with offset |
| Rate limit | 60 tool calls per minute per project | Default; shared by every session and key for the project. ping, initialize, tools/list, and stream requests don't count |
| Idle session | 10 minutes | Sessions with no requests close; start a new one |
| Concurrent sessions | 128 per project, 256 per organization | New sessions beyond this get HTTP 429 |
See Also
- MCP Integration Guide - Connection, sessions, and workflow examples
- Create a detection - Decide what a detection should catch before authoring it here
- Span Kinds -
MCP_TOOLand the other span kindslog_traceaccepts - Long-Running Sessions - Follow a cloud coding-agent run from an incident until it opens a pull request
