MCP Span Attributes Reference
This page documents every span attribute set by the MCP auto-instrumentor. Use it as a lookup when inspecting traces in Grafana, writing TraceQL queries, or building dashboards from MCP governance data.
How to Read This Reference
Each attribute table uses the following columns:
| Column | Meaning |
|---|---|
| Attribute | The span attribute key as it appears in trace data |
| Type | The OTel attribute type (string, int, bool) |
| Description | What the attribute represents |
| Example | A representative value you would see in a real trace |
Attributes are grouped by functional category. Within each group, attributes appear in the order they are set during the tool call lifecycle.
All waxell.mcp.* attributes are searchable in TraceQL. For example, to find all blocked tool calls:
{ span.waxell.mcp.governance_action = "block" }
OTel Standard Attributes
These attributes follow the OpenTelemetry semantic conventions for MCP and network instrumentation. They use standard OTel namespaces so that generic observability tools can interpret them without Waxell-specific knowledge.
| Attribute | Type | Description | Example |
|---|---|---|---|
mcp.method.name | string | The MCP JSON-RPC method being called | "tools/call" |
mcp.session.id | string | The MCP session identifier for the current connection | "sess_a1b2c3d4e5f6" |
network.transport | string | The network transport protocol used by the MCP connection | "stdio", "sse", "http" |
These three attributes appear on every MCP span alongside the waxell.mcp.* attributes. They enable interoperability with OTel-native dashboards and tooling that don't know about Waxell's custom namespace.
Core Tool Call Attributes
These attributes are set on every MCP tool call span, regardless of whether governance is enabled. They capture the basic identity and outcome of the tool invocation.
| Attribute | Type | Description | Example |
|---|---|---|---|
waxell.mcp.server_name | string | Name of the MCP server being called | "composio" |
waxell.mcp.tool_name | string | Name of the tool being invoked on the server | "search_documents" |
waxell.mcp.transport | string | Transport protocol (mirrors network.transport in the Waxell namespace) | "stdio" |
waxell.mcp.policy_id | string | Policy matching identifier in mcp:{server}:{tool} format | "mcp:composio:search_documents" |
waxell.mcp.arguments | string | JSON-serialized tool call arguments (truncated to 4KB) | "{\"query\": \"quarterly revenue\"}" |
waxell.mcp.result | string | JSON-serialized tool result (truncated to 4KB) | "{\"content\": [{\"type\": \"text\", ...}]}" |
waxell.mcp.is_error | bool | Whether the tool call returned an error | true |
waxell.mcp.error_type | string | Category of error when is_error is true | "timeout", "transport_error", "server_error", "tool_execution_error" |
waxell.mcp.content_count | int | Number of content items in the tool result | 3 |
waxell.mcp.timeout_ms | int | Configured timeout for this tool call in milliseconds | 30000 |
waxell.mcp.arguments and waxell.mcp.result are truncated to 4KB to prevent oversized spans. If you need the full payload, use the audit trail or structured logging.
Governance: Policy Attributes
These attributes record the outcome of the policy check that runs before every governed tool call. They are only set when governance is enabled (i.e., the controlplane is configured).
| Attribute | Type | Description | Example |
|---|---|---|---|
waxell.mcp.governance_checked | bool | Whether a policy check was performed for this call | true |
waxell.mcp.governance_action | string | The policy engine's decision for this tool call | "allow", "block", "warn", "throttle" |
waxell.mcp.policy_skipped | bool | Whether the policy check was skipped (e.g., controlplane unreachable, fail-open) | false |
waxell.mcp.policy_reason | string | Human-readable explanation of the policy decision | "Tool blocked by allowlist policy: composio:send_email not in allowed tools" |
waxell.mcp.policy_rule_ids | string | Comma-separated IDs of the policy rules that matched | "rule_42,rule_87" |
waxell.mcp.throttle_delay_ms | int | Delay applied before tool execution when action is throttle (capped at 30s) | 5000 |
Policy action values:
| Action | Meaning | Tool executes? |
|---|---|---|
allow | Policy permits the call | Yes |
block | Policy forbids the call | No -- synthetic error result returned |
warn | Policy flags the call but permits execution | Yes |
throttle | Policy permits the call after an enforced delay | Yes (after delay) |
Governance: Approval Attributes
These attributes record the outcome of human-in-the-loop approval workflows. They are set when a policy rule requires human approval before a tool call can proceed.
| Attribute | Type | Description | Example |
|---|---|---|---|
waxell.mcp.approval_status | string | Outcome of the approval request | "approved", "denied", "timeout", "not_required" |
waxell.mcp.approval_approver | string | Identifier of the person or system that approved/denied the call | "admin@company.com" |
waxell.mcp.approval_elapsed_ms | int | Time spent waiting for approval in milliseconds | 12450 |
Approval status values:
| Status | Meaning | Tool executes? |
|---|---|---|
approved | A human or system approved the call | Yes |
denied | A human or system denied the call | No |
timeout | Approval request timed out without a response | No (treated as denial) |
not_required | No approval was needed for this call | Yes |
Governance: PII Attributes
These attributes record the results of PII and credential scanning performed on tool call arguments and/or results. They are set when PII scanning is enabled in the governance configuration.
| Attribute | Type | Description | Example |
|---|---|---|---|
waxell.mcp.pii_detected | bool | Whether any PII or credentials were found | true |
waxell.mcp.pii_count | int | Total number of PII findings across all scanned content | 2 |
waxell.mcp.pii_scan_direction | string | Which direction was scanned for PII | "inputs", "outputs", "both" |
waxell.mcp.pii_action_taken | string | The highest-severity action taken in response to PII detection | "warn", "block", "redact" |
PII action severity (highest wins):
| Action | Severity | Meaning |
|---|---|---|
warn | 0 (lowest) | PII detected and logged, but tool call proceeds unchanged |
redact | 1 | PII values replaced with placeholders before tool execution |
block | 2 (highest) | Tool call blocked entirely due to PII in arguments |
PII scanning on tool outputs (results) always uses warn -- it cannot block or redact because the tool has already executed. Output PII findings are recorded for audit purposes.
Governance: Audit Attributes
These attributes create an immutable audit trail for every governed tool call. They enable compliance reporting, forensic investigation, and tamper detection.
| Attribute | Type | Description | Example |
|---|---|---|---|
waxell.mcp.governance_timestamp | string | ISO 8601 timestamp of when governance processing occurred | "2026-03-05T14:32:01.456Z" |
waxell.mcp.audit_agent | string | Name of the agent that initiated the tool call | "customer-support-agent" |
waxell.mcp.audit_user | string | User ID associated with the agent session (if available) | "user_9f8e7d6c" |
waxell.mcp.params_hash | string | SHA256 hash of the tool arguments, truncated to 16 hex characters | "a3f2b8c1e9d04f67" |
waxell.mcp.blocked_synthetic | bool | Whether a blocked call returned a synthetic CallToolResult instead of executing | true |
The params_hash attribute lets you verify that logged arguments match the actual call. Compare the hash of the recorded arguments attribute with params_hash to detect any post-hoc modification of audit records.
Security: Server Identity Attributes
These attributes capture information about the MCP server itself, recorded during the initial connection handshake. They enable monitoring for unexpected server changes across sessions.
| Attribute | Type | Description | Example |
|---|---|---|---|
waxell.mcp.server_version | string | Server version string from the MCP initialize response | "1.2.0" |
waxell.mcp.server_capabilities | string | JSON-serialized server capabilities object | "{\"tools\": {\"listChanged\": true}}" |
waxell.mcp.server_connection | string | The URL or command used to connect to the server | "npx -y @modelcontextprotocol/server-filesystem /tmp" |
waxell.mcp.server_version_changed | bool | Whether the server version differs from the last observed session | false |
Security: Fingerprint Attributes
These attributes record the results of tool fingerprinting, which detects when an MCP server's tool definitions change between sessions (rug pull detection). They are set on a dedicated session-info span emitted at the start of each MCP session.
| Attribute | Type | Description | Example |
|---|---|---|---|
waxell.mcp.fingerprint_hash | string | SHA256 hash of the current tool set (name + description + schemas) | "e4a1c9f2b83d7065" |
waxell.mcp.fingerprint_status | string | Result of comparing the current fingerprint against the stored baseline | "match", "changed", "new", "first_observation", "skipped" |
waxell.mcp.fingerprint_skipped | bool | Whether fingerprint capture was skipped (e.g., list_tools failed or feature disabled) | false |
waxell.mcp.fingerprint_tool_count | int | Number of tools observed on the server | 12 |
waxell.mcp.fingerprint_changes_detected | int | Number of individual tool changes found since baseline | 2 |
waxell.mcp.fingerprint_diff | string | Unified diff text showing what changed (truncated to 2KB) | "- search_documents: Search files...\n+ search_documents: Exfiltrate data..." |
Fingerprint status values:
| Status | Meaning | Action recommended |
|---|---|---|
match | Tool definitions match the stored baseline | None -- server is consistent |
changed | One or more tool definitions differ from baseline | Investigate changes, review diff |
new | A previously unseen tool appeared | Review new tool before allowing use |
first_observation | First time connecting to this server (no baseline exists) | Baseline stored silently, no alert |
skipped | Fingerprint capture failed or was disabled | Check server connectivity |
Security: Tool Set Integrity Attributes
These attributes track additions and removals from the MCP server's tool list. They complement fingerprint attributes by identifying exactly which tools changed.
| Attribute | Type | Description | Example |
|---|---|---|---|
waxell.mcp.tools_added | string | Comma-separated names of tools that appeared since last observation | "exfil_data,backdoor_shell" |
waxell.mcp.tools_removed | string | Comma-separated names of tools that disappeared since last observation | "search_documents" |
A tool being removed and a new tool being added in the same session is a strong signal of a rug pull attack. Monitor for spans where both tools_added and tools_removed are non-empty.
{ span.waxell.mcp.tools_added != "" && span.waxell.mcp.tools_removed != "" }
Server-Side Middleware Attributes
These attributes are set by the server-side governance middleware (GovernanceMiddleware and SecurityMiddleware) rather than the client-side auto-instrumentor. They appear on spans with SpanKind.SERVER and use the same waxell.mcp.* namespace for unified querying.
| Attribute | Type | Description | Example |
|---|---|---|---|
waxell.mcp.middleware_active | bool | Whether governance middleware is actively processing this call | true |
waxell.mcp.server_side | bool | Whether this span was emitted by server-side middleware (vs client-side) | true |
waxell.mcp.caller_client_id | string | MCP client ID from the initialize handshake | "claude-desktop-1.4" |
waxell.mcp.caller_session_id | string | MCP session ID for the caller's connection | "sess_x7y8z9" |
waxell.mcp.caller_api_key_hash | string | SHA256 hash (first 8 chars) of the caller's API key for identity without exposure | "a3f2b8c1" |
waxell.mcp.caller_ip | string | Caller's IP address from HTTP headers (available for HTTP/SSE transports) | "192.168.1.42" |
waxell.mcp.caller_user_agent | string | Caller's user-agent header (available for HTTP/SSE transports) | "mcp-client/1.0" |
waxell.mcp.rate_limited | bool | Whether the call was rejected due to rate limiting | true |
waxell.mcp.rate_limit_remaining | int | Number of remaining calls allowed in the current rate limit window | 7 |
Client-side spans (waxell.mcp.server_side = false or absent) are emitted by the auto-instrumentor running inside the agent process. Server-side spans (waxell.mcp.server_side = true) are emitted by middleware running inside the MCP server. Both use the same attribute namespace, so a single TraceQL query like { span.waxell.mcp.tool_name = "send_email" } finds tool calls from both perspectives.
Span Naming Convention
All MCP tool call spans follow the naming pattern:
tools/call {server}:{tool}
Examples:
| Span Name | Server | Tool |
|---|---|---|
tools/call composio:GITHUB_CREATE_ISSUE | composio | GITHUB_CREATE_ISSUE |
tools/call filesystem:read_file | filesystem | read_file |
tools/call slack:send_message | slack | send_message |
This convention allows TraceQL queries by server, by tool, or by the combination:
# All calls to the composio server
{ name =~ "tools/call composio:.*" }
# All send_message calls across any server
{ name =~ "tools/call .*:send_message" }
# Exact tool on exact server
{ name = "tools/call slack:send_message" }
Accessing Attributes Programmatically
All attribute constants are available in the MCPAttributes class for use in custom instrumentation, testing, or TraceQL query builders.
from waxell_observe.tracing.attributes import MCPAttributes
# Use constants instead of raw strings
span.set_attribute(MCPAttributes.SERVER_NAME, "composio")
span.set_attribute(MCPAttributes.TOOL_NAME, "search_documents")
span.set_attribute(MCPAttributes.GOVERNANCE_ACTION, "allow")
# OTel standard attributes are also on the class
span.set_attribute(MCPAttributes.METHOD_NAME, "tools/call")
span.set_attribute(MCPAttributes.SESSION_ID, session_id)
span.set_attribute(MCPAttributes.NETWORK_TRANSPORT, "stdio")
Full constant list:
# OTel standard
MCPAttributes.METHOD_NAME # "mcp.method.name"
MCPAttributes.SESSION_ID # "mcp.session.id"
MCPAttributes.NETWORK_TRANSPORT # "network.transport"
# Core tool call
MCPAttributes.SERVER_NAME # "waxell.mcp.server_name"
MCPAttributes.TOOL_NAME # "waxell.mcp.tool_name"
MCPAttributes.TRANSPORT # "waxell.mcp.transport"
MCPAttributes.POLICY_ID # "waxell.mcp.policy_id"
MCPAttributes.ARGUMENTS # "waxell.mcp.arguments"
MCPAttributes.RESULT # "waxell.mcp.result"
MCPAttributes.IS_ERROR # "waxell.mcp.is_error"
MCPAttributes.ERROR_TYPE # "waxell.mcp.error_type"
MCPAttributes.CONTENT_COUNT # "waxell.mcp.content_count"
MCPAttributes.TIMEOUT_MS # "waxell.mcp.timeout_ms"
# Governance: Policy
MCPAttributes.GOVERNANCE_CHECKED # "waxell.mcp.governance_checked"
MCPAttributes.GOVERNANCE_ACTION # "waxell.mcp.governance_action"
MCPAttributes.POLICY_SKIPPED # "waxell.mcp.policy_skipped"
MCPAttributes.POLICY_REASON # "waxell.mcp.policy_reason"
MCPAttributes.POLICY_RULE_IDS # "waxell.mcp.policy_rule_ids"
MCPAttributes.THROTTLE_DELAY_MS # "waxell.mcp.throttle_delay_ms"
# Governance: Approval
MCPAttributes.APPROVAL_STATUS # "waxell.mcp.approval_status"
MCPAttributes.APPROVAL_APPROVER # "waxell.mcp.approval_approver"
MCPAttributes.APPROVAL_ELAPSED_MS # "waxell.mcp.approval_elapsed_ms"
# Governance: PII
MCPAttributes.PII_DETECTED # "waxell.mcp.pii_detected"
MCPAttributes.PII_COUNT # "waxell.mcp.pii_count"
MCPAttributes.PII_SCAN_DIRECTION # "waxell.mcp.pii_scan_direction"
MCPAttributes.PII_ACTION_TAKEN # "waxell.mcp.pii_action_taken"
# Governance: Audit
MCPAttributes.GOVERNANCE_TIMESTAMP # "waxell.mcp.governance_timestamp"
MCPAttributes.AUDIT_AGENT # "waxell.mcp.audit_agent"
MCPAttributes.AUDIT_USER # "waxell.mcp.audit_user"
MCPAttributes.PARAMS_HASH # "waxell.mcp.params_hash"
MCPAttributes.BLOCKED_SYNTHETIC # "waxell.mcp.blocked_synthetic"
# Security: Server identity
MCPAttributes.SERVER_VERSION # "waxell.mcp.server_version"
MCPAttributes.SERVER_CAPABILITIES # "waxell.mcp.server_capabilities"
MCPAttributes.SERVER_CONNECTION # "waxell.mcp.server_connection"
MCPAttributes.SERVER_VERSION_CHANGED # "waxell.mcp.server_version_changed"
# Security: Fingerprint
MCPAttributes.FINGERPRINT_HASH # "waxell.mcp.fingerprint_hash"
MCPAttributes.FINGERPRINT_STATUS # "waxell.mcp.fingerprint_status"
MCPAttributes.FINGERPRINT_SKIPPED # "waxell.mcp.fingerprint_skipped"
MCPAttributes.FINGERPRINT_TOOL_COUNT # "waxell.mcp.fingerprint_tool_count"
MCPAttributes.FINGERPRINT_CHANGES_DETECTED # "waxell.mcp.fingerprint_changes_detected"
MCPAttributes.FINGERPRINT_DIFF # "waxell.mcp.fingerprint_diff"
# Security: Tool set integrity
MCPAttributes.TOOLS_ADDED # "waxell.mcp.tools_added"
MCPAttributes.TOOLS_REMOVED # "waxell.mcp.tools_removed"
# Server-side middleware
MCPAttributes.MIDDLEWARE_ACTIVE # "waxell.mcp.middleware_active"
MCPAttributes.SERVER_SIDE # "waxell.mcp.server_side"
MCPAttributes.CALLER_CLIENT_ID # "waxell.mcp.caller_client_id"
MCPAttributes.CALLER_SESSION_ID # "waxell.mcp.caller_session_id"
MCPAttributes.CALLER_API_KEY_HASH # "waxell.mcp.caller_api_key_hash"
MCPAttributes.CALLER_IP # "waxell.mcp.caller_ip"
MCPAttributes.CALLER_USER_AGENT # "waxell.mcp.caller_user_agent"
MCPAttributes.RATE_LIMITED # "waxell.mcp.rate_limited"
MCPAttributes.RATE_LIMIT_REMAINING # "waxell.mcp.rate_limit_remaining"
Related Pages
- MCP Governance Overview -- What is MCP governance and why it matters
- Quickstart -- Set up MCP governance in 5 minutes
- Policy Configuration -- Allowlists, blocklists, and policy rules
- Approval Workflows -- Human-in-the-loop approval for tool calls
- PII Scanning -- Detect and handle PII in tool arguments and results
- Rug Pull Detection -- Fingerprinting and tool change alerts