Skip to content

Commit 95c8737

Browse files
Feat/list hosts and Mute Hosts (#8)
* feat: add hosts tools and handlers to the server * feat: add hosts mute, unmute, and listing tools with validation schemas * feat: update README with new host management functions and their specifications * feat: enhance Datadog host management tools with detailed schemas and documentation comments * feat: update Datadog host URL to use dynamic site configuration * docs: update README fomat * refactor: improve code formatting and documentation comments with prettier
1 parent 78433aa commit 95c8737

File tree

5 files changed

+360
-0
lines changed

5 files changed

+360
-0
lines changed

README.md

+38
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ MCP server for the Datadog API, enabling incident management and more.
6161
- **Returns**: Metrics data for the queried timeframe.
6262

6363
7. `list_traces`
64+
6465
- Retrieve a list of APM traces from Datadog.
6566
- **Inputs**:
6667
- `query` (string): Datadog APM trace query string.
@@ -72,6 +73,43 @@ MCP server for the Datadog API, enabling incident management and more.
7273
- `operation` (optional string): Filter by operation name.
7374
- **Returns**: Array of matching traces from Datadog APM.
7475

76+
8. `list_hosts`
77+
78+
- Get list of hosts from Datadog.
79+
- **Inputs**:
80+
- `filter` (optional string): Filter string for search results.
81+
- `sort_field` (optional string): Field to sort hosts by.
82+
- `sort_dir` (optional string): Sort direction (asc/desc).
83+
- `start` (optional number): Starting offset for pagination.
84+
- `count` (optional number): Max number of hosts to return (max: 1000).
85+
- `from` (optional number): Search hosts from this UNIX timestamp.
86+
- `include_muted_hosts_data` (optional boolean): Include muted hosts status and expiry.
87+
- `include_hosts_metadata` (optional boolean): Include host metadata (version, platform, etc).
88+
- **Returns**: Array of hosts with details including name, ID, aliases, apps, mute status, and more.
89+
90+
9. `get_active_hosts_count`
91+
92+
- Get the total number of active hosts in Datadog.
93+
- **Inputs**:
94+
- `from` (optional number): Number of seconds from which you want to get total number of active hosts (defaults to 2h).
95+
- **Returns**: Count of total active and up hosts.
96+
97+
10. `mute_host`
98+
99+
- Mute a host in Datadog.
100+
- **Inputs**:
101+
- `hostname` (string): The name of the host to mute.
102+
- `message` (optional string): Message to associate with the muting of this host.
103+
- `end` (optional number): POSIX timestamp for when the mute should end.
104+
- `override` (optional boolean): If true and the host is already muted, replaces existing end time.
105+
- **Returns**: Success status and confirmation message.
106+
107+
11. `unmute_host`
108+
- Unmute a host in Datadog.
109+
- **Inputs**:
110+
- `hostname` (string): The name of the host to unmute.
111+
- **Returns**: Success status and confirmation message.
112+
75113
## Setup
76114

77115
### Datadog Credentials

src/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { LOGS_TOOLS, LOGS_HANDLERS } from './tools/logs'
2020
import { MONITORS_TOOLS, MONITORS_HANDLERS } from './tools/monitors'
2121
import { DASHBOARDS_TOOLS, DASHBOARDS_HANDLERS } from './tools/dashboards'
2222
import { TRACES_TOOLS, TRACES_HANDLERS } from './tools/traces'
23+
import { HOSTS_TOOLS, HOSTS_HANDLERS } from './tools/hosts'
2324
import { ToolHandlers } from './utils/types'
2425

2526
const server = new Server(
@@ -51,6 +52,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
5152
...MONITORS_TOOLS,
5253
...DASHBOARDS_TOOLS,
5354
...TRACES_TOOLS,
55+
...HOSTS_TOOLS,
5456
],
5557
}
5658
})
@@ -62,6 +64,7 @@ const TOOL_HANDLERS: ToolHandlers = {
6264
...MONITORS_HANDLERS,
6365
...DASHBOARDS_HANDLERS,
6466
...TRACES_HANDLERS,
67+
...HOSTS_HANDLERS,
6568
}
6669
/**
6770
* Handler for invoking Datadog-related tools in the mcp-server-datadog.

src/tools/hosts/index.ts

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
/**
2+
* Central export file for the Datadog Hosts management tools.
3+
* Re-exports the tools and their handlers from the implementation file.
4+
*
5+
* HOSTS_TOOLS: Array of tool schemas defining the available host management operations
6+
* HOSTS_HANDLERS: Object containing the implementation of each host management operation
7+
*/
8+
export { HOSTS_TOOLS, HOSTS_HANDLERS } from './tool'

src/tools/hosts/schema.ts

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
import { z } from 'zod'
2+
3+
/**
4+
* Zod schemas for validating input parameters for Datadog host management operations.
5+
* These schemas define the expected shape and types of data for each host-related tool.
6+
*/
7+
8+
/**
9+
* Schema for muting a host in Datadog.
10+
* Defines required and optional parameters for temporarily silencing a host's alerts.
11+
*
12+
* @param hostname - Required. Identifies the host to be muted
13+
* @param message - Optional. Adds context about why the host is being muted
14+
* @param end - Optional. Unix timestamp defining when the mute should automatically expire
15+
* @param override - Optional. Controls whether to replace an existing mute's end time
16+
*/
17+
export const MuteHostZodSchema = z.object({
18+
hostname: z.string().describe('The name of the host to mute'),
19+
message: z
20+
.string()
21+
.optional()
22+
.describe('Message to associate with the muting of this host'),
23+
end: z
24+
.number()
25+
.int()
26+
.optional()
27+
.describe('POSIX timestamp for when the mute should end'),
28+
override: z
29+
.boolean()
30+
.optional()
31+
.default(false)
32+
.describe(
33+
'If true and the host is already muted, replaces existing end time',
34+
),
35+
})
36+
37+
/**
38+
* Schema for unmuting a host in Datadog.
39+
* Defines parameters for re-enabling alerts for a previously muted host.
40+
*
41+
* @param hostname - Required. Identifies the host to be unmuted
42+
*/
43+
export const UnmuteHostZodSchema = z.object({
44+
hostname: z.string().describe('The name of the host to unmute'),
45+
})
46+
47+
/**
48+
* Schema for retrieving active host counts from Datadog.
49+
* Defines parameters for querying the number of reporting hosts within a time window.
50+
*
51+
* @param from - Optional. Time window in seconds to check for host activity
52+
* Defaults to 7200 seconds (2 hours)
53+
*/
54+
export const GetActiveHostsCountZodSchema = z.object({
55+
from: z
56+
.number()
57+
.int()
58+
.optional()
59+
.default(7200)
60+
.describe(
61+
'Number of seconds from which you want to get total number of active hosts (defaults to 2h)',
62+
),
63+
})
64+
65+
/**
66+
* Schema for listing and filtering hosts in Datadog.
67+
* Defines comprehensive parameters for querying and filtering host information.
68+
*
69+
* @param filter - Optional. Search string to filter hosts
70+
* @param sort_field - Optional. Field to sort results by
71+
* @param sort_dir - Optional. Sort direction ('asc' or 'desc')
72+
* @param start - Optional. Pagination offset
73+
* @param count - Optional. Number of hosts to return (max 1000)
74+
* @param from - Optional. Unix timestamp to start searching from
75+
* @param include_muted_hosts_data - Optional. Include muting information
76+
* @param include_hosts_metadata - Optional. Include detailed host metadata
77+
*/
78+
export const ListHostsZodSchema = z.object({
79+
filter: z.string().optional().describe('Filter string for search results'),
80+
sort_field: z.string().optional().describe('Field to sort hosts by'),
81+
sort_dir: z.string().optional().describe('Sort direction (asc/desc)'),
82+
start: z.number().int().optional().describe('Starting offset for pagination'),
83+
count: z
84+
.number()
85+
.int()
86+
.max(1000)
87+
.optional()
88+
.describe('Max number of hosts to return (max: 1000)'),
89+
from: z
90+
.number()
91+
.int()
92+
.optional()
93+
.describe('Search hosts from this UNIX timestamp'),
94+
include_muted_hosts_data: z
95+
.boolean()
96+
.optional()
97+
.describe('Include muted hosts status and expiry'),
98+
include_hosts_metadata: z
99+
.boolean()
100+
.optional()
101+
.describe('Include host metadata (version, platform, etc)'),
102+
})

src/tools/hosts/tool.ts

+209
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
import { ExtendedTool, ToolHandlers } from '../../utils/types'
2+
import { v1 } from '@datadog/datadog-api-client'
3+
import { createToolSchema } from '../../utils/tool'
4+
import {
5+
ListHostsZodSchema,
6+
GetActiveHostsCountZodSchema,
7+
MuteHostZodSchema,
8+
UnmuteHostZodSchema,
9+
} from './schema'
10+
import { datadogConfig } from '../../utils/datadog'
11+
12+
/**
13+
* This module implements Datadog host management tools for muting, unmuting,
14+
* and retrieving host information using the Datadog API client.
15+
*/
16+
17+
/** Available host management tool names */
18+
type HostsToolName =
19+
| 'list_hosts'
20+
| 'get_active_hosts_count'
21+
| 'mute_host'
22+
| 'unmute_host'
23+
/** Extended tool type with host-specific operations */
24+
type HostsTool = ExtendedTool<HostsToolName>
25+
26+
/**
27+
* Array of available host management tools.
28+
* Each tool is created with a schema for input validation and includes a description.
29+
*/
30+
export const HOSTS_TOOLS: HostsTool[] = [
31+
createToolSchema(MuteHostZodSchema, 'mute_host', 'Mute a host in Datadog'),
32+
createToolSchema(
33+
UnmuteHostZodSchema,
34+
'unmute_host',
35+
'Unmute a host in Datadog',
36+
),
37+
createToolSchema(
38+
ListHostsZodSchema,
39+
'list_hosts',
40+
'Get list of hosts from Datadog',
41+
),
42+
createToolSchema(
43+
GetActiveHostsCountZodSchema,
44+
'get_active_hosts_count',
45+
'Get the total number of active hosts in Datadog (defaults to last 5 minutes)',
46+
),
47+
] as const
48+
49+
/** Datadog API client instance for host operations */
50+
const API_INSTANCE = new v1.HostsApi(datadogConfig)
51+
52+
/** Type definition for host management tool implementations */
53+
type HostsToolHandlers = ToolHandlers<HostsToolName>
54+
55+
/**
56+
* Implementation of host management tool handlers.
57+
* Each handler validates inputs using Zod schemas and interacts with the Datadog API.
58+
*/
59+
export const HOSTS_HANDLERS: HostsToolHandlers = {
60+
/**
61+
* Mutes a specified host in Datadog.
62+
* Silences alerts and notifications for the host until unmuted or until the specified end time.
63+
*/
64+
mute_host: async (request) => {
65+
const { hostname, message, end, override } = MuteHostZodSchema.parse(
66+
request.params.arguments,
67+
)
68+
69+
await API_INSTANCE.muteHost({
70+
hostName: hostname,
71+
body: {
72+
message,
73+
end,
74+
override,
75+
},
76+
})
77+
78+
return {
79+
content: [
80+
{
81+
type: 'text',
82+
text: JSON.stringify(
83+
{
84+
status: 'success',
85+
message: `Host ${hostname} has been muted successfully${message ? ` with message: ${message}` : ''}${end ? ` until ${new Date(end * 1000).toISOString()}` : ''}`,
86+
},
87+
null,
88+
2,
89+
),
90+
},
91+
],
92+
}
93+
},
94+
95+
/**
96+
* Unmutes a previously muted host in Datadog.
97+
* Re-enables alerts and notifications for the specified host.
98+
*/
99+
unmute_host: async (request) => {
100+
const { hostname } = UnmuteHostZodSchema.parse(request.params.arguments)
101+
102+
await API_INSTANCE.unmuteHost({
103+
hostName: hostname,
104+
})
105+
106+
return {
107+
content: [
108+
{
109+
type: 'text',
110+
text: JSON.stringify(
111+
{
112+
status: 'success',
113+
message: `Host ${hostname} has been unmuted successfully`,
114+
},
115+
null,
116+
2,
117+
),
118+
},
119+
],
120+
}
121+
},
122+
123+
/**
124+
* Retrieves counts of active and up hosts in Datadog.
125+
* Provides total counts of hosts that are reporting and operational.
126+
*/
127+
get_active_hosts_count: async (request) => {
128+
const { from } = GetActiveHostsCountZodSchema.parse(
129+
request.params.arguments,
130+
)
131+
132+
const response = await API_INSTANCE.getHostTotals({
133+
from,
134+
})
135+
136+
return {
137+
content: [
138+
{
139+
type: 'text',
140+
text: JSON.stringify(
141+
{
142+
total_active: response.totalActive || 0, // Total number of active hosts (UP and reporting) to Datadog
143+
total_up: response.totalUp || 0, // Number of hosts that are UP and reporting to Datadog
144+
},
145+
null,
146+
2,
147+
),
148+
},
149+
],
150+
}
151+
},
152+
153+
/**
154+
* Lists and filters hosts monitored by Datadog.
155+
* Supports comprehensive querying with filtering, sorting, and pagination.
156+
* Returns detailed host information including status, metadata, and monitoring data.
157+
*/
158+
list_hosts: async (request) => {
159+
const {
160+
filter,
161+
sort_field,
162+
sort_dir,
163+
start,
164+
count,
165+
from,
166+
include_muted_hosts_data,
167+
include_hosts_metadata,
168+
} = ListHostsZodSchema.parse(request.params.arguments)
169+
170+
const response = await API_INSTANCE.listHosts({
171+
filter,
172+
sortField: sort_field,
173+
sortDir: sort_dir,
174+
start,
175+
count,
176+
from,
177+
includeMutedHostsData: include_muted_hosts_data,
178+
includeHostsMetadata: include_hosts_metadata,
179+
})
180+
181+
if (!response.hostList) {
182+
throw new Error('No hosts data returned')
183+
}
184+
185+
// Transform API response into a more convenient format
186+
const hosts = response.hostList.map((host) => ({
187+
name: host.name,
188+
id: host.id,
189+
aliases: host.aliases,
190+
apps: host.apps,
191+
mute: host.isMuted,
192+
last_reported: host.lastReportedTime,
193+
meta: host.meta,
194+
metrics: host.metrics,
195+
sources: host.sources,
196+
up: host.up,
197+
url: `https://${datadogConfig.site}/infrastructure?host=${host.name}`,
198+
}))
199+
200+
return {
201+
content: [
202+
{
203+
type: 'text',
204+
text: `Hosts: ${JSON.stringify(hosts)}`,
205+
},
206+
],
207+
}
208+
},
209+
} as const

0 commit comments

Comments
 (0)