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.

Note

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.

Note

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.

CategoryToolsPurpose
Connectionping, whoamiVerify connectivity and the project the session is bound to
Tracessearch_traces, get_trace_context, get_trace_evaluations, log_traceFind runs, read a run's spans and evaluations, push a run into Neatlogs
Analyticsget_project_analyticsDashboard aggregates over an explicit time window
Detectionslist_detections, get_detection_trend, get_detection_status, get_detection_capabilitiesSee what the project monitors, how often it fires, and detection state
Detection authoringlist_detection_groups, create_detection_group, preview_detection, create_detectionDry-run and create detections from your editor
Incident fixestriage_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_versionRead 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:

ParameterTypeRequiredDescription
querystringYesFree-text search query
modekeyword | semanticNoDefault keyword
limitinteger 1-100NoDefault 20
offsetinteger ≥ 0NoPagination offset, default 0
workflow_namestringNoFilter by workflow name
date_from, date_tostringNoISO 8601 start and end
modelstringNoFilter by LLM model
frameworkstringNoFilter by framework
detection_namestringNoFilter by detection, for example hallucination
min_tokensintegerNoMinimum total tokens
min_durationintegerNoMinimum trace duration in ms
min_errored_spansintegerNoMinimum number of errored spans
min_cost_usdnumberNoMinimum cost in USD
preview_charsinteger 1-2000NoCharacters 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:

ParameterTypeRequiredDescription
trace_idstringOne selector32-character hex or UUID trace ID
created_afterstringOne selectorISO timestamp; returns the latest project trace after it
verification_markerstringOne selectorReturns a trace carrying this process-scoped runtime marker
candidate_offsetinteger 0-100NoWhich distinct marker match to return; only with verification_marker
limitinteger 1-200NoSpans per page, default 50
offsetintegerNoSpan offset for the next page
include_evaluationsbooleanNoInclude 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:

ParameterTypeRequiredDescription
trace_idstringYesTrace ID
evaluation_idUUIDNoOne evaluation; use it when paging its responses or runs
span_idstringNoLimit to evaluations on one span
offsetintegerNoEvaluation offset, default 0
limitinteger 1-10NoEvaluations per page, default 3
response_pageinteger ≥ 1NoResponse page, default 1
response_limitinteger 1-50NoResponses per page, default 10
run_offsetintegerNoJudge-run offset, default 0
run_limitinteger 1-50NoJudge 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:

ParameterTypeRequiredDescription
workflow_namestringYesWorkflow name shown in the dashboard
agent_namestringNoName of the child agent span
frameworkstringNoFor example langchain
input, outputstringNoTop-level agent input and output
latency_msnumberNoTotal execution time
token_usageobjectNoprompt_tokens, completion_tokens, total_tokens; adds an LLM span so counts appear in the dashboard
cost_usdnumberNoKept as metadata; dashboard cost is computed from tokens and model pricing
metadataobjectNoCustom context such as git_sha or environment
timestampstringNoTrace start (ISO 8601), default now
spansarrayNoChild 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:

ParameterTypeRequiredDescription
from, tostringYesISO 8601 date-times with offset
workflow_namestringNoLimit to one workflow
viewstringNokpis (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:

ParameterTypeRequiredDescription
group_idstringNoLimit 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:

ParameterTypeRequiredDescription
detection_namestringYesSlug or display name; case-insensitive, and suffixes such as "Detector" are ignored
period24h | 7d | 30dNoDefault 7d
granularityhour | day | weekNoDefault 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:

ParameterTypeRequiredDescription
enginestringNoclassifier, regex, conditional, pii, custom_trained, code, trace_rules, or decision
targetspan | trace | sessionNoDefault 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:

ParameterTypeRequiredDescription
typeregex | conditionalYesclassifier and pii can't be previewed
configobjectYesregex: input_pattern and/or output_pattern, optional operator (default OR) and case_sensitive (default false). conditional: { "root": { "type": "group", "logic": "AND", "children": [ ... ] } }
run_onobjectNofrequency: trace (default), span_type (with span_types), or span_name (with span_names)
timeframe_daysinteger 1-365NoHow far back to scan
limitinteger 1-500NoSample 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:

ParameterTypeRequiredDescription
display_namestringYesName shown in the dashboard
group_idUUIDYesFrom list_detection_groups or create_detection_group
typeclassifier | regex | conditional | piiYesDetection type
configobjectYesclassifier: { "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)
descriptionstringNoWhat the detection flags
thresholdnumber 0-1NoDefault 0.5
run_onobjectNoAs 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).

Warning

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:

ParameterTypeRequiredDescription
statusstringNodraft (awaiting review), open (default), in_progress, resolved, or archived
severitystringNocritical, high, medium, or low
categorystringNoLayer to change: prompt, tool, model, config, or cost
triage_labelstringNoFailure 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:

ParameterTypeRequiredDescription
triage_idUUIDYesFix to move
user_emailstringYesActing member's email
statusin_progress | resolved | archivedYesTarget status
resolution_notestringFor resolved and archivedWhat 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\"}"
    }
  ]
}
errorCodeMeaning
invalid_argumentA parameter is missing or invalid, or the result is too large
not_foundThe trace, detection, fix, or user email doesn't exist in this project
conflictThe change conflicts with the current state
forbiddenThe credential isn't allowed to do this
not_enabledThe feature or parameter isn't enabled on this deployment
rate_limitedCapacity is exhausted; retry with backoff
timeoutThe call exceeded its time limit
upstream_unavailableA dependent service failed; retry
internal_errorUnexpected server failure

Transport errors (missing or invalid key, unknown session, rate limit) are plain HTTP responses. See Error handling.


Limits

LimitValueNotes
Request body1 MBPOST requests must use Content-Type: application/json
Tool result2 MBLarger results return invalid_argument; narrow the query or paginate
Tool time limit15 secondsPer call
log_trace payloadAbout 700 KBSplit larger traces across calls
Search results100 per callDefault 20; page with offset
Trace spans200 per callDefault 50; page with offset
Rate limit60 tool calls per minute per projectDefault; shared by every session and key for the project. ping, initialize, tools/list, and stream requests don't count
Idle session10 minutesSessions with no requests close; start a new one
Concurrent sessions128 per project, 256 per organizationNew sessions beyond this get HTTP 429

See Also

On this page

Ask Neatlogs AI

Answers from the docs

How can I help?

Ask anything about instrumenting, tracing, or the Neatlogs dashboard.