@last9/mcp-server 0.2.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,6 @@
1
1
  # Last9 MCP Server
2
2
 
3
3
  ![last9 mcp demo](mcp-demo.gif)
4
-
5
4
  A [Model Context Protocol](https://modelcontextprotocol.io/) server
6
5
  implementation for [Last9](https://last9.io/mcp/) that enables AI agents to
7
6
  seamlessly bring real-time production context — logs, metrics, and traces — into
@@ -11,12 +10,114 @@ your local environment to auto-fix code faster.
11
10
  - Read our
12
11
  [announcement blog post](https://last9.io/blog/launching-last9-mcp-server/)
13
12
 
13
+ ## Quick Links
14
+
15
+ - [Status](#status)
16
+ - [Installation](#installation)
17
+ - [Configuration](#configuration)
18
+ - [Usage](#usage)
19
+ - [Tools Documentation](#tools-documentation)
20
+ - [Development](#development)
21
+ - [Testing](#testing)
22
+ - [Badges](#badges)
23
+
24
+ ## Installation
25
+
26
+ You can connect to Last9 MCP in two ways:
27
+
28
+ ### Recommended: Managed MCP over HTTP
29
+
30
+ This is the easiest and cleanest setup. You do not need to run a local binary.
31
+ 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>/...`
32
+
33
+ ```bash
34
+ claude mcp add --transport http last9 https://app.last9.io/api/v4/organizations/<organization_slug>/mcp \
35
+ --header "X-LAST9-API-TOKEN: Bearer <last9_api_token>"
36
+ ```
37
+
38
+ Or add it directly to your MCP client config:
39
+
40
+ ```json
41
+ {
42
+ "mcpServers": {
43
+ "last9": {
44
+ "type": "http",
45
+ "url": "https://app.last9.io/api/v4/organizations/<organization_slug>/mcp",
46
+ "headers": {
47
+ "X-LAST9-API-TOKEN": "Bearer <last9_api_token>"
48
+ }
49
+ }
50
+ }
51
+ }
52
+ ```
53
+
54
+ ### Local Installation (STDIO fallback)
55
+
56
+ Use this only if your client needs a local STDIO server process.
57
+
58
+ #### Homebrew
59
+
60
+ ```bash
61
+ brew update
62
+ brew install last9/tap/last9-mcp
63
+ brew upgrade last9/tap/last9-mcp
64
+ last9-mcp --version
65
+ ```
66
+
67
+ #### NPM
68
+
69
+ ```bash
70
+ # Install globally
71
+ npm install -g @last9/mcp-server@latest
72
+ # Or run directly with npx
73
+ npx -y @last9/mcp-server@latest
74
+ ```
75
+
76
+ #### GitHub Releases (Windows / manual install)
77
+
78
+ Download the binary for your platform from [GitHub Releases](https://github.com/last9/last9-mcp-server/releases/latest):
79
+
80
+ | Platform | Archive |
81
+ |----------|---------|
82
+ | Windows (x64) | `last9-mcp-server_Windows_x86_64.zip` |
83
+ | Windows (ARM64) | `last9-mcp-server_Windows_arm64.zip` |
84
+ | Linux (x64) | `last9-mcp-server_Linux_x86_64.tar.gz` |
85
+ | Linux (ARM64) | `last9-mcp-server_Linux_arm64.tar.gz` |
86
+ | macOS (x64) | `last9-mcp-server_Darwin_x86_64.tar.gz` |
87
+ | macOS (ARM64) | `last9-mcp-server_Darwin_arm64.tar.gz` |
88
+
89
+ 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).
90
+
91
+ > 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.
92
+
93
+ ## Getting Your Credentials
94
+
95
+ ### For hosted MCP (recommended)
96
+
97
+ 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).
98
+
99
+ 1. Go to [Ingestion Tokens](https://app.last9.io/control-plane/ingestion-tokens)
100
+ 2. Click **New Ingestion Token**
101
+ 3. Set **Token Type** to **Client**
102
+ 4. Set **Client Type** to **MCP**
103
+ 5. Enter a name (e.g., `claude-desktop`, `cursor`)
104
+ 6. Click **Create** — copy the token immediately (shown only once)
105
+
106
+ Your **organization slug** is in your Last9 URL: `https://app.last9.io/<org_slug>/...`
107
+
108
+ ### For local binary (STDIO mode)
109
+
110
+ You need a **Refresh Token** with Write permissions. Only **admins** can create them.
111
+
112
+ 1. Go to [API Access](https://app.last9.io/settings/api-access)
113
+ 2. Click **Generate Token** with Write permissions
114
+ 3. Copy the token
115
+
14
116
  ## Status
15
117
 
16
118
  Works with Claude desktop app, or Cursor, Windsurf, and VSCode (Github Copilot)
17
119
  IDEs. Implements the following MCP
18
120
  [tools](https://modelcontextprotocol.io/docs/concepts/tools):
19
-
20
121
  **Observability & APM Tools:**
21
122
 
22
123
  - `get_exceptions`: Get the list of exceptions.
@@ -25,16 +126,12 @@ IDEs. Implements the following MCP
25
126
  - `get_service_performance_details`: Get detailed performance metrics for a service.
26
127
  - `get_service_operations_summary`: Get operations summary for a service.
27
128
  - `get_service_dependency_graph`: Get service dependency graph showing incoming/outgoing dependencies.
28
-
29
- **Prometheus/PromQL Tools:**
30
-
129
+ **Prometheus/PromQL Tools:**
31
130
  - `prometheus_range_query`: Execute PromQL range queries for metrics data.
32
131
  - `prometheus_instant_query`: Execute PromQL instant queries for metrics data.
33
132
  - `prometheus_label_values`: Get label values for PromQL queries.
34
133
  - `prometheus_labels`: Get available labels for PromQL queries.
35
-
36
- **Logs Management:**
37
-
134
+ **Logs Management:**
38
135
  - `get_logs`: Get logs filtered by service name and/or severity level.
39
136
  - `get_drop_rules`: Get drop rules for logs that determine what logs get
40
137
  filtered out at [Last9 Control Plane](https://last9.io/control-plane)
@@ -42,38 +139,45 @@ IDEs. Implements the following MCP
42
139
  [Last9 Control Plane](https://last9.io/control-plane)
43
140
  - `get_service_logs`: Get raw log entries for a specific service over a time range. Can apply filters on severity and body.
44
141
  - `get_log_attributes`: Get available log attributes (labels) for a specified time window.
142
+ **Traces Management:**
143
+ - `get_traces`: Retrieve traces using JSON pipeline queries for advanced filtering.
144
+ - `get_service_traces`: Retrieve traces by trace ID or service name with time range filtering.
145
+ - `get_trace_attributes`: Get available trace attributes (series) for a specified time window.
146
+ **Change Events:**
147
+ - `get_change_events`: Get change events from the last9_change_events prometheus metric over a given time range.
148
+ **Alert Management:**
149
+ - `get_alert_config`: Get alert configurations (alert rules) from Last9.
150
+ - `get_alerts`: Get currently active alerts from Last9 monitoring system.
45
151
 
46
- **Traces Management:**
152
+ ## Tools Documentation
47
153
 
48
- - `get_traces`: Retrieve traces by trace ID or service name with time range filtering.
49
- - `get_service_traces`: Query traces for a specific service with filtering options for span kinds, status codes, and other trace attributes.
50
- - `get_trace_attributes`: Get available trace attributes (series) for a specified time window.
154
+ ### Time Input Standard
51
155
 
52
- **Change Events:**
156
+ - For relative windows, prefer `lookback_minutes` (up to 20160 minutes = 14 days).
157
+ - For absolute windows, use `start_time_iso`, `end_time_iso`, or `time_iso` in RFC3339/ISO8601 (for example, `2026-02-09T15:04:05Z`).
158
+ - If both relative and absolute inputs are provided, absolute time inputs take precedence.
159
+ - Legacy `YYYY-MM-DD HH:MM:SS` is accepted only for compatibility.
160
+ - If a lookback limit error occurs, retry using explicit `start_time_iso`/`end_time_iso` timestamps.
53
161
 
54
- - `get_change_events`: Get change events from the last9_change_events prometheus metric over a given time range.
162
+ ### Deep Links
55
163
 
56
- **Alert Management:**
164
+ 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.
57
165
 
58
- - `get_alert_config`: Get alert configurations (alert rules) from Last9.
59
- - `get_alerts`: Get currently active alerts from Last9 monitoring system.
166
+ ### Attribute Caching
60
167
 
61
- ## Tools Documentation
168
+ 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.
62
169
 
63
170
  ### get_exceptions
64
171
 
65
172
  Retrieves server-side exceptions over a specified time range.
66
-
67
173
  Parameters:
68
174
 
69
175
  - `limit` (integer, optional): Maximum number of exceptions to return.
70
176
  Default: 20.
71
177
  - `lookback_minutes` (integer, recommended): Number of minutes to look back from
72
- now. Default: 60. Examples: 60, 30, 15.
73
- - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD
74
- HH:MM:SS). Leave empty to use lookback_minutes.
75
- - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD
76
- HH:MM:SS). Leave empty to default to current time.
178
+ now. Default: 60. Range: 1–20160 (14 days). Examples: 60, 30, 15.
179
+ - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to use lookback_minutes.
180
+ - `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.
77
181
  - `service_name` (string, optional): Filter exceptions by service name (e.g., api-service).
78
182
  - `span_name` (string, optional): Name of the span to filter by.
79
183
  - `deployment_environment` (string, optional): Filter exceptions by deployment environment from resource attributes (e.g., production, staging).
@@ -81,110 +185,104 @@ Parameters:
81
185
  ### get_service_summary
82
186
 
83
187
  Get service summary over a given time range. Includes service name, environment, throughput, error rate, and response time. All values are p95 quantiles over the time range.
84
-
85
188
  Parameters:
86
189
 
87
- - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to end_time_iso - 1 hour.
88
- - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
190
+ - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to default to end_time_iso - 1 hour.
191
+ - `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.
89
192
  - `env` (string, optional): Environment to filter by. Defaults to 'prod'.
90
193
 
91
194
  ### get_service_environments
92
195
 
93
196
  Get available environments for services. Returns an array of environments that can be used with other APM tools.
94
-
95
197
  Parameters:
96
198
 
97
- - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to end_time_iso - 1 hour.
98
- - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
99
-
100
- Note: All other APM tools that retrieve service information (like `get_service_performance_details`, `get_service_dependency_graph`, `get_service_operations_summary`, `get_service_summary`) require an `env` parameter. This parameter must be one of the environments returned by this tool. If this tool returns an empty array, use an empty string `""` for the env parameter.
199
+ - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to default to end_time_iso - 1 hour.
200
+ - `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.
201
+ Note: All other APM tools that retrieve service information (like `get_service_performance_details`, `get_service_dependency_graph`, `get_service_operations_summary`, `get_service_summary`) require an `env` parameter. This parameter must be one of the environments returned by this tool. If this tool returns an empty array, use an empty string `""` for the env parameter.
101
202
 
102
203
  ### get_service_performance_details
103
204
 
104
205
  Get detailed performance metrics for a specific service over a given time range.
105
-
106
206
  Parameters:
107
207
 
108
208
  - `service_name` (string, required): Name of the service to get performance details for.
109
- - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - 60 minutes.
110
- - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
209
+ - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60. Range: 1–20160 (14 days).
210
+ - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to use lookback_minutes.
211
+ - `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.
111
212
  - `env` (string, optional): Environment to filter by. Defaults to 'prod'.
213
+ Returns: throughput, error rate, p50/p90/p95/avg/max response times, apdex score, availability, top operations, and top errors.
112
214
 
113
215
  ### get_service_operations_summary
114
216
 
115
217
  Get a summary of operations inside a service over a given time range. Returns operations like HTTP endpoints, database queries, messaging producer and HTTP client calls.
116
-
117
218
  Parameters:
118
219
 
119
220
  - `service_name` (string, required): Name of the service to get operations summary for.
120
- - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - 60 minutes.
121
- - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
221
+ - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60. Range: 1–20160 (14 days).
222
+ - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to use lookback_minutes.
223
+ - `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.
122
224
  - `env` (string, optional): Environment to filter by. Defaults to 'prod'.
225
+ Each operation includes: throughput (rpm), error rate (rpm), error percentage, and p50/p90/p95/avg/max response times (ms).
123
226
 
124
227
  ### get_service_dependency_graph
125
228
 
126
229
  Get details of the throughput, response times and error rates of incoming, outgoing and infrastructure components of a service. Useful for analyzing cascading effects of errors and performance issues.
127
-
128
230
  Parameters:
129
231
 
130
232
  - `service_name` (string, optional): Name of the service to get the dependency graph for.
131
- - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - 60 minutes.
132
- - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
233
+ - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60. Range: 1–20160 (14 days).
234
+ - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to use lookback_minutes.
235
+ - `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.
133
236
  - `env` (string, optional): Environment to filter by. Defaults to 'prod'.
237
+ Each node includes: throughput (rpm), error rate (rpm), error percentage, and p50/p90/p95/avg/max response times (ms).
134
238
 
135
239
  ### prometheus_range_query
136
240
 
137
241
  Perform a Prometheus range query to get metrics data over a specified time range. Recommended to check available labels first using `prometheus_labels` tool.
138
-
139
242
  Parameters:
140
243
 
141
244
  - `query` (string, required): The range query to execute.
142
- - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - 60 minutes.
143
- - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
245
+ - `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.
246
+ - `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.
144
247
 
145
248
  ### prometheus_instant_query
146
249
 
147
- Perform a Prometheus instant query to get metrics data at a specific point in time. Typically should use rollup functions like sum_over_time, avg_over_time, quantile_over_time over a time window.
148
-
250
+ Perform a Prometheus instant query to get metrics data at a specific time. Typically should use rollup functions like sum_over_time, avg_over_time, quantile_over_time over a time window.
149
251
  Parameters:
150
252
 
151
253
  - `query` (string, required): The instant query to execute.
152
- - `time_iso` (string, optional): Time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
254
+ - `time_iso` (string, optional): Time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to default to current time.
153
255
 
154
256
  ### prometheus_label_values
155
257
 
156
258
  Return the label values for a particular label and PromQL filter query. Similar to Prometheus /label_values call.
157
-
158
259
  Parameters:
159
260
 
160
261
  - `match_query` (string, required): A valid PromQL filter query.
161
262
  - `label` (string, required): The label to get values for.
162
- - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - 60 minutes.
163
- - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
263
+ - `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.
264
+ - `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.
164
265
 
165
266
  ### prometheus_labels
166
267
 
167
268
  Return the labels for a given PromQL match query. Similar to Prometheus /labels call.
168
-
169
269
  Parameters:
170
270
 
171
271
  - `match_query` (string, required): A valid PromQL filter query.
172
- - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - 60 minutes.
173
- - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
272
+ - `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.
273
+ - `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.
174
274
 
175
275
  ### get_logs
176
276
 
177
277
  Gets logs filtered by service name and/or severity level within a specified time range. This tool now uses the advanced v2 logs API with physical index optimization for better performance.
178
-
179
278
  **Note**: This tool now requires a `service_name` parameter and internally uses the same advanced infrastructure as `get_service_logs`.
180
-
181
279
  Parameters:
182
280
 
183
281
  - `service_name` (string, required): Name of the service to get logs for.
184
282
  - `severity` (string, optional): Severity of the logs to get (automatically converted to severity_filters format).
185
- - `lookback_minutes` (integer, recommended): Number of minutes to look back from now. Default: 60. Examples: 60, 30, 15.
186
- - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to use lookback_minutes.
187
- - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
283
+ - `lookback_minutes` (integer, recommended): Number of minutes to look back from now. Default: 60. Range: 1–20160 (14 days). Examples: 60, 30, 15.
284
+ - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to use lookback_minutes.
285
+ - `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.
188
286
  - `limit` (integer, optional): Maximum number of logs to return. Default: 20.
189
287
  - `env` (string, optional): Environment to filter by. Use "get_service_environments" tool to get available environments.
190
288
 
@@ -197,7 +295,6 @@ reaching Last9.
197
295
 
198
296
  Adds a new drop rule to filter out specific logs at
199
297
  [Last9 Control Plane](https://last9.io/control-plane)
200
-
201
298
  Parameters:
202
299
 
203
300
  - `name` (string, required): Name of the drop rule.
@@ -219,11 +316,8 @@ Parameters:
219
316
  ### get_alert_config
220
317
 
221
318
  Get alert configurations (alert rules) from Last9. Returns all configured alert rules including their conditions, labels, and annotations.
222
-
223
319
  Parameters:
224
-
225
320
  None - This tool retrieves all available alert configurations.
226
-
227
321
  Returns information about:
228
322
 
229
323
  - Alert rule ID and name
@@ -238,14 +332,13 @@ Returns information about:
238
332
  ### get_alerts
239
333
 
240
334
  Get currently active alerts from Last9 monitoring system. Returns all alerts that are currently firing or have fired recently within the specified time window.
241
-
242
335
  Parameters:
243
336
 
244
- - `timestamp` (integer, optional): Unix timestamp for the query time. Leave empty to default to current time.
337
+ - `time_iso` (string, optional): Evaluation time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Preferred.
338
+ - `timestamp` (integer, optional): Unix timestamp for the query time. Deprecated alias.
245
339
  - `window` (integer, optional): Time window in seconds to look back for alerts. Defaults to 900 seconds (15 minutes). Range: 60-86400 seconds.
246
-
247
- Returns information about:
248
-
340
+ - `lookback_minutes` (integer, optional): Relative time window in minutes. Used only when `window` is not provided. Range: 1-1440.
341
+ Returns information about:
249
342
  - Alert rule details (ID, name, group, type)
250
343
  - Current state and severity
251
344
  - Last fired timestamp and duration
@@ -257,182 +350,135 @@ Returns information about:
257
350
  ### get_service_logs
258
351
 
259
352
  Get raw log entries for a specific service over a time range. This tool retrieves actual log entries including log messages, timestamps, severity levels, and other metadata. Useful for debugging issues, monitoring service behavior, and analyzing specific log patterns.
260
-
261
353
  Parameters:
262
354
 
263
355
  - `service_name` (string, required): Name of the service to get logs for.
264
- - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60 minutes. Examples: 60, 30, 15.
356
+ - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60. Range: 1–20160 (14 days). Examples: 60, 30, 15.
265
357
  - `limit` (integer, optional): Maximum number of log entries to return. Default: 20.
266
358
  - `env` (string, optional): Environment to filter by. Use "get_service_environments" tool to get available environments.
267
359
  - `severity_filters` (array, optional): Array of severity patterns to filter logs (e.g., ["error", "warn"]). Uses OR logic.
268
360
  - `body_filters` (array, optional): Array of message content patterns to filter logs (e.g., ["timeout", "failed"]). Uses OR logic.
269
- - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - lookback_minutes.
270
- - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
271
-
272
- Filtering behavior:
361
+ - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to default to now - lookback_minutes.
362
+ - `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.
363
+ Filtering behavior:
273
364
  - Multiple filter types are combined with AND logic (service AND severity AND body)
274
365
  - Each filter array uses OR logic (matches any pattern in the array)
275
-
276
- Examples:
366
+ Examples:
277
367
  - service_name="api" + severity_filters=["error"] + body_filters=["timeout"] → finds error logs containing "timeout"
278
368
  - service_name="web" + body_filters=["timeout", "failed", "error 500"] → finds logs containing any of these patterns
279
369
 
280
370
  ### get_log_attributes
281
371
 
282
372
  Get available log attributes (labels) for a specified time window. This tool retrieves all attribute names that exist in logs during the specified time range, which can be used for filtering and querying logs.
283
-
284
373
  Parameters:
285
374
 
286
375
  - `lookback_minutes` (integer, optional): Number of minutes to look back from now for the time window. Default: 15. Examples: 15, 30, 60.
287
- - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to use lookback_minutes.
288
- - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
376
+ - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to use lookback_minutes.
377
+ - `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.
289
378
  - `region` (string, optional): AWS region to query. Leave empty to use default from configuration. Examples: ap-south-1, us-east-1, eu-west-1.
290
-
291
- Returns:
379
+ Returns:
292
380
  - List of log attributes grouped into two categories:
293
381
  - Log Attributes: Standard log fields like service, severity, body, level, etc.
294
- - Resource Attributes: Resource-related fields prefixed with "resource_" like resource_k8s.pod.name, resource_service.name, etc.
382
+ - Resource Attributes: Resource-related fields prefixed with "resource\_" like resource_k8s.pod.name, resource_service.name, etc.
295
383
 
296
384
  ### get_traces
297
385
 
298
- Retrieve traces from Last9 by trace ID or service name. This tool allows you to get specific traces either by providing a trace ID for a single trace, or by providing a service name to get all traces for that service within a time range.
386
+ Execute advanced trace queries using JSON pipeline syntax for complex filtering and aggregation. This tool provides powerful querying capabilities for traces using a pipeline-based approach with filters, aggregations, and transformations.
387
+ Parameters:
388
+
389
+ - `tracejson_query` (array, required): JSON pipeline query for traces. Use the tracejson_query_builder prompt to generate JSON pipeline queries from natural language.
390
+ - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z).
391
+ - `end_time_iso` (string, optional): End time in RFC3339/ISO8601 format (e.g. 2026-02-09T16:04:05Z).
392
+ - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60. Range: 1–20160 (14 days).
393
+ - `limit` (integer, optional): Maximum number of traces to return. Default: 20. Range: 1-100.
394
+ This tool supports complex queries with multiple filter conditions, aggregations, and custom processing pipelines for advanced trace analysis.
395
+
396
+ ### get_service_traces
299
397
 
398
+ Retrieve traces from Last9 by trace ID or service name. This tool allows you to get specific traces either by providing a trace ID for a single trace, or by providing a service name to get all traces for that service within a time range.
300
399
  Parameters:
301
400
 
302
401
  - `trace_id` (string, optional): Specific trace ID to retrieve. Cannot be used with service_name.
303
402
  - `service_name` (string, optional): Name of service to get traces for. Cannot be used with trace_id.
304
- - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60 minutes. Examples: 60, 30, 15.
305
- - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - lookback_minutes.
306
- - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
403
+ - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60. Range: 1–20160 (14 days). Examples: 60, 30, 15.
404
+ - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to use lookback_minutes.
405
+ - `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.
307
406
  - `limit` (integer, optional): Maximum number of traces to return. Default: 10. Range: 1-100.
308
407
  - `env` (string, optional): Environment to filter by. Use "get_service_environments" tool to get available environments.
309
-
310
- Usage rules:
408
+ Usage rules:
311
409
  - Exactly one of `trace_id` or `service_name` must be provided (not both, not neither)
312
410
  - Time range filtering only applies when using `service_name`
313
-
314
- Examples:
411
+ Examples:
315
412
  - trace_id="abc123def456" - retrieves the specific trace
316
413
  - service_name="payment-service" + lookback_minutes=30 - gets all payment service traces from last 30 minutes
317
-
318
- Returns trace data including trace IDs, spans, duration, timestamps, and status information.
319
-
320
- ### get_service_traces
321
-
322
- Query traces for a specific service with filtering options for span kinds, status codes, and other trace attributes. This tool retrieves distributed tracing data for debugging performance issues, understanding request flows, and analyzing service interactions.
323
-
324
- Parameters:
325
-
326
- - `service_name` (string, required): Name of the service to get traces for.
327
- - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60 minutes. Examples: 60, 30, 15.
328
- - `limit` (integer, optional): Maximum number of traces to return. Default: 10.
329
- - `env` (string, optional): Environment to filter by. Use "get_service_environments" tool to get available environments.
330
- - `span_kind` (array, optional): Filter by span types (server, client, internal, consumer, producer).
331
- - `span_name` (string, optional): Filter by specific span name.
332
- - `status_code` (array, optional): Filter by trace status (ok, error, unset, success).
333
- - `order` (string, optional): Field to order traces by. Default: "Duration". Options: Duration, Timestamp.
334
- - `direction` (string, optional): Sort direction. Default: "backward". Options: forward, backward.
335
- - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - lookback_minutes.
336
- - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
337
-
338
- Filtering options:
339
- - Combine multiple filters to narrow down specific traces of interest
340
- - Use time range filters with lookback_minutes or explicit start/end times
341
-
342
- Examples:
343
- - service_name="api" + span_kind=["server"] + status_code=["error"] → finds failed server-side traces
344
- - service_name="payment" + span_name="process_payment" + lookback_minutes=30 → finds payment processing traces from last 30 minutes
414
+ Returns trace data including trace IDs, spans, duration, timestamps, and status information.
345
415
 
346
416
  ### get_trace_attributes
347
417
 
348
418
  Get available trace attributes (series) for a specified time window. This tool retrieves all attribute names that exist in traces during the specified time range, which can be used for filtering and querying traces.
349
-
350
419
  Parameters:
351
420
 
352
421
  - `lookback_minutes` (integer, optional): Number of minutes to look back from now for the time window. Default: 15. Examples: 15, 30, 60.
353
- - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to use lookback_minutes.
354
- - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
422
+ - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to use lookback_minutes.
423
+ - `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.
355
424
  - `region` (string, optional): AWS region to query. Leave empty to use default from configuration. Examples: ap-south-1, us-east-1, eu-west-1.
356
-
357
- Returns:
425
+ Returns:
358
426
  - An alphabetically sorted list of all available trace attributes (e.g., http.method, http.status_code, db.name, resource_service.name, duration, etc.)
359
427
 
360
428
  ### get_change_events
361
429
 
362
430
  Get change events from the last9_change_events prometheus metric over a given time range. Returns change events that occurred in the specified time window, including deployments, configuration changes, and other system modifications.
363
-
364
431
  Parameters:
365
432
 
366
- - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - lookback_minutes.
367
- - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
368
- - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60 minutes. Examples: 60, 30, 15.
433
+ - `start_time_iso` (string, optional): Start time in RFC3339/ISO8601 format (e.g. 2026-02-09T15:04:05Z). Leave empty to default to now - lookback_minutes.
434
+ - `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.
435
+ - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60. Range: 1–20160 (14 days). Examples: 60, 30, 15.
369
436
  - `service` (string, optional): Name of the service to filter change events for.
370
437
  - `environment` (string, optional): Environment to filter by.
371
438
  - `event_name` (string, optional): Name of the change event to filter by (use available_event_names to see valid values).
372
-
373
- Returns:
439
+ Returns:
374
440
  - `available_event_names`: List of all available event types that can be used for filtering
375
441
  - `change_events`: Array of timeseries data with metric labels and timestamp-value pairs
376
442
  - `count`: Total number of change events returned
377
443
  - `time_range`: Start and end time of the query window
378
-
379
- Each change event includes:
444
+ Each change event includes:
380
445
  - `metric`: Map of metric labels (service_name, env, event_type, message, etc.)
381
446
  - `values`: Array of timestamp-value pairs representing the timeseries data
447
+ Common event types include: deployment, config_change, rollback, scale_up/scale_down, restart, upgrade/downgrade, maintenance, backup/restore, health_check, certificate, database.
448
+ Best practices:
382
449
 
383
- Common event types include: deployment, config_change, rollback, scale_up/scale_down, restart, upgrade/downgrade, maintenance, backup/restore, health_check, certificate, database.
384
-
385
- Best practices:
386
450
  1. First call without event_name to get available_event_names
387
451
  2. Use exact event name from available_event_names for the event_name parameter
388
452
  3. Combine with other filters (service, environment, time) for precise results
389
453
 
390
- ## Installation
391
-
392
- You can install and run the Last9 Observability MCP server in several ways:
393
-
394
- ### Local Installation
395
-
396
- For local development and traditional STDIO usage:
397
-
398
- #### Homebrew
399
-
400
- ```bash
401
- # Add the Last9 tap
402
- brew tap last9/tap
454
+ ## Configuration
403
455
 
404
- # Install the Last9 MCP CLI
405
- brew install last9-mcp
406
- ```
456
+ ### Managed HTTP transport (recommended)
407
457
 
408
- #### NPM
458
+ Set this header in your MCP client config:
409
459
 
410
- ```bash
411
- # Install globally
412
- npm install -g @last9/mcp-server
460
+ - `X-LAST9-API-TOKEN`: Bearer token for Last9 API access.
413
461
 
414
- # Or run directly with npx
415
- npx @last9/mcp-server
416
- ```
462
+ ### Local STDIO server environment variables
417
463
 
418
- ## Configuration
464
+ If you run the server locally (`last9-mcp`), use these environment variables:
419
465
 
420
- ### Environment Variables
466
+ - `LAST9_REFRESH_TOKEN`: (required) Refresh Token with Write permissions from
467
+ [API Access](https://app.last9.io/settings/api-access). Only admins can create
468
+ refresh tokens.
421
469
 
422
- The Last9 MCP server requires the following environment variables:
470
+ Optional environment variables:
423
471
 
424
- - `LAST9_BASE_URL`: (required) Last9 API URL from
425
- [OTel integration](https://app.last9.io/integrations?integration=OpenTelemetry)
426
- - `LAST9_AUTH_TOKEN`: (required) Authentication token for Last9 MCP server from
427
- [OTel integration](https://app.last9.io/integrations?integration=OpenTelemetry)
428
- - `LAST9_REFRESH_TOKEN`: (required) Refresh Token with Write permissions, needed
429
- for accessing control plane APIs from
430
- [API Access](https://app.last9.io/settings/api-access)
431
- - `OTEL_EXPORTER_OTLP_ENDPOINT`: (required) OpenTelemetry collector endpoint URL
432
- - `OTEL_EXPORTER_OTLP_HEADERS`: (required) Headers for OTLP exporter authentication
472
+ - `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.
473
+ - `OTEL_EXPORTER_OTLP_ENDPOINT`: OpenTelemetry collector endpoint URL. Only needed if `LAST9_DISABLE_TELEMETRY=false`.
474
+ - `OTEL_EXPORTER_OTLP_HEADERS`: Headers for OTLP exporter authentication. Only needed if `LAST9_DISABLE_TELEMETRY=false`.
475
+ - `LAST9_DATASOURCE`: Name of the datasource/cluster to use. If not specified, the default datasource configured in your Last9 organization will be used.
476
+ - `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).
433
477
 
434
478
  ## Usage
435
479
 
480
+ Use the managed HTTP transport config from [Installation](#installation) whenever possible. The examples below are for local STDIO setup via Homebrew or NPM.
481
+
436
482
  ## Usage with Claude Desktop
437
483
 
438
484
  Configure the Claude app to use the MCP server:
@@ -443,18 +489,23 @@ Configure the Claude app to use the MCP server:
443
489
  4. Copy and paste the server config to your existing file, then save
444
490
  5. Restart Claude
445
491
 
492
+ ### Local STDIO
493
+
494
+ > **Note:** Claude Desktop currently supports local STDIO-based MCP servers only. Hosted HTTP transport is not yet supported in Claude Desktop.
495
+
496
+ Use a [Refresh Token](#getting-your-credentials).
497
+
498
+ Install via [Homebrew](#homebrew) or [NPM](#npm) first, then use a [Refresh Token](#getting-your-credentials).
499
+
446
500
  ### If installed via Homebrew:
501
+
447
502
  ```json
448
503
  {
449
504
  "mcpServers": {
450
505
  "last9": {
451
506
  "command": "/opt/homebrew/bin/last9-mcp",
452
507
  "env": {
453
- "LAST9_BASE_URL": "<last9_otlp_host>",
454
- "LAST9_AUTH_TOKEN": "<last9_otlp_auth_token>",
455
- "LAST9_REFRESH_TOKEN": "<last9_write_refresh_token>",
456
- "OTEL_EXPORTER_OTLP_ENDPOINT": "<otel_endpoint_url>",
457
- "OTEL_EXPORTER_OTLP_HEADERS": "<otel_headers>"
508
+ "LAST9_REFRESH_TOKEN": "<last9_refresh_token>"
458
509
  }
459
510
  }
460
511
  }
@@ -462,18 +513,15 @@ Configure the Claude app to use the MCP server:
462
513
  ```
463
514
 
464
515
  ### If installed via NPM:
516
+
465
517
  ```json
466
518
  {
467
519
  "mcpServers": {
468
520
  "last9": {
469
521
  "command": "npx",
470
- "args": ["-y", "@last9/mcp-server"],
522
+ "args": ["-y", "@last9/mcp-server@latest"],
471
523
  "env": {
472
- "LAST9_BASE_URL": "<last9_otlp_host>",
473
- "LAST9_AUTH_TOKEN": "<last9_otlp_auth_token>",
474
- "LAST9_REFRESH_TOKEN": "<last9_write_refresh_token>",
475
- "OTEL_EXPORTER_OTLP_ENDPOINT": "<otel_endpoint_url>",
476
- "OTEL_EXPORTER_OTLP_HEADERS": "<otel_headers>"
524
+ "LAST9_REFRESH_TOKEN": "<last9_refresh_token>"
477
525
  }
478
526
  }
479
527
  }
@@ -490,18 +538,33 @@ Configure Cursor to use the MCP server:
490
538
  4. Copy and paste the server config to your existing file, then save
491
539
  5. Restart Cursor
492
540
 
541
+ ### Hosted MCP over HTTP (recommended)
542
+
543
+ ```json
544
+ {
545
+ "mcpServers": {
546
+ "last9": {
547
+ "type": "http",
548
+ "url": "https://app.last9.io/api/v4/organizations/<org_slug>/mcp",
549
+ "headers": {
550
+ "X-LAST9-API-TOKEN": "Bearer <mcp_client_token>"
551
+ }
552
+ }
553
+ }
554
+ }
555
+ ```
556
+
557
+ ### Local STDIO (alternative)
558
+
493
559
  ### If installed via Homebrew:
560
+
494
561
  ```json
495
562
  {
496
563
  "mcpServers": {
497
564
  "last9": {
498
565
  "command": "/opt/homebrew/bin/last9-mcp",
499
566
  "env": {
500
- "LAST9_BASE_URL": "<last9_otlp_host>",
501
- "LAST9_AUTH_TOKEN": "<last9_otlp_auth_token>",
502
- "LAST9_REFRESH_TOKEN": "<last9_write_refresh_token>",
503
- "OTEL_EXPORTER_OTLP_ENDPOINT": "<otel_endpoint_url>",
504
- "OTEL_EXPORTER_OTLP_HEADERS": "<otel_headers>"
567
+ "LAST9_REFRESH_TOKEN": "<last9_refresh_token>"
505
568
  }
506
569
  }
507
570
  }
@@ -509,18 +572,15 @@ Configure Cursor to use the MCP server:
509
572
  ```
510
573
 
511
574
  ### If installed via NPM:
575
+
512
576
  ```json
513
577
  {
514
578
  "mcpServers": {
515
579
  "last9": {
516
580
  "command": "npx",
517
- "args": ["-y", "@last9/mcp-server"],
581
+ "args": ["-y", "@last9/mcp-server@latest"],
518
582
  "env": {
519
- "LAST9_BASE_URL": "<last9_otlp_host>",
520
- "LAST9_AUTH_TOKEN": "<last9_otlp_auth_token>",
521
- "LAST9_REFRESH_TOKEN": "<last9_write_refresh_token>",
522
- "OTEL_EXPORTER_OTLP_ENDPOINT": "<otel_endpoint_url>",
523
- "OTEL_EXPORTER_OTLP_HEADERS": "<otel_headers>"
583
+ "LAST9_REFRESH_TOKEN": "<last9_refresh_token>"
524
584
  }
525
585
  }
526
586
  }
@@ -537,18 +597,33 @@ Configure Windsurf to use the MCP server:
537
597
  4. Copy and paste the server config to your existing file, then save
538
598
  5. Restart Windsurf
539
599
 
600
+ ### Hosted MCP over HTTP (recommended)
601
+
602
+ ```json
603
+ {
604
+ "mcpServers": {
605
+ "last9": {
606
+ "type": "http",
607
+ "url": "https://app.last9.io/api/v4/organizations/<org_slug>/mcp",
608
+ "headers": {
609
+ "X-LAST9-API-TOKEN": "Bearer <mcp_client_token>"
610
+ }
611
+ }
612
+ }
613
+ }
614
+ ```
615
+
616
+ ### Local STDIO (alternative)
617
+
540
618
  ### If installed via Homebrew:
619
+
541
620
  ```json
542
621
  {
543
622
  "mcpServers": {
544
623
  "last9": {
545
624
  "command": "/opt/homebrew/bin/last9-mcp",
546
625
  "env": {
547
- "LAST9_BASE_URL": "<last9_otlp_host>",
548
- "LAST9_AUTH_TOKEN": "<last9_otlp_auth_token>",
549
- "LAST9_REFRESH_TOKEN": "<last9_write_refresh_token>",
550
- "OTEL_EXPORTER_OTLP_ENDPOINT": "<otel_endpoint_url>",
551
- "OTEL_EXPORTER_OTLP_HEADERS": "<otel_headers>"
626
+ "LAST9_REFRESH_TOKEN": "<last9_refresh_token>"
552
627
  }
553
628
  }
554
629
  }
@@ -556,18 +631,15 @@ Configure Windsurf to use the MCP server:
556
631
  ```
557
632
 
558
633
  ### If installed via NPM:
634
+
559
635
  ```json
560
636
  {
561
637
  "mcpServers": {
562
638
  "last9": {
563
639
  "command": "npx",
564
- "args": ["-y", "@last9/mcp-server"],
640
+ "args": ["-y", "@last9/mcp-server@latest"],
565
641
  "env": {
566
- "LAST9_BASE_URL": "<last9_otlp_host>",
567
- "LAST9_AUTH_TOKEN": "<last9_otlp_auth_token>",
568
- "LAST9_REFRESH_TOKEN": "<last9_write_refresh_token>",
569
- "OTEL_EXPORTER_OTLP_ENDPOINT": "<otel_endpoint_url>",
570
- "OTEL_EXPORTER_OTLP_HEADERS": "<otel_headers>"
642
+ "LAST9_REFRESH_TOKEN": "<last9_refresh_token>"
571
643
  }
572
644
  }
573
645
  }
@@ -585,7 +657,28 @@ Configure Windsurf to use the MCP server:
585
657
  3. Copy and paste the server config to your existing file, then save
586
658
  4. Restart VS Code
587
659
 
660
+ ### Hosted MCP over HTTP (recommended)
661
+
662
+ ```json
663
+ {
664
+ "mcp": {
665
+ "servers": {
666
+ "last9": {
667
+ "type": "http",
668
+ "url": "https://app.last9.io/api/v4/organizations/<org_slug>/mcp",
669
+ "headers": {
670
+ "X-LAST9-API-TOKEN": "Bearer <mcp_client_token>"
671
+ }
672
+ }
673
+ }
674
+ }
675
+ }
676
+ ```
677
+
678
+ ### Local STDIO (alternative)
679
+
588
680
  ### If installed via Homebrew:
681
+
589
682
  ```json
590
683
  {
591
684
  "mcp": {
@@ -594,11 +687,7 @@ Configure Windsurf to use the MCP server:
594
687
  "type": "stdio",
595
688
  "command": "/opt/homebrew/bin/last9-mcp",
596
689
  "env": {
597
- "LAST9_BASE_URL": "<last9_otlp_host>",
598
- "LAST9_AUTH_TOKEN": "<last9_otlp_auth_token>",
599
- "LAST9_REFRESH_TOKEN": "<last9_write_refresh_token>",
600
- "OTEL_EXPORTER_OTLP_ENDPOINT": "<otel_endpoint_url>",
601
- "OTEL_EXPORTER_OTLP_HEADERS": "<otel_headers>"
690
+ "LAST9_REFRESH_TOKEN": "<last9_refresh_token>"
602
691
  }
603
692
  }
604
693
  }
@@ -607,6 +696,7 @@ Configure Windsurf to use the MCP server:
607
696
  ```
608
697
 
609
698
  ### If installed via NPM:
699
+
610
700
  ```json
611
701
  {
612
702
  "mcp": {
@@ -614,13 +704,9 @@ Configure Windsurf to use the MCP server:
614
704
  "last9": {
615
705
  "type": "stdio",
616
706
  "command": "npx",
617
- "args": ["-y", "@last9/mcp-server"],
707
+ "args": ["-y", "@last9/mcp-server@latest"],
618
708
  "env": {
619
- "LAST9_BASE_URL": "<last9_otlp_host>",
620
- "LAST9_AUTH_TOKEN": "<last9_otlp_auth_token>",
621
- "LAST9_REFRESH_TOKEN": "<last9_write_refresh_token>",
622
- "OTEL_EXPORTER_OTLP_ENDPOINT": "<otel_endpoint_url>",
623
- "OTEL_EXPORTER_OTLP_HEADERS": "<otel_headers>"
709
+ "LAST9_REFRESH_TOKEN": "<last9_refresh_token>"
624
710
  }
625
711
  }
626
712
  }
@@ -628,23 +714,38 @@ Configure Windsurf to use the MCP server:
628
714
  }
629
715
  ```
630
716
 
717
+ ## Windows Example (Claude Desktop)
718
+
719
+ 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:
720
+
721
+ ```json
722
+ {
723
+ "mcpServers": {
724
+ "last9": {
725
+ "command": "C:\\Users\\<user>\\AppData\\Local\\Programs\\last9-mcp-server.exe",
726
+ "env": {
727
+ "LAST9_REFRESH_TOKEN": "<last9_refresh_token>"
728
+ }
729
+ }
730
+ }
731
+ }
732
+ ```
733
+
734
+ 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.
735
+
631
736
  ## Development
632
737
 
633
738
  For local development and testing, you can run the MCP server in HTTP mode which makes it easier to debug requests and responses.
634
739
 
635
740
  ### Running in HTTP Mode
636
741
 
637
- Set the `HTTP_MODE` environment variable to enable HTTP server mode:
742
+ Set the `LAST9_HTTP` environment variable to enable HTTP server mode:
638
743
 
639
744
  ```bash
640
745
  # Export required environment variables
641
- export LAST9_API_TOKEN="your_api_token"
642
- export LAST9_BASE_URL="https://your-last9-endpoint" # Your Last9 endpoint
643
- export OTEL_EXPORTER_OTLP_ENDPOINT="<otel_endpoint_url>"
644
- export OTEL_EXPORTER_OTLP_HEADERS="<otel_headers>"
645
- export HTTP_MODE=true
646
- export HTTP_PORT=8080 # Optional, defaults to 8080
647
-
746
+ export LAST9_REFRESH_TOKEN="your_refresh_token"
747
+ export LAST9_HTTP=true
748
+ export LAST9_PORT=8080 # Optional, defaults to 8080
648
749
  # Run the server
649
750
  ./last9-mcp-server
650
751
  ```
@@ -653,53 +754,54 @@ The server will start on `http://localhost:8080/mcp` and you can test it with cu
653
754
 
654
755
  ### Testing with curl
655
756
 
757
+ 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.
758
+
656
759
  ```bash
657
- # Test get_service_logs
658
- curl -X POST http://localhost:8080/mcp \
760
+ # Step 1: Initialize — omit Mcp-Session-Id so the server creates the session.
761
+ # Extract the returned Mcp-Session-Id from the response headers.
762
+ SESSION_ID=$(curl -si -X POST http://localhost:8080/mcp \
659
763
  -H "Content-Type: application/json" \
660
- -H "Mcp-Session-Id: session_$(date +%s)000000000" \
661
764
  -d '{
662
765
  "jsonrpc": "2.0",
663
766
  "id": 1,
664
- "method": "tools/call",
767
+ "method": "initialize",
665
768
  "params": {
666
- "name": "get_service_logs",
667
- "arguments": {
668
- "service_name": "your-service-name",
669
- "lookback_minutes": 30,
670
- "limit": 10
671
- }
769
+ "protocolVersion": "2024-11-05",
770
+ "capabilities": {},
771
+ "clientInfo": {"name": "curl-test", "version": "1.0"}
672
772
  }
673
- }'
773
+ }' | grep -i "^Mcp-Session-Id:" | awk '{print $2}' | tr -d '\r')
774
+ echo "Session: $SESSION_ID"
775
+
776
+ # Step 2: Send the initialized notification
777
+ curl -s -X POST http://localhost:8080/mcp \
778
+ -H "Content-Type: application/json" \
779
+ -H "Mcp-Session-Id: $SESSION_ID" \
780
+ -d '{"jsonrpc": "2.0", "method": "notifications/initialized", "params": {}}'
674
781
 
675
- # Test get_service_traces
676
- curl -X POST http://localhost:8080/mcp \
782
+ # Step 3: List available tools
783
+ curl -s -X POST http://localhost:8080/mcp \
677
784
  -H "Content-Type: application/json" \
678
- -H "Mcp-Session-Id: session_$(date +%s)000000000" \
785
+ -H "Mcp-Session-Id: $SESSION_ID" \
786
+ -d '{"jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {}}'
787
+
788
+ # Step 4: Call a tool
789
+ curl -s -X POST http://localhost:8080/mcp \
790
+ -H "Content-Type: application/json" \
791
+ -H "Mcp-Session-Id: $SESSION_ID" \
679
792
  -d '{
680
793
  "jsonrpc": "2.0",
681
- "id": 2,
794
+ "id": 3,
682
795
  "method": "tools/call",
683
796
  "params": {
684
- "name": "get_service_traces",
797
+ "name": "get_service_logs",
685
798
  "arguments": {
686
799
  "service_name": "your-service-name",
687
- "lookback_minutes": 60,
688
- "limit": 5
800
+ "lookback_minutes": 30,
801
+ "limit": 10
689
802
  }
690
803
  }
691
804
  }'
692
-
693
- # List available tools
694
- curl -X POST http://localhost:8080/mcp \
695
- -H "Content-Type: application/json" \
696
- -H "Mcp-Session-Id: session_$(date +%s)000000000" \
697
- -d '{
698
- "jsonrpc": "2.0",
699
- "id": 3,
700
- "method": "tools/list",
701
- "params": {}
702
- }'
703
805
  ```
704
806
 
705
807
  ### Building from Source
@@ -708,15 +810,17 @@ curl -X POST http://localhost:8080/mcp \
708
810
  # Clone the repository
709
811
  git clone https://github.com/last9/last9-mcp-server.git
710
812
  cd last9-mcp-server
711
-
712
813
  # Build the binary
713
814
  go build -o last9-mcp-server
714
-
715
815
  # Run in development mode
716
- HTTP_MODE=true ./last9-mcp-server
816
+ LAST9_HTTP=true ./last9-mcp-server
717
817
  ```
718
818
 
719
- **Note**: HTTP mode is for development and testing only. When integrating with Claude Desktop or other MCP clients, use the default STDIO mode (without `HTTP_MODE=true`).
819
+ **Note**: `LAST9_HTTP=true` is for local development and debugging of your own server process. For normal client integration, prefer the managed HTTP endpoint from [Installation](#installation).
820
+
821
+ ## Testing
822
+
823
+ See [TESTING.md](TESTING.md) for detailed testing instructions.
720
824
 
721
825
  ## Badges
722
826