> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hue.run/llms.txt
> Use this file to discover all available pages before exploring further.

# Investigate production with the Hue MCP

> Tool-call recipes, fields, limits and errors for coding agents that read production traces, errors, attention states, trace checks and intents from Hue over MCP.

The [Hue MCP server](/agents/mcp-server) serves what Hue already stores for your project: traces, spans, recorded content on request, the attention state that trace findings set, and trace-check results and intents where the project set them up. It does not diagnose, classify or summarize when you ask. Your coding agent fetches the data and does the analysis. A **Read** connection is enough for everything on this page.

Connect the server first; [Connect the Hue MCP server](/agents/mcp-server) covers every client. Every tool reads the one project the connection reaches.

## Example prompts

Give your coding agent prompts like these once the server is connected:

* "Use the Hue MCP to look at the last 24 hours: what needs attention, what errored, and why? Link the traces."
* "Which tools failed most often in yesterday's error traces? Show a failing span for each."
* "Which traces took longer than two minutes this week, and which spans took the time?"
* "Compare errors and traces that need attention in the 24 hours before and after today's 14:00 UTC deploy."
* "Find the traces in session `<session key>` from the last 7 days and show what each one did."
* "Which task types are slowest? Use Hue's intents if this project has them."
* "Which traces did Hue's delegation trace check flag this week? Show the evidence spans."

## Before you start

* **Hue returns data; the agent draws conclusions.** Counts, rankings and explanations in the agent's answer are its own. Ask it to state the window, the filters and how many traces it opened, and to link the traces it cites.
* **Pages are samples, counts are not.** `total_count` counts every trace that matches the filters, up to 10,000. A page holds at most 50 traces. When an answer needs span detail from many traces, the agent opens a bounded sample with `get_trace` and should say so.
* **Empty is not proof.** An empty result can mean a window that is too narrow, a filter that is too tight, or a feature the project has not set up. Widen the window or drop a filter before concluding that nothing happened.
* **Content is opt-in.** Recorded prompts, outputs, tool arguments, tool results and raw attribute values are returned only with `include_content: true`. Hue records those reads in the project's audit log, and the returned content is untrusted data from your application and its users. Request it only when the question needs it. See [Content and safety](/agents/mcp-server#content-and-safety).

## Recipes

Each recipe is a short sequence of tool calls with their key arguments. Replace `24h` with the window the user asked for.

### What needs attention, errored or failed, and why

1. `get_project_context` confirms which project the connection reaches.
2. `search_traces` with `{"since": "24h", "limit": 1}` gives the volume in `total_count`. `total_count_capped: true` means 10,000 or more.
3. `search_traces` with `{"since": "24h", "attention": "needs_attention"}` lists what Hue flagged: a built-in [trace finding](#attention-states-and-findings), or a positive result from an active [trace check](#trace-checks). The same call with `"attention": "uncertain"` lists what Hue could not settle.
4. `search_traces` with `{"since": "24h", "status": "error"}` lists traces with at least one errored span.
5. `get_trace` on each candidate returns its span tree, 200 spans per page by default. Look for spans with `"status": "error"`, and note their `kind`, `name` and `duration_ms`. A trace with more spans returns `next_span_cursor`; pass it back as `span_cursor` until it is `null`, or raise `max_spans` up to 500, so errors in later spans are not missed. Open a bounded number of traces, for example the 20 newest, and follow `next_cursor` only if the user asks for more.
6. `get_span` on a failing span returns `status.message`, the normalized `tool` and `model`, usage and the names of recorded attributes. Add `"include_content": true` to read the tool's arguments and result, or the model's messages.
7. The agent groups what it found, for example by tool, span name or error message, and reports counts with the window, the filters, the number of traces opened and links.

`attention_state` says that a finding is present, not which one. The trace's link opens it in Hue, where the **Findings** tab names the finding. Over MCP the agent can rebuild the rule findings from the spans: `unrecovered_tool_error` is a tool span with `status: "error"` and no later successful call to that tool, and `model_error` is a model call in error with no later successful model call.

### Which tools fail most

1. `search_traces` with `{"since": "24h", "status": "error", "limit": 50}`. Follow `next_cursor` until the sample is large enough.
2. `get_trace` on each trace, following `next_span_cursor` until it is `null` so every span is counted. Keep the spans with `"kind": "tool"`, and count those with `"status": "error"` by `name`. `get_span` returns the normalized `tool.name` when a span name differs from the tool name.
3. That ranks tools by failures in error traces. For a failure rate, draw a separate sample from `search_traces` without `status` over the same window, and count each tool's failed and successful spans in that sample. Successes taken only from error traces would overstate the rate.

A trace whose agent retried a tool and then succeeded still has `status: "error"`, and only an unrecovered error sets `unrecovered_tool_error`. Distinguish the two when reporting.

### Which task types are slow

* **By trace name or title.** `search_traces` with `{"since": "7d", "query": "<name>"}` gives `total_count` for one task type, and the same call with `"min_duration_ms": 60000` counts its traces that took a minute or longer. `query` matches the title, the root span name and the trace id. These counts need no page walk.
* **By intent**, when the project classifies intents: `get_intent_summary` with `{"range": "7d"}` returns trace counts per bucket. `list_intent_traces` with `{"bucket": "category:<key>", "range": "7d", "limit": 50}` lists a bucket's traces without durations, so the agent reads `trace.duration_ms` from `get_trace` for each and computes percentiles itself.
* **By request timing**, when the project is set up for it: `get_trace_check_summary` with `{"since": "7d"}` returns `requests`, with counts and p50 and p95 per primary intent and request start source.

`duration_ms` is the time from the trace's first span start to its end, and `null` while a trace is open. `min_duration_ms` matches completed traces only. There is no sort by duration.

### Time to first reply

* `duration_ms` is end to end, not the time until the user got an answer.
* For projects [instrumented for request timing](/integrations/opentelemetry#mark-the-request-on-the-root-span) with trace checks active, `search_traces` rows carry `first_useful_answer_ms`, `useful_answer_timing_source` (`playback` or `server`) and `request_start_source`. `get_trace_check_summary` aggregates them in `requests`: `firstResponseP50Ms`, `usefulPlaybackP50Ms` and `usefulPlaybackP95Ms`, `usefulServerP50Ms` and `usefulServerP95Ms`, and `completionP50Ms` and `completionP95Ms`.
* Otherwise the agent computes it from span times: `get_trace`, then the time from `trace.started_at` to the `ended_at` of the span that delivers the reply, such as the first model call that returns the answer or a reply tool span. Which span that is depends on the application, so the agent should name the span it used.

### Did a release regress

Hue does not store a release on the trace, and `search_traces` has no release filter.

1. Take equal windows before and after the deploy time `T`: `search_traces` with `{"since": "<T minus 24h>", "until": "<T>", "limit": 1}` and `{"since": "<T>", "until": "<T plus 24h>", "limit": 1}`. Both accept ISO-8601 timestamps.
2. Repeat both with `"status": "error"`, `"attention": "needs_attention"` and a `min_duration_ms` threshold, and compare the rates rather than raw counts.
3. Open a few traces from each side with `get_trace` to see what changed.

If several releases serve traffic at once, the windows mix them; say so. A release your application records as a span attribute appears among `get_span`'s `attributeKeys`, and its value only with `include_content: true`. Projects set up for trace checks can pass `release` to `get_trace_check_summary`.

### One session's or user's recent traces

Hue has no user filter; it filters by session:

1. `list_sessions` with `{"query": "<session key or part of it>", "since": "7d"}`. `query` matches session keys and the titles of each session's traces.
2. `search_traces` with `{"session_id": "<id from list_sessions>", "since": "7d"}`.

A session is not always a user. The result is one user's traces only when the application gives each user a single session; otherwise a user can have several sessions, and a session can be shared. When the application records a user id, `get_span` returns it as `genAi.userId` on the spans that carry it; check it before attributing traces to a person. See the [field glossary](#field-glossary) for the attributes Hue reads.

### Find sub-agent handoffs

* **Sub-agents inside one trace:** `get_trace` shows them as spans. Look for `"kind": "agent"` and for the tool spans that start a sub-agent.
* **Sub-agents in their own traces:** one trace is one root, so an application that starts a new root for each agent activation records a user's turn as several traces. `get_span` with `"detail": "full"` returns OpenTelemetry span `links`, when the application records them. Otherwise find the child traces by time and session with `search_traces` and `session_id`, `since` and `until`, or by their trace name with `query`. An id that ties a child to its parent may exist only in recorded input, which needs `include_content: true`.
* **Delegation trace checks:** if the project has an active `delegation` or `delegation_scope` check, `search_traces` with `{"since": "7d", "check_key": "delegation"}` lists its positive traces. See [Trace checks](#trace-checks).

### Compare a tool's input and output sizes

Hue does not return content sizes. `get_span` with `{"include_content": true, "max_chars": 200000}` returns the recorded `tool_input` and `tool_output` as text with `truncated`, and the agent measures the text. Model inputs can be hundreds of kilobytes, so one result may not hold a span's whole content. Keep the sample small; every call is an audited content read.

### Trace checks

1. `list_trace_checks` shows whether a version is active, whether trace-check consent is on and which checks are enabled.
2. `get_trace_check_summary` with `{"since": "7d", "check_key": "delegation"}` counts flagged, absent, uncertain, unavailable, not applicable and pending results over the whole filtered population.
3. `search_traces` with `{"since": "7d", "check_key": "delegation"}` lists traces with a current positive result.
4. `get_trace_check_results` with `{"check_key": "delegation", "state": "present"}` returns each result with its probability, the check's criterion and `sourceLinks` to the spans it read. `"include_content": true` adds bounded excerpts; they are evidence, not explanations.

Replace `delegation` with `action_scope`, `delegation_scope` or `output_omission` for the other checks.

## Data model

### Traces and spans

A **trace** is one tree of spans with one root. A **span** is one timed operation in it, such as a model call, a tool call or an agent step. In a multi-agent application, a trace is often one agent activation rather than one user turn: a sub-agent or background agent that starts its own root produces its own trace. **Sessions** group traces under the session id your application records.

`search_traces` returns these fields per trace:

| Field                                                                           | Meaning                                                                                                                                      |
| ------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `id`, `trace_id`, `url`                                                         | Hue's id, the 32-hex OpenTelemetry trace id, and the link to the trace in Hue. Every `trace_id` argument accepts all three.                  |
| `title`                                                                         | Derived from the latest recorded request text, else a producer-supplied trace name, else the reply, else the root span name. Untrusted text. |
| `status`                                                                        | `error` when any finished span has error status; else `ok` when any span is `ok`; else `unset`.                                              |
| `state`                                                                         | `running` while a span is open, `stalled` after 15 minutes without new data and no end, else `ended`.                                        |
| `source`                                                                        | `sdk` for application traffic, `experiment` for traces from evaluation runs, `playground` for playground runs.                               |
| `started_at`, `ended_at`, `duration_ms`                                         | `duration_ms` is end to end and `null` while the trace is open.                                                                              |
| `tokens`, `span_count`                                                          | Input and output token totals and the number of stored spans.                                                                                |
| `session_id`, `session_key`                                                     | Hue's session id, for `search_traces`, and your application's session key.                                                                   |
| `attention_state`, `check_state`                                                | See [attention states and findings](#attention-states-and-findings) and [trace checks](#trace-checks).                                       |
| `first_useful_answer_ms`, `useful_answer_timing_source`, `request_start_source` | Request timing, for projects set up for it; otherwise `null`.                                                                                |

`get_trace` adds `has_input`, `has_output` and `revision`, and returns span rows in start order: `id`, `span_id`, `parent_span_id`, `name`, `kind`, `status`, `state`, `started_at`, `ended_at`, `duration_ms`, `model` and `tokens`. A span's `kind` is `tool`, `agent`, `embedding` or `llm` when Hue recognizes the operation. Otherwise it is the recorded operation name, such as `chain`, or the OpenTelemetry span kind, such as `internal`. A span's `status` comes only from its OpenTelemetry status code.

`get_span` returns one span: `status` with its `code` and a `message` of up to 200 characters, `model`, `usage` (input, output, cache and reasoning tokens where recorded), `genAi` (`operation`, `provider`, `responseModel`, `agentName`, `sessionId`, `userId` and the detected `profiles`), `tool` (`name` and `callId`), `hasInput` and `hasOutput`, `service`, `attributeKeys` (the names of up to 100 recorded attributes, never their values) and `eventNames`. `"detail": "full"` adds the instrumentation scope, dropped-attribute counts and span `links`.

### Attention states and findings

When Hue's trace findings are on, which is the default, Hue assesses each ended trace from its recorded spans once it is quiet. Traces from evaluation runs are not assessed. `attention_state` is one of:

| State             | Meaning                                                                                  |
| ----------------- | ---------------------------------------------------------------------------------------- |
| `needs_attention` | At least one finding is present, or an active trace check has a current positive result. |
| `uncertain`       | No finding is present, but one could not be settled.                                     |
| `rules_only`      | Only the rule findings ran; the model pass is off or unavailable for the project.        |
| `no_findings`     | No findings in the recorded evidence.                                                    |
| `not_assessable`  | The trace recorded no readable request, reply or tool calls.                             |
| `dismissed`       | A member dismissed the assessment's findings in Hue.                                     |
| `null`            | Not assessed yet, or an evaluation-run trace.                                            |

The `attention` filter of `search_traces` takes `needs_attention` or `uncertain`. The findings behind `needs_attention` are:

| Finding                           | Source         | Present when                                                                                                                         |
| --------------------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `unrecovered_tool_error`          | Rule           | A tool returned an error and no later call to that tool succeeded.                                                                   |
| `model_error`                     | Rule           | A model call ended in error and no later model call succeeded.                                                                       |
| `missing_reply`                   | Rule           | No assistant reply text was found.                                                                                                   |
| `possible_inability`              | Model          | The reply appears to say the agent could not do this or lacked access or a capability.                                               |
| `possible_unresolved`             | Model          | The reply appears to address something other than the request, without answering or asking for input.                                |
| `possible_unsupported_completion` | Model and rule | The reply appears to say the action was done, but no recorded tool call succeeded, or a tool it called failed with no later success. |
| `possible_action_not_taken`       | Model and rule | The request asks for an action, the reply neither reports it done nor asks for input, and no recorded tool call succeeded.           |

Model findings need the project's **AI trace findings** setting, which is on by default; see [production safety](/guides/production-safety#what-hue-computes-from-your-traces). The MCP returns the attention state, not the individual findings; the trace's page in Hue lists them.

### Trace checks

Trace checks are project-owned, versioned checks of production behavior. They are advisory, not evaluator scores. The four checks are `delegation` (execution stayed with the orchestrator instead of a sub-agent), `action_scope` (execution expanded the request), `delegation_scope` (a handoff expanded the request) and `output_omission` (needed tool information was omitted). They produce results only after a project sets them up: [instrumentation](/integrations/opentelemetry#instrument-for-trace-checks-and-request-timing) that marks the request and its boundaries, trace-check consent, which is off by default, and a version activated against labelled traces.

A result is `present`, `absent`, `uncertain`, `unavailable` (not enough evidence) or `not_applicable`. A trace's `check_state` is `needs_attention`, `pending`, `uncertain`, `unavailable`, `not_applicable`, `no_findings` or `null` when no active version applies to it.

### Intents

Intents classify traces into the project's taxonomy of task types. `get_intent_summary` returns `consent` (whether AI intent classification is on), `total`, `coverage` and `buckets`. Bucket keys are `category:<key>`, `other`, `uncertain`, `no_user_text`, `failed` and `pending` (not classified yet). Classification needs a published taxonomy (`get_intent_taxonomy` returns `null` without one) and the project's **AI intent classification** setting. `range` is `24h`, `7d`, `30d`, `90d` or `all`.

## Field glossary

Hue reads these span attributes into its fields. When several are present, the first one listed wins, so the OpenTelemetry GenAI attribute wins over a Langfuse one. Only span attributes are read; of the resource attributes, `get_span` returns only `service.name`, as `service`.

| Hue field                             | Span attributes, highest precedence first                                                                                                                                                                                                                             |
| ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| User id (`genAi.userId`)              | `user.id`, `enduser.id`, `hue.user.id`, `ai.telemetry.metadata.userId`, `langfuse.user.id`                                                                                                                                                                            |
| Session                               | `gen_ai.conversation.id`, `session.id`, `hue.session.id`, `ai.telemetry.metadata.sessionId`, `langfuse.session.id`. The trace's session is its root span's, else the earliest span that has one.                                                                      |
| Agent name (`genAi.agentName`)        | `gen_ai.agent.name`, `ai.telemetry.functionId`, `traceloop.entity.name`                                                                                                                                                                                               |
| Operation, which sets the span `kind` | `gen_ai.operation.name`, `openinference.span.kind`, `traceloop.span.kind`, `ai.operationId`, `operation.name`, `langfuse.observation.type`                                                                                                                            |
| Model                                 | `gen_ai.response.model` or `ai.response.model`, else the requested model: `gen_ai.request.model`, `llm.model_name`, `ai.model.id`, `langfuse.observation.model.name`                                                                                                  |
| Provider                              | `gen_ai.provider.name`, `gen_ai.system`, `llm.provider`, `llm.system`, `ai.model.provider`                                                                                                                                                                            |
| Input and output tokens               | `gen_ai.usage.input_tokens` and `output_tokens`, then the `prompt_tokens` and `completion_tokens` forms, `llm.token_count.prompt` and `completion`, `ai.usage.*`, and last `langfuse.observation.usage_details`                                                       |
| Tool name and call id                 | `gen_ai.tool.name`, `tool.name`, `ai.toolCall.name`; `gen_ai.tool.call.id`, `tool_call.id`, `ai.toolCall.id`                                                                                                                                                          |
| Tool arguments and result (content)   | `gen_ai.tool.call.arguments`, `ai.toolCall.args`, `tool.parameters`; `gen_ai.tool.call.result`, `ai.toolCall.result`                                                                                                                                                  |
| Messages (content)                    | `gen_ai.input.messages` and `gen_ai.output.messages`, OpenInference and OpenLLMetry message attributes, `ai.prompt` and `ai.response.*`, `input.value` and `output.value`, and last `langfuse.observation.input` and `output` and `langfuse.trace.input` and `output` |
| Trace title                           | Derived from recorded request text first; a producer name from `hue.trace.name`, then `langfuse.trace.name`, is the fallback                                                                                                                                          |
| Release                               | Not stored on the trace. A span attribute such as `langfuse.release` stays among the raw attributes.                                                                                                                                                                  |

Langfuse metadata (`langfuse.observation.metadata.*`, `langfuse.trace.metadata.*`), `langfuse.release`, `langfuse.environment`, tags and levels are kept as raw attributes. `get_span` lists their names in `attributeKeys` and returns their values only with `include_content: true`. The [OpenTelemetry guide](/integrations/opentelemetry#make-traces-useful-to-a-coding-agent) lists the attributes worth recording so these fields are filled.

## Limits and errors

| Limit                      | Value                                                                                                                                                                                                                            |
| -------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Time windows               | `since` and `until` take ISO-8601 or relative values from `15m` to `90d`. A window spans at most 90 days. `get_trace_check_summary` defaults to the last 7 days.                                                                 |
| Page sizes                 | `search_traces`, `list_sessions` and `list_intent_traces` return up to 50 rows (25 by default for the first two). `get_trace_check_results` and most list tools return up to 100. Pass `next_cursor` back unchanged as `cursor`. |
| Spans per `get_trace` call | `max_spans` from 1 to 500, 200 by default; pass `next_span_cursor` back as `span_cursor`. A trace that changes between pages answers `conflict`; start again without the cursor.                                                 |
| Result size                | `max_chars` from 1,000 to 200,000, 24,000 by default. A result that does not fit is shortened and says `truncated: true` with a `hint`.                                                                                          |
| Counts                     | `total_count` counts up to 10,000 traces; beyond that `total_count_capped` is `true`.                                                                                                                                            |
| Query time                 | A `search_traces` query has a 2-second budget; a slower one fails with `timeout`.                                                                                                                                                |
| Request size               | 1 MiB.                                                                                                                                                                                                                           |
| Text caps                  | Titles and names are capped at 200 characters, session keys at 128 and status messages at 200.                                                                                                                                   |

A tool that fails returns an MCP error result (`isError: true`) whose text starts with a code, then the message and sometimes a hint, for example `timeout: The query exceeded its time budget. Narrow the window …`.

| Code                                     | Meaning                                                                  | Retry?                                          |
| ---------------------------------------- | ------------------------------------------------------------------------ | ----------------------------------------------- |
| `invalid_argument`                       | An argument, window or cursor is invalid.                                | No: fix the argument.                           |
| `not_found`                              | No such object in this project. Ids from other projects answer this too. | No.                                             |
| `conflict`                               | The object changed, or the cursor belongs to another object or version.  | Reload, then retry.                             |
| `content_not_captured`                   | The application recorded this trace without content.                     | No.                                             |
| `timeout`                                | The query exceeded its time budget.                                      | Yes, with a narrower window or a lower `limit`. |
| `rate_limited`                           | Too many requests for this operation.                                    | Yes, after about a second.                      |
| `unavailable`                            | A transient failure.                                                     | Yes.                                            |
| `docs_unavailable`                       | The documentation search is unavailable.                                 | Yes.                                            |
| `forbidden_capability`, `read_only_mode` | The connection cannot use this write tool.                               | No.                                             |

At the HTTP level, a busy server instance answers `503` with `Retry-After: 1`; retry after a second and keep parallel tool calls to a few. Ten failed authentications for one key within a minute answer `429` with `Retry-After: 60`. The [connection guide's troubleshooting](/agents/mcp-server#troubleshooting) covers authentication errors.
