@dynatrace-oss/dynatrace-mcp-server 0.1.2 → 0.1.4
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 +2 -2
- package/dist/dynatrace-clients.js +15 -4
- package/dist/index.js +20 -1
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ Bring real-time observability data directly into your development workflow.
|
|
|
25
25
|
|
|
26
26
|
**Work in progress**
|
|
27
27
|
|
|
28
|
-
You can add this MCP server (using STDIO) to your MCP Client like VS Code, Claude, Cursor, Windsurf Github Copilot via the package `@dynatrace-oss/dynatrace-mcp-server`.
|
|
28
|
+
You can add this MCP server (using STDIO) to your MCP Client like VS Code, Claude, Cursor, Amazon Q Developer CLI, Windsurf Github Copilot via the package `@dynatrace-oss/dynatrace-mcp-server`.
|
|
29
29
|
|
|
30
30
|
**VS Code**
|
|
31
31
|
|
|
@@ -79,7 +79,7 @@ This only works if the config is stored in the current workspaces, e.g., `<your-
|
|
|
79
79
|
|
|
80
80
|
**Amazon Q Developer CLI**
|
|
81
81
|
|
|
82
|
-
The [Amazon Q Developer CLI](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-
|
|
82
|
+
The [Amazon Q Developer CLI](https://docs.aws.amazon.com/amazonq/latest/qdeveloper-ug/command-line-mcp-configuration.html) provides an interactive chat experience directly in your terminal. You can ask questions, get help with AWS services, troubleshoot issues, and generate code snippets without leaving your command line environment.
|
|
83
83
|
```json
|
|
84
84
|
{
|
|
85
85
|
"mcpServers": {
|
|
@@ -3,7 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.callAppFunction = exports.createOAuthClient = void 0;
|
|
4
4
|
const http_client_1 = require("@dynatrace-sdk/http-client");
|
|
5
5
|
const dt_app_1 = require("dt-app");
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Uses the provided oauth Client ID and Secret and requests a token
|
|
8
|
+
* @param clientId - OAuth Client ID for Dynatrace
|
|
9
|
+
* @param clientSecret - Oauth Client Secret for Dynatrace
|
|
10
|
+
* @param authUrl - SSO Authentication URL
|
|
11
|
+
* @param scopes - List of requested scopes
|
|
12
|
+
* @returns
|
|
13
|
+
*/
|
|
7
14
|
const requestToken = async (clientId, clientSecret, authUrl, scopes) => {
|
|
8
15
|
const res = await fetch(authUrl, {
|
|
9
16
|
method: 'POST',
|
|
@@ -17,9 +24,12 @@ const requestToken = async (clientId, clientSecret, authUrl, scopes) => {
|
|
|
17
24
|
scope: scopes.join(' '),
|
|
18
25
|
}),
|
|
19
26
|
});
|
|
27
|
+
// check if the response was okay (HTTP 2xx) or not (HTTP 4xx or 5xx)
|
|
20
28
|
if (!res.ok) {
|
|
21
|
-
|
|
29
|
+
// log the error
|
|
30
|
+
console.error(`Failed to fetch token: ${res.status} ${res.statusText}`);
|
|
22
31
|
}
|
|
32
|
+
// and return the JSON result, as it contains additional information
|
|
23
33
|
return await res.json();
|
|
24
34
|
};
|
|
25
35
|
/** Create an Oauth Client based on clientId, clientSecret, environmentUrl and scopes */
|
|
@@ -39,8 +49,9 @@ const createOAuthClient = async (clientId, clientSecret, environmentUrl, scopes)
|
|
|
39
49
|
console.error(`Using SSO auth URL: ${ssoAuthUrl}`);
|
|
40
50
|
// try to request a token, just to verify that everything is set up correctly
|
|
41
51
|
const tokenResponse = await requestToken(clientId, clientSecret, ssoAuthUrl, scopes);
|
|
42
|
-
|
|
43
|
-
|
|
52
|
+
// in case we didn't get a token, or error / error_description / issueId is set, we throw an error
|
|
53
|
+
if (!tokenResponse.access_token || tokenResponse.error || tokenResponse.error_description || tokenResponse.issueId) {
|
|
54
|
+
throw new Error(`Failed to retrieve OAuth token (IssueId: ${tokenResponse.issueId}): ${tokenResponse.error} - ${tokenResponse.error_description}. Note: Your OAuth client is most likely not configured correctly.`);
|
|
44
55
|
}
|
|
45
56
|
console.error(`Successfully retrieved token from SSO!`);
|
|
46
57
|
return new http_client_1._OAuthHttpClient({
|
package/dist/index.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"use strict";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
const client_platform_management_service_1 = require("@dynatrace-sdk/client-platform-management-service");
|
|
5
|
+
const shared_errors_1 = require("@dynatrace-sdk/shared-errors");
|
|
5
6
|
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
6
7
|
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
7
8
|
const dotenv_1 = require("dotenv");
|
|
@@ -74,7 +75,7 @@ const main = async () => {
|
|
|
74
75
|
tools: {},
|
|
75
76
|
},
|
|
76
77
|
});
|
|
77
|
-
// quick abstraction/wrapper to make it easier to reply
|
|
78
|
+
// quick abstraction/wrapper to make it easier for tools to reply text instead of JSON
|
|
78
79
|
const tool = (name, description, paramsSchema, cb) => {
|
|
79
80
|
const wrappedCb = async (args) => {
|
|
80
81
|
try {
|
|
@@ -84,6 +85,24 @@ const main = async () => {
|
|
|
84
85
|
};
|
|
85
86
|
}
|
|
86
87
|
catch (error) {
|
|
88
|
+
// check if it's an error originating from the Dynatrace SDK / API Gateway and provide an appropriate message to the user
|
|
89
|
+
if ((0, shared_errors_1.isClientRequestError)(error)) {
|
|
90
|
+
const e = error;
|
|
91
|
+
let additionalErrorInformation = '';
|
|
92
|
+
if (e.response.status == 403) {
|
|
93
|
+
additionalErrorInformation = 'Note: Your user or service-user is most likely lacking the necessary permissions/scopes for this API Call.';
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
content: [{
|
|
97
|
+
type: "text",
|
|
98
|
+
text: `Client Request Error: ${e.message} with HTTP status: ${e.response.status}. ${additionalErrorInformation} (body: ${JSON.stringify(e.body)})`
|
|
99
|
+
}
|
|
100
|
+
],
|
|
101
|
+
isError: true,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
// else: We don't know what kind of error happened - best-case we can provide error.message
|
|
105
|
+
console.log(error);
|
|
87
106
|
return {
|
|
88
107
|
content: [{ type: "text", text: `Error: ${error.message}` }],
|
|
89
108
|
isError: true,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynatrace-oss/dynatrace-mcp-server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "Model Context Protocol (MCP) server for Dynatrace",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Dynatrace",
|
|
@@ -45,6 +45,7 @@
|
|
|
45
45
|
"@dynatrace-sdk/client-classic-environment-v2": "^3.6.8",
|
|
46
46
|
"@dynatrace-sdk/client-platform-management-service": "^1.6.3",
|
|
47
47
|
"@dynatrace-sdk/client-query": "^1.18.1",
|
|
48
|
+
"@dynatrace-sdk/shared-errors": "^1.0.0",
|
|
48
49
|
"@modelcontextprotocol/sdk": "^1.8.0",
|
|
49
50
|
"dotenv": "^16.4.7",
|
|
50
51
|
"dt-app": "^0.140.1",
|