@last9/mcp-server
Advanced tools
+1
-1
| { | ||
| "name": "@last9/mcp-server", | ||
| "version": "0.4.0", | ||
| "version": "0.5.0", | ||
| "description": "Last9 MCP Server - Model Context Protocol server implementation for Last9", | ||
@@ -5,0 +5,0 @@ "bin": { |
+194
-70
@@ -31,3 +31,3 @@ # Last9 MCP Server | ||
| This is the easiest and cleanest setup. You do not need to run a local binary. | ||
| Use an API token from [Last9 API Access](https://app.last9.io/settings/api-access). | ||
| You'll need a **Client Token** (MCP type) — see [Getting your credentials](#getting-your-credentials) below. Your org slug is in your Last9 URL: `app.last9.io/<org_slug>/...` | ||
@@ -77,2 +77,42 @@ ```bash | ||
| #### GitHub Releases (Windows / manual install) | ||
| Download the binary for your platform from [GitHub Releases](https://github.com/last9/last9-mcp-server/releases/latest): | ||
| | Platform | Archive | | ||
| |----------|---------| | ||
| | Windows (x64) | `last9-mcp-server_Windows_x86_64.zip` | | ||
| | Windows (ARM64) | `last9-mcp-server_Windows_arm64.zip` | | ||
| | Linux (x64) | `last9-mcp-server_Linux_x86_64.tar.gz` | | ||
| | Linux (ARM64) | `last9-mcp-server_Linux_arm64.tar.gz` | | ||
| | macOS (x64) | `last9-mcp-server_Darwin_x86_64.tar.gz` | | ||
| | macOS (ARM64) | `last9-mcp-server_Darwin_arm64.tar.gz` | | ||
| Extract the archive. On Windows the binary is `last9-mcp-server.exe`. Use the full path to the binary in your MCP client config (see [Windows example](#windows-example-claude-desktop) below). | ||
| > On Windows, [NPM](#npm) is easier to set up (no path management needed), or use the [hosted HTTP transport](#recommended-managed-mcp-over-http) to skip local installation entirely. | ||
| ## Getting Your Credentials | ||
| ### For hosted MCP (recommended) | ||
| You need a **Client Token** with MCP type. Only **admins** can create tokens. If you're not an admin, ask your admin to create one or grant you admin access via [User Access settings](https://app.last9.io/settings/user-access). | ||
| 1. Go to [Ingestion Tokens](https://app.last9.io/control-plane/ingestion-tokens) | ||
| 2. Click **New Ingestion Token** | ||
| 3. Set **Token Type** to **Client** | ||
| 4. Set **Client Type** to **MCP** | ||
| 5. Enter a name (e.g., `claude-desktop`, `cursor`) | ||
| 6. Click **Create** — copy the token immediately (shown only once) | ||
| Your **organization slug** is in your Last9 URL: `https://app.last9.io/<org_slug>/...` | ||
| ### For local binary (STDIO mode) | ||
| You need a **Refresh Token** with Write permissions. Only **admins** can create them. | ||
| 1. Go to [API Access](https://app.last9.io/settings/api-access) | ||
| 2. Click **Generate Token** with Write permissions | ||
| 3. Copy the token | ||
| ## Status | ||
@@ -118,7 +158,16 @@ | ||
| - For relative windows, prefer `lookback_minutes`. | ||
| - For relative windows, prefer `lookback_minutes` (up to 20160 minutes = 14 days). | ||
| - For absolute windows, use `start_time_iso`, `end_time_iso`, or `time_iso` in RFC3339/ISO8601 (for example, `2026-02-09T15:04:05Z`). | ||
| - If both relative and absolute inputs are provided, absolute time inputs take precedence. | ||
| - Legacy `YYYY-MM-DD HH:MM:SS` is accepted only for compatibility. | ||
| - If a lookback limit error occurs, retry using explicit `start_time_iso`/`end_time_iso` timestamps. | ||
| ### Deep Links | ||
| Most tools return a `deep_link` field in the response metadata. This is a direct URL to the relevant Last9 dashboard view for the queried data — click it to open the corresponding alerts, logs, traces, or APM dashboard page. | ||
| ### Attribute Caching | ||
| The server automatically fetches and caches available log and trace attribute names at startup (with a 10-second timeout) and refreshes the cache every 2 hours in the background. These dynamic attributes are embedded into the `get_logs`, `get_traces`, and `prometheus_range_query` tool descriptions, so AI assistants always see up-to-date field names when constructing queries. | ||
| ### get_exceptions | ||
@@ -132,3 +181,3 @@ | ||
| - `lookback_minutes` (integer, recommended): Number of minutes to look back from | ||
| now. Default: 60. Examples: 60, 30, 15. | ||
| now. Default: 60. Range: 1–20160 (14 days). Examples: 60, 30, 15. | ||
| - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to use lookback_minutes. | ||
@@ -164,5 +213,7 @@ - `end_time_iso` (string, optional): End time in RFC3339/ISO8601 format (e.g. 2026-02-09T16:04:05Z). Leave empty to default to current time. | ||
| - `service_name` (string, required): Name of the service to get performance details for. | ||
| - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to default to now - 60 minutes. | ||
| - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60. Range: 1–20160 (14 days). | ||
| - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to use lookback_minutes. | ||
| - `end_time_iso` (string, optional): End time in RFC3339/ISO8601 format (e.g. 2026-02-09T16:04:05Z). Leave empty to default to current time. | ||
| - `env` (string, optional): Environment to filter by. Defaults to 'prod'. | ||
| Returns: throughput, error rate, p50/p90/p95/avg/max response times, apdex score, availability, top operations, and top errors. | ||
@@ -175,5 +226,7 @@ ### get_service_operations_summary | ||
| - `service_name` (string, required): Name of the service to get operations summary for. | ||
| - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to default to now - 60 minutes. | ||
| - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60. Range: 1–20160 (14 days). | ||
| - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to use lookback_minutes. | ||
| - `end_time_iso` (string, optional): End time in RFC3339/ISO8601 format (e.g. 2026-02-09T16:04:05Z). Leave empty to default to current time. | ||
| - `env` (string, optional): Environment to filter by. Defaults to 'prod'. | ||
| Each operation includes: throughput (rpm), error rate (rpm), error percentage, and p50/p90/p95/avg/max response times (ms). | ||
@@ -186,5 +239,7 @@ ### get_service_dependency_graph | ||
| - `service_name` (string, optional): Name of the service to get the dependency graph for. | ||
| - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to default to now - 60 minutes. | ||
| - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60. Range: 1–20160 (14 days). | ||
| - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to use lookback_minutes. | ||
| - `end_time_iso` (string, optional): End time in RFC3339/ISO8601 format (e.g. 2026-02-09T16:04:05Z). Leave empty to default to current time. | ||
| - `env` (string, optional): Environment to filter by. Defaults to 'prod'. | ||
| Each node includes: throughput (rpm), error rate (rpm), error percentage, and p50/p90/p95/avg/max response times (ms). | ||
@@ -235,3 +290,3 @@ ### prometheus_range_query | ||
| - `severity` (string, optional): Severity of the logs to get (automatically converted to severity_filters format). | ||
| - `lookback_minutes` (integer, recommended): Number of minutes to look back from now. Default: 60. Examples: 60, 30, 15. | ||
| - `lookback_minutes` (integer, recommended): Number of minutes to look back from now. Default: 60. Range: 1–20160 (14 days). Examples: 60, 30, 15. | ||
| - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to use lookback_minutes. | ||
@@ -293,2 +348,3 @@ - `end_time_iso` (string, optional): End time in RFC3339/ISO8601 format (e.g. 2026-02-09T16:04:05Z). Leave empty to default to current time. | ||
| - `window` (integer, optional): Time window in seconds to look back for alerts. Defaults to 900 seconds (15 minutes). Range: 60-86400 seconds. | ||
| - `lookback_minutes` (integer, optional): Relative time window in minutes. Used only when `window` is not provided. Range: 1-1440. | ||
| Returns information about: | ||
@@ -309,3 +365,3 @@ - Alert rule details (ID, name, group, type) | ||
| - `service_name` (string, required): Name of the service to get logs for. | ||
| - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60 minutes. Examples: 60, 30, 15. | ||
| - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60. Range: 1–20160 (14 days). Examples: 60, 30, 15. | ||
| - `limit` (integer, optional): Maximum number of log entries to return. Default: 20. | ||
@@ -346,3 +402,3 @@ - `env` (string, optional): Environment to filter by. Use "get_service_environments" tool to get available environments. | ||
| - `end_time_iso` (string, optional): End time in RFC3339/ISO8601 format (e.g. 2026-02-09T16:04:05Z). | ||
| - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60 minutes. | ||
| - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60. Range: 1–20160 (14 days). | ||
| - `limit` (integer, optional): Maximum number of traces to return. Default: 20. Range: 1-100. | ||
@@ -358,3 +414,3 @@ This tool supports complex queries with multiple filter conditions, aggregations, and custom processing pipelines for advanced trace analysis. | ||
| - `service_name` (string, optional): Name of service to get traces for. Cannot be used with trace_id. | ||
| - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60 minutes. Examples: 60, 30, 15. | ||
| - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60. Range: 1–20160 (14 days). Examples: 60, 30, 15. | ||
| - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to use lookback_minutes. | ||
@@ -391,3 +447,3 @@ - `end_time_iso` (string, optional): End time in RFC3339/ISO8601 format (e.g. 2026-02-09T16:04:05Z). Leave empty to default to current time. | ||
| - `end_time_iso` (string, optional): End time in RFC3339/ISO8601 format (e.g. 2026-02-09T16:04:05Z). Leave empty to default to current time. | ||
| - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60 minutes. Examples: 60, 30, 15. | ||
| - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60. Range: 1–20160 (14 days). Examples: 60, 30, 15. | ||
| - `service` (string, optional): Name of the service to filter change events for. | ||
@@ -424,12 +480,12 @@ - `environment` (string, optional): Environment to filter by. | ||
| - `LAST9_REFRESH_TOKEN`: (required) Refresh Token with Write permissions from | ||
| [API Access](https://app.last9.io/settings/api-access). This token is used for | ||
| all authentication and will automatically obtain access tokens as needed. | ||
| - `OTEL_EXPORTER_OTLP_ENDPOINT`: (required) OpenTelemetry collector endpoint URL | ||
| - `OTEL_EXPORTER_OTLP_HEADERS`: (required) Headers for OTLP exporter authentication | ||
| [API Access](https://app.last9.io/settings/api-access). Only admins can create | ||
| refresh tokens. | ||
| Optional environment variables: | ||
| - `LAST9_DISABLE_TELEMETRY`: Defaults to `true` (telemetry is disabled by default). Set to `false` to enable OpenTelemetry tracing if you have an OTLP collector configured. | ||
| - `OTEL_EXPORTER_OTLP_ENDPOINT`: OpenTelemetry collector endpoint URL. Only needed if `LAST9_DISABLE_TELEMETRY=false`. | ||
| - `OTEL_EXPORTER_OTLP_HEADERS`: Headers for OTLP exporter authentication. Only needed if `LAST9_DISABLE_TELEMETRY=false`. | ||
| - `LAST9_DATASOURCE`: Name of the datasource/cluster to use. If not specified, the default datasource configured in your Last9 organization will be used. | ||
| - `LAST9_API_HOST`: API host to connect to. Defaults to `app.last9.io`. Use this if you need to connect to a different Last9 endpoint (e.g., regional or self-hosted instances). | ||
| - `LAST9_DISABLE_TELEMETRY`: Set to `true` to disable OpenTelemetry tracing and metrics. Use this if you don't have an OTLP collector running or want to skip telemetry. | ||
@@ -450,2 +506,10 @@ ## Usage | ||
| ### Local STDIO | ||
| > **Note:** Claude Desktop currently supports local STDIO-based MCP servers only. Hosted HTTP transport is not yet supported in Claude Desktop. | ||
| Use a [Refresh Token](#getting-your-credentials). | ||
| Install via [Homebrew](#homebrew) or [NPM](#npm) first, then use a [Refresh Token](#getting-your-credentials). | ||
| ### If installed via Homebrew: | ||
@@ -459,5 +523,3 @@ | ||
| "env": { | ||
| "LAST9_REFRESH_TOKEN": "<last9_refresh_token>", | ||
| "OTEL_EXPORTER_OTLP_ENDPOINT": "<otel_endpoint_url>", | ||
| "OTEL_EXPORTER_OTLP_HEADERS": "<otel_headers>" | ||
| "LAST9_REFRESH_TOKEN": "<last9_refresh_token>" | ||
| } | ||
@@ -478,5 +540,3 @@ } | ||
| "env": { | ||
| "LAST9_REFRESH_TOKEN": "<last9_refresh_token>", | ||
| "OTEL_EXPORTER_OTLP_ENDPOINT": "<otel_endpoint_url>", | ||
| "OTEL_EXPORTER_OTLP_HEADERS": "<otel_headers>" | ||
| "LAST9_REFRESH_TOKEN": "<last9_refresh_token>" | ||
| } | ||
@@ -498,2 +558,20 @@ } | ||
| ### Hosted MCP over HTTP (recommended) | ||
| ```json | ||
| { | ||
| "mcpServers": { | ||
| "last9": { | ||
| "type": "http", | ||
| "url": "https://app.last9.io/api/v4/organizations/<org_slug>/mcp", | ||
| "headers": { | ||
| "X-LAST9-API-TOKEN": "Bearer <mcp_client_token>" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
| ### Local STDIO (alternative) | ||
| ### If installed via Homebrew: | ||
@@ -507,5 +585,3 @@ | ||
| "env": { | ||
| "LAST9_REFRESH_TOKEN": "<last9_refresh_token>", | ||
| "OTEL_EXPORTER_OTLP_ENDPOINT": "<otel_endpoint_url>", | ||
| "OTEL_EXPORTER_OTLP_HEADERS": "<otel_headers>" | ||
| "LAST9_REFRESH_TOKEN": "<last9_refresh_token>" | ||
| } | ||
@@ -526,5 +602,3 @@ } | ||
| "env": { | ||
| "LAST9_REFRESH_TOKEN": "<last9_refresh_token>", | ||
| "OTEL_EXPORTER_OTLP_ENDPOINT": "<otel_endpoint_url>", | ||
| "OTEL_EXPORTER_OTLP_HEADERS": "<otel_headers>" | ||
| "LAST9_REFRESH_TOKEN": "<last9_refresh_token>" | ||
| } | ||
@@ -546,2 +620,20 @@ } | ||
| ### Hosted MCP over HTTP (recommended) | ||
| ```json | ||
| { | ||
| "mcpServers": { | ||
| "last9": { | ||
| "type": "http", | ||
| "url": "https://app.last9.io/api/v4/organizations/<org_slug>/mcp", | ||
| "headers": { | ||
| "X-LAST9-API-TOKEN": "Bearer <mcp_client_token>" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
| ### Local STDIO (alternative) | ||
| ### If installed via Homebrew: | ||
@@ -555,5 +647,3 @@ | ||
| "env": { | ||
| "LAST9_REFRESH_TOKEN": "<last9_refresh_token>", | ||
| "OTEL_EXPORTER_OTLP_ENDPOINT": "<otel_endpoint_url>", | ||
| "OTEL_EXPORTER_OTLP_HEADERS": "<otel_headers>" | ||
| "LAST9_REFRESH_TOKEN": "<last9_refresh_token>" | ||
| } | ||
@@ -574,5 +664,3 @@ } | ||
| "env": { | ||
| "LAST9_REFRESH_TOKEN": "<last9_refresh_token>", | ||
| "OTEL_EXPORTER_OTLP_ENDPOINT": "<otel_endpoint_url>", | ||
| "OTEL_EXPORTER_OTLP_HEADERS": "<otel_headers>" | ||
| "LAST9_REFRESH_TOKEN": "<last9_refresh_token>" | ||
| } | ||
@@ -595,2 +683,22 @@ } | ||
| ### Hosted MCP over HTTP (recommended) | ||
| ```json | ||
| { | ||
| "mcp": { | ||
| "servers": { | ||
| "last9": { | ||
| "type": "http", | ||
| "url": "https://app.last9.io/api/v4/organizations/<org_slug>/mcp", | ||
| "headers": { | ||
| "X-LAST9-API-TOKEN": "Bearer <mcp_client_token>" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
| ### Local STDIO (alternative) | ||
| ### If installed via Homebrew: | ||
@@ -606,5 +714,3 @@ | ||
| "env": { | ||
| "LAST9_REFRESH_TOKEN": "<last9_refresh_token>", | ||
| "OTEL_EXPORTER_OTLP_ENDPOINT": "<otel_endpoint_url>", | ||
| "OTEL_EXPORTER_OTLP_HEADERS": "<otel_headers>" | ||
| "LAST9_REFRESH_TOKEN": "<last9_refresh_token>" | ||
| } | ||
@@ -628,5 +734,3 @@ } | ||
| "env": { | ||
| "LAST9_REFRESH_TOKEN": "<last9_refresh_token>", | ||
| "OTEL_EXPORTER_OTLP_ENDPOINT": "<otel_endpoint_url>", | ||
| "OTEL_EXPORTER_OTLP_HEADERS": "<otel_headers>" | ||
| "LAST9_REFRESH_TOKEN": "<last9_refresh_token>" | ||
| } | ||
@@ -639,2 +743,21 @@ } | ||
| ## Windows Example (Claude Desktop) | ||
| After downloading `last9-mcp-server_Windows_x86_64.zip` from [GitHub Releases](https://github.com/last9/last9-mcp-server/releases/latest), extract to get `last9-mcp-server.exe` and use its full path: | ||
| ```json | ||
| { | ||
| "mcpServers": { | ||
| "last9": { | ||
| "command": "C:\\Users\\<user>\\AppData\\Local\\Programs\\last9-mcp-server.exe", | ||
| "env": { | ||
| "LAST9_REFRESH_TOKEN": "<last9_refresh_token>" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
| The same pattern applies for Cursor and Windsurf on Windows. For VS Code, use the `"mcp": { "servers": { ... } }` wrapper. On Windows, prefer [NPM](#npm) to avoid path management, or use the [hosted HTTP transport](#recommended-managed-mcp-over-http) to skip local installation entirely. | ||
| ## Development | ||
@@ -651,4 +774,2 @@ | ||
| export LAST9_REFRESH_TOKEN="your_refresh_token" | ||
| export OTEL_EXPORTER_OTLP_ENDPOINT="<otel_endpoint_url>" | ||
| export OTEL_EXPORTER_OTLP_HEADERS="<otel_headers>" | ||
| export LAST9_HTTP=true | ||
@@ -664,47 +785,50 @@ export LAST9_PORT=8080 # Optional, defaults to 8080 | ||
| The MCP Streamable HTTP protocol requires an initialize handshake first. The server creates and returns a session ID in the response — do **not** set `Mcp-Session-Id` on the first request. | ||
| ```bash | ||
| # Test get_service_logs | ||
| curl -X POST http://localhost:8080/mcp \ | ||
| # Step 1: Initialize — omit Mcp-Session-Id so the server creates the session. | ||
| # Extract the returned Mcp-Session-Id from the response headers. | ||
| SESSION_ID=$(curl -si -X POST http://localhost:8080/mcp \ | ||
| -H "Content-Type: application/json" \ | ||
| -H "Mcp-Session-Id: session_$(date +%s)000000000" \ | ||
| -d '{ | ||
| "jsonrpc": "2.0", | ||
| "id": 1, | ||
| "method": "tools/call", | ||
| "method": "initialize", | ||
| "params": { | ||
| "name": "get_service_logs", | ||
| "arguments": { | ||
| "service_name": "your-service-name", | ||
| "lookback_minutes": 30, | ||
| "limit": 10 | ||
| } | ||
| "protocolVersion": "2024-11-05", | ||
| "capabilities": {}, | ||
| "clientInfo": {"name": "curl-test", "version": "1.0"} | ||
| } | ||
| }' | ||
| # Test get_service_traces | ||
| curl -X POST http://localhost:8080/mcp \ | ||
| }' | grep -i "^Mcp-Session-Id:" | awk '{print $2}' | tr -d '\r') | ||
| echo "Session: $SESSION_ID" | ||
| # Step 2: Send the initialized notification | ||
| curl -s -X POST http://localhost:8080/mcp \ | ||
| -H "Content-Type: application/json" \ | ||
| -H "Mcp-Session-Id: session_$(date +%s)000000000" \ | ||
| -H "Mcp-Session-Id: $SESSION_ID" \ | ||
| -d '{"jsonrpc": "2.0", "method": "notifications/initialized", "params": {}}' | ||
| # Step 3: List available tools | ||
| curl -s -X POST http://localhost:8080/mcp \ | ||
| -H "Content-Type: application/json" \ | ||
| -H "Mcp-Session-Id: $SESSION_ID" \ | ||
| -d '{"jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {}}' | ||
| # Step 4: Call a tool | ||
| curl -s -X POST http://localhost:8080/mcp \ | ||
| -H "Content-Type: application/json" \ | ||
| -H "Mcp-Session-Id: $SESSION_ID" \ | ||
| -d '{ | ||
| "jsonrpc": "2.0", | ||
| "id": 2, | ||
| "id": 3, | ||
| "method": "tools/call", | ||
| "params": { | ||
| "name": "get_service_traces", | ||
| "name": "get_service_logs", | ||
| "arguments": { | ||
| "service_name": "your-service-name", | ||
| "lookback_minutes": 60, | ||
| "limit": 5 | ||
| "lookback_minutes": 30, | ||
| "limit": 10 | ||
| } | ||
| } | ||
| }' | ||
| # List available tools | ||
| curl -X POST http://localhost:8080/mcp \ | ||
| -H "Content-Type: application/json" \ | ||
| -H "Mcp-Session-Id: session_$(date +%s)000000000" \ | ||
| -d '{ | ||
| "jsonrpc": "2.0", | ||
| "id": 3, | ||
| "method": "tools/list", | ||
| "params": {} | ||
| }' | ||
| ``` | ||
@@ -711,0 +835,0 @@ |
AI-detected potential malware
Supply chain riskAI has identified this package as malware. This is a strong signal that the package may be malicious.
51763
11.34%828
17.61%2
100%