Skip to content

Commit 6a5bf33

Browse files
authored
feat: add traces tool for Datadog APM trace retrieval (#6)
1 parent 01b020b commit 6a5bf33

File tree

6 files changed

+118
-1
lines changed

6 files changed

+118
-1
lines changed

README.md

+13
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,26 @@ MCP server for the Datadog API, enabling incident management and more.
5252
- **Returns**: Array of dashboards with URL references.
5353

5454
6. `get_metrics`
55+
5556
- Retrieve metrics data from Datadog.
5657
- **Inputs**:
5758
- `query` (string): Metrics query string.
5859
- `from` (number): Start time in epoch seconds.
5960
- `to` (number): End time in epoch seconds.
6061
- **Returns**: Metrics data for the queried timeframe.
6162

63+
7. `list_traces`
64+
- Retrieve a list of APM traces from Datadog.
65+
- **Inputs**:
66+
- `query` (string): Datadog APM trace query string.
67+
- `from` (number): Start time in epoch seconds.
68+
- `to` (number): End time in epoch seconds.
69+
- `limit` (optional number): Maximum number of traces to return (defaults to 100).
70+
- `sort` (optional string): Sort order for traces (defaults to '-timestamp').
71+
- `service` (optional string): Filter by service name.
72+
- `operation` (optional string): Filter by operation name.
73+
- **Returns**: Array of matching traces from Datadog APM.
74+
6275
## Setup
6376

6477
### Datadog Credentials

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@winor30/mcp-server-datadog",
3-
"version": "1.0.0",
3+
"version": "1.0.1",
44
"description": "MCP server for interacting with Datadog API",
55
"repository": {
66
"type": "git",

src/index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { METRICS_TOOLS, METRICS_HANDLERS } from './tools/metrics'
1919
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'
22+
import { TRACES_TOOLS, TRACES_HANDLERS } from './tools/traces'
2223
import { ToolHandlers } from './utils/types'
2324

2425
const server = new Server(
@@ -49,6 +50,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
4950
...LOGS_TOOLS,
5051
...MONITORS_TOOLS,
5152
...DASHBOARDS_TOOLS,
53+
...TRACES_TOOLS,
5254
],
5355
}
5456
})
@@ -59,6 +61,7 @@ const TOOL_HANDLERS: ToolHandlers = {
5961
...LOGS_HANDLERS,
6062
...MONITORS_HANDLERS,
6163
...DASHBOARDS_HANDLERS,
64+
...TRACES_HANDLERS,
6265
}
6366
/**
6467
* Handler for invoking Datadog-related tools in the mcp-server-datadog.

src/tools/traces/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { TRACES_TOOLS, TRACES_HANDLERS } from './tool'

src/tools/traces/schema.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { z } from 'zod'
2+
3+
export const ListTracesZodSchema = z.object({
4+
query: z.string().describe('Datadog APM trace query string'),
5+
from: z.number().describe('Start time in epoch seconds'),
6+
to: z.number().describe('End time in epoch seconds'),
7+
limit: z
8+
.number()
9+
.optional()
10+
.default(100)
11+
.describe('Maximum number of traces to return'),
12+
sort: z
13+
.enum(['timestamp', '-timestamp'])
14+
.optional()
15+
.default('-timestamp')
16+
.describe('Sort order for traces'),
17+
service: z.string().optional().describe('Filter by service name'),
18+
operation: z.string().optional().describe('Filter by operation name'),
19+
})
20+
21+
export type ListTracesArgs = z.infer<typeof ListTracesZodSchema>

src/tools/traces/tool.ts

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import { ExtendedTool, ToolHandlers } from '../../utils/types'
2+
import { v2 } from '@datadog/datadog-api-client'
3+
import { createToolSchema } from '../../utils/tool'
4+
import { datadogConfig as config } from '../../utils/datadog'
5+
import { ListTracesZodSchema } from './schema'
6+
7+
type TracesToolName = 'list_traces'
8+
type TracesTool = ExtendedTool<TracesToolName>
9+
10+
export const TRACES_TOOLS: TracesTool[] = [
11+
createToolSchema(
12+
ListTracesZodSchema,
13+
'list_traces',
14+
'Get APM traces from Datadog',
15+
),
16+
] as const
17+
18+
const API_INSTANCE = new v2.SpansApi(config)
19+
20+
type TracesToolHandlers = ToolHandlers<TracesToolName>
21+
22+
export const TRACES_HANDLERS: TracesToolHandlers = {
23+
list_traces: async (request) => {
24+
const {
25+
query,
26+
from,
27+
to,
28+
limit = 100,
29+
sort = '-timestamp',
30+
service,
31+
operation,
32+
} = request.params.arguments as {
33+
query: string
34+
from: number
35+
to: number
36+
limit?: number
37+
sort?: string
38+
service?: string
39+
operation?: string
40+
}
41+
42+
const response = await API_INSTANCE.listSpans({
43+
body: {
44+
data: {
45+
attributes: {
46+
filter: {
47+
query: [
48+
query,
49+
...(service ? [`service:${service}`] : []),
50+
...(operation ? [`operation:${operation}`] : []),
51+
].join(' '),
52+
from: new Date(from * 1000).toISOString(),
53+
to: new Date(to * 1000).toISOString(),
54+
},
55+
sort: sort as 'timestamp' | '-timestamp',
56+
page: { limit },
57+
},
58+
type: 'search_request',
59+
},
60+
},
61+
})
62+
63+
if (!response.data) {
64+
throw new Error('No traces data returned')
65+
}
66+
67+
return {
68+
content: [
69+
{
70+
type: 'text',
71+
text: `Traces: ${JSON.stringify({
72+
traces: response.data,
73+
count: response.data.length,
74+
})}`,
75+
},
76+
],
77+
}
78+
},
79+
} as const

0 commit comments

Comments
 (0)