dd-mcp-server 1.0.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/.claude/settings.local.json +8 -0
- package/.env.example +9 -0
- package/dist/datadog/client.d.ts +19 -0
- package/dist/datadog/client.d.ts.map +1 -0
- package/dist/datadog/client.js +61 -0
- package/dist/datadog/client.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +74 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/dashboards.d.ts +29 -0
- package/dist/tools/dashboards.d.ts.map +1 -0
- package/dist/tools/dashboards.js +58 -0
- package/dist/tools/dashboards.js.map +1 -0
- package/dist/tools/logs.d.ts +35 -0
- package/dist/tools/logs.d.ts.map +1 -0
- package/dist/tools/logs.js +55 -0
- package/dist/tools/logs.js.map +1 -0
- package/dist/tools/monitors.d.ts +225 -0
- package/dist/tools/monitors.d.ts.map +1 -0
- package/dist/tools/monitors.js +201 -0
- package/dist/tools/monitors.js.map +1 -0
- package/package.json +34 -0
- package/src/datadog/client.ts +88 -0
- package/src/index.ts +168 -0
- package/src/tools/dashboards.ts +104 -0
- package/src/tools/logs.ts +110 -0
- package/src/tools/monitors.ts +252 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { getClient } from "../datadog/client.js";
|
|
3
|
+
export const listMonitorsSchema = z.object({
|
|
4
|
+
name: z.string().optional().describe("Filter monitors by name (partial match)"),
|
|
5
|
+
tags: z.string().optional().describe("Comma-separated list of tags to filter by"),
|
|
6
|
+
monitorTags: z.string().optional().describe("Comma-separated list of monitor tags to filter by"),
|
|
7
|
+
});
|
|
8
|
+
export async function listMonitors(input) {
|
|
9
|
+
const client = getClient();
|
|
10
|
+
const params = new URLSearchParams();
|
|
11
|
+
if (input.name)
|
|
12
|
+
params.append("name", input.name);
|
|
13
|
+
if (input.tags)
|
|
14
|
+
params.append("tags", input.tags);
|
|
15
|
+
if (input.monitorTags)
|
|
16
|
+
params.append("monitor_tags", input.monitorTags);
|
|
17
|
+
const queryString = params.toString();
|
|
18
|
+
const path = `/api/v1/monitor${queryString ? `?${queryString}` : ""}`;
|
|
19
|
+
const response = await client.get(path);
|
|
20
|
+
const monitors = response.map((m) => ({
|
|
21
|
+
id: m.id,
|
|
22
|
+
name: m.name,
|
|
23
|
+
type: m.type,
|
|
24
|
+
state: m.overall_state,
|
|
25
|
+
tags: m.tags,
|
|
26
|
+
}));
|
|
27
|
+
return JSON.stringify({ monitors, count: monitors.length }, null, 2);
|
|
28
|
+
}
|
|
29
|
+
export const getMonitorSchema = z.object({
|
|
30
|
+
monitorId: z.number().describe("The ID of the monitor to retrieve"),
|
|
31
|
+
});
|
|
32
|
+
export async function getMonitor(input) {
|
|
33
|
+
const client = getClient();
|
|
34
|
+
const response = await client.get(`/api/v1/monitor/${input.monitorId}`);
|
|
35
|
+
return JSON.stringify({
|
|
36
|
+
id: response.id,
|
|
37
|
+
name: response.name,
|
|
38
|
+
type: response.type,
|
|
39
|
+
query: response.query,
|
|
40
|
+
message: response.message,
|
|
41
|
+
tags: response.tags,
|
|
42
|
+
state: response.overall_state,
|
|
43
|
+
created: response.created,
|
|
44
|
+
modified: response.modified,
|
|
45
|
+
options: response.options,
|
|
46
|
+
}, null, 2);
|
|
47
|
+
}
|
|
48
|
+
export const createMonitorSchema = z.object({
|
|
49
|
+
name: z.string().describe("Name of the monitor"),
|
|
50
|
+
type: z.enum([
|
|
51
|
+
"metric alert",
|
|
52
|
+
"service check",
|
|
53
|
+
"event alert",
|
|
54
|
+
"query alert",
|
|
55
|
+
"composite",
|
|
56
|
+
"log alert",
|
|
57
|
+
"process alert",
|
|
58
|
+
"rum alert",
|
|
59
|
+
"trace-analytics alert",
|
|
60
|
+
"slo alert",
|
|
61
|
+
"event-v2 alert",
|
|
62
|
+
"audit alert",
|
|
63
|
+
"ci-pipelines alert",
|
|
64
|
+
"ci-tests alert",
|
|
65
|
+
"error-tracking alert",
|
|
66
|
+
]).describe("Type of the monitor"),
|
|
67
|
+
query: z.string().describe("The monitor query"),
|
|
68
|
+
message: z.string().describe("Message to include with notifications"),
|
|
69
|
+
tags: z.array(z.string()).optional().describe("Tags to associate with the monitor"),
|
|
70
|
+
priority: z.number().optional().describe("Priority of the monitor (1-5)"),
|
|
71
|
+
options: z.object({
|
|
72
|
+
thresholds: z.object({
|
|
73
|
+
critical: z.number().optional(),
|
|
74
|
+
warning: z.number().optional(),
|
|
75
|
+
ok: z.number().optional(),
|
|
76
|
+
}).optional(),
|
|
77
|
+
notifyNoData: z.boolean().optional(),
|
|
78
|
+
noDataTimeframe: z.number().optional(),
|
|
79
|
+
renotifyInterval: z.number().optional(),
|
|
80
|
+
}).optional().describe("Monitor options"),
|
|
81
|
+
});
|
|
82
|
+
export async function createMonitor(input) {
|
|
83
|
+
const client = getClient();
|
|
84
|
+
const body = {
|
|
85
|
+
name: input.name,
|
|
86
|
+
type: input.type,
|
|
87
|
+
query: input.query,
|
|
88
|
+
message: input.message,
|
|
89
|
+
tags: input.tags || [],
|
|
90
|
+
priority: input.priority,
|
|
91
|
+
options: input.options ? {
|
|
92
|
+
thresholds: input.options.thresholds,
|
|
93
|
+
notify_no_data: input.options.notifyNoData,
|
|
94
|
+
no_data_timeframe: input.options.noDataTimeframe,
|
|
95
|
+
renotify_interval: input.options.renotifyInterval,
|
|
96
|
+
} : undefined,
|
|
97
|
+
};
|
|
98
|
+
const response = await client.post("/api/v1/monitor", body);
|
|
99
|
+
return JSON.stringify({
|
|
100
|
+
id: response.id,
|
|
101
|
+
name: response.name,
|
|
102
|
+
type: response.type,
|
|
103
|
+
message: "Monitor created successfully",
|
|
104
|
+
}, null, 2);
|
|
105
|
+
}
|
|
106
|
+
export const updateMonitorSchema = z.object({
|
|
107
|
+
monitorId: z.number().describe("The ID of the monitor to update"),
|
|
108
|
+
name: z.string().optional().describe("New name for the monitor"),
|
|
109
|
+
query: z.string().optional().describe("New query for the monitor"),
|
|
110
|
+
message: z.string().optional().describe("New message for notifications"),
|
|
111
|
+
tags: z.array(z.string()).optional().describe("New tags for the monitor"),
|
|
112
|
+
priority: z.number().optional().describe("New priority (1-5)"),
|
|
113
|
+
options: z.object({
|
|
114
|
+
thresholds: z.object({
|
|
115
|
+
critical: z.number().optional(),
|
|
116
|
+
warning: z.number().optional(),
|
|
117
|
+
ok: z.number().optional(),
|
|
118
|
+
}).optional(),
|
|
119
|
+
notifyNoData: z.boolean().optional(),
|
|
120
|
+
noDataTimeframe: z.number().optional(),
|
|
121
|
+
renotifyInterval: z.number().optional(),
|
|
122
|
+
}).optional().describe("Updated monitor options"),
|
|
123
|
+
});
|
|
124
|
+
export async function updateMonitor(input) {
|
|
125
|
+
const client = getClient();
|
|
126
|
+
const body = {};
|
|
127
|
+
if (input.name)
|
|
128
|
+
body.name = input.name;
|
|
129
|
+
if (input.query)
|
|
130
|
+
body.query = input.query;
|
|
131
|
+
if (input.message)
|
|
132
|
+
body.message = input.message;
|
|
133
|
+
if (input.tags)
|
|
134
|
+
body.tags = input.tags;
|
|
135
|
+
if (input.priority)
|
|
136
|
+
body.priority = input.priority;
|
|
137
|
+
if (input.options) {
|
|
138
|
+
body.options = {
|
|
139
|
+
thresholds: input.options.thresholds,
|
|
140
|
+
notify_no_data: input.options.notifyNoData,
|
|
141
|
+
no_data_timeframe: input.options.noDataTimeframe,
|
|
142
|
+
renotify_interval: input.options.renotifyInterval,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
const response = await client.put(`/api/v1/monitor/${input.monitorId}`, body);
|
|
146
|
+
return JSON.stringify({
|
|
147
|
+
id: response.id,
|
|
148
|
+
name: response.name,
|
|
149
|
+
message: "Monitor updated successfully",
|
|
150
|
+
}, null, 2);
|
|
151
|
+
}
|
|
152
|
+
export const deleteMonitorSchema = z.object({
|
|
153
|
+
monitorId: z.number().describe("The ID of the monitor to delete"),
|
|
154
|
+
});
|
|
155
|
+
export async function deleteMonitor(input) {
|
|
156
|
+
const client = getClient();
|
|
157
|
+
await client.delete(`/api/v1/monitor/${input.monitorId}`);
|
|
158
|
+
return JSON.stringify({
|
|
159
|
+
monitorId: input.monitorId,
|
|
160
|
+
message: "Monitor deleted successfully",
|
|
161
|
+
}, null, 2);
|
|
162
|
+
}
|
|
163
|
+
export const muteMonitorSchema = z.object({
|
|
164
|
+
monitorId: z.number().describe("The ID of the monitor to mute"),
|
|
165
|
+
scope: z.string().optional().describe("Scope to apply the mute to (e.g., 'host:myhost')"),
|
|
166
|
+
end: z.number().optional().describe("POSIX timestamp when the mute should end"),
|
|
167
|
+
});
|
|
168
|
+
export async function muteMonitor(input) {
|
|
169
|
+
const client = getClient();
|
|
170
|
+
const body = {};
|
|
171
|
+
if (input.scope)
|
|
172
|
+
body.scope = input.scope;
|
|
173
|
+
if (input.end)
|
|
174
|
+
body.end = input.end;
|
|
175
|
+
await client.post(`/api/v1/monitor/${input.monitorId}/mute`, body);
|
|
176
|
+
return JSON.stringify({
|
|
177
|
+
monitorId: input.monitorId,
|
|
178
|
+
message: "Monitor muted successfully",
|
|
179
|
+
}, null, 2);
|
|
180
|
+
}
|
|
181
|
+
export const unmuteMonitorSchema = z.object({
|
|
182
|
+
monitorId: z.number().describe("The ID of the monitor to unmute"),
|
|
183
|
+
scope: z.string().optional().describe("Scope to unmute (e.g., 'host:myhost')"),
|
|
184
|
+
allScopes: z.boolean().optional().describe("If true, unmute all scopes"),
|
|
185
|
+
});
|
|
186
|
+
export async function unmuteMonitor(input) {
|
|
187
|
+
const client = getClient();
|
|
188
|
+
const params = new URLSearchParams();
|
|
189
|
+
if (input.scope)
|
|
190
|
+
params.append("scope", input.scope);
|
|
191
|
+
if (input.allScopes)
|
|
192
|
+
params.append("all_scopes", "true");
|
|
193
|
+
const queryString = params.toString();
|
|
194
|
+
const path = `/api/v1/monitor/${input.monitorId}/unmute${queryString ? `?${queryString}` : ""}`;
|
|
195
|
+
await client.post(path, {});
|
|
196
|
+
return JSON.stringify({
|
|
197
|
+
monitorId: input.monitorId,
|
|
198
|
+
message: "Monitor unmuted successfully",
|
|
199
|
+
}, null, 2);
|
|
200
|
+
}
|
|
201
|
+
//# sourceMappingURL=monitors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"monitors.js","sourceRoot":"","sources":["../../src/tools/monitors.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "dd-mcp-server",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Datadog MCP Server - Access Datadog logs, monitors, and dashboards via MCP",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"dd-mcp-server": "./dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"start": "node dist/index.js",
|
|
13
|
+
"dev": "tsc --watch"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"mcp",
|
|
17
|
+
"datadog",
|
|
18
|
+
"monitoring",
|
|
19
|
+
"logs",
|
|
20
|
+
"claude"
|
|
21
|
+
],
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
25
|
+
"zod": "^3.25.0"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^20.0.0",
|
|
29
|
+
"typescript": "^5.0.0"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=18.0.0"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
export interface DatadogConfig {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
appKey: string;
|
|
4
|
+
site: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export class DatadogClient {
|
|
8
|
+
private config: DatadogConfig;
|
|
9
|
+
private baseUrl: string;
|
|
10
|
+
|
|
11
|
+
constructor(config: DatadogConfig) {
|
|
12
|
+
this.config = config;
|
|
13
|
+
this.baseUrl = `https://api.${config.site}`;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
private getHeaders(): Record<string, string> {
|
|
17
|
+
return {
|
|
18
|
+
"Content-Type": "application/json",
|
|
19
|
+
"DD-API-KEY": this.config.apiKey,
|
|
20
|
+
"DD-APPLICATION-KEY": this.config.appKey,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
async request<T>(
|
|
25
|
+
method: string,
|
|
26
|
+
path: string,
|
|
27
|
+
body?: unknown
|
|
28
|
+
): Promise<T> {
|
|
29
|
+
const url = `${this.baseUrl}${path}`;
|
|
30
|
+
const options: RequestInit = {
|
|
31
|
+
method,
|
|
32
|
+
headers: this.getHeaders(),
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
if (body) {
|
|
36
|
+
options.body = JSON.stringify(body);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const response = await fetch(url, options);
|
|
40
|
+
|
|
41
|
+
if (!response.ok) {
|
|
42
|
+
const errorText = await response.text();
|
|
43
|
+
throw new Error(`Datadog API error: ${response.status} - ${errorText}`);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return response.json() as Promise<T>;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
async get<T>(path: string): Promise<T> {
|
|
50
|
+
return this.request<T>("GET", path);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async post<T>(path: string, body: unknown): Promise<T> {
|
|
54
|
+
return this.request<T>("POST", path, body);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async put<T>(path: string, body: unknown): Promise<T> {
|
|
58
|
+
return this.request<T>("PUT", path, body);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async delete<T>(path: string): Promise<T> {
|
|
62
|
+
return this.request<T>("DELETE", path);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
let clientInstance: DatadogClient | null = null;
|
|
67
|
+
|
|
68
|
+
export function initializeClient(): DatadogClient {
|
|
69
|
+
const apiKey = process.env.DD_API_KEY;
|
|
70
|
+
const appKey = process.env.DD_APP_KEY;
|
|
71
|
+
const site = process.env.DD_SITE || "datadoghq.com";
|
|
72
|
+
|
|
73
|
+
if (!apiKey || !appKey) {
|
|
74
|
+
throw new Error(
|
|
75
|
+
"DD_API_KEY and DD_APP_KEY environment variables are required"
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
clientInstance = new DatadogClient({ apiKey, appKey, site });
|
|
80
|
+
return clientInstance;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function getClient(): DatadogClient {
|
|
84
|
+
if (!clientInstance) {
|
|
85
|
+
throw new Error("Datadog client not initialized. Call initializeClient() first.");
|
|
86
|
+
}
|
|
87
|
+
return clientInstance;
|
|
88
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
5
|
+
import { initializeClient } from "./datadog/client.js";
|
|
6
|
+
import {
|
|
7
|
+
searchLogs,
|
|
8
|
+
searchLogsSchema,
|
|
9
|
+
getLog,
|
|
10
|
+
getLogSchema,
|
|
11
|
+
} from "./tools/logs.js";
|
|
12
|
+
import {
|
|
13
|
+
listMonitors,
|
|
14
|
+
listMonitorsSchema,
|
|
15
|
+
getMonitor,
|
|
16
|
+
getMonitorSchema,
|
|
17
|
+
createMonitor,
|
|
18
|
+
createMonitorSchema,
|
|
19
|
+
updateMonitor,
|
|
20
|
+
updateMonitorSchema,
|
|
21
|
+
deleteMonitor,
|
|
22
|
+
deleteMonitorSchema,
|
|
23
|
+
muteMonitor,
|
|
24
|
+
muteMonitorSchema,
|
|
25
|
+
unmuteMonitor,
|
|
26
|
+
unmuteMonitorSchema,
|
|
27
|
+
} from "./tools/monitors.js";
|
|
28
|
+
import {
|
|
29
|
+
listDashboards,
|
|
30
|
+
listDashboardsSchema,
|
|
31
|
+
getDashboard,
|
|
32
|
+
getDashboardSchema,
|
|
33
|
+
} from "./tools/dashboards.js";
|
|
34
|
+
|
|
35
|
+
const server = new McpServer({
|
|
36
|
+
name: "datadog-mcp",
|
|
37
|
+
version: "1.0.0",
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Logs tools
|
|
41
|
+
server.tool(
|
|
42
|
+
"search_logs",
|
|
43
|
+
"Search and retrieve logs from Datadog",
|
|
44
|
+
searchLogsSchema.shape,
|
|
45
|
+
async (input) => {
|
|
46
|
+
const result = await searchLogs(input);
|
|
47
|
+
return { content: [{ type: "text", text: result }] };
|
|
48
|
+
}
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
server.tool(
|
|
52
|
+
"get_log",
|
|
53
|
+
"Get details of a specific log by ID",
|
|
54
|
+
getLogSchema.shape,
|
|
55
|
+
async (input) => {
|
|
56
|
+
const result = await getLog(input);
|
|
57
|
+
return { content: [{ type: "text", text: result }] };
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
// Monitor tools
|
|
62
|
+
server.tool(
|
|
63
|
+
"list_monitors",
|
|
64
|
+
"List all monitors with optional filtering",
|
|
65
|
+
listMonitorsSchema.shape,
|
|
66
|
+
async (input) => {
|
|
67
|
+
const result = await listMonitors(input);
|
|
68
|
+
return { content: [{ type: "text", text: result }] };
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
server.tool(
|
|
73
|
+
"get_monitor",
|
|
74
|
+
"Get details of a specific monitor by ID",
|
|
75
|
+
getMonitorSchema.shape,
|
|
76
|
+
async (input) => {
|
|
77
|
+
const result = await getMonitor(input);
|
|
78
|
+
return { content: [{ type: "text", text: result }] };
|
|
79
|
+
}
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
server.tool(
|
|
83
|
+
"create_monitor",
|
|
84
|
+
"Create a new Datadog monitor",
|
|
85
|
+
createMonitorSchema.shape,
|
|
86
|
+
async (input) => {
|
|
87
|
+
const result = await createMonitor(input);
|
|
88
|
+
return { content: [{ type: "text", text: result }] };
|
|
89
|
+
}
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
server.tool(
|
|
93
|
+
"update_monitor",
|
|
94
|
+
"Update an existing monitor",
|
|
95
|
+
updateMonitorSchema.shape,
|
|
96
|
+
async (input) => {
|
|
97
|
+
const result = await updateMonitor(input);
|
|
98
|
+
return { content: [{ type: "text", text: result }] };
|
|
99
|
+
}
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
server.tool(
|
|
103
|
+
"delete_monitor",
|
|
104
|
+
"Delete a monitor by ID",
|
|
105
|
+
deleteMonitorSchema.shape,
|
|
106
|
+
async (input) => {
|
|
107
|
+
const result = await deleteMonitor(input);
|
|
108
|
+
return { content: [{ type: "text", text: result }] };
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
|
|
112
|
+
server.tool(
|
|
113
|
+
"mute_monitor",
|
|
114
|
+
"Mute a monitor to suppress notifications",
|
|
115
|
+
muteMonitorSchema.shape,
|
|
116
|
+
async (input) => {
|
|
117
|
+
const result = await muteMonitor(input);
|
|
118
|
+
return { content: [{ type: "text", text: result }] };
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
server.tool(
|
|
123
|
+
"unmute_monitor",
|
|
124
|
+
"Unmute a previously muted monitor",
|
|
125
|
+
unmuteMonitorSchema.shape,
|
|
126
|
+
async (input) => {
|
|
127
|
+
const result = await unmuteMonitor(input);
|
|
128
|
+
return { content: [{ type: "text", text: result }] };
|
|
129
|
+
}
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
// Dashboard tools
|
|
133
|
+
server.tool(
|
|
134
|
+
"list_dashboards",
|
|
135
|
+
"List all dashboards",
|
|
136
|
+
listDashboardsSchema.shape,
|
|
137
|
+
async (input) => {
|
|
138
|
+
const result = await listDashboards(input);
|
|
139
|
+
return { content: [{ type: "text", text: result }] };
|
|
140
|
+
}
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
server.tool(
|
|
144
|
+
"get_dashboard",
|
|
145
|
+
"Get details of a specific dashboard",
|
|
146
|
+
getDashboardSchema.shape,
|
|
147
|
+
async (input) => {
|
|
148
|
+
const result = await getDashboard(input);
|
|
149
|
+
return { content: [{ type: "text", text: result }] };
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
|
|
153
|
+
async function main() {
|
|
154
|
+
try {
|
|
155
|
+
initializeClient();
|
|
156
|
+
} catch (error) {
|
|
157
|
+
console.error("Failed to initialize Datadog client:", error);
|
|
158
|
+
process.exit(1);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const transport = new StdioServerTransport();
|
|
162
|
+
await server.connect(transport);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
main().catch((error) => {
|
|
166
|
+
console.error("Server error:", error);
|
|
167
|
+
process.exit(1);
|
|
168
|
+
});
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { getClient } from "../datadog/client.js";
|
|
3
|
+
|
|
4
|
+
interface DashboardSummary {
|
|
5
|
+
id: string;
|
|
6
|
+
title: string;
|
|
7
|
+
description: string | null;
|
|
8
|
+
layout_type: string;
|
|
9
|
+
url: string;
|
|
10
|
+
is_read_only: boolean;
|
|
11
|
+
created_at: string;
|
|
12
|
+
modified_at: string;
|
|
13
|
+
author_handle: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface DashboardListResponse {
|
|
17
|
+
dashboards: DashboardSummary[];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
interface Dashboard {
|
|
21
|
+
id: string;
|
|
22
|
+
title: string;
|
|
23
|
+
description: string | null;
|
|
24
|
+
layout_type: string;
|
|
25
|
+
widgets: Array<{
|
|
26
|
+
id?: number;
|
|
27
|
+
definition: Record<string, unknown>;
|
|
28
|
+
}>;
|
|
29
|
+
template_variables?: Array<{
|
|
30
|
+
name: string;
|
|
31
|
+
prefix?: string;
|
|
32
|
+
default?: string;
|
|
33
|
+
}>;
|
|
34
|
+
url: string;
|
|
35
|
+
created_at: string;
|
|
36
|
+
modified_at: string;
|
|
37
|
+
author_handle: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const listDashboardsSchema = z.object({
|
|
41
|
+
filterShared: z.boolean().optional().describe("Filter to only shared dashboards"),
|
|
42
|
+
filterDeleted: z.boolean().optional().describe("Include deleted dashboards"),
|
|
43
|
+
count: z.number().optional().describe("Number of dashboards to return (default: 100)"),
|
|
44
|
+
start: z.number().optional().describe("Starting point for pagination"),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
export type ListDashboardsInput = z.infer<typeof listDashboardsSchema>;
|
|
48
|
+
|
|
49
|
+
export async function listDashboards(input: ListDashboardsInput): Promise<string> {
|
|
50
|
+
const client = getClient();
|
|
51
|
+
|
|
52
|
+
const params = new URLSearchParams();
|
|
53
|
+
if (input.filterShared !== undefined) params.append("filter[shared]", String(input.filterShared));
|
|
54
|
+
if (input.filterDeleted !== undefined) params.append("filter[deleted]", String(input.filterDeleted));
|
|
55
|
+
if (input.count) params.append("count", String(input.count));
|
|
56
|
+
if (input.start) params.append("start", String(input.start));
|
|
57
|
+
|
|
58
|
+
const queryString = params.toString();
|
|
59
|
+
const path = `/api/v1/dashboard${queryString ? `?${queryString}` : ""}`;
|
|
60
|
+
|
|
61
|
+
const response = await client.get<DashboardListResponse>(path);
|
|
62
|
+
|
|
63
|
+
const dashboards = response.dashboards.map((d) => ({
|
|
64
|
+
id: d.id,
|
|
65
|
+
title: d.title,
|
|
66
|
+
description: d.description,
|
|
67
|
+
layoutType: d.layout_type,
|
|
68
|
+
url: d.url,
|
|
69
|
+
createdAt: d.created_at,
|
|
70
|
+
modifiedAt: d.modified_at,
|
|
71
|
+
author: d.author_handle,
|
|
72
|
+
}));
|
|
73
|
+
|
|
74
|
+
return JSON.stringify({ dashboards, count: dashboards.length }, null, 2);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export const getDashboardSchema = z.object({
|
|
78
|
+
dashboardId: z.string().describe("The ID of the dashboard to retrieve"),
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
export type GetDashboardInput = z.infer<typeof getDashboardSchema>;
|
|
82
|
+
|
|
83
|
+
export async function getDashboard(input: GetDashboardInput): Promise<string> {
|
|
84
|
+
const client = getClient();
|
|
85
|
+
|
|
86
|
+
const response = await client.get<Dashboard>(`/api/v1/dashboard/${input.dashboardId}`);
|
|
87
|
+
|
|
88
|
+
return JSON.stringify({
|
|
89
|
+
id: response.id,
|
|
90
|
+
title: response.title,
|
|
91
|
+
description: response.description,
|
|
92
|
+
layoutType: response.layout_type,
|
|
93
|
+
widgets: response.widgets.map((w) => ({
|
|
94
|
+
id: w.id,
|
|
95
|
+
type: w.definition.type,
|
|
96
|
+
title: w.definition.title,
|
|
97
|
+
})),
|
|
98
|
+
templateVariables: response.template_variables,
|
|
99
|
+
url: response.url,
|
|
100
|
+
createdAt: response.created_at,
|
|
101
|
+
modifiedAt: response.modified_at,
|
|
102
|
+
author: response.author_handle,
|
|
103
|
+
}, null, 2);
|
|
104
|
+
}
|