@last9/mcp-server 0.1.11 → 0.1.13

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/LICENSE CHANGED
@@ -186,7 +186,7 @@
186
186
  same "printed page" as the copyright notice for easier
187
187
  identification within third-party archives.
188
188
 
189
- Copyright [yyyy] [name of copyright owner]
189
+ Copyright 2024-present Last9
190
190
 
191
191
  Licensed under the Apache License, Version 2.0 (the "License");
192
192
  you may not use this file except in compliance with the License.
package/README.md CHANGED
@@ -18,6 +18,7 @@ IDEs. Implements the following MCP
18
18
  [tools](https://modelcontextprotocol.io/docs/concepts/tools):
19
19
 
20
20
  **Observability & APM Tools:**
21
+
21
22
  - `get_exceptions`: Get the list of exceptions.
22
23
  - `get_service_summary`: Get service summary with throughput, error rate, and response time.
23
24
  - `get_service_environments`: Get available environments for services.
@@ -26,19 +27,27 @@ IDEs. Implements the following MCP
26
27
  - `get_service_dependency_graph`: Get service dependency graph showing incoming/outgoing dependencies.
27
28
 
28
29
  **Prometheus/PromQL Tools:**
30
+
29
31
  - `promptheus_range_query`: Execute PromQL range queries for metrics data.
30
32
  - `prometheus_instant_query`: Execute PromQL instant queries for metrics data.
31
33
  - `prometheus_label_values`: Get label values for PromQL queries.
32
34
  - `prometheus_labels`: Get available labels for PromQL queries.
33
35
 
34
36
  **Logs Management:**
37
+
35
38
  - `get_logs`: Get logs filtered by service name and/or severity level.
36
39
  - `get_drop_rules`: Get drop rules for logs that determine what logs get
37
40
  filtered out at [Last9 Control Plane](https://last9.io/control-plane)
38
41
  - `add_drop_rule`: Create a drop rule for logs at
39
42
  [Last9 Control Plane](https://last9.io/control-plane)
43
+ - `get_service_logs`: Get raw log entries for a specific service over a time range. Can apply filters on severity and body.
44
+
45
+ **Traces Management:**
46
+
47
+ - `get_service_traces`: Query traces for a specific service with filtering options for span kinds, status codes, and other trace attributes.
40
48
 
41
49
  **Alert Management:**
50
+
42
51
  - `get_alert_config`: Get alert configurations (alert rules) from Last9.
43
52
  - `get_alerts`: Get currently active alerts from Last9 monitoring system.
44
53
 
@@ -156,20 +165,19 @@ Parameters:
156
165
 
157
166
  ### get_logs
158
167
 
159
- Gets logs filtered by optional service name and/or severity level within a
160
- specified time range.
168
+ 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.
169
+
170
+ **Note**: This tool now requires a `service_name` parameter and internally uses the same advanced infrastructure as `get_service_logs`.
161
171
 
162
172
  Parameters:
163
173
 
164
- - `service` (string, optional): Name of the service to get logs for.
165
- - `severity` (string, optional): Severity of the logs to get.
166
- - `lookback_minutes` (integer, recommended): Number of minutes to look back from
167
- now. Default: 60. Examples: 60, 30, 15.
168
- - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD
169
- HH:MM:SS). Leave empty to use lookback_minutes.
170
- - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD
171
- HH:MM:SS). Leave empty to default to current time.
174
+ - `service_name` (string, required): Name of the service to get logs for.
175
+ - `severity` (string, optional): Severity of the logs to get (automatically converted to severity_filters format).
176
+ - `lookback_minutes` (integer, recommended): Number of minutes to look back from now. Default: 60. Examples: 60, 30, 15.
177
+ - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to use lookback_minutes.
178
+ - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
172
179
  - `limit` (integer, optional): Maximum number of logs to return. Default: 20.
180
+ - `env` (string, optional): Environment to filter by. Use "get_service_environments" tool to get available environments.
173
181
 
174
182
  ### get_drop_rules
175
183
 
@@ -237,13 +245,62 @@ Returns information about:
237
245
  - Metric degradation information
238
246
  - Group labels and annotations for each instance
239
247
 
248
+ ### get_service_logs
249
+
250
+ 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.
251
+
252
+ Parameters:
253
+
254
+ - `service_name` (string, required): Name of the service to get logs for.
255
+ - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60 minutes. Examples: 60, 30, 15.
256
+ - `limit` (integer, optional): Maximum number of log entries to return. Default: 20.
257
+ - `env` (string, optional): Environment to filter by. Use "get_service_environments" tool to get available environments.
258
+ - `severity_filters` (array, optional): Array of severity patterns to filter logs (e.g., ["error", "warn"]). Uses OR logic.
259
+ - `body_filters` (array, optional): Array of message content patterns to filter logs (e.g., ["timeout", "failed"]). Uses OR logic.
260
+ - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - lookback_minutes.
261
+ - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
262
+
263
+ Filtering behavior:
264
+ - Multiple filter types are combined with AND logic (service AND severity AND body)
265
+ - Each filter array uses OR logic (matches any pattern in the array)
266
+
267
+ Examples:
268
+ - service_name="api" + severity_filters=["error"] + body_filters=["timeout"] → finds error logs containing "timeout"
269
+ - service_name="web" + body_filters=["timeout", "failed", "error 500"] → finds logs containing any of these patterns
270
+
271
+ ### get_service_traces
272
+
273
+ 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.
274
+
275
+ Parameters:
276
+
277
+ - `service_name` (string, required): Name of the service to get traces for.
278
+ - `lookback_minutes` (integer, optional): Number of minutes to look back from now. Default: 60 minutes. Examples: 60, 30, 15.
279
+ - `limit` (integer, optional): Maximum number of traces to return. Default: 10.
280
+ - `env` (string, optional): Environment to filter by. Use "get_service_environments" tool to get available environments.
281
+ - `span_kind` (array, optional): Filter by span types (server, client, internal, consumer, producer).
282
+ - `span_name` (string, optional): Filter by specific span name.
283
+ - `status_code` (array, optional): Filter by trace status (ok, error, unset, success).
284
+ - `order` (string, optional): Field to order traces by. Default: "Duration". Options: Duration, Timestamp.
285
+ - `direction` (string, optional): Sort direction. Default: "backward". Options: forward, backward.
286
+ - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - lookback_minutes.
287
+ - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
288
+
289
+ Filtering options:
290
+ - Combine multiple filters to narrow down specific traces of interest
291
+ - Use time range filters with lookback_minutes or explicit start/end times
292
+
293
+ Examples:
294
+ - service_name="api" + span_kind=["server"] + status_code=["error"] → finds failed server-side traces
295
+ - service_name="payment" + span_name="process_payment" + lookback_minutes=30 → finds payment processing traces from last 30 minutes
296
+
240
297
  ## Installation
241
298
 
242
299
  You can install the Last9 Observability MCP server using either:
243
300
 
244
301
  ### Homebrew
245
302
 
246
- ```
303
+ ```bash
247
304
  # Add the Last9 tap
248
305
  brew tap last9/tap
249
306
 
@@ -285,6 +342,7 @@ Configure the Claude app to use the MCP server:
285
342
  4. Copy and paste the server config to your existing file, then save
286
343
  5. Restart Claude
287
344
 
345
+ ### If installed via Homebrew:
288
346
  ```json
289
347
  {
290
348
  "mcpServers": {
@@ -300,6 +358,23 @@ Configure the Claude app to use the MCP server:
300
358
  }
301
359
  ```
302
360
 
361
+ ### If installed via NPM:
362
+ ```json
363
+ {
364
+ "mcpServers": {
365
+ "last9": {
366
+ "command": "npx",
367
+ "args": ["-y", "@last9/mcp-server"],
368
+ "env": {
369
+ "LAST9_BASE_URL": "<last9_otlp_host>",
370
+ "LAST9_AUTH_TOKEN": "<last9_otlp_auth_token>",
371
+ "LAST9_REFRESH_TOKEN": "<last9_write_refresh_token>"
372
+ }
373
+ }
374
+ }
375
+ }
376
+ ```
377
+
303
378
  ## Usage with Cursor
304
379
 
305
380
  Configure Cursor to use the MCP server:
@@ -310,6 +385,7 @@ Configure Cursor to use the MCP server:
310
385
  4. Copy and paste the server config to your existing file, then save
311
386
  5. Restart Cursor
312
387
 
388
+ ### If installed via Homebrew:
313
389
  ```json
314
390
  {
315
391
  "mcpServers": {
@@ -325,6 +401,23 @@ Configure Cursor to use the MCP server:
325
401
  }
326
402
  ```
327
403
 
404
+ ### If installed via NPM:
405
+ ```json
406
+ {
407
+ "mcpServers": {
408
+ "last9": {
409
+ "command": "npx",
410
+ "args": ["-y", "@last9/mcp-server"],
411
+ "env": {
412
+ "LAST9_BASE_URL": "<last9_otlp_host>",
413
+ "LAST9_AUTH_TOKEN": "<last9_otlp_auth_token>",
414
+ "LAST9_REFRESH_TOKEN": "<last9_write_refresh_token>"
415
+ }
416
+ }
417
+ }
418
+ }
419
+ ```
420
+
328
421
  ## Usage with Windsurf
329
422
 
330
423
  Configure Windsurf to use the MCP server:
@@ -335,6 +428,7 @@ Configure Windsurf to use the MCP server:
335
428
  4. Copy and paste the server config to your existing file, then save
336
429
  5. Restart Windsurf
337
430
 
431
+ ### If installed via Homebrew:
338
432
  ```json
339
433
  {
340
434
  "mcpServers": {
@@ -350,17 +444,35 @@ Configure Windsurf to use the MCP server:
350
444
  }
351
445
  ```
352
446
 
447
+ ### If installed via NPM:
448
+ ```json
449
+ {
450
+ "mcpServers": {
451
+ "last9": {
452
+ "command": "npx",
453
+ "args": ["-y", "@last9/mcp-server"],
454
+ "env": {
455
+ "LAST9_BASE_URL": "<last9_otlp_host>",
456
+ "LAST9_AUTH_TOKEN": "<last9_otlp_auth_token>",
457
+ "LAST9_REFRESH_TOKEN": "<last9_write_refresh_token>"
458
+ }
459
+ }
460
+ }
461
+ }
462
+ ```
463
+
353
464
  ## Usage with VS Code
354
465
 
355
466
  > Note: MCP support in VS Code is available starting v1.99 and is currently in
356
467
  > preview. For advanced configuration options and alternative setup methods,
357
468
  > [view the VS Code MCP documentation](https://code.visualstudio.com/docs/copilot/chat/mcp-servers).
358
469
 
359
- 1. Open VS Code, go to Settings, select the User tab, then Features, then Chat
360
- 2. Click "Edit settings.json"
361
- 3. Copy and paste the server config to your existing file, then save
362
- 4. Restart VS Code
470
+ 1. Open VS Code, go to Settings, select the User tab, then Features, then Chat
471
+ 2. Click "Edit settings.json"
472
+ 3. Copy and paste the server config to your existing file, then save
473
+ 4. Restart VS Code
363
474
 
475
+ ### If installed via Homebrew:
364
476
  ```json
365
477
  {
366
478
  "mcp": {
@@ -379,6 +491,114 @@ Configure Windsurf to use the MCP server:
379
491
  }
380
492
  ```
381
493
 
494
+ ### If installed via NPM:
495
+ ```json
496
+ {
497
+ "mcp": {
498
+ "servers": {
499
+ "last9": {
500
+ "type": "stdio",
501
+ "command": "npx",
502
+ "args": ["-y", "@last9/mcp-server"],
503
+ "env": {
504
+ "LAST9_BASE_URL": "<last9_otlp_host>",
505
+ "LAST9_AUTH_TOKEN": "<last9_otlp_auth_token>",
506
+ "LAST9_REFRESH_TOKEN": "<last9_write_refresh_token>"
507
+ }
508
+ }
509
+ }
510
+ }
511
+ }
512
+ ```
513
+
514
+ ## Development
515
+
516
+ For local development and testing, you can run the MCP server in HTTP mode which makes it easier to debug requests and responses.
517
+
518
+ ### Running in HTTP Mode
519
+
520
+ Set the `HTTP_MODE` environment variable to enable HTTP server mode:
521
+
522
+ ```bash
523
+ # Export required environment variables
524
+ export LAST9_API_TOKEN="your_api_token"
525
+ export LAST9_BASE_URL="https://your-last9-endpoint" # Your Last9 endpoint
526
+ export HTTP_MODE=true
527
+ export HTTP_PORT=8080 # Optional, defaults to 8080
528
+
529
+ # Run the server
530
+ ./last9-mcp-server
531
+ ```
532
+
533
+ The server will start on `http://localhost:8080/mcp` and you can test it with curl:
534
+
535
+ ### Testing with curl
536
+
537
+ ```bash
538
+ # Test get_service_logs
539
+ curl -X POST http://localhost:8080/mcp \
540
+ -H "Content-Type: application/json" \
541
+ -H "Mcp-Session-Id: session_$(date +%s)000000000" \
542
+ -d '{
543
+ "jsonrpc": "2.0",
544
+ "id": 1,
545
+ "method": "tools/call",
546
+ "params": {
547
+ "name": "get_service_logs",
548
+ "arguments": {
549
+ "service_name": "your-service-name",
550
+ "lookback_minutes": 30,
551
+ "limit": 10
552
+ }
553
+ }
554
+ }'
555
+
556
+ # Test get_service_traces
557
+ curl -X POST http://localhost:8080/mcp \
558
+ -H "Content-Type: application/json" \
559
+ -H "Mcp-Session-Id: session_$(date +%s)000000000" \
560
+ -d '{
561
+ "jsonrpc": "2.0",
562
+ "id": 2,
563
+ "method": "tools/call",
564
+ "params": {
565
+ "name": "get_service_traces",
566
+ "arguments": {
567
+ "service_name": "your-service-name",
568
+ "lookback_minutes": 60,
569
+ "limit": 5
570
+ }
571
+ }
572
+ }'
573
+
574
+ # List available tools
575
+ curl -X POST http://localhost:8080/mcp \
576
+ -H "Content-Type: application/json" \
577
+ -H "Mcp-Session-Id: session_$(date +%s)000000000" \
578
+ -d '{
579
+ "jsonrpc": "2.0",
580
+ "id": 3,
581
+ "method": "tools/list",
582
+ "params": {}
583
+ }'
584
+ ```
585
+
586
+ ### Building from Source
587
+
588
+ ```bash
589
+ # Clone the repository
590
+ git clone https://github.com/last9/last9-mcp-server.git
591
+ cd last9-mcp-server
592
+
593
+ # Build the binary
594
+ go build -o last9-mcp-server
595
+
596
+ # Run in development mode
597
+ HTTP_MODE=true ./last9-mcp-server
598
+ ```
599
+
600
+ **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`).
601
+
382
602
  ## Badges
383
603
 
384
604
  [![MseeP.ai Security Assessment Badge](https://mseep.net/pr/last9-last9-mcp-server-badge.png)](https://mseep.ai/app/last9-last9-mcp-server)
@@ -1,7 +1,8 @@
1
1
  const https = require('https');
2
2
  const fs = require('fs');
3
3
  const path = require('path');
4
- const { execSync } = require('child_process');
4
+ const { execSync, execFileSync } = require('child_process');
5
+ const os = require('os');
5
6
 
6
7
  // Get version from package.json
7
8
  const version = require('../package.json').version;
@@ -34,9 +35,11 @@ if (!fs.existsSync(distDir)) {
34
35
  const downloadUrl = `https://github.com/last9/last9-mcp-server/releases/download/v${version}/last9-mcp-server_${osMap[platform]}_${archMap[arch]}${platform === 'win32' ? '.zip' : '.tar.gz'}`;
35
36
 
36
37
  console.log(`Downloading from: ${downloadUrl}`);
37
- console.log(`Saving to: ${binaryPath}`);
38
+ console.log(`Extracting to: ${binaryPath}`);
38
39
 
39
- const file = fs.createWriteStream(binaryPath);
40
+ // Create temporary file for the archive
41
+ const tempArchivePath = path.join(os.tmpdir(), `last9-mcp-server-${Date.now()}${platform === 'win32' ? '.zip' : '.tar.gz'}`);
42
+ const file = fs.createWriteStream(tempArchivePath);
40
43
 
41
44
  const download = (url) => {
42
45
  return new Promise((resolve, reject) => {
@@ -59,22 +62,36 @@ const download = (url) => {
59
62
  file.on('finish', () => {
60
63
  file.close();
61
64
  console.log('Download completed');
62
-
63
- // Make binary executable on Unix-like systems
64
- if (platform !== 'win32') {
65
- try {
66
- execSync(`chmod +x ${binaryPath}`);
65
+
66
+ // Extract the archive
67
+ try {
68
+ if (platform === 'win32') {
69
+ // Extract zip file (requires unzip or similar)
70
+ execSync(`cd "${distDir}" && unzip -o "${tempArchivePath}"`);
71
+ } else {
72
+ // Extract tar.gz file
73
+ execSync(`tar -xzf "${tempArchivePath}" -C "${distDir}"`);
74
+ }
75
+ console.log('Archive extracted');
76
+
77
+ // Clean up temporary file
78
+ fs.unlinkSync(tempArchivePath);
79
+
80
+ // Make binary executable on Unix-like systems
81
+ if (platform !== 'win32') {
82
+ execFileSync('chmod', ['+x', binaryPath]);
67
83
  console.log('Made binary executable');
68
- } catch (err) {
69
- reject(new Error(`Failed to make binary executable: ${err.message}`));
70
- return;
71
84
  }
85
+
86
+ resolve();
87
+ } catch (err) {
88
+ // Clean up on error
89
+ try { fs.unlinkSync(tempArchivePath); } catch {}
90
+ reject(new Error(`Failed to extract or setup binary: ${err.message}`));
72
91
  }
73
-
74
- resolve();
75
92
  });
76
93
  }).on('error', (err) => {
77
- fs.unlink(binaryPath, () => {}); // Delete the file async
94
+ fs.unlink(tempArchivePath, () => {}); // Delete the temp file async
78
95
  reject(new Error(`Download failed: ${err.message}`));
79
96
  });
80
97
  });
package/dist/LICENSE ADDED
@@ -0,0 +1,201 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "[]"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright [yyyy] [name of copyright owner]
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
package/dist/README.md ADDED
@@ -0,0 +1,384 @@
1
+ # Last9 MCP Server
2
+
3
+ ![last9 mcp demo](mcp-demo.gif)
4
+
5
+ A [Model Context Protocol](https://modelcontextprotocol.io/) server
6
+ implementation for [Last9](https://last9.io/mcp/) that enables AI agents to
7
+ seamlessly bring real-time production context — logs, metrics, and traces — into
8
+ your local environment to auto-fix code faster.
9
+
10
+ - [View demo](https://www.youtube.com/watch?v=AQH5xq6qzjI)
11
+ - Read our
12
+ [announcement blog post](https://last9.io/blog/launching-last9-mcp-server/)
13
+
14
+ ## Status
15
+
16
+ Works with Claude desktop app, or Cursor, Windsurf, and VSCode (Github Copilot)
17
+ IDEs. Implements the following MCP
18
+ [tools](https://modelcontextprotocol.io/docs/concepts/tools):
19
+
20
+ **Observability & APM Tools:**
21
+ - `get_exceptions`: Get the list of exceptions.
22
+ - `get_service_summary`: Get service summary with throughput, error rate, and response time.
23
+ - `get_service_environments`: Get available environments for services.
24
+ - `get_service_performance_details`: Get detailed performance metrics for a service.
25
+ - `get_service_operations_summary`: Get operations summary for a service.
26
+ - `get_service_dependency_graph`: Get service dependency graph showing incoming/outgoing dependencies.
27
+
28
+ **Prometheus/PromQL Tools:**
29
+ - `promptheus_range_query`: Execute PromQL range queries for metrics data.
30
+ - `prometheus_instant_query`: Execute PromQL instant queries for metrics data.
31
+ - `prometheus_label_values`: Get label values for PromQL queries.
32
+ - `prometheus_labels`: Get available labels for PromQL queries.
33
+
34
+ **Logs Management:**
35
+ - `get_logs`: Get logs filtered by service name and/or severity level.
36
+ - `get_drop_rules`: Get drop rules for logs that determine what logs get
37
+ filtered out at [Last9 Control Plane](https://last9.io/control-plane)
38
+ - `add_drop_rule`: Create a drop rule for logs at
39
+ [Last9 Control Plane](https://last9.io/control-plane)
40
+
41
+ **Alert Management:**
42
+ - `get_alert_config`: Get alert configurations (alert rules) from Last9.
43
+ - `get_alerts`: Get currently active alerts from Last9 monitoring system.
44
+
45
+ ## Tools Documentation
46
+
47
+ ### get_exceptions
48
+
49
+ Retrieves server-side exceptions over a specified time range.
50
+
51
+ Parameters:
52
+
53
+ - `limit` (integer, optional): Maximum number of exceptions to return.
54
+ Default: 20.
55
+ - `lookback_minutes` (integer, recommended): Number of minutes to look back from
56
+ now. Default: 60. Examples: 60, 30, 15.
57
+ - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD
58
+ HH:MM:SS). Leave empty to use lookback_minutes.
59
+ - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD
60
+ HH:MM:SS). Leave empty to default to current time.
61
+ - `span_name` (string, optional): Name of the span to filter by.
62
+
63
+ ### get_service_summary
64
+
65
+ 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.
66
+
67
+ Parameters:
68
+
69
+ - `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.
70
+ - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
71
+ - `env` (string, optional): Environment to filter by. Defaults to 'prod'.
72
+
73
+ ### get_service_environments
74
+
75
+ Get available environments for services. Returns an array of environments that can be used with other APM tools.
76
+
77
+ Parameters:
78
+
79
+ - `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.
80
+ - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
81
+
82
+ 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.
83
+
84
+ ### get_service_performance_details
85
+
86
+ Get detailed performance metrics for a specific service over a given time range.
87
+
88
+ Parameters:
89
+
90
+ - `service_name` (string, required): Name of the service to get performance details for.
91
+ - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - 60 minutes.
92
+ - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
93
+ - `env` (string, optional): Environment to filter by. Defaults to 'prod'.
94
+
95
+ ### get_service_operations_summary
96
+
97
+ 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.
98
+
99
+ Parameters:
100
+
101
+ - `service_name` (string, required): Name of the service to get operations summary for.
102
+ - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - 60 minutes.
103
+ - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
104
+ - `env` (string, optional): Environment to filter by. Defaults to 'prod'.
105
+
106
+ ### get_service_dependency_graph
107
+
108
+ 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.
109
+
110
+ Parameters:
111
+
112
+ - `service_name` (string, optional): Name of the service to get the dependency graph for.
113
+ - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - 60 minutes.
114
+ - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
115
+ - `env` (string, optional): Environment to filter by. Defaults to 'prod'.
116
+
117
+ ### promptheus_range_query
118
+
119
+ Perform a Prometheus range query to get metrics data over a specified time range. Recommended to check available labels first using `prometheus_labels` tool.
120
+
121
+ Parameters:
122
+
123
+ - `query` (string, required): The range query to execute.
124
+ - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - 60 minutes.
125
+ - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
126
+
127
+ ### prometheus_instant_query
128
+
129
+ 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.
130
+
131
+ Parameters:
132
+
133
+ - `query` (string, required): The instant query to execute.
134
+ - `time_iso` (string, optional): Time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
135
+
136
+ ### prometheus_label_values
137
+
138
+ Return the label values for a particular label and PromQL filter query. Similar to Prometheus /label_values call.
139
+
140
+ Parameters:
141
+
142
+ - `match_query` (string, required): A valid PromQL filter query.
143
+ - `label` (string, required): The label to get values for.
144
+ - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - 60 minutes.
145
+ - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
146
+
147
+ ### prometheus_labels
148
+
149
+ Return the labels for a given PromQL match query. Similar to Prometheus /labels call.
150
+
151
+ Parameters:
152
+
153
+ - `match_query` (string, required): A valid PromQL filter query.
154
+ - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to now - 60 minutes.
155
+ - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD HH:MM:SS). Leave empty to default to current time.
156
+
157
+ ### get_logs
158
+
159
+ Gets logs filtered by optional service name and/or severity level within a
160
+ specified time range.
161
+
162
+ Parameters:
163
+
164
+ - `service` (string, optional): Name of the service to get logs for.
165
+ - `severity` (string, optional): Severity of the logs to get.
166
+ - `lookback_minutes` (integer, recommended): Number of minutes to look back from
167
+ now. Default: 60. Examples: 60, 30, 15.
168
+ - `start_time_iso` (string, optional): Start time in ISO format (YYYY-MM-DD
169
+ HH:MM:SS). Leave empty to use lookback_minutes.
170
+ - `end_time_iso` (string, optional): End time in ISO format (YYYY-MM-DD
171
+ HH:MM:SS). Leave empty to default to current time.
172
+ - `limit` (integer, optional): Maximum number of logs to return. Default: 20.
173
+
174
+ ### get_drop_rules
175
+
176
+ Gets drop rules for logs, which determine what logs get filtered out from
177
+ reaching Last9.
178
+
179
+ ### add_drop_rule
180
+
181
+ Adds a new drop rule to filter out specific logs at
182
+ [Last9 Control Plane](https://last9.io/control-plane)
183
+
184
+ Parameters:
185
+
186
+ - `name` (string, required): Name of the drop rule.
187
+ - `filters` (array, required): List of filter conditions to apply. Each filter
188
+ has:
189
+ - `key` (string, required): The key to filter on. Only attributes and
190
+ resource.attributes keys are supported. For resource attributes, use format:
191
+ resource.attributes[key_name] and for log attributes, use format:
192
+ attributes[key_name] Double quotes in key names must be escaped.
193
+ - `value` (string, required): The value to filter against.
194
+ - `operator` (string, required): The operator used for filtering. Valid
195
+ values:
196
+ - "equals"
197
+ - "not_equals"
198
+ - `conjunction` (string, required): The logical conjunction between filters.
199
+ Valid values:
200
+ - "and"
201
+
202
+ ### get_alert_config
203
+
204
+ Get alert configurations (alert rules) from Last9. Returns all configured alert rules including their conditions, labels, and annotations.
205
+
206
+ Parameters:
207
+
208
+ None - This tool retrieves all available alert configurations.
209
+
210
+ Returns information about:
211
+
212
+ - Alert rule ID and name
213
+ - Primary indicator being monitored
214
+ - Current state and severity
215
+ - Algorithm used for alerting
216
+ - Entity ID and organization details
217
+ - Properties and configuration
218
+ - Creation and update timestamps
219
+ - Group timeseries notification settings
220
+
221
+ ### get_alerts
222
+
223
+ Get currently active alerts from Last9 monitoring system. Returns all alerts that are currently firing or have fired recently within the specified time window.
224
+
225
+ Parameters:
226
+
227
+ - `timestamp` (integer, optional): Unix timestamp for the query time. Leave empty to default to current time.
228
+ - `window` (integer, optional): Time window in seconds to look back for alerts. Defaults to 900 seconds (15 minutes). Range: 60-86400 seconds.
229
+
230
+ Returns information about:
231
+
232
+ - Alert rule details (ID, name, group, type)
233
+ - Current state and severity
234
+ - Last fired timestamp and duration
235
+ - Rule properties and configuration
236
+ - Alert instances with current values
237
+ - Metric degradation information
238
+ - Group labels and annotations for each instance
239
+
240
+ ## Installation
241
+
242
+ You can install the Last9 Observability MCP server using either:
243
+
244
+ ### Homebrew
245
+
246
+ ```
247
+ # Add the Last9 tap
248
+ brew tap last9/tap
249
+
250
+ # Install the Last9 MCP CLI
251
+ brew install last9-mcp
252
+ ```
253
+
254
+ ### NPM
255
+
256
+ ```bash
257
+ # Install globally
258
+ npm install -g @last9/mcp-server
259
+
260
+ # Or run directly with npx
261
+ npx @last9/mcp-server
262
+ ```
263
+
264
+ ## Configuration
265
+
266
+ ### Environment Variables
267
+
268
+ The Last9 MCP server requires the following environment variables:
269
+
270
+ - `LAST9_BASE_URL`: (required) Last9 API URL from
271
+ [OTel integration](https://app.last9.io/integrations?integration=OpenTelemetry)
272
+ - `LAST9_AUTH_TOKEN`: (required) Authentication token for Last9 MCP server from
273
+ [OTel integration](https://app.last9.io/integrations?integration=OpenTelemetry)
274
+ - `LAST9_REFRESH_TOKEN`: (required) Refresh Token with Write permissions, needed
275
+ for accessing control plane APIs from
276
+ [API Access](https://app.last9.io/settings/api-access)
277
+
278
+ ## Usage with Claude Desktop
279
+
280
+ Configure the Claude app to use the MCP server:
281
+
282
+ 1. Open the Claude Desktop app, go to Settings, then Developer
283
+ 2. Click Edit Config
284
+ 3. Open the `claude_desktop_config.json` file
285
+ 4. Copy and paste the server config to your existing file, then save
286
+ 5. Restart Claude
287
+
288
+ ```json
289
+ {
290
+ "mcpServers": {
291
+ "last9": {
292
+ "command": "/opt/homebrew/bin/last9-mcp",
293
+ "env": {
294
+ "LAST9_BASE_URL": "<last9_otlp_host>",
295
+ "LAST9_AUTH_TOKEN": "<last9_otlp_auth_token>",
296
+ "LAST9_REFRESH_TOKEN": "<last9_write_refresh_token>"
297
+ }
298
+ }
299
+ }
300
+ }
301
+ ```
302
+
303
+ ## Usage with Cursor
304
+
305
+ Configure Cursor to use the MCP server:
306
+
307
+ 1. Open Cursor, go to Settings, then Cursor Settings
308
+ 2. Select MCP on the left
309
+ 3. Click Add "New Global MCP Server" at the top right
310
+ 4. Copy and paste the server config to your existing file, then save
311
+ 5. Restart Cursor
312
+
313
+ ```json
314
+ {
315
+ "mcpServers": {
316
+ "last9": {
317
+ "command": "/opt/homebrew/bin/last9-mcp",
318
+ "env": {
319
+ "LAST9_BASE_URL": "<last9_otlp_host>",
320
+ "LAST9_AUTH_TOKEN": "<last9_otlp_auth_token>",
321
+ "LAST9_REFRESH_TOKEN": "<last9_write_refresh_token>"
322
+ }
323
+ }
324
+ }
325
+ }
326
+ ```
327
+
328
+ ## Usage with Windsurf
329
+
330
+ Configure Windsurf to use the MCP server:
331
+
332
+ 1. Open Windsurf, go to Settings, then Developer
333
+ 2. Click Edit Config
334
+ 3. Open the `windsurf_config.json` file
335
+ 4. Copy and paste the server config to your existing file, then save
336
+ 5. Restart Windsurf
337
+
338
+ ```json
339
+ {
340
+ "mcpServers": {
341
+ "last9": {
342
+ "command": "/opt/homebrew/bin/last9-mcp",
343
+ "env": {
344
+ "LAST9_BASE_URL": "<last9_otlp_host>",
345
+ "LAST9_AUTH_TOKEN": "<last9_otlp_auth_token>",
346
+ "LAST9_REFRESH_TOKEN": "<last9_write_refresh_token>"
347
+ }
348
+ }
349
+ }
350
+ }
351
+ ```
352
+
353
+ ## Usage with VS Code
354
+
355
+ > Note: MCP support in VS Code is available starting v1.99 and is currently in
356
+ > preview. For advanced configuration options and alternative setup methods,
357
+ > [view the VS Code MCP documentation](https://code.visualstudio.com/docs/copilot/chat/mcp-servers).
358
+
359
+ 1. Open VS Code, go to Settings, select the User tab, then Features, then Chat
360
+ 2. Click "Edit settings.json"
361
+ 3. Copy and paste the server config to your existing file, then save
362
+ 4. Restart VS Code
363
+
364
+ ```json
365
+ {
366
+ "mcp": {
367
+ "servers": {
368
+ "last9": {
369
+ "type": "stdio",
370
+ "command": "/opt/homebrew/bin/last9-mcp",
371
+ "env": {
372
+ "LAST9_BASE_URL": "<last9_otlp_host>",
373
+ "LAST9_AUTH_TOKEN": "<last9_otlp_auth_token>",
374
+ "LAST9_REFRESH_TOKEN": "<last9_write_refresh_token>"
375
+ }
376
+ }
377
+ }
378
+ }
379
+ }
380
+ ```
381
+
382
+ ## Badges
383
+
384
+ [![MseeP.ai Security Assessment Badge](https://mseep.net/pr/last9-last9-mcp-server-badge.png)](https://mseep.ai/app/last9-last9-mcp-server)
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@last9/mcp-server",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "description": "Last9 MCP Server - Model Context Protocol server implementation for Last9",
5
5
  "bin": {
6
6
  "last9-mcp": "./bin/cli.js"
@@ -30,7 +30,7 @@
30
30
  "claude"
31
31
  ],
32
32
  "author": "Last9",
33
- "license": "MIT",
33
+ "license": "Apache-2.0",
34
34
  "bugs": {
35
35
  "url": "https://github.com/last9/last9-mcp-server/issues"
36
36
  },