SigNoz MCP Server
Officialby SigNoz
README.md
# SigNoz MCP Server
[](https://golang.org)
[](LICENSE)
[](https://modelcontextprotocol.io)
A Model Context Protocol (MCP) server that provides seamless access to SigNoz observability data through AI assistants and LLMs. Query metrics, traces, logs, alerts, dashboards, and services using natural language.
**[📖 Full Documentation](https://signoz.io/docs/ai/signoz-mcp-server/)**
## Table of Contents
- [Connect to SigNoz Cloud](#connect-to-signoz-cloud)
- [Self-Hosted Installation](#self-hosted-installation)
- [Connect to Self-Hosted SigNoz](#connect-to-self-hosted-signoz)
- [MCP Protocol Compatibility](#mcp-protocol-compatibility)
- [What Can You Do With It?](#what-can-you-do-with-it)
- [Available Tools](#available-tools)
- [Environment Variables](#environment-variables)
- [Claude Desktop Extension](#claude-desktop-extension)
- [End-to-End Tests](#end-to-end-tests)
- [Architecture](#architecture)
- [Contributing](#contributing)
## Connect to SigNoz Cloud
Connect your AI tool to SigNoz Cloud's hosted MCP server. No installation is required; just add the hosted MCP URL and authenticate.
```text
https://mcp.<region>.signoz.cloud/mcp
```
> Make sure you select the correct region that matches your SigNoz Cloud account. Using the wrong region will result in authentication failures.
>
> Find your region under **Settings → Ingestion** in SigNoz, or see the [SigNoz Cloud region reference](https://signoz.io/docs/ingestion/signoz-cloud/overview/#endpoint).
### One-Click Install Links
GitHub does not reliably make custom-protocol links like `cursor://` and `vscode:` clickable in README rendering.
Use the documentation page for one-click install buttons:
- [Open one-click install links for Cursor](https://signoz.io/docs/ai/signoz-mcp-server/#install-in-one-click)
- [Open one-click install links for VS Code](https://signoz.io/docs/ai/signoz-mcp-server/#install-in-one-click-1)
If you prefer, use the manual configuration examples below in this README.
### Cursor
#### Manual Configuration
Add this configuration to `.cursor/mcp.json`:
```json
{
"mcpServers": {
"signoz": {
"url": "https://mcp.<region>.signoz.cloud/mcp"
}
}
}
```
Need help? See the [Cursor MCP docs](https://docs.cursor.com/context/model-context-protocol).
### VS Code / GitHub Copilot
#### Manual Configuration
Add this configuration to `.vscode/mcp.json`:
```json
{
"servers": {
"signoz": {
"type": "http",
"url": "https://mcp.<region>.signoz.cloud/mcp"
}
}
}
```
Need help? See the [VS Code MCP docs](https://code.visualstudio.com/docs/copilot/chat/mcp-servers).
### Claude Desktop
Add SigNoz Cloud as a custom connector in Claude Desktop:
1. Open Claude Desktop.
2. Go to **Settings → Developer** (or **Features**, depending on your version).
3. Click **Add Custom Connector** or **Add Remote MCP Server**.
4. Enter your SigNoz MCP URL: `https://mcp.<region>.signoz.cloud/mcp`
When prompted, complete the authentication flow.
### Claude Code
Run this command to add the hosted SigNoz MCP server:
```bash
claude mcp add --scope user --transport http signoz https://mcp.<region>.signoz.cloud/mcp
```
After configuring the MCP server, authenticate in a terminal:
```bash
claude /mcp
```
Select the `signoz` server and complete the authentication flow.
### OpenAI Codex
Run this command to add the hosted SigNoz MCP server:
```bash
codex mcp add signoz --url https://mcp.<region>.signoz.cloud/mcp
```
Or add this configuration to `config.toml`:
```toml
[mcp_servers.signoz]
url = "https://mcp.<region>.signoz.cloud/mcp"
```
After adding the server, authenticate:
```bash
codex mcp login signoz
```
Then run `/mcp` inside Codex to verify the connection.
### Grok Build
Run this command to add the hosted SigNoz MCP server:
```bash
grok mcp add -t http signoz https://mcp.<region>.signoz.cloud/mcp
```
Or add this configuration to `~/.grok/config.toml`:
```toml
[mcp_servers.signoz]
url = "https://mcp.<region>.signoz.cloud/mcp"
enabled = true
```
Adding the server does not authenticate it. Start Grok Build, run `/mcps`, select the `signoz` server, and complete the OAuth flow in your browser:
```bash
grok
```
```
/mcps
```
No API key is stored in the config file; credentials are saved separately once the OAuth flow completes.
Use `-s project` on the `add` command to write to `./.grok/config.toml` instead, so the server is shared with everyone working in that directory.
Verify the connection with:
```bash
grok mcp list
grok mcp doctor
```
### SigNoz Cloud Authentication
When you add the hosted MCP URL to your client, the client initiates an authentication flow. You will be prompted to enter:
1. Your SigNoz instance URL (for example, `your-instance.signoz.cloud`). Protocol-less URLs are accepted; paths, query parameters, and fragments are ignored.
2. Your API key
Create an API key in **Settings → API Keys** in SigNoz. Only **Admin** users can create API keys.
## Self-Hosted Installation
### Download Binary (Recommended)
Download the latest binary from [GitHub Releases](https://github.com/SigNoz/signoz-mcp-server/releases):
```bash
# macOS (Apple Silicon)
curl -L https://github.com/SigNoz/signoz-mcp-server/releases/latest/download/signoz-mcp-server_darwin_arm64.tar.gz | tar xz
# macOS (Intel)
curl -L https://github.com/SigNoz/signoz-mcp-server/releases/latest/download/signoz-mcp-server_darwin_amd64.tar.gz | tar xz
# Linux (amd64)
curl -L https://github.com/SigNoz/signoz-mcp-server/releases/latest/download/signoz-mcp-server_linux_amd64.tar.gz | tar xz
```
This extracts a `signoz-mcp-server` binary in the current directory. Move it somewhere on your PATH or note the absolute path for the config below.
### Go Install
```bash
go install github.com/SigNoz/signoz-mcp-server/cmd/server@latest
```
The binary is installed as `server` to `$GOPATH/bin/` (default: `$HOME/go/bin/server`). You may want to rename it:
```bash
mv "$(go env GOPATH)/bin/server" "$(go env GOPATH)/bin/signoz-mcp-server"
```
### Docker
Docker images are available on [Docker Hub](https://hub.docker.com/r/signoz/signoz-mcp-server/tags):
```bash
docker pull signoz/signoz-mcp-server:latest
```
Run in HTTP mode:
```bash
docker run -p 8000:8000 \
-e TRANSPORT_MODE=http \
-e MCP_SERVER_PORT=8000 \
-e SIGNOZ_URL=https://your-signoz-instance.com \
-e SIGNOZ_API_KEY=your-api-key \
signoz/signoz-mcp-server:latest
```
Use a specific version tag (e.g. `v0.1.0`) instead of `latest` for pinned deployments.
### Build from Source
```bash
git clone https://github.com/SigNoz/signoz-mcp-server.git
cd signoz-mcp-server
make build
```
The binary is at `./bin/signoz-mcp-server`.
## Connect to Self-Hosted SigNoz
### Prerequisites
- A running [SigNoz](https://signoz.io) instance on the latest release. Each server release targets the latest SigNoz release and is not tested against older versions; see [CHANGELOG.md](CHANGELOG.md) for breaking changes.
- A SigNoz API key (Settings → API Keys in the SigNoz UI)
- The `signoz-mcp-server` binary (see [Self-Hosted Installation](#self-hosted-installation))
### Stdio Mode (Claude Desktop / Cursor / Any MCP Client)
Add this to your MCP client config (`claude_desktop_config.json`, `.cursor/mcp.json`, etc.). Replace the `command` path with the absolute path to your `signoz-mcp-server` binary:
```json
{
"mcpServers": {
"signoz": {
"command": "/absolute/path/to/signoz-mcp-server",
"args": [],
"env": {
"SIGNOZ_URL": "https://your-signoz-instance.com",
"SIGNOZ_API_KEY": "your-api-key-here",
"LOG_LEVEL": "info"
}
}
}
}
```
### HTTP Mode
HTTP mode listens on all interfaces by default. Set `MCP_SERVER_HOST=127.0.0.1` when the server should accept loopback connections only.
#### Memory footprint
The server keeps the SigNoz docs search index in memory. With stemming on titles and headings and a single standard-analyzed body field, the embedded 746-page index used 28 to 36 MiB of resident heap across eight local Go 1.26 whole-package test runs. Build peaks ranged from 97 to 134 MiB above the pre-build heap baseline, using 64-page batches. These are index measurements, not whole-process RSS or container memory guarantees; request handling and refresh work add memory.
| Moment | Index memory behavior |
| --- | --- |
| Startup build from the embedded corpus (746 pages) | Up to 134 MiB above the pre-build heap baseline in the measured runs |
| Scheduled full rebuild | Builds a new index while the old index is still serving; combined peak has not been re-measured with this configuration |
| Scheduled refresh that changes a few pages | Applies changed pages in one atomic batch to the live index; peak depends on the changed content and has not been re-measured with this configuration |
| Scheduled refresh that finds no changed pages | no index work; pages are revalidated with `If-None-Match` and unchanged ones cost a 304 |
A scheduled refresh (default every `6h`) first compares the live sitemap with the served one and stops there when it is unchanged. Otherwise it revalidates every page with `If-None-Match` and touches the index only when at least one page's content changed. A change set covering up to a quarter of the pages is applied to the live index in place; a larger one, the 25th in-place update on the same index, and any forced refresh (default every `24h`) that finds changed content rebuild the index from scratch, which also compacts the segments that in-place updates leave behind. Full rebuilds use 64-page batches. In-place updates use one atomic batch bounded by the quarter-of-pages threshold, not the full-build batch size.
Recommendations for containerized HTTP deployments:
- Set the memory limit to at least `512Mi`, and monitor memory during refreshes and concurrent requests. The highest measured index-only build peak is 134 MiB above baseline and the resident index is 28 to 36 MiB; rebuilds also retain the serving index. Setting Go's `GOMEMLIMIT` is optional: it can reclaim garbage earlier but cannot shrink live data inside an index batch.
- Set both `SIGNOZ_DOCS_REFRESH_INTERVAL=0` and `SIGNOZ_DOCS_FULL_REFRESH_INTERVAL=0` when you would rather serve the docs snapshot that shipped with the release than pay any refresh. New docs pages then arrive with the next server upgrade. Setting only the first keeps the daily forced refresh.
- Every refresh logs `docs refresh starting` and ends with a completion or failure line, for example `docs refresh no-op; sitemap unchanged`, `docs refresh found no page changes; index kept`, `docs refresh applied delta`, `docs refresh rebuilt index`, or a `docs refresh failed` / `docs full refresh failed` warning. A refresh normally finishes within a few minutes. A container whose last docs line is `docs refresh starting`, `docs refresh fetching pages`, or `docs refresh rebuilding index` and that then restarted most likely died mid-refresh.
#### With OAuth (Multi-Tenant / Cloud)
Start the server:
```bash
TRANSPORT_MODE=http \
MCP_SERVER_PORT=8000 \
OAUTH_ENABLED=true \
OAUTH_TOKEN_SECRET=$(openssl rand -base64 32) \
OAUTH_ISSUER_URL=https://your-public-mcp-url.com \
./signoz-mcp-server
```
Client config needs just the URL, no keys:
```json
{
"mcpServers": {
"signoz": {
"url": "https://your-public-mcp-url.com/mcp"
}
}
}
```
The client discovers OAuth endpoints automatically, opens a browser for credentials, and handles token exchange.
#### Without OAuth (Simple Setup)
The API key and SigNoz URL only need to be provided in **one** place: the server or the client.
**Option A — Credentials on the server** (simpler client config):
```bash
SIGNOZ_URL=https://your-signoz-instance.com \
SIGNOZ_API_KEY=your-api-key \
TRANSPORT_MODE=http \
MCP_SERVER_PORT=8000 \
./signoz-mcp-server
```
```json
{
"mcpServers": {
"signoz": {
"url": "http://localhost:8000/mcp"
}
}
}
```
**Option B — API key on the client** (server holds the URL, client sends the key):
```bash
SIGNOZ_URL=https://your-signoz-instance.com \
TRANSPORT_MODE=http \
MCP_SERVER_PORT=8000 \
./signoz-mcp-server
```
```json
{
"mcpServers": {
"signoz": {
"url": "http://localhost:8000/mcp",
"headers": {
"SIGNOZ-API-KEY": "your-api-key-here"
}
}
}
}
```
## MCP Protocol Compatibility
SigNoz uses the official MCP Go SDK v1.8.0 and supports both current lifecycle
models over HTTP and stdio:
| Protocol era | Lifecycle |
|---|---|
| `2025-11-25` | Legacy clients use `initialize`, then `notifications/initialized`, before ordinary requests. |
| `2026-07-28` | Clients may call `server/discover`, then send direct requests carrying protocol and client capabilities in per-request `_meta`; no initialize handshake is required. |
The HTTP `/mcp` endpoint is stateless and sessionless. MCP messages use JSON
`POST` requests and successful responses use `application/json`; the server does
not issue or require `Mcp-Session-Id`. `GET /mcp` and `DELETE /mcp` return
`405 Method Not Allowed`, so deployments need neither sticky routing nor the old
GET listener/heartbeat. Existing client configuration does not change.
Stdio input has a 16 MiB frame limit. Split larger requests into smaller calls.
`MCP_MAX_REQUEST_BYTES` controls HTTP request bodies only.
The server intentionally does not advertise the deprecated logging capability.
Discovery ordering is not a compatibility guarantee. Unknown tools, resources,
and prompts use the official SDK's standard invalid-params behavior rather than
legacy implementation-specific wording or error codes.
### HTTP Probe Endpoints
HTTP mode exposes unauthenticated probe endpoints. New Kubernetes deployments should use `/livez` for `livenessProbe` and `/readyz` for `readinessProbe`.
| Endpoint | Purpose |
|----------|---------|
| `/livez` | Shallow liveness probe. Returns `200 OK` when the server process can answer HTTP requests. It does not check dependencies. |
| `/readyz` | Readiness probe. Returns `200 OK` only after the pod is ready to receive traffic; currently this requires the docs index to be ready. Otherwise returns `503`. |
| `/healthz` | Legacy/generic health check kept for backward compatibility. It follows the same strict status as `/readyz`; use `/livez` for shallow liveness. |
## What Can You Do With It?
```
"Show me all available metrics"
"What's the p99 latency for http_request_duration_seconds?"
"List all active alerts"
"Show me error logs for the paymentservice from the last hour"
"How many errors per service in the last hour?"
"Search traces for the checkout service from the last hour"
"Get details for trace ID abc123"
"Create a dashboard with CPU and memory widgets"
"How do I send Docker logs to SigNoz?"
```
## Available Tools
> **Tool metadata:** every tool accepts `searchContext`. Copy the user's entire original request verbatim, including preflight or confirmation context; it is used for MCP observability and is not forwarded to SigNoz APIs.
> **Input validation:** calls are never rejected for schema mismatches. Arguments are validated against each tool's advertised schema; a mismatched call still runs best-effort, and the successful result carries a deterministic appended `Input validation notice:` naming the affected top-level parameter when it can be derived safely from the advertised schema. Complex root-only mismatches use a generic fallback. Mismatches are also counted in the `mcp.tool.validation.mismatches` metric.
> **Upstream errors:** upstream SigNoz 401 and 403 tool failures carry a stable structured `code` (`UNAUTHORIZED` or `PERMISSION_DENIED`) and numeric `status`. Recognized SigNoz error envelopes may also include bounded `upstreamURL`, `upstreamSuggestions`, `upstreamDetails` (`[{message, suggestions}]`), and `upstreamRetry` (`{delay}` in nanoseconds); the same recovery guidance appears in agent-readable text. Unrecognized bodies use the local status-derived coded fallback instead of raw passthrough, and authorization failures still name the failed tool and immediate recovery action. This error-only addition does not change tool names, schemas or descriptions, success payloads, resources or templates, or prompts.
| Tool | Description |
|------|-------------|
| `signoz_get_org_overview` | Get the current status and overall posture of the SigNoz deployment, with typed projections plus `sourceStats` containing every reported stats field |
| `signoz_list_metrics` | Discover active metric names and catalog metadata |
| `signoz_query_metrics` | Query known metrics for values, trends, breakdowns, or formulas |
| `signoz_get_top_metrics` | Return top 100 metrics ranked by ingested sample volume with pre-computed percentages for cost and volume analysis |
| `signoz_check_metric_usage` | Given a list of metric names (up to 50 per call), return which dashboards and alerts reference each one |
| `signoz_check_metric_cardinality` | Return label/attribute keys for a single metric with cardinality counts and sample values, sorted highest-cardinality first |
| `signoz_get_field_keys` | Discover available field keys for metrics, traces, or logs |
| `signoz_get_field_values` | Get possible values for a field key |
| `signoz_list_alerts` | List firing/silenced/inhibited Alertmanager alert *instances* (not rule definitions) |
| `signoz_list_alert_rules` | List configured alert-rule summaries, including inactive/OK and disabled rules |
| `signoz_get_alert` | Get one alert rule's full definition by `id` |
| `signoz_get_alert_history` | Get one rule's firing or state-transition history |
| `signoz_create_alert` | Create a v2 direct/policy-routed alert or a direct-routed v1 anomaly alert |
| `signoz_update_alert` | Fully replace an existing alert rule by `id` |
| `signoz_delete_alert` | Permanently delete a confirmed alert rule by UUIDv7 `id` |
| `signoz_list_dashboards` | List tenant-dashboard summaries and discover UUIDs |
| `signoz_get_dashboard` | Get one dashboard's full layout, variables, panels, and queries |
| `signoz_create_dashboard` | Create a custom multi-panel dashboard |
| `signoz_update_dashboard` | Fully replace a fetched dashboard while preserving unrequested fields |
| `signoz_patch_dashboard` | Apply a partial RFC 6902 JSON Patch without resending the whole dashboard |
| `signoz_delete_dashboard` | Permanently delete a confirmed dashboard by `id` |
| `signoz_import_dashboard` | Create a dashboard from a known curated template path |
| `signoz_list_dashboard_templates` | List curated templates and discover an import path |
| `signoz_list_services` | List APM services with trace activity in a time range |
| `signoz_get_service_top_operations` | Get ranked operations for one traced service |
| `signoz_list_views` | List saved Explorer views for traces/logs/metrics/Cost Meter/AI Observability and discover UUIDs |
| `signoz_get_view` | Get one saved Explorer view's complete definition by `id` |
| `signoz_search_docs` | Find ranked official-doc matches when no exact page is selected |
| `signoz_fetch_doc` | Fetch one known official-doc page or heading as Markdown |
| `signoz_create_view` | Save one reusable Explorer query spec |
| `signoz_update_view` | Fully replace a fetched saved view while preserving unrequested fields |
| `signoz_delete_view` | Permanently delete a confirmed saved view by `id` |
| `signoz_aggregate_logs` | Aggregate log statistics and grouped or top-N breakdowns |
| `signoz_search_logs` | Return individual log records matching filters |
| `signoz_aggregate_traces` | Aggregate span statistics and grouped or top-N breakdowns |
| `signoz_search_traces` | Return individual span rows or discover trace IDs |
| `signoz_get_trace_details` | Get one known trace with all spans and hierarchy |
| `signoz_execute_builder_query` | Query Builder v5 requests the dedicated tools cannot express |
| `signoz_list_notification_channels` | List channel IDs, names, and display names without provider settings |
| `signoz_get_notification_channel` | Get all provider-specific settings for one channel by ID |
| `signoz_create_notification_channel` | Create a notification channel |
| `signoz_update_notification_channel` | Fully replace a fetched channel's config |
| `signoz_delete_notification_channel` | Permanently delete a confirmed channel by ID |
For detailed usage and examples, see the [full documentation](https://signoz.io/docs/ai/signoz-mcp-server/).
> **Resource deep links:** the resource read tools (`signoz_list_dashboards`, `signoz_get_dashboard`, `signoz_list_alerts`, `signoz_list_alert_rules`, `signoz_get_alert`, `signoz_list_services`, `signoz_search_traces`, `signoz_get_trace_details`) and the dashboard write tools (`signoz_create_dashboard`, `signoz_update_dashboard`, `signoz_patch_dashboard`, `signoz_import_dashboard`) include a `webUrl` field when the request carries a SigNoz instance URL: an absolute deep link to the resource in the SigNoz web UI (per result row for `signoz_search_traces`).
### Agent Routing Guidance
Use `signoz_search_docs` for topical discovery when no exact documentation page is selected, then `signoz_fetch_doc` for the chosen page or heading. Use live data tools for tenant telemetry, alert state, dashboards, saved views, and notification channels.
Docs tools use the same authentication path as other MCP tools.
### Available Resources
| Resource | Read when you need |
|---|---|
| `signoz://alert/instructions` | Alert schemas, fields, thresholds, evaluation, and notification workflow |
| `signoz://alert/examples` | Alert payload examples for v2 direct/policy routing and v1 direct anomaly routing |
| `signoz://dashboard/instructions` | Dashboard fields, variables, chaining, and layout |
| `signoz://dashboard/widgets-instructions` | Panel choices and query-specific guides |
| `signoz://dashboard/widgets-examples` | Panel examples and validation patterns |
| `signoz://dashboard/list-filter-guide` | `signoz_list_dashboards` filter DSL: grammar, per-key operators, and examples |
| `signoz://dashboard/patch-instructions` | `signoz_patch_dashboard` JSON Patch recipes and exact paths (add/edit/move/remove a panel, query, variable) |
| `signoz://dashboard/examples` | Complete server-verified dashboard payloads (metrics timeseries, dynamic-variable filter, number panel, multi-panel) |
| `signoz://dashboard/query-builder-example` | Dashboard Query Builder aggregations, filters, legends, and functions |
| `signoz://promql/instructions` | PromQL widgets or alerts, especially dotted OTel metric names |
| `signoz://dashboard/clickhouse-schema-for-logs` | Bundled logs schema snapshot for dashboard SQL |
| `signoz://dashboard/clickhouse-logs-example` | Raw ClickHouse logs widget patterns |
| `signoz://dashboard/clickhouse-schema-for-metrics` | Bundled metrics schema snapshot for dashboard SQL |
| `signoz://dashboard/clickhouse-metrics-example` | Raw ClickHouse metrics widget patterns |
| `signoz://dashboard/clickhouse-schema-for-traces` | Bundled traces schema snapshot for dashboard SQL |
| `signoz://dashboard/clickhouse-traces-example` | Raw ClickHouse traces widget patterns |
| `signoz://logs/query-builder-guide` | Logs Query Builder v5 JSON or unfamiliar log fields |
| `signoz://traces/query-builder-guide` | Traces Query Builder v5 JSON or unfamiliar trace fields |
| `signoz://metrics-aggregation-guide` | Metric aggregations, formulas, grouping, limits, and Cost Meter queries |
| `signoz://view/instructions` | Saved view fields, the v2 typed spec, and read-before-replace workflow |
| `signoz://view/examples` | Saved-view typed-spec payloads for traces, logs, metrics, and Cost Meter |
| `signoz://docs/sitemap` | Indexed official-doc catalog and page URLs |
### Resource Template Migration
The live `signoz://dashboard/{id}/summary` and `signoz://alert/{id}/summary`
resource templates are retired. `resources/templates/list` now returns an empty
catalog. Use `signoz_get_dashboard` for a dashboard definition. For the former
alert summary, call `signoz_get_alert`, then `signoz_get_alert_history`; omit the
time range for the same six-hour window and set `limit: 10` and `order: "desc"`
for the closest history result.
<details>
<summary><strong>Parameter Reference</strong></summary>
#### `signoz_get_org_overview`
Get the current status and overall posture of the SigNoz deployment before drilling into exact resources. `data.sourceStats` is the authoritative complete flat bag containing every key and value reported by the deployment stats endpoint, including current and future fields. Typed convenience projections cover telemetry freshness and volume, infrastructure presence, dashboards, alert rules and runtime, notification channels, saved views, log pipelines, cloud integrations, users, authentication, service accounts, roles, licensing, and configuration.
- **Parameters**: no task parameters; like every tool, it accepts non-required `searchContext` for MCP observability.
- **Authoritative source**: `sourceStats` preserves every successfully decoded entry from the upstream `data` object under its original dotted key. Use the grouped fields for convenient interpretation and `sourceStats` when exact backend coverage or a newly introduced field matters. Counts are deployment aggregates; use `signoz_list_dashboards`, `signoz_list_alert_rules`, `signoz_list_notification_channels`, or `signoz_list_views` for exact inventories; `signoz_list_metrics` for metric names; `signoz_list_alerts` for current alert instances; and `signoz_search_logs`, `signoz_search_traces`, or `signoz_query_metrics` for time-windowed or per-service data.
- **Missing fields**: a key absent from `sourceStats` was not reported by the upstream collector and must not be interpreted as zero. The endpoint can return a partial HTTP 200 when an individual collector fails. In typed projections, a missing group total produces `available: false`; a reported zero produces `available: true`. Expected missing or invalid projection fields set `metadata.projectionPartial` and add an `incompleteGroups` entry with affected output paths, reason, next action, and exact fallback tools where available. An invalid projection value is still retained unchanged in `sourceStats` and named in `invalidProjectionFields`.
- **Cloud-integration completeness**: `cloudIntegrations.sourceAvailability` reports whether both current AWS/Azure provider counts were reported. Each provider has its own `dataAvailable`; an absent provider count is never converted to zero. If neither provider is reported, source availability is `unavailable` without setting overall `metadata.projectionPartial`; this can mean cloud integrations are unsupported/edition-gated **or** both provider queries failed, so do not interpret it as “no cloud integrations configured.” If exactly one is reported, source availability is `partial` and the missing provider receives non-recursive recovery guidance. `connectedAccounts` means a non-removed account with an account ID and at least one agent report, not a recent check-in or proof that an integration service is enabled.
- **Projection metadata**: `reportedStatCount` is the number of authoritative entries in `sourceStats`; `projectedStatCount` counts entries also represented in typed groups; and `unprojectedStatCount` counts entries available only in `sourceStats`, including future fields. `projectionPartial`, `incompleteGroups`, and `invalidProjectionFields` describe only typed-projection gaps; they do not indicate data was removed from `sourceStats` or claim endpoint-wide completeness.
#### `signoz_list_metrics`
Discover metric names and catalog metadata such as type, temporality, unit, and monotonicity. Use `signoz_query_metrics` for values or trends. This list has a limit but no offset pagination.
- **Parameters**:
- `searchText` (optional) - Filter metrics by name substring (e.g., 'cpu', 'memory')
- `limit` (optional) - Maximum number of metrics to return (default: 50)
- `timeRange` (optional) - Relative range: 30m, 1h, 6h, 24h, 7d (default: 1h; ignored when both `start` and `end` are provided)
- `start`/`end` (optional) - Unix ms timestamps. When both are provided, they override `timeRange`.
- `source` (optional) - Data-source filter. Use `"meter"` to list Cost Meter metrics, the usage/billing metrics SigNoz meters on (currently telemetry ingestion volume); omit for the default metrics store
- **Completeness note**: the response appends a note reporting `hasMore` (inferred from `returnedRows == limit`) so a `limit`-truncated list is never mistaken for the full set; narrow with `searchText` for more specificity
#### `signoz_query_metrics`
Query a known metric for values, trends, breakdowns, or formulas. The tool applies metric-aware defaults and auto-fetches omitted metadata; call it directly when `metricName` is known. Use `signoz_list_metrics` only to discover a name or inspect catalog metadata.
- **Parameters**:
- `metricName` (required) - Metric name to query
- `metricType` (optional) - gauge, sum, histogram, exponential_histogram (auto-fetched if absent)
- `isMonotonic` (optional) - Boolean (or the strings `"true"`/`"false"`); auto-fetched if absent. An invalid value is rejected rather than silently treated as false
- `temporality` (optional) - cumulative, delta, unspecified (auto-fetched if absent)
- `timeAggregation` (optional) - Aggregation over time (auto-defaulted by type)
- `spaceAggregation` (optional) - Aggregation across dimensions (auto-defaulted by type)
- `groupBy` (optional) - Comma-separated field names or an array. Resource context is inferred for `k8s.*`, `container.*`, `host.*`, `cloud.*`, `deployment.*`, `process.*`, `service.*`, `telemetry.*`, and `os.*`; other names use attribute context
- `filter` (optional) - Filter expression
- `timeRange` (optional) - Relative time range `<number><unit>` where unit is `m`/`h`/`d` (e.g. '30m', '1h', '6h', '7d'; default: '1h'; ignored when both `start` and `end` are provided)
- `start`/`end` (optional) - Unix ms timestamps. When both are provided, they override `timeRange`.
- `stepInterval` (optional) - Step in seconds (auto-calculated if omitted)
- `requestType` (optional) - Response format. Enum: `time_series` (default), `scalar`. Unknown values are rejected.
- `reduceTo` (optional) - For scalar: sum, count, avg, min, max, last, median
- `formula` (optional) - Expression over named queries (e.g., "A / B * 100")
- `formulaQueries` (optional) - Array or JSON-encoded array string of additional named metric queries for formula. Each object supports `name`, `metricName`, `metricType`, `isMonotonic`, `temporality`, `timeAggregation`, `spaceAggregation`, `groupBy`, and `filter`; `name` and `metricName` are required.
- `source` (optional) - Data-source filter. Use `"meter"` to query Cost Meter data; omit for the default metrics store
- **Result bounds**: standalone generated metric queries and formula results use `limit: 100` with `__result desc`. Every query feeding a formula uses `limit: 10000`, because component limits are applied before formula evaluation and independent top-100 inputs can discard a high-ratio group. The response decisions note reports both bounds. Narrow the filters/grouping when formula-input cardinality can exceed 10000.
- **Key-not-found errors**: a filter referencing a key absent from this workspace's metrics metadata fails with recovery guidance in the error text plus a machine-readable `missingKeys` array in the structured error content
#### `signoz_get_top_metrics`
Return top 100 metrics ranked by ingested sample volume with pre-computed percentages. Use this to identify which metrics are driving the most ingestion volume and cost. Wraps `POST /api/v2/metrics/treemap`. Response fields: `metricName`, `percentage` (share of total sample volume), `totalValue` (absolute sample count).
- **Parameters**:
- `timeRange` (optional) - Relative time range `<number><unit>` where unit is `m`/`h`/`d` (e.g. '1h', '24h', '3d', '7d', '30d'; default: '7d'; ignored when both `start` and `end` are provided). Start with 7d; if the query times out, retry with 3d, then 24h
- `start`/`end` (optional) - Unix ms timestamps. When both are provided, they override `timeRange`
- **Completeness note**: returns a fixed top 100 by ingested sample volume; the response appends a note flagging whether the list was truncated at that cap (`hasMore`)
#### `signoz_check_metric_usage`
Given a list of metric names, return which dashboards and alerts reference each one. Wraps `/api/v3/metrics/dashboards?metricName=...` and `/api/v2/metrics/alerts?metricName=...` per metric.
- **Parameters**:
- `metricNames` (required) - Array of metric name strings to check (max 50 per call). Example: `["system.disk.io", "k8s.node.condition"]`. For larger lists, split into batches of 50 and merge results.
- **Response**: per metric, `dashboards` (list of dashboard names that reference the metric), `alerts` (list of alert names that reference the metric), `error` (non-empty when the lookup failed; do not treat the metric as unused in that case)
- **Limits**: Maximum 50 metrics per call; 30-second overall timeout (partial results returned on expiry)
#### `signoz_check_metric_cardinality`
Return label/attribute keys for one metric with cardinality counts and sample values, sorted highest first. Samples help distinguish unbounded values such as UUIDs from bounded dimensions such as status codes. This tool does not show whether the metric is used; call `signoz_check_metric_usage` before recommending a drop.
- **Parameters**:
- `metricName` (required) - Metric name to inspect. Example: `k8s.container.memory_limit`
- `timeRange` (optional) - Relative time range `<number><unit>` where unit is `m`/`h`/`d` (e.g. '30m', '1h', '6h', '24h', '3d', '7d'; default: '7d'; ignored when both `start` and `end` are provided)
- `start`/`end` (optional) - Unix ms timestamps. When both are provided, they override `timeRange`
#### `signoz_list_alerts`
Lists currently firing/silenced/inhibited alert *instances* from Alertmanager, **not** rule definitions. Use `signoz_list_alert_rules` for configured rules, `signoz_get_alert` with an `id` for one full rule definition, or `signoz_get_alert_history` for the state timeline.
- **Parameters**:
- `limit` (optional) - Maximum number of alerts per page (default: 50)
- `offset` (optional) - Number of results to skip for pagination (default: 0)
- `active` / `silenced` / `inhibited` (optional) - Tri-state filters. Boolean (or the strings `"true"`/`"false"`). Omit to defer to the backend default (all states included). An invalid value is rejected rather than silently dropped
- `filter` (optional) - Comma-separated alert-label comparisons using `=`, `!=`, `=~` (regex), or `!~` (negative regex), e.g. `alertname="HighCPU",severity="critical"`
- `receiver` (optional) - Regex to filter alerts by receiver name
#### `signoz_list_alert_rules`
Lists configured alert-rule summaries from `GET /api/v2/rules`, including inactive/OK and disabled rules. Use `signoz_get_alert` for one full definition; use `signoz_list_alerts` for current Alertmanager instances.
- **Parameters**:
- `limit` (optional) - Maximum number of rules to return per page (default: 50, max: 1000; higher values are clamped)
- `offset` (optional) - Number of rules to skip for pagination (default: 0)
#### `signoz_get_alert`
Gets one alert rule's full definition (`GET /api/v2/rules/{id}`). Use `signoz_list_alert_rules` to discover IDs. Before `signoz_update_alert`, call this only when a complete current definition is not already available for the prepared operation; reuse a still-current result and preserve unchanged fields.
- **Parameters**: `id` (required) - Alert rule ID (UUIDv7 on v2-capable servers).
- **Note**: Response shape depends on the SigNoz server version. Post-#10997 servers return the canonical `Rule` type with `createdAt/updatedAt/createdBy/updatedBy`; older servers return `GettableRule` with `createAt/updateAt/createBy/updateBy` (no 'd').
#### `signoz_list_dashboards`
Lists paginated tenant-dashboard summaries (name, UUID, description, tags, timestamps). Use `signoz_get_dashboard` for panel and query definitions, and page by raising `offset` by `limit` until you have covered `total` before concluding a dashboard is absent.
- **Parameters:**
- `limit` (default 50), `offset` (default 0) – offset-based pagination
- `filter` (optional) – server-side filter DSL over dashboard metadata (name, description, tags, creator, timestamps, locked state)
- `sort` (optional) – `updated_at` (default), `created_at`, or `name`
- `order` (optional) – `asc` or `desc` (default `desc`)
Only `source: user` dashboards can be updated, patched, or deleted. `source` is
not a server-side list-filter column; filter returned rows locally across pages
when needed.
The `filter` DSL is a boolean expression of `key operator value` terms and bare free-text words joined with `AND`/`OR`/`NOT` and parentheses (e.g. `name CONTAINS 'overview' AND locked = true`). Read [`signoz://dashboard/list-filter-guide`](#mcp-resources) for the full grammar, the filterable keys with their operators, value formats, and worked examples; the list response also echoes the authoritative reserved-key set in `reservedKeywords`.
#### `signoz_get_dashboard`
Gets one known tenant dashboard's complete layout, variables, panels, and queries. Use `signoz_list_dashboards` to discover the UUID.
- **Parameters**: `id` (required) - Dashboard UUID
#### `signoz_create_dashboard`
Creates a custom multi-panel dashboard. Use `signoz_import_dashboard` when a curated template fits, or `signoz_create_view` to save one Explorer query. Read `signoz://dashboard/instructions`, `signoz://dashboard/widgets-instructions`, and `signoz://dashboard/widgets-examples` before composing the payload.
- **Parameters:**
- `schemaVersion` (required) – Must be `"v6"`
- `name` (DNS-1123 label) or `generateName: true` to derive it from `spec.display.name`
- `tags` (required) – Array of key/value tags (may be empty)
- `spec` (required) – Perses spec: `display`, `variables` (array), `panels` (map keyed by panel id), `layouts` (array)
Static Markdown panels use `signoz/TextPanel` with `queries: []`, plus
`plugin.spec.mode: "markdown"`, `text`, `presentation`, and `headerOptions`.
Include the panel's layout reference. Query-bearing panels still require one
query; Text panels do not need a query dry run. Widget examples and patch
instructions include both kinds. Area charts use `signoz/AreaChartPanel` with
one `time_series` query; `visualization.stack` (`none`, `normal`, or
`percent`) stacks grouped series, and `chartAppearance.fillMode` is `solid` or
`gradient`. Dashboard inputs use canonical `id`; the
legacy `uuid` input is rejected on the changed dashboard tools.
#### `signoz_import_dashboard`
Creates a dashboard from a curated template hosted in the [SigNoz/dashboards](https://github.com/SigNoz/dashboards) repo (`main` branch). The server fetches the template JSON and creates the dashboard in one call.
When the relative template path is unknown, call `signoz_list_dashboard_templates` first. Pass its `path`, not a URL or absolute path.
- **Parameters:**
- `path` (required) – Template path within the SigNoz/dashboards repo, e.g. `hostmetrics/hostmetrics.json`
#### `signoz_list_dashboard_templates`
Returns the full bundled catalog of curated SigNoz dashboard templates as `{"templates": [...], "total": N}`, where each entry has id, title, path, description, category, and keywords. It does not list dashboards already created in the tenant; use `signoz_list_dashboards` for those.
- **Parameters:** none
#### `signoz_update_dashboard`
Fully replaces an existing dashboard. Fetch it with `signoz_get_dashboard`, take the `data` object out of that response, merge only the requested changes into it, and send that object's fields at the top level, preserving every other field. The `{status, data}` response envelope is not accepted as input. Use `signoz_update_view` for a saved Explorer query.
- **Parameters:**
- `id` (required) – Dashboard id (the legacy `uuid` key is also accepted)
- `schemaVersion`, `name`, `tags`, `spec` – the complete post-update state (see the tool's JSON Schema)
#### `signoz_patch_dashboard`
Applies an RFC 6902 JSON Patch to a dashboard: a partial update without re-sending the entire dashboard. Prefer this over `signoz_update_dashboard` for targeted edits (rename, add/edit one panel or query, tweak a variable). Read `signoz://dashboard/patch-instructions` for worked recipes and exact paths; notably, adding a panel needs two ops (the panel plus its grid item) or it won't render.
- **Parameters:**
- `id` (required) – Dashboard id (the legacy `uuid` key is also accepted)
- `patch` (required) – Array of `{op, path, value}` operations; paths are JSON Pointers into the dashboard's postable shape, e.g. `/spec/display/name`, `/spec/panels/<panelId>`, `/spec/layouts/0/spec/items/-`, `/tags/-`
#### `signoz_list_services`
Lists paginated APM services with trace activity in a time range. Absence means no trace activity in that window, not that the same `service.name` never appears in logs; use `signoz_get_field_values` with `signal="logs"` for log values.
- **Parameters**:
- `timeRange` (optional) - Relative time range `<number><unit>` where unit is `m`/`h`/`d` (e.g. '30m', '1h', '6h', '7d'; defaults to last 6 hours; ignored when both `start` and `end` are provided)
- `start` (optional) - Start time in unix milliseconds (defaults to 6 hours ago).
- `end` (optional) - End time in unix milliseconds (defaults to now)
- `limit` (optional) - Maximum services per page (default: 50, max: 1000; higher values are clamped)
- `offset` (optional) - Number of results to skip for pagination (default: 0)
#### `signoz_get_service_top_operations`
Gets the built-in operation table for one traced service, ranked by p99 latency with each operation's p50, p95, p99, call count, and error count. Use `signoz_aggregate_traces` for custom aggregation, grouping, time series, cross-service comparison, or arbitrary trace filters.
- **Parameters**:
- `service` (required) - Exact traced service name, typically from `signoz_list_services`
- `timeRange` (optional) - Relative time range `<number><unit>` where unit is `m`/`h`/`d` (e.g. '30m', '1h', '6h', '7d'; defaults to last 6 hours; ignored when both `start` and `end` are provided)
- `start` (optional) - Start time in unix milliseconds (defaults to 6 hours ago).
- `end` (optional) - End time in unix milliseconds (defaults to now)
- `tags` (optional) - JSON-encoded `TagQueryParam` array passed as a string, for example `[{"key":"http.method","tagType":"SpanAttribute","operator":"In","stringValues":["GET"]}]`; omit for no tag filter
#### `signoz_get_alert_history`
Gets one configured rule's firing or state-transition history. Defaults to the last 6 hours. Use `state` and `filter` to narrow results. For the next page, pass `data.nextCursor` as `cursor` and repeat the original filters, time range, and order.
The response is `{ "status": "success", "data": { "items": [...], "total": <n>, "nextCursor": "<opaque>" } }`; `nextCursor` is omitted on the final page.
- **Parameters**:
- `id` (required) - Alert rule ID from `signoz_list_alert_rules`
- `timeRange` (optional) - Relative time range `<number><unit>` where unit is `m`/`h`/`d` (e.g. '30m', '1h', '6h', '7d'; defaults to last 6 hours; ignored when both `start` and `end` are provided)
- `start` (optional) - Start timestamp in unix milliseconds (defaults to 6 hours ago).
- `end` (optional) - End timestamp in unix milliseconds (defaults to now)
- `state` (optional) - Filter by alert state. Enum: `inactive`, `pending`, `recovering`, `firing`, `nodata`, `disabled` (omit for all transitions)
- `filter` (optional) - SigNoz query-builder expression over timeline labels. Combine conditions with `AND`, `OR`, and parentheses; quote strings with single quotes. Example: `severity = 'critical' AND (team = 'payments' OR service.name = 'checkout')`. To discover keys, first call without a filter and inspect `data.items[].labels[].key.name`. The backend-shaped `filterExpression` alias remains accepted for compatibility, but `filter` is canonical.
- `cursor` (optional) - Opaque continuation cursor. Repeat the original time range, state, filter, and order when fetching the next page. Omit `cursor` for the first page.
- `limit` (optional) - Rows per page. Default: 20; max: 10000 (higher values are clamped).
- `order` (optional) - Sort order. Enum: `asc`, `desc` (default: 'asc')
- **Legacy `offset`**: no longer supported; use the returned cursor instead.
- **Completeness note**: the response appends a note reporting `hasMore` from `data.nextCursor` and names the cursor for the next page.
#### `signoz_list_views`
List saved Explorer views or discover a view UUID for one Logs, Traces, Metrics, Cost Meter, or AI Observability page. A view stores one reusable Explorer query spec; it is not a multi-panel dashboard. Apply name filters before pagination and follow `pagination.nextOffset` while `pagination.hasMore` is true.
- **Parameters**:
- `source` (required) - One of: `traces`, `logs`, `metrics`, `meter`. Cost Meter views are filed under `meter` (a distinct Explorer page), not `metrics`
- `name` (optional) - Partial-match filter on view name (server-side)
- `limit` (optional) - Page size (default: 50, max: 1000; higher values are clamped)
- `offset` (optional) - Number of results to skip (default: 0)
#### `signoz_get_view`
Get one saved Explorer view's complete definition by UUID. Call this before `signoz_update_view`, which fully replaces the view.
- **Parameters**: `id` (required) - Saved view UUID
#### `signoz_search_docs`
Search official SigNoz documentation and return ranked pages with URLs and snippets for product, setup, instrumentation, configuration, API, deployment, or troubleshooting questions. Send 2 to 6 keywords for one topic and keep product and technology names as the user wrote them; split multi-intent questions into separate calls. If the top result is off-topic, retry with fewer or different terms. Do not use for live tenant data; use signoz_fetch_doc for the full content of a selected result or exact docs URL.
- **Parameters**:
- `searchText` (required) - 2 to 6 keywords for one topic, for example "Kubernetes pod logs". Keep product and technology names as the user wrote them.
- `limit` (optional) - Maximum results to return as a string (default: 10, max: 25; a numeric value is also accepted). The 25 ceiling is deliberate: each result hydrates document text out of the in-process docs index, so a larger limit inflates this server's resident memory.
- `section_slug` (optional) - Exact top-level docs section filter, such as `setup`, `logs-management`, `apm-distributed-tracing`, `metrics`, `alerts`, `dashboards`, `signoz-apis`, `querying`, or `collection-agents`. Reuse the `section_slug` from an earlier result when narrowing; an unknown slug returns zero results
- `searchContext` - User's original question
Docs search telemetry counts executed searches in `signoz_docs_searches_total` with
`outcome=ok|error`. Only successful searches have `result_count_bucket` (`0`, `1-4`,
`5-9`, or `10+`). `signoz_docs_search_top_score` records the top hit's raw Bleve score
only for successful non-empty searches. Scores are uncalibrated and depend on query
terms, boosts, and analyzer settings; they are not relevance probabilities or thresholds.
Search spans record `mcp.docs.search_text` (the executed query, truncated to 256 Unicode
runes), `mcp.docs.section_slug`, and `mcp.docs.result_count`. Successful non-empty searches
also record `mcp.docs.top_score`. These span attributes distinguish the client's keyword
query from the user's original request in `mcp.search_context`; query text is not a metric
attribute. If the query is invalid Bleve query-string syntax, search drops that clause,
continues with text matching, and records `mcp.docs.query_string_dropped=true`. Empty or
whitespace-only queries remain validation errors.
#### `signoz_fetch_doc`
Fetch one known official SigNoz docs page's full Markdown or a requested heading. Use `signoz_search_docs` to discover a page first; accepted inputs are `https://signoz.io/docs/...` URLs or `/docs/...` paths.
- **Parameters**:
- `url` (required) - Docs page URL or path
- `heading` (optional) - Heading anchor ID or heading text
- `searchContext` - User's original question
#### `signoz_create_view`
Save one reusable Explorer query spec. Use `signoz_create_dashboard` for a multi-panel dashboard. Cost Meter views use `source="meter"` with `signal="metrics"` and builder-spec `source="meter"`.
- **Parameters** (v2 typed shape):
- `name` (optional) - View name (DNS-1123 label). Required unless `generateName` is true
- `generateName` (optional) - When true, the server generates `name` from `spec.displayName` and `name` must be empty
- `source` (required) - Which Explorer this view belongs to
- `spec` (required) - Typed view content: `displayName`, `panelType`, `requestType`, `queries`, `selectedFields`, `display`
- `schemaVersion` (optional) - Always `v2`; defaults when omitted
- **Required**: Read both MCP resources `signoz://view/instructions` and `signoz://view/examples` before composing any payload.
#### `signoz_update_view`
Fully replace an existing saved Explorer view. Fetch it with `signoz_get_view`, modify its returned `data` object, preserve every unrequested field, and pass that full object as `view`. Upstream keeps `name` immutable on update; the display label lives in `spec.displayName`.
- **Parameters**:
- `id` (required) - UUID of the view to replace
- `view` (required) - Full `source`/`spec` pair (required); drop `name` and server-populated fields
- **Resource rule**: Read `signoz://view/instructions` and `signoz://view/examples` when changing `source` or `spec`. Skip them for a pass-through of the fetched body. Call `signoz_get_view` first; partial bodies wipe unspecified fields.
#### `signoz_delete_view`
Permanently delete a confirmed saved Explorer view by UUID. Use `signoz_list_views` to discover the ID; use `signoz_delete_dashboard` for a dashboard.
- **Parameters**: `id` (required) - Saved view UUID
#### `signoz_aggregate_logs`
Return aggregate statistics over logs (counts, rates, averages, percentiles, or grouped/top-N breakdowns) rather than individual records. Use `signoz_search_logs` for log rows and message inspection.
- **Parameters**:
- `aggregation` (required) - Aggregation function: count, count_distinct, avg, sum, min, max, p50, p75, p90, p95, p99, rate
- `aggregateOn` (optional) - Field to aggregate on (required for all except count and rate)
- `groupBy` (optional) - Comma-separated fields to group by (e.g., 'service.name, severity_text')
- `filter` (optional) - Filter expression using SigNoz search syntax. Combine conditions with AND, OR, and parentheses. Unknown keys hard-error; ambiguous keys default to resource context. Log keys are workspace-specific; even `service.name` is only present when the log pipeline sets it. See `signoz://logs/query-builder-guide`
- `service` (optional) - Shortcut filter for service name (adds `service.name = '<value>'`; fails with `key service.name not found` when the workspace's logs lack that attribute)
- `severity` (optional) - Exact `severity_text`; DEBUG, INFO, WARN, ERROR, and FATAL are common examples, not an exhaustive enum. Discover values with `signoz_get_field_values(signal="logs", name="severity_text", fieldContext="log")`
- `orderBy` (optional) - Order expression and direction (e.g., 'count() desc')
- `limit` (optional) - Maximum number of groups to return (default: 100, max: 10000; higher values are clamped to bound server memory)
- `timeRange` (optional) - Relative time range `<number><unit>` where unit is `m`/`h`/`d` (e.g. '30m', '1h', '6h', '24h', '7d'; default: '1h'; ignored when both `start` and `end` are provided)
- `start` / `end` (optional) - Start/end time in unix milliseconds. When both are provided, they override `timeRange`.
- `requestType` (optional) - `scalar` (default; one aggregate value over the whole range) or `time_series` (one value per time bucket). Unknown values are rejected.
- `stepInterval` (optional) - Time bucket size in seconds for `time_series` mode. Accepts a number or numeric string (backend auto-selects when omitted)
- **Time-series ranking note**: the limit selects top groups over the whole requested window, not independently per bucket. Narrow the window or adjust the limit when a short-lived series could otherwise be hidden.
- **Key-not-found errors**: a filter referencing a key absent from this workspace's logs metadata fails with recovery guidance in the error text plus a machine-readable `missingKeys` array in the structured error content
#### `signoz_search_logs`
Return individual paginated log records matching text, service, severity, or field filters. Use `signoz_aggregate_logs` for counts, trends, or grouped breakdowns.
Calls using only `searchText`, `service`, `severity`, time, or pagination parameters need no guide read. Read `signoz://logs/query-builder-guide` only before composing `filter` with unfamiliar workspace fields.
- **Parameters**:
- `filter` (optional) - Filter expression using SigNoz search syntax. Combine conditions with AND, OR, and parentheses (e.g., "(severity_text = 'ERROR' OR body CONTAINS 'panic') AND service.name = 'payment-svc'"). Log keys are workspace-specific; even `service.name` is only present when the log pipeline sets it. See `signoz://logs/query-builder-guide`
- `service` (optional) - Service name to filter by (adds `service.name = '<value>'`; fails with `key service.name not found` when the workspace's logs lack that attribute)
- `severity` (optional) - Exact `severity_text`; DEBUG, INFO, WARN, ERROR, and FATAL are common examples, not an exhaustive enum. Discover values with `signoz_get_field_values(signal="logs", name="severity_text", fieldContext="log")`
- `searchText` (optional) - Literal text to find, escaped automatically; combines with `filter` using AND
- `searchScope` (optional) - Where `searchText` matches: `body` (default, `body CONTAINS`), `attribute` or `resource` (keys and values), or `all` (unscoped `search()`, slow on wide time ranges)
- `timeRange` (optional) - Relative time range `<number><unit>` where unit is `m`/`h`/`d` (e.g. '30m', '1h', '6h', '24h', '7d'; default: '1h'; ignored when both `start` and `end` are provided)
- `start` / `end` (optional) - Start/end time in unix milliseconds. When both are provided, they override `timeRange`.
- `limit` (optional) - Maximum number of logs to return (default: 100, max: 10000; higher values are clamped; paginate with `offset`)
- `offset` (optional) - Offset for pagination (default: 0)
- **Ordering**: generated raw log queries use `timestamp desc`, then `id desc`, so offset pagination is deterministic when multiple rows share a timestamp.
- **Completeness note**: the response appends a note reporting `hasMore` (inferred from `returnedRows == limit`) and the `nextOffset` to fetch, so a truncated page is never mistaken for the full result set
- **Key-not-found errors**: a filter referencing a key absent from this workspace's logs metadata fails with recovery guidance in the error text plus a machine-readable `missingKeys` array in the structured error content
Use `filter: "search('timeout')"` when the field containing a term is unknown.
Use `search('checkout', body)` to scope it, or combine the function with field
predicates using AND/OR/NOT. Scopes are `body`, `attribute`, `resource`, and
`log`. Once the field is known, prefer a field predicate. `searchText` with
`searchScope` builds these predicates for you. Escape backslashes and apostrophes
inside expression literals; explicit filters are passed through, not rewritten.
The same expressions work in log aggregations and saved-query specs.
#### `signoz_get_field_keys`
Discover field names available for filtering or grouping metrics, traces, or logs. This returns keys, not observed values; use `signoz_get_field_values` after selecting a key.
- **Parameters**:
- `signal` (required) - Signal type. Enum: `metrics`, `traces`, `logs`
- `searchText` (optional) - Filter field keys by name substring
- `metricName` (optional) - Filter by metric name (relevant for metrics signal)
- `fieldContext` (optional) - Restrict to a field context: `resource`, `attribute` (alias `tag`), `scope`, `log`/`span`/`metric` (intrinsic/built-in columns), or `body` (JSON log body). Distinguishes intrinsic columns from user attributes.
- `fieldDataType` (optional) - Restrict to a data type: `string`, `bool`, `int64`, `float64`, `number`, or array forms like `[]string`
- `source` (optional) - For metrics, use `meter` for Cost Meter fields; omit for the default metrics store
#### `signoz_get_field_values`
Get observed values for a known field key. Use `signoz_get_field_keys` when the key is unknown, and match `signal` and `fieldContext` to the query that will use the value.
- **Parameters**:
- `signal` (required) - Signal type. Enum: `metrics`, `traces`, `logs`
- `name` (required) - Field key name to get values for (e.g., `service.name`, `http.method`)
- `searchText` (optional) - Filter values by substring
- `metricName` (optional) - Filter by metric name (relevant for metrics signal)
- `fieldContext` (optional) - Restrict the lookup to a field context (`resource`, `attribute`/`tag`, `scope`, `log`/`span`/`metric`, `body`) when the same key name exists in more than one
- `source` (optional) - For metrics, use `meter` for Cost Meter values; omit for the default metrics store
#### `signoz_search_traces`
Return individual paginated span rows matching service, operation, error, duration, or field filters, and use them to discover trace IDs. Use `signoz_aggregate_traces` for statistics or `signoz_get_trace_details` for one known trace.
- **Parameters**:
- `filter` (optional) - Filter expression using SigNoz search syntax. Combine conditions with AND, OR, and parentheses (e.g., "service.name = 'payment-svc' AND (has_error = true OR attribute.http.response.status_code >= 500)"). Legacy `query` is still accepted for backward compatibility, but `filter` is canonical. See `signoz://traces/query-builder-guide`
- `service` (optional) - Service name to filter by
- `operation` (optional) - Operation/span name to filter by
- `error` (optional) - Filter by error status. Boolean (or the strings `"true"`/`"false"`). An invalid value is rejected rather than silently dropped
- `minDuration` / `maxDuration` (optional) - Min/max span duration in nanoseconds (e.g., '500000000' for 500ms)
- `timeRange` (optional) - Relative time range `<number><unit>` where unit is `m`/`h`/`d` (e.g. '30m', '1h', '6h', '24h', '7d'; default: '1h'; ignored when both `start` and `end` are provided)
- `start` / `end` (optional) - Start/end time in unix milliseconds. When both are provided, they override `timeRange`.
- `limit` (optional) - Maximum span rows to return (default: 100, max: 10000; higher values are clamped; paginate with `offset`)
- `offset` (optional) - Number of span rows to skip (default: 0)
- `selectFields` (optional) - Extra fields to return on each row, added to the default set. An array of field names or a comma-separated string, at most 50. Names can be span columns (`db_name`), resource attributes (`k8s.pod.name`), or span attributes (`http.route`); a `resource.`, `attribute.`, or `span.` prefix picks the context. Discover names with `signoz_get_field_keys` (`signal="traces"`)
- **Default fields**: each row carries `timestamp`, `trace_id`, `span_id`, `parent_span_id`, `name`, `service.name`, `kind_string`, `duration_nano`, `has_error`, `status_code_string`, `status_message`, `response_status_code`, and `http_method`, plus any `selectFields`. Every field is a flat row key; a field missing from a row was not selected
- **Ordering**: generated raw trace queries use `timestamp desc`.
- **Completeness note**: the response appends a note reporting `hasMore` (inferred from `returnedRows == limit`) and the `nextOffset` to fetch, so a truncated page is never mistaken for the full result set
- **Output note**: raw result row keys follow canonical Query Builder field names (for example `trace_id`, `span_id`, `duration_nano`, `has_error`). Legacy caller-provided filters such as `hasError` still pass through to the backend alias layer, but new response parsers should read the canonical snake_case keys.
- **Key-not-found errors**: a filter referencing a key absent from this workspace's traces metadata fails with recovery guidance in the error text plus a machine-readable `missingKeys` array in the structured error content
#### `signoz_aggregate_traces`
Return custom aggregate statistics over spans (counts, rates, latency percentiles, grouped/top-N breakdowns, or time series) rather than individual rows or a full trace hierarchy. For one traced service's built-in operation table ranked by p99, use `signoz_get_service_top_operations`. Read `signoz://traces/query-builder-guide` before calling this tool.
- **Parameters**:
- `aggregation` (required) - Aggregation function: count, count_distinct, avg, sum, min, max, p50, p75, p90, p95, p99, rate
- `aggregateOn` (optional) - Field to aggregate on (e.g., 'duration_nano'). Required for all except count and rate
- `groupBy` (optional) - Comma-separated fields to group by (e.g., 'service.name, name')
- `filter` (optional) - Filter expression using SigNoz search syntax. Combine conditions with AND, OR, and parentheses. Unknown keys hard-error; ambiguous keys default to resource context. See `signoz://traces/query-builder-guide`
- `service` (optional) - Shortcut filter for service name
- `operation` (optional) - Shortcut filter for span/operation name
- `error` (optional) - Shortcut filter for error spans. Boolean (or the strings `"true"`/`"false"`). An invalid value is rejected rather than silently dropped
- `orderBy` (optional) - Order expression and direction (e.g., 'avg(duration_nano) desc')
- `limit` (optional) - Maximum number of groups to return (default: 100, max: 10000; higher values are clamped to bound server memory)
- `timeRange` (optional) - Relative time range `<number><unit>` where unit is `m`/`h`/`d` (e.g. '30m', '1h', '6h', '24h', '7d'; default: '1h'; ignored when both `start` and `end` are provided)
- `start` / `end` (optional) - Start/end time in unix milliseconds. When both are provided, they override `timeRange`.
- `requestType` (optional) - `scalar` (default; one aggregate value over the whole range) or `time_series` (one value per time bucket). Unknown values are rejected.
- `stepInterval` (optional) - Time bucket size in seconds for `time_series` mode. Accepts a number or numeric string (backend auto-selects when omitted)
- **Time-series ranking note**: the limit selects top groups over the whole requested window, not independently per bucket. Narrow the window or adjust the limit when a short-lived series could otherwise be hidden.
- **Key-not-found errors**: a filter referencing a key absent from this workspace's traces metadata fails with recovery guidance in the error text plus a machine-readable `missingKeys` array in the structured error content
#### `signoz_get_trace_details`
For a known trace ID, return its spans, metadata, and hierarchy. Use `signoz_search_traces` first when the ID is unknown, and choose a time window that contains the trace; the default last six hours can miss older traces.
- **Parameters**:
- `traceId` (required) - Known trace ID, usually discovered with `signoz_search_traces`
- `timeRange` (optional) - Relative time range `<number><unit>` where unit is `m`/`h`/`d` (e.g. '30m', '1h', '6h', '7d'; defaults to last 6 hours; ignored when both `start` and `end` are provided)
- `start` (optional) - Start time in unix milliseconds (defaults to 6 hours ago).
- `end` (optional) - End time in unix milliseconds (defaults to now)
- `includeSpans` (optional) - Include detailed span information. Boolean (or the strings `"true"`/`"false"`), default: true
#### `signoz_create_alert`
Create a new alert rule in SigNoz via `POST /api/v2/rules`.
- **Parameters**: JSON payload matching the SigNoz alert rule schema.
- **Schema varies by `ruleType`**:
- `threshold_rule` / `promql_rule` → **v2alpha1** (structured `condition.thresholds`, `evaluation`, `notificationSettings`).
- `anomaly_rule` → **v1**, metrics only: top-level `evalWindow`/`frequency`, condition anomaly fields, and direct top-level `preferredChannels`. Omit `thresholds`, `evaluation`, `notificationSettings`, and `schemaVersion`; policy routing is unsupported.
- **Notification routing**: For direct routing, reuse a fully paginated `signoz_list_notification_channels` result only from the same still-current prepared operation; otherwise call it, refreshing only if state may have changed. V2 needs an exact returned displayName on every tier and rejects top-level `preferredChannels`; v1 anomaly uses direct top-level `preferredChannels`. If none fits, ask the user or offer `signoz_create_notification_channel` with user-provided config; never create automatically. Confirmed v2 policy routing may omit tier channels; supplied names are still validated.
- **Tip**: Reuse alert resources only when already read for the same prepared operation; otherwise read `signoz://alert/instructions` and `signoz://alert/examples`. For PromQL, read `signoz://promql/instructions` when needed.
#### `signoz_update_alert`
Update an existing alert rule via `PUT /api/v2/rules/{id}`. This fully replaces the rule: reuse `signoz_get_alert`, `signoz://alert/instructions`, `signoz://alert/examples`, and fully paginated `signoz_list_notification_channels` results only from the same still-current prepared operation; otherwise read/call them, refreshing only if state may have changed, then preserve unchanged fields. Direct v2 needs an exact listed displayName on every tier; confirmed v2 policy routing may omit them. V1 anomalies use direct top-level `preferredChannels` and cannot use policy routing.
- **Parameters**:
- `id` (required) - UUIDv7 of the rule to update (obtain from `signoz_list_alert_rules` / `signoz_get_alert`).
- Plus all fields of the alert rule schema (same shape as `signoz_create_alert`).
#### `signoz_delete_alert`
Delete an alert rule via `DELETE /api/v2/rules/{id}`. Irreversible: discover the ID with `signoz_list_alert_rules` and confirm the exact rule first. When both steps are already complete, call the delete tool directly without repeating list/get preflight.
- **Parameters**:
- `id` (required) - UUIDv7 of the rule to delete. The server rejects non-UUIDv7 values with `invalid_input`.
#### `signoz_delete_dashboard`
Permanently delete a confirmed tenant dashboard by ID. The deletion is irreversible; use `signoz_list_dashboards` to discover the UUID. Use `signoz_delete_view` for a saved Explorer view.
- **Parameters**: `id` (required) - Dashboard UUID to delete
#### `signoz_list_notification_channels`
List paginated v2 channel summaries (`id`, `name`, `displayName`, `kind`, timestamps).
Alert routing uses `displayName`; `name` is the immutable machine identifier.
Results omit provider settings and credentials. Use `signoz_get_notification_channel`
for the complete configuration, and cover every page before declaring a channel absent.
- **Parameters**: `query` searches display names; `kind` filters provider kind;
`sort` is `updated_at`, `created_at`, or `name`; `order` is `asc` or `desc`.
`limit` defaults to 20 and is capped at 200; `offset` defaults to 0.
- **Defaults**: newest update first. The response includes the filtered total
and explicit pagination metadata. Follow `pagination.nextOffset` while
`pagination.hasMore` is true; `pagination.limit` reports the effective cap.
#### `signoz_create_notification_channel`
Create a notification channel from `config: {kind, spec}`. Check existing
display names before creating a channel.
- **Parameters**: `config` is required. Supply a DNS1123 `name`, or use
`generateName: true` with a `displayName`. `displayName` defaults to an explicit
`name` when omitted. Both names become immutable after creation. Alert
routing references use `displayName`, not `name`.
- **Provider kinds**: `slack`, `email`, `webhook`, `pagerduty`, `opsgenie`,
`msteams`, `googlechat`, `jira`, `jsmops`, and `incidentio`. The registered
`config.spec` schema documents each provider's fields and required settings.
Slack also accepts message settings: `color`, `titleLink`, `pretext`,
`fallback`, `footer`, `fields`, and `actions`.
- **Resolve notifications**: `config.spec.sendResolved` uses the provider's
default when omitted. Get returns its effective value; preserve it on update.
- **Test sends**: `test` defaults to `false`. Set `test: true` only when a test
notification is intended. A failed test does not undo the created channel;
inspect its reported status before retrying. Post-write authorization errors
include `mutationCommitted: true` and the known ID so callers can authenticate
and inspect the existing channel without creating another one.
Example without a test send:
```json
{
"name": "checkout-oncall",
"displayName": "Checkout on-call",
"config": {
"kind": "webhook",
"spec": {"url": "https://alerts.example.com/signoz", "sendResolved": true}
},
"test": false
}
```
#### `signoz_update_notification_channel`
Fully replace one channel's `config` using `id` and the complete canonical
`config: {kind, spec}` object. Fetch the channel, copy its `config`, change only
requested fields, then submit the complete object. Names cannot be changed.
Preserve every untouched setting and credential without echoing secrets. Empty
optional template strings returned by SigNoz are normalized back to unset on
update, so its fetched config remains writable.
`test` defaults to `false`; an explicit `true` sends a test after the update.
A test failure does not undo the update. Do not replay an ambiguous write or
an opt-in test automatically.
#### `signoz_get_notification_channel`
Get one channel's canonical `id`, machine `name`, `displayName`, timestamps,
and full `config`. The `config.spec` can contain plaintext credentials; use it
for updates without displaying or logging secrets. **Parameter**: `id`.
#### `signoz_delete_notification_channel`
Permanently delete a confirmed channel by `id`. Resolve and confirm the exact
channel first; call directly when those steps are already complete. The backend
may reject deletion while a routing policy references the channel. Propagate
that dependency error and resolve references before retrying.
#### `signoz_execute_builder_query`
Runs a SigNoz Query Builder v5 request that the dedicated tools cannot express, including multi-query requests, formulas, PromQL, and ClickHouse SQL. Prefer `signoz_search_logs` / `signoz_search_traces` for rows, `signoz_aggregate_logs` / `signoz_aggregate_traces` for grouped results, and `signoz_query_metrics` for ordinary metrics.
- **Parameters**: `query` (required) - Complete SigNoz Query Builder v5 JSON object
- **Query types**: the per-envelope `compositeQuery.queries[i].type` selects the spec shape:
- `builder_query`: signal-specific spec (logs/traces/metrics) with filter, aggregations, groupBy, etc.
- `builder_formula`: formula expression referencing other query names (e.g. `A / B * 100`).
- `promql`: `{name, query, disabled, step?, legend?}`. PromQL for OTel metrics requires the Prometheus 3.x UTF-8 quoted-selector form `{"metric.name.with.dots"}`; read the `signoz://promql/instructions` resource for details.
- `clickhouse_sql`: `{name, query, disabled, legend?}`.
- **Builder result bounds**: for predictable authored queries, explicitly supply a positive `spec.limit` and non-empty v5 `spec.order` (not dashboard/editor `orderBy`) on every `builder_query` and `builder_formula`. When omitted, null, or zero, standalone limits and formula-result limits default to `100`; a builder query referenced by a formula defaults to `10000` because base-query limits are applied before formula evaluation. Raw logs order by `timestamp desc, id desc`; raw traces by `timestamp desc`; metric scalar/time-series queries and formulas by `__result desc`; and log/trace scalar/time-series queries by the primary aggregation descending. Valid caller-supplied values are preserved. The response appends a decisions note when defaults are inserted.
- **Guide routing**: read `signoz://logs/query-builder-guide` for logs, `signoz://traces/query-builder-guide` for traces, `signoz://metrics-aggregation-guide` for metrics/formulas, and `signoz://promql/instructions` for PromQL.
- **Time-series ranking caveat**: top-N groups are ranked over the entire requested window. A short-lived spike can be omitted even when it dominates one bucket; narrow the window or adjust the limit when that matters.
- **Backend warnings**: non-fatal warnings the backend returns (e.g. ambiguous-key resolution) are surfaced as a note alongside the raw response and WARN-logged, matching the search/aggregate/query_metrics tools (previously the body was returned verbatim and warnings were dropped).
- **Key-not-found errors**: a filter referencing a key absent from the workspace's metadata for the queried signal fails with recovery guidance in the error text plus a machine-readable `missingKeys` array in the structured error content
- **Documentation**: See [SigNoz Query Builder v5 docs](https://signoz.io/docs/userguide/query-builder-v5/)
</details>
## Environment Variables
| Variable | Description | Required |
| ----------------- | ------------------------------------------------------------------------------ | ----------------------------------- |
| `SIGNOZ_URL` | SigNoz instance URL | Yes (stdio); Optional (http with OAuth) |
| `SIGNOZ_API_KEY` | SigNoz API key (get from Settings → API Keys in the SigNoz UI) | Yes (stdio); Optional (http with OAuth) |
| `LOG_LEVEL` | Logging level: `info`(default), `debug`, `warn`, `error` | No |
| `TRANSPORT_MODE` | MCP transport mode: `stdio`(default) or `http` | No |
| `MCP_SERVER_HOST` | Host/interface for HTTP transport mode (default: empty, which listens on all interfaces). Set to `127.0.0.1` for loopback-only access. | No |
| `MCP_SERVER_PORT` | Port for HTTP transport mode (default: `8000`) | No |
| `MCP_MAX_REQUEST_BYTES` | Max inbound MCP HTTP request body size in bytes (default: `4194304` / 4 MiB). Bounds memory from a single oversized request. | No |
| `CLIENT_CACHE_SIZE` | Maximum cached tenant clients in multi-tenant HTTP mode (default: `256`) | No |
| `CLIENT_CACHE_TTL_MINUTES` | Tenant-client cache lifetime in minutes (default: `30`) | No |
| `SIGNOZ_DOCS_REFRESH_INTERVAL` | Scheduled incremental docs refresh interval (Go duration, default: `6h`). Set to `0` (or `off`) to disable it. To stop every scheduled refresh and serve the embedded docs index unchanged, set `SIGNOZ_DOCS_FULL_REFRESH_INTERVAL=0` as well. See [Memory footprint](#memory-footprint). | No |
| `SIGNOZ_DOCS_FULL_REFRESH_INTERVAL` | Scheduled forced full docs refresh interval (Go duration, default: `24h`). Set to `0` (or `off`) to disable only the forced full refresh. | No |
| `OAUTH_ENABLED` | Enable OAuth 2.1 authentication flow (`true`/`false`) | No (default: `false`) |
| `OAUTH_TOKEN_SECRET` | Encryption key for OAuth tokens (min 32 bytes, e.g. `openssl rand -base64 32`) | Yes when `OAUTH_ENABLED=true` |
| `OAUTH_ISSUER_URL` | Public URL of this MCP server (used in OAuth metadata discovery) | Yes when `OAUTH_ENABLED=true` |
| `OAUTH_ACCESS_TOKEN_TTL_MINUTES` | Access token lifetime in minutes (default: 60) | No |
| `OAUTH_REFRESH_TOKEN_TTL_MINUTES` | Refresh token lifetime in minutes (default: 43200 / 30d) | No |
| `OAUTH_AUTH_CODE_TTL_SECONDS` | Authorization code lifetime in seconds (default: 600 / 10min) | No |
| `SIGNOZ_CUSTOM_HEADERS` | Extra HTTP headers added to every API request, useful when SigNoz is behind a reverse proxy requiring auth (e.g. `CF-Access-Client-Id:id.access,CF-Access-Client-Secret:secret`). Format: `Key1:Value1,Key2:Value2` | No |
| `SIGNOZ_INSTANCE_URL_ALLOWLIST` | Multi-tenant (http) only: comma-separated allowlist of SigNoz backend hosts the server will proxy to. Entries are exact hosts (`signoz.example.com`) or wildcards (`*.us.signoz.cloud`, which matches any subdomain ending in `.us.signoz.cloud`); a scheme/port/path accidentally included in an entry is tolerated and reduced to the bare host. When set, SigNoz instance URLs that do not match are refused at every ingress: the OAuth setup form and `X-SigNoz-URL` header return HTTP 403, the OAuth token endpoint (incl. existing refresh tokens) returns `invalid_grant`, and `/mcp` requests via an OAuth token return 403. All increment a `disallowed_signoz_url`-tagged failure metric for alerting (not logged per-request, to avoid noise from misconfigured/looping clients), and the rejection message points SigNoz Cloud users to their region's MCP URL (`mcp.<region>.signoz.cloud`) with a docs link. Empty/unset allows any host. The operator's own `SIGNOZ_URL` is exempt. | No |
| `ANALYTICS_ENABLED` | Enable product analytics (`true`/`false`; default: `false`) | No |
| `SEGMENT_KEY` | Segment write key used only when analytics is enabled | No |
| `OTEL_EXPORTER_OTLP_ENDPOINT` | OTLP gRPC endpoint for the MCP server's own traces and metrics. Internal telemetry export is disabled when no OTLP endpoint/exporter is configured. For plaintext collectors, use an `http://` endpoint such as `http://localhost:4317`. | No |
| `OTEL_EXPORTER_OTLP_TRACES_ENDPOINT` | Trace-specific OTLP gRPC endpoint; overrides `OTEL_EXPORTER_OTLP_ENDPOINT` for traces. | No |
| `OTEL_EXPORTER_OTLP_METRICS_ENDPOINT` | Metrics-specific OTLP gRPC endpoint; overrides `OTEL_EXPORTER_OTLP_ENDPOINT` for metrics. | No |
| `OTEL_TRACES_EXPORTER` | Set to `none` to disable internal trace export even when an OTLP endpoint is configured. | No |
| `OTEL_METRICS_EXPORTER` | Set to `none` to disable internal metrics export and runtime metrics even when an OTLP endpoint is configured. | No |
The MCP server does not run an OTLP log exporter; logs are emitted as JSON to stderr. `OTEL_LOGS_EXPORTER` is therefore not used.
## Claude Desktop Extension
### Building the Bundle
Requires **Node.js**. See [Anthropic MCPB](https://github.com/anthropics/mcpb) for details.
```bash
make bundle
```
### Installing
1. Open **Claude Desktop → Settings → Developer → Edit Config → Add bundle.mcpb**
2. Select `./bundle/bundle.mcpb`
3. Enter your `SIGNOZ_URL`, `SIGNOZ_API_KEY`, and optionally `LOG_LEVEL`
4. Restart Claude Desktop
## End-to-End Tests
The e2e suite under [`tests/`](tests/README.md) runs the server (built from the working tree) against a real SigNoz instance provisioned by foundry and drives it over the MCP HTTP transport:
```bash
make test-e2e # cast SigNoz, run the suites, tear down
make test-e2e-reuse # rerun against the cached environment
```
Requires Docker, `foundryctl`, Go, and uv. See [tests/README.md](tests/README.md) for the full workflow.
## Architecture
For a detailed overview of request flow, component interactions, and design decisions, see [docs/architecture.md](docs/architecture.md).
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md) for development workflow, required docs/manifest sync for MCP changes, and PR checklist.
**Made with ❤️ for the observability community**
This server cannot be deployed
Maintenance
ActivityActive
ResponsivenessSlow