Skip to main content
Glama
Nozomuts

Datadog MCP Server

by Nozomuts

search_spans

Search Datadog trace spans by query, time range, and pagination to analyze application performance and troubleshoot issues.

Instructions

Tool for searching Datadog trace spans

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
filterQueryNoQuery string to search for (optional, default is '*')*
filterFromNoSearch start time (UNIX timestamp in seconds, optional, default is 15 minutes ago)
filterToNoSearch end time (UNIX timestamp in seconds, optional, default is current time)
pageLimitNoMaximum number of spans to retrieve (optional, default is 25)
pageCursorNoCursor to retrieve the next page (optional)

Implementation Reference

  • Handler function that validates parameters using Zod schema, calls the searchSpans helper with converted timestamps, generates a formatted summary and Datadog URL, and returns success or error response.
    export const searchSpansHandler = async ( parameters: z.infer<typeof searchSpansZodSchema> ): Promise<ToolResponse> => { const validation = searchSpansZodSchema.safeParse(parameters); if (!validation.success) { return createErrorResponse( `Parameter validation error: ${validation.error.message}` ); } try { // Convert to Date objects after validation const validatedParams = { ...validation.data, filterFrom: new Date(validation.data.filterFrom * 1000), filterTo: new Date(validation.data.filterTo * 1000), }; const result = await searchSpans(validatedParams); const formattedResult = generateSummaryText(validation.data, result); const urlText = `[View in Datadog](https://app.datadoghq.com/apm/traces?query=${encodeURIComponent( validation.data.filterQuery )}&start=${validation.data.filterFrom}&end=${validation.data.filterTo})`; return createSuccessResponse([formattedResult, urlText]); } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); return createErrorResponse(`Span search error: ${errorMessage}`); } };
  • Zod schema defining the input parameters for the search_spans tool: filterQuery, filterFrom, filterTo, pageLimit, pageCursor with defaults and descriptions.
    export const searchSpansZodSchema = z.object({ filterQuery: z .string() .optional() .default("*") .describe("Query string to search for (optional, default is '*')"), filterFrom: z .number() .optional() .default(Date.now() / 1000 - 15 * 60) .describe( "Search start time (UNIX timestamp in seconds, optional, default is 15 minutes ago)" ), filterTo: z .number() .optional() .default(Date.now() / 1000) .describe( "Search end time (UNIX timestamp in seconds, optional, default is current time)" ), pageLimit: z .number() .min(1) .max(1000) .optional() .default(25) .describe("Maximum number of spans to retrieve (optional, default is 25)"), pageCursor: z .string() .optional() .describe("Cursor to retrieve the next page (optional)"), });
  • src/index.ts:25-30 (registration)
    Registration of the 'search_spans' tool in the MCP server using server.tool() with name, description, input schema, and handler.
    server.tool( "search_spans", "Tool for searching Datadog trace spans", searchSpansZodSchema.shape, searchSpansHandler );
  • Core helper function that performs the actual Datadog API call to search spans using the SpansApi, maps the response to Span objects, handles pagination cursor, and propagates errors.
    export const searchSpans = async ( params: SpanSearchParams ): Promise<SpanSearchResult> => { try { const configuration = createConfiguration(); const spansApi = new v2.SpansApi(configuration); const response = await spansApi.listSpansGet({ filterQuery: params.filterQuery, filterFrom: params.filterFrom.toISOString(), filterTo: params.filterTo.toISOString(), pageLimit: params.pageLimit || 25, pageCursor: params.pageCursor, }); if (!response.data || response.data.length === 0) { return { spans: [] }; } const spans = response.data.map((spanData) => ({ id: spanData.id || "", traceId: spanData.attributes?.traceId, spanId: spanData.attributes?.spanId, parentId: spanData.attributes?.parentId, service: spanData.attributes?.service, resource: spanData.attributes?.resourceName, host: spanData.attributes?.host, env: spanData.attributes?.env, startTimestamp: spanData.attributes?.startTimestamp?.toISOString(), endTimestamp: spanData.attributes?.endTimestamp?.toISOString(), duration: spanData.attributes?.attributes?.duration, type: spanData.attributes?.type, tags: spanData.attributes?.tags || [], attributes: spanData.attributes?.attributes || {}, })); const nextCursor = response.meta?.page?.after; return { spans, nextCursor, }; } catch (error: unknown) { const errorMessage = error instanceof Error ? error.message : String(error); console.error(`Error searching spans: ${errorMessage}`); throw new Error(`Datadog API error: ${errorMessage}`); } };
  • Helper function to generate a markdown-formatted summary text of the search results, including criteria, span summaries, and key attributes for display in responses.
    const generateSummaryText = ( data: z.infer<typeof searchSpansZodSchema>, result: SpanSearchResult ): string => { let responseText = ""; responseText += `# Span Search Results\n`; responseText += `## Search Criteria\n`; responseText += `* Query: ${data.filterQuery || "*"}\n`; responseText += `* Time Range: ${new Date( data.filterFrom * 1000 ).toLocaleString()} to ${new Date(data.filterTo * 1000).toLocaleString()}\n`; responseText += `* Retrieved: ${result.spans.length} spans`; if (result.spans.length === 0) { return responseText; } if (result.nextCursor) { responseText += `* Next Page Cursor: ${result.nextCursor}\n`; } responseText += "## Span Summary\n"; for (const [index, span] of result.spans.entries()) { responseText += `### [${index + 1}]\n`; if (span.service) { responseText += `* Service: ${span.service}\n`; } if (span.startTimestamp) { responseText += `* Time: ${new Date( span.startTimestamp ).toLocaleString()}\n`; } if (span.resource) { responseText += `* Resource: ${span.resource}\n`; } if (span.duration) { responseText += `* Duration: ${(span.duration / 1000).toFixed( 3 )} seconds\n`; } if (span.host) { responseText += `* Host: ${span.host}\n`; } if (span.env) { responseText += `* Environment: ${span.env}\n`; } if (span.type) { responseText += `* Type: ${span.type}\n`; } responseText += `#### Key Attributes\n`; for (const key of [ "http.method", "http.url", "http.status_code", "error", ]) { if (span.attributes && key in span.attributes) { responseText += `* ${key}: \`${JSON.stringify( span.attributes[key] )}\`\n`; } } } return responseText; };
Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Nozomuts/datadog-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server