@dynatrace-oss/dynatrace-mcp-server 1.5.0-beta.1 ā 1.5.0-beta.2
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 +28 -24
- package/dist/index.js +41 -25
- package/dist/ui/execute-dql/index.html +52 -53
- package/dist/utils/environment-url-parser.js +17 -0
- package/dist/utils/environment-url-parser.test.js +43 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -43,8 +43,26 @@ Furthermore, you need to configure the URL to a Dynatrace environment:
|
|
|
43
43
|
|
|
44
44
|
- `DT_ENVIRONMENT` (string, e.g., `https://abc12345.apps.dynatrace.com`) - URL to your Dynatrace Platform (do not use Dynatrace classic URLs like `abc12345.live.dynatrace.com`)
|
|
45
45
|
|
|
46
|
+
Authentication will be handled via Authorization Code Flow in your browser, you don't need to define a Platform Token nor an OAuth Client to get started.
|
|
47
|
+
|
|
46
48
|
Once you are done, we recommend looking into [example prompts](#-example-prompts-), like `Get all details of the entity 'my-service'` or `Show me error logs`. Please mind that these prompts lead to executing DQL statements which may incur [costs](#costs) in accordance to your licence.
|
|
47
49
|
|
|
50
|
+
**VSCode**
|
|
51
|
+
|
|
52
|
+
```json
|
|
53
|
+
{
|
|
54
|
+
"servers": {
|
|
55
|
+
"npx-dynatrace-mcp-server": {
|
|
56
|
+
"command": "npx",
|
|
57
|
+
"args": ["-y", "@dynatrace-oss/dynatrace-mcp-server@latest"],
|
|
58
|
+
"env": {
|
|
59
|
+
"DT_ENVIRONMENT": "https://abc12345.apps.dynatrace.com"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
48
66
|
## Architecture
|
|
49
67
|
|
|
50
68
|

|
|
@@ -124,22 +142,6 @@ We recommend to always set it up for your current workspace instead of using it
|
|
|
124
142
|
|
|
125
143
|
**VS Code**
|
|
126
144
|
|
|
127
|
-
```json
|
|
128
|
-
{
|
|
129
|
-
"servers": {
|
|
130
|
-
"npx-dynatrace-mcp-server": {
|
|
131
|
-
"command": "npx",
|
|
132
|
-
"cwd": "${workspaceFolder}",
|
|
133
|
-
"args": ["-y", "@dynatrace-oss/dynatrace-mcp-server@latest"],
|
|
134
|
-
"envFile": "${workspaceFolder}/.env"
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
Please note: In this config, [the `${workspaceFolder}` variable](https://code.visualstudio.com/docs/reference/variables-reference#_predefined-variables) is used.
|
|
141
|
-
This only works if the config is stored in the current workspaces, e.g., `<your-repo>/.vscode/mcp.json`. Alternatively, this can also be stored in user-settings, and you can define `env` as follows:
|
|
142
|
-
|
|
143
145
|
```json
|
|
144
146
|
{
|
|
145
147
|
"servers": {
|
|
@@ -147,7 +149,7 @@ This only works if the config is stored in the current workspaces, e.g., `<your-
|
|
|
147
149
|
"command": "npx",
|
|
148
150
|
"args": ["-y", "@dynatrace-oss/dynatrace-mcp-server@latest"],
|
|
149
151
|
"env": {
|
|
150
|
-
"DT_ENVIRONMENT": ""
|
|
152
|
+
"DT_ENVIRONMENT": "https://abc12345.apps.dynatrace.com"
|
|
151
153
|
}
|
|
152
154
|
}
|
|
153
155
|
}
|
|
@@ -163,7 +165,7 @@ This only works if the config is stored in the current workspaces, e.g., `<your-
|
|
|
163
165
|
"command": "npx",
|
|
164
166
|
"args": ["-y", "@dynatrace-oss/dynatrace-mcp-server@latest"],
|
|
165
167
|
"env": {
|
|
166
|
-
"DT_ENVIRONMENT": ""
|
|
168
|
+
"DT_ENVIRONMENT": "https://abc12345.apps.dynatrace.com"
|
|
167
169
|
}
|
|
168
170
|
}
|
|
169
171
|
}
|
|
@@ -181,7 +183,7 @@ The [Amazon Q Developer CLI](https://docs.aws.amazon.com/amazonq/latest/qdevelop
|
|
|
181
183
|
"command": "npx",
|
|
182
184
|
"args": ["-y", "@dynatrace-oss/dynatrace-mcp-server@latest"],
|
|
183
185
|
"env": {
|
|
184
|
-
"DT_ENVIRONMENT": ""
|
|
186
|
+
"DT_ENVIRONMENT": "https://abc12345.apps.dynatrace.com"
|
|
185
187
|
}
|
|
186
188
|
}
|
|
187
189
|
}
|
|
@@ -201,7 +203,7 @@ The [Amazon Kiro](https://kiro.dev/) is an agentic IDE that helps you do your be
|
|
|
201
203
|
"command": "npx",
|
|
202
204
|
"args": ["-y", "@dynatrace-oss/dynatrace-mcp-server@latest"],
|
|
203
205
|
"env": {
|
|
204
|
-
"DT_ENVIRONMENT": ""
|
|
206
|
+
"DT_ENVIRONMENT": "https://abc12345.apps.dynatrace.com"
|
|
205
207
|
}
|
|
206
208
|
}
|
|
207
209
|
}
|
|
@@ -219,10 +221,11 @@ Using `gemini` CLI directly (recommended):
|
|
|
219
221
|
```bash
|
|
220
222
|
gemini extensions install https://github.com/dynatrace-oss/dynatrace-mcp
|
|
221
223
|
export DT_PLATFORM_TOKEN=... # optional
|
|
222
|
-
export DT_ENVIRONMENT=https://...
|
|
223
224
|
```
|
|
224
225
|
|
|
225
|
-
|
|
226
|
+
The command will ask for the value Dynatrace Environment.
|
|
227
|
+
|
|
228
|
+
Verify that the server is running via
|
|
226
229
|
|
|
227
230
|
```bash
|
|
228
231
|
gemini mcp list
|
|
@@ -237,7 +240,7 @@ Or manually in your `~/.gemini/settings.json` or `.gemini/settings.json`:
|
|
|
237
240
|
"command": "npx",
|
|
238
241
|
"args": ["@dynatrace-oss/dynatrace-mcp-server@latest"],
|
|
239
242
|
"env": {
|
|
240
|
-
"DT_ENVIRONMENT": ""
|
|
243
|
+
"DT_ENVIRONMENT": "https://abc12345.apps.dynatrace.com"
|
|
241
244
|
},
|
|
242
245
|
"timeout": 30000,
|
|
243
246
|
"trust": false
|
|
@@ -325,7 +328,7 @@ When just providing `DT_ENVIRONMENT`, the local MCP server will try to open a br
|
|
|
325
328
|
|
|
326
329
|
For more information about the other authentication methods, please have a look at the documentation about
|
|
327
330
|
[creating a Platform Token in Dynatrace](https://docs.dynatrace.com/docs/manage/identity-access-management/access-tokens-and-oauth-clients/platform-tokens), as well as
|
|
328
|
-
[creating an OAuth Client in Dynatrace](https://docs.dynatrace.com/docs/manage/identity-access-management/access-tokens-and-oauth-clients/oauth-clients) for advanced scenarios.
|
|
331
|
+
[creating an OAuth Client in Dynatrace](https://docs.dynatrace.com/docs/manage/identity-access-management/access-tokens-and-oauth-clients/oauth-clients) for advanced scenarios (service-users, backend-to-backend communication).
|
|
329
332
|
|
|
330
333
|
In addition, depending on the features you use, the following variables can be configured:
|
|
331
334
|
|
|
@@ -338,6 +341,7 @@ The MCP server honors system proxy settings for corporate environments:
|
|
|
338
341
|
- `https_proxy` or `HTTPS_PROXY` (optional, string, e.g., `http://proxy.example.com:8080`) - Proxy server URL for HTTPS requests
|
|
339
342
|
- `http_proxy` or `HTTP_PROXY` (optional, string, e.g., `http://proxy.example.com:8080`) - Proxy server URL for HTTP requests
|
|
340
343
|
- `no_proxy` or `NO_PROXY` (optional, string, e.g., `localhost,127.0.0.1,.local`) - Comma-separated list of hostnames or domains that should bypass the proxy
|
|
344
|
+
- `NODE_EXTRA_CA_CERTS` (optional, string, e.g., `C:\some-path\certificate.pem`) - When set, the well known "root" CAs (like VeriSign) will be extended with the extra certificates
|
|
341
345
|
|
|
342
346
|
**Note:** The `no_proxy` environment variable is currently logged for informational purposes but not fully enforced by the underlying HTTP client. If you need to bypass the proxy for specific hosts, consider configuring your proxy server to handle these exclusions.
|
|
343
347
|
|
package/dist/index.js
CHANGED
|
@@ -521,7 +521,7 @@ const main = async () => {
|
|
|
521
521
|
// Register the execute_dql tool with MCP App UI support.
|
|
522
522
|
registerAppTool(server, 'execute_dql', {
|
|
523
523
|
title: 'Execute DQL',
|
|
524
|
-
description: 'Get data like Logs, Metrics, Spans, Events, or Entity Data from Dynatrace
|
|
524
|
+
description: 'Get data like Logs, Metrics, Spans, Events, or Entity Data from Dynatrace Grail by executing a Dynatrace Query Language (DQL) statement. ' +
|
|
525
525
|
'Use the "generate_dql_from_natural_language" tool upfront to generate or refine a DQL statement based on your request. ' +
|
|
526
526
|
'To learn about possible fields available for filtering, use the query "fetch dt.semantic_dictionary.models | filter data_object == \\"logs\\""',
|
|
527
527
|
inputSchema: {
|
|
@@ -565,17 +565,20 @@ const main = async () => {
|
|
|
565
565
|
if (!response) {
|
|
566
566
|
return 'DQL execution failed or returned no result.';
|
|
567
567
|
}
|
|
568
|
-
|
|
569
|
-
|
|
568
|
+
// Build warnings array for structured metadata
|
|
569
|
+
const warnings = [];
|
|
570
570
|
if (response.budgetWarning) {
|
|
571
|
-
|
|
571
|
+
warnings.push(response.budgetWarning);
|
|
572
572
|
}
|
|
573
|
+
// Build human-readable text result
|
|
574
|
+
let result = `š **DQL Query Results**\n\n`;
|
|
573
575
|
// Cost and Performance Information
|
|
574
576
|
if (response.scannedRecords !== undefined) {
|
|
575
577
|
result += `- **Scanned Records:** ${response.scannedRecords.toLocaleString()}\n`;
|
|
576
578
|
}
|
|
577
579
|
if (response.scannedBytes !== undefined) {
|
|
578
|
-
|
|
580
|
+
// calculate scanned gigabytes for better readability in warnings and result text
|
|
581
|
+
const scannedGB = response.scannedBytes !== undefined ? response.scannedBytes / (1000 * 1000 * 1000) : 0;
|
|
579
582
|
result += `- **Scanned Bytes:** ${scannedGB.toFixed(2)} GB`;
|
|
580
583
|
// Show budget status if available
|
|
581
584
|
if (response.budgetState) {
|
|
@@ -591,38 +594,51 @@ const main = async () => {
|
|
|
591
594
|
}
|
|
592
595
|
result += '\n';
|
|
593
596
|
if (scannedGB > 500) {
|
|
594
|
-
|
|
597
|
+
warnings.push(`Very High Data Usage: This query scanned ${scannedGB.toFixed(1)} GB of data, which may impact your Dynatrace consumption. Please take measures to optimize your query, like limiting the timeframe or selecting a bucket.`);
|
|
595
598
|
}
|
|
596
599
|
else if (scannedGB > 50) {
|
|
597
|
-
|
|
600
|
+
warnings.push(`High Data Usage: This query scanned ${scannedGB.toFixed(2)} GB of data, which may impact your Dynatrace consumption.`);
|
|
598
601
|
}
|
|
599
|
-
|
|
602
|
+
// Add informational messages (not warnings) about data usage
|
|
603
|
+
else if (scannedGB > 5 && scannedGB <= 50) {
|
|
600
604
|
result += ` š” **Moderate Data Usage:** This query scanned ${scannedGB.toFixed(2)} GB of data.\n`;
|
|
601
605
|
}
|
|
602
606
|
else if (response.scannedBytes === 0) {
|
|
603
607
|
result += ` š” **No Data consumed:** This query did not consume any data.\n`;
|
|
604
608
|
}
|
|
609
|
+
if (response.sampled) {
|
|
610
|
+
warnings.push('Sampling Used: Results may be approximate');
|
|
611
|
+
}
|
|
612
|
+
if (response.records.length === recordLimit) {
|
|
613
|
+
warnings.push(`Record Limit Reached: The result set was limited to ${recordLimit} records. Consider changing your query with a smaller timeframe, an aggregation or a more concise filter. Alternatively, increase the recordLimit if you expect more results.`);
|
|
614
|
+
}
|
|
605
615
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
616
|
+
// Add all warnings to result
|
|
617
|
+
if (warnings.length > 0) {
|
|
618
|
+
result += '\n';
|
|
619
|
+
warnings.forEach((warning) => {
|
|
620
|
+
result += `- **ā ļø ${warning}**\n`;
|
|
621
|
+
});
|
|
611
622
|
}
|
|
612
623
|
result += `\nš **Query Results**: (${response.records?.length || 0} records):\n\n`;
|
|
613
624
|
result += `\`\`\`json\n${JSON.stringify(response.records, null, 2)}\n\`\`\``;
|
|
614
|
-
//
|
|
615
|
-
|
|
616
|
-
result
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
625
|
+
// Return structured data in _meta for MCP App UI instead of embedding in text
|
|
626
|
+
return {
|
|
627
|
+
text: result,
|
|
628
|
+
_meta: {
|
|
629
|
+
records: response.records,
|
|
630
|
+
types: response.types,
|
|
631
|
+
analysisTimeframe: response.metadata?.grail?.analysisTimeframe,
|
|
632
|
+
scannedRecords: response.scannedRecords,
|
|
633
|
+
scannedBytes: response.scannedBytes,
|
|
634
|
+
sampled: response.sampled,
|
|
635
|
+
environmentUrl: dtEnvironment,
|
|
636
|
+
budgetState: response.budgetState,
|
|
637
|
+
warnings,
|
|
638
|
+
recordLimit,
|
|
639
|
+
recordLimitReached: response.records.length === recordLimit,
|
|
640
|
+
},
|
|
641
|
+
};
|
|
626
642
|
}));
|
|
627
643
|
// MCP App: Register the HTML resource for the execute_dql interactive UI (MCP App)
|
|
628
644
|
registerAppResource(server, 'DQL Results Viewer', executeDqlResourceUri, {}, async () => {
|