Files
Sid PremkumarandGitHub 342a4e7255 Add support for getting real metrics/logs/trace fields + options (#49)
### Summary

Add support to get real metrics/log/trace fields and options instead of
a hardcoded piece of text.

Tried to reverse engineer the UI, so apologies if I got the endpoints
wrong here!

### Testing

Tested by starting and calling the mcp server. 

Snipped from my typescript test: 
```ts
       /* Test the available fields tools */
        const availableFieldsTools = [
            {
                name: "signoz_get_trace_available_fields",
                args: { searchText: "" },
            },
            {
                name: "signoz_get_logs_available_fields",
                args: { searchText: "" },
            },
            {
                name: "signoz_get_metrics_available_fields",
                args: { searchText: "" },
            },
        ];

        console.log("\n=== Testing Available Fields Tools ===\n");

        for (const testTool of availableFieldsTools) {
            const tool = toolsResponse.tools.find((t) => t.name === testTool.name);

            if (!tool) {
                console.log(`❌ Tool not found: ${testTool.name}`);
                continue;
            }

            logger.info(
                { toolName: testTool.name },
                "[MCP Test] Calling test tool"
            );

            try {
                const result = await client.callTool({
                    name: testTool.name,
                    arguments: testTool.args,
                });

                console.log(`\n--- ${testTool.name} ---`);
                console.log(`Is Error: ${result.isError}`);

                if (result.isError) {
                    console.log(`❌ Error occurred`);
                    if (result.content && Array.isArray(result.content)) {
                        for (const item of result.content) {
                            if (item.type === "text") {
                                console.log(item.text);
                            }
                        }
                    }
                } else {
                    console.log(`✅ Success!`);
                    if (result.content && Array.isArray(result.content)) {
                        for (const item of result.content) {
                            if (item.type === "text") {
                                try {
                                    const jsonData = JSON.parse(item.text);
                                    console.log(`Status: ${jsonData.status || "unknown"}`);
                                    if (jsonData.data) {
                                        const data = jsonData.data;
                                        if (data.attributeKeys) {
                                            console.log(`Found ${data.attributeKeys.length} attribute keys`);
                                            if (data.attributeKeys.length > 0) {
                                                console.log(`First key: ${JSON.stringify(data.attributeKeys[0])}`);
                                            }
                                        } else if (data.attributes) {
                                            console.log(`Found ${data.attributes.length} attributes`);
                                            if (data.attributes.length > 0) {
                                                console.log(`First attribute: ${JSON.stringify(data.attributes[0])}`);
                                            }
                                        }
                                    }
                                } catch (e) {
                                    console.log(item.text.substring(0, 200) + "...");
                                }
                            }
                        }
                    }
                }
                console.log("");

                logger.info({ toolName: testTool.name }, "[MCP Test] Tool call completed");
            } catch (error) {
                console.log(`❌ Exception calling ${testTool.name}:`, error);
                logger.error({ toolName: testTool.name, error }, "[MCP Test] Tool call failed");
            }
        }

        /* Test the field values tools */
        const fieldValuesTools = [
            {
                name: "signoz_get_trace_field_values",
                args: { fieldName: "service.name", searchText: "" },
            },
            {
                name: "signoz_get_logs_field_values",
                args: { fieldName: "service.name", searchText: "" },
            },
            {
                name: "signoz_get_metrics_field_values",
                args: { fieldName: "aws_ApplicationELB_ConsumedLCUs_max", searchText: "" },
            },
        ];

        console.log("\n=== Testing Field Values Tools ===\n");

        for (const testTool of fieldValuesTools) {
            const tool = toolsResponse.tools.find((t) => t.name === testTool.name);

            if (!tool) {
                console.log(`❌ Tool not found: ${testTool.name}`);
                continue;
            }

            logger.info(
                { toolName: testTool.name },
                "[MCP Test] Calling test tool"
            );

            try {
                const result = await client.callTool({
                    name: testTool.name,
                    arguments: testTool.args,
                });

                console.log(`\n--- ${testTool.name} ---`);
                console.log(`Field Name: ${testTool.args.fieldName}`);
                console.log(`Is Error: ${result.isError}`);

                if (result.isError) {
                    console.log(`❌ Error occurred`);
                    if (result.content && Array.isArray(result.content)) {
                        for (const item of result.content) {
                            if (item.type === "text") {
                                console.log(item.text);
                            }
                        }
                    }
                } else {
                    console.log(`✅ Success!`);
                    if (result.content && Array.isArray(result.content)) {
                        for (const item of result.content) {
                            if (item.type === "text") {
                                try {
                                    const jsonData = JSON.parse(item.text);
                                    console.log(`Status: ${jsonData.status || "unknown"}`);
                                    if (jsonData.data) {
                                        const data = jsonData.data;
                                        if (Array.isArray(data)) {
                                            console.log(`Found ${data.length} values`);
                                            if (data.length > 0) {
                                                console.log(`First value: ${JSON.stringify(data[0])}`);
                                                if (data.length > 1) {
                                                    console.log(`Last value: ${JSON.stringify(data[data.length - 1])}`);
                                                }
                                            }
                                        } else if (data.attributeKeys) {
                                            console.log(`Found ${data.attributeKeys.length} attribute keys`);
                                            if (data.attributeKeys.length > 0) {
                                                console.log(`First key: ${JSON.stringify(data.attributeKeys[0])}`);
                                            }
                                        } else if (data.attributes) {
                                            console.log(`Found ${data.attributes.length} attributes`);
                                            if (data.attributes.length > 0) {
                                                console.log(`First attribute: ${JSON.stringify(data.attributes[0])}`);
                                            }
                                        }
                                    }
                                } catch (e) {
                                    console.log(item.text.substring(0, 200) + "...");
                                }
                            }
                        }
                    }
                }
                console.log("");

                logger.info({ toolName: testTool.name }, "[MCP Test] Tool call completed");
            } catch (error) {
                console.log(`❌ Exception calling ${testTool.name}:`, error);
                logger.error({ toolName: testTool.name, error }, "[MCP Test] Tool call failed");
            }
        }
```

Results:
```
npm run test:mcp

> [email protected] test:mcp
> ts-node src/random-mcp.ts

info: [MCP Test] Connecting to MCP server {"mcpServerUrl":"http://localhost:3000/mcp","service":"ai-bot-lambda","timestamp":"2025-11-27T01:29:41.942Z"}
info: [MCP Test] Successfully connected to MCP server {"service":"ai-bot-lambda","timestamp":"2025-11-27T01:29:41.990Z"}
info: [MCP Test] Listing available tools... {"service":"ai-bot-lambda","timestamp":"2025-11-27T01:29:41.990Z"}
info: [MCP Test] Found tools {"service":"ai-bot-lambda","timestamp":"2025-11-27T01:29:41.996Z","toolCount":25}

=== Available Tools ===
- signoz_execute_builder_query: Executes a SigNoz Query Builder v5 query. See SigNoz Query Builder v5 docs: https://signoz.io/docs/userguide/query-builder-v5/
- signoz_get_alert: Gets details of a specific alert rule
- signoz_get_alert_history: Gets alert history timeline for a specific rule
- signoz_get_dashboard: Gets complete dashboard configuration
- signoz_get_error_logs: Gets logs with ERROR or FATAL severity within a time range
- signoz_get_log_view: Gets full details of a specific log view by ID
- signoz_get_logs_available_fields: Gets available field names for log queries
- signoz_get_logs_field_values: Gets available field values for log queries
- signoz_get_logs_for_alert: Gets logs related to a specific alert automatically
- signoz_get_metrics_available_fields: Gets available field names for metric queries
- signoz_get_metrics_field_values: Gets available field values for metric queries
- signoz_get_service_top_operations: Gets top operations for a specific service
- signoz_get_trace_available_fields: Gets available field names for trace queries
- signoz_get_trace_details: Gets trace information including all spans and metadata
- signoz_get_trace_error_analysis: Analyzes error patterns in traces. Returns traces with errors, useful for identifying patterns and affected services
- signoz_get_trace_field_values: Gets available field values for trace queries
- signoz_get_trace_span_hierarchy: Gets trace span relationships and hierarchy
- signoz_list_alerts: Lists all active alerts from SigNoz
- signoz_list_dashboards: Lists all dashboards with summaries (name, UUID, description, tags). Returns simplified dashboard information for better LLM processing
- signoz_list_log_views: Lists all saved log views from SigNoz. Returns summary with name, ID, description, and query details
- signoz_list_metric_keys: Lists all available metric keys from SigNoz
- signoz_list_services: Lists all services within a time range
- signoz_search_logs_by_service: Searches logs for a specific service within a time range
- signoz_search_metric_by_text: Searches metrics by text (uses SigNoz aggregate_attributes autocomplete)
- signoz_search_traces_by_service: Searches traces for a specific service


=== Testing Available Fields Tools ===

info: [MCP Test] Calling test tool {"service":"ai-bot-lambda","timestamp":"2025-11-27T01:29:41.997Z","toolName":"signoz_get_trace_available_fields"}

--- signoz_get_trace_available_fields ---
Is Error: false
✅ Success!
Status: success
Found 81 attribute keys
First key: {"key":"client.address","dataType":"string","type":"tag","isColumn":false,"isJSON":false}

info: [MCP Test] Tool call completed {"service":"ai-bot-lambda","timestamp":"2025-11-27T01:29:42.221Z","toolName":"signoz_get_trace_available_fields"}
info: [MCP Test] Calling test tool {"service":"ai-bot-lambda","timestamp":"2025-11-27T01:29:42.221Z","toolName":"signoz_get_logs_available_fields"}

--- signoz_get_logs_available_fields ---
Is Error: false
✅ Success!
Status: success
Found 59 attributes
First attribute: {"key":"service.name","dataType":"string","type":"resource","isColumn":false,"isJSON":false}

info: [MCP Test] Tool call completed {"service":"ai-bot-lambda","timestamp":"2025-11-27T01:29:42.364Z","toolName":"signoz_get_logs_available_fields"}
info: [MCP Test] Calling test tool {"service":"ai-bot-lambda","timestamp":"2025-11-27T01:29:42.364Z","toolName":"signoz_get_metrics_available_fields"}

--- signoz_get_metrics_available_fields ---
Is Error: false
✅ Success!
Status: success
Found 50 attribute keys
First key: {"key":"aws_ApplicationELB_ConsumedLCUs_count","dataType":"float64","type":"Gauge","isColumn":true,"isJSON":false}

info: [MCP Test] Tool call completed {"service":"ai-bot-lambda","timestamp":"2025-11-27T01:29:42.447Z","toolName":"signoz_get_metrics_available_fields"}

=== Testing Field Values Tools ===

info: [MCP Test] Calling test tool {"service":"ai-bot-lambda","timestamp":"2025-11-27T01:29:42.448Z","toolName":"signoz_get_trace_field_values"}

--- signoz_get_trace_field_values ---
Field Name: service.name
Is Error: false
✅ Success!
Status: success

info: [MCP Test] Tool call completed {"service":"ai-bot-lambda","timestamp":"2025-11-27T01:29:42.513Z","toolName":"signoz_get_trace_field_values"}
info: [MCP Test] Calling test tool {"service":"ai-bot-lambda","timestamp":"2025-11-27T01:29:42.513Z","toolName":"signoz_get_logs_field_values"}

--- signoz_get_logs_field_values ---
Field Name: service.name
Is Error: false
✅ Success!
Status: success

info: [MCP Test] Tool call completed {"service":"ai-bot-lambda","timestamp":"2025-11-27T01:29:42.608Z","toolName":"signoz_get_logs_field_values"}
info: [MCP Test] Calling test tool {"service":"ai-bot-lambda","timestamp":"2025-11-27T01:29:42.608Z","toolName":"signoz_get_metrics_field_values"}

--- signoz_get_metrics_field_values ---
Field Name: aws_ApplicationELB_ConsumedLCUs_max
Is Error: false
✅ Success!
Status: success

info: [MCP Test] Tool call completed {"service":"ai-bot-lambda","timestamp":"2025-11-27T01:29:42.721Z","toolName":"signoz_get_metrics_field_values"}
info: [MCP Test] Test completed successfully {"service":"ai-bot-lambda","timestamp":"2025-11-27T01:29:42.736Z"}
✅ All tests passed!
```
2026-01-02 14:56:53 +05:30

173 lines
6.9 KiB
JSON

{
"manifest_version": "0.2",
"name": "signoz",
"display_name": "SigNoz MCP Server",
"version": "0.0.4",
"description": "Access SigNoz metrics, traces, logs, and dashboards.",
"author": {
"name": "SigNoz Team"
},
"homepage": "https://github.com/SigNoz/signoz-mcp-server",
"documentation": "https://signoz.io/docs/signoz-mcp-server",
"support": "https://github.com/SigNoz/signoz-mcp-server/issues",
"icon": "signoz_icon.png",
"server": {
"type": "binary",
"entry_point": "server/signoz-mcp-server",
"mcp_config": {
"command": "${__dirname}/server/signoz-mcp-server",
"args": [],
"env": {
"SIGNOZ_URL": "${user_config.signoz_url}",
"SIGNOZ_API_KEY": "${user_config.signoz_api_key}",
"LOG_LEVEL": "${user_config.log_level}"
}
}
},
"tools": [
{
"name": "signoz_list_metric_keys",
"description": "List all available metric keys"
},
{
"name": "signoz_search_metric_by_text",
"description": "Search metrics by text query"
},
{
"name": "signoz_list_alerts",
"description": "List all active alerts"
},
{
"name": "signoz_get_alert",
"description": "Get details of a specific alert"
},
{
"name": "signoz_get_alert_history",
"description": "Retrieve alert history for a rule"
},
{
"name": "signoz_list_dashboards",
"description": "List all dashboards with summaries"
},
{
"name": "signoz_get_dashboard",
"description": "Retrieve full dashboard configuration"
},
{
"name": "signoz_list_services",
"description": "List services within a given time range"
},
{
"name": "signoz_get_service_top_operations",
"description": "Get top operations for a service"
},
{
"name": "signoz_list_log_views",
"description": "List all saved log views"
},
{
"name": "signoz_get_log_view",
"description": "Get full details of a log view"
},
{
"name": "signoz_get_logs_for_alert",
"description": "Fetch logs related to a specific alert"
},
{
"name": "signoz_get_error_logs",
"description": "Retrieve error and fatal logs"
},
{
"name": "signoz_search_logs_by_service",
"description": "Search logs for a specific service"
},
{
"name": "signoz_get_trace_field_values",
"description": "List available trace field values"
},
{
"name": "signoz_search_traces_by_service",
"description": "Search traces for a specific service"
},
{
"name": "signoz_get_trace_details",
"description": "Retrieve full trace details"
},
{
"name": "signoz_get_trace_error_analysis",
"description": "Analyze error patterns in traces"
},
{
"name": "signoz_get_trace_span_hierarchy",
"description": "Retrieve span hierarchy for a trace"
},
{
"name": "signoz_execute_builder_query",
"description": "Execute SigNoz Query Builder v5 query"
},
{
"name": "signoz_get_trace_available_fields",
"description": "Get available field names for trace queries"
},
{
"name": "signoz_get_logs_available_fields",
"description": "Get available field names for log queries"
},
{
"name": "signoz_get_metrics_available_fields",
"description": "Get available field names for metric queries"
},
{
"name": "signoz_create_dashboard",
"description": "Creates a new monitoring dashboard based on the provided title, layout, and widget configuration. CRITICAL: You MUST read these resources BEFORE generating any dashboard output: 1. signoz://dashboard/instructions - REQUIRED: Dashboard structure and basics 2. signoz://dashboard/widgets-instructions - REQUIRED: Widget configuration rules 3. signoz://dashboard/widgets-examples - REQUIRED: Complete widget examples with all required fields QUERY-SPECIFIC RESOURCES (read based on query type used): - For PromQL queries: signoz://dashboard/promql-example - For Query Builder queries: signoz://dashboard/query-builder-example - For ClickHouse SQL on logs: signoz://dashboard/clickhouse-schema-for-logs + signoz://dashboard/clickhouse-logs-example - For ClickHouse SQL on metrics: signoz://dashboard/clickhouse-schema-for-metrics + signoz://dashboard/clickhouse-metrics-example - For ClickHouse SQL on traces: signoz://dashboard/clickhouse-schema-for-traces + signoz://dashboard/clickhouse-traces-example IMPORTANT: The widgets-examples resource contains complete, working widget configurations. You must consult it to ensure all required fields (id, panelTypes, title, query, selectedLogFields, selectedTracesFields, thresholds, contextLinks) are properly populated."
},
{
"name": "signoz_update_dashboard",
"description": "Update an existing dashboard by supplying its UUID along with a fully assembled dashboard JSON object. MANDATORY FIRST STEP: Read signoz://dashboard/widgets-examples before doing ANYTHING else. This is NON-NEGOTIABLE. The provided object must represent the complete post-update state, combining the current dashboard data and the intended modifications. REQUIRED RESOURCES (read ALL before generating output): 1. signoz://dashboard/instructions 2. signoz://dashboard/widgets-instructions 3. signoz://dashboard/widgets-examples ← CRITICAL: Shows complete widget field structure CONDITIONAL RESOURCES (based on query type): • PromQL → signoz://dashboard/promql-example • Query Builder → signoz://dashboard/query-builder-example • ClickHouse Logs → signoz://dashboard/clickhouse-schema-for-logs + clickhouse-logs-example • ClickHouse Metrics → signoz://dashboard/clickhouse-schema-for-metrics + clickhouse-metrics-example • ClickHouse Traces → signoz://dashboard/clickhouse-schema-for-traces + clickhouse-traces-example WARNING: Failing to consult widgets-examples will result in incomplete widget configurations missing required fields (id, panelTypes, title, query, selectedLogFields, selectedTracesFields, thresholds, contextLinks)."
}
],
"compatibility": {
"platforms": [
"darwin",
"win32"
]
},
"user_config": {
"signoz_url": {
"type": "string",
"title": "SigNoz URL",
"description": "URL to your SigNoz instance",
"required": true,
"sensitive": false
},
"signoz_api_key": {
"type": "string",
"title": "SigNoz API Key",
"description": "API key for accessing SigNoz API",
"required": true,
"sensitive": true
},
"log_level": {
"type": "string",
"title": "Log Level",
"description": "Logging level (debug, info, warn, error)",
"required": false,
"sensitive": false
}
},
"keywords": [
"signoz",
"observability",
"metrics",
"traces",
"logs",
"dashboards",
"alerts"
],
"license": "Apache-2.0",
"repository": {
"type": "git",
"url": "https://github.com/SigNoz/signoz-mcp-server"
}
}