Skip to main content
Glama
ClaudioLazaro

MCP Datadog Server

http-client.js3.91 kB
import { request } from 'undici'; class DatadogHttpError extends Error { constructor(message, status, response) { super(message); this.name = 'DatadogHttpError'; this.status = status; this.response = response; } } function buildUrl(baseUrl, rawUrlTemplate, pathParams = {}) { let url = rawUrlTemplate.replace('{{baseUrl}}', baseUrl).replace('{{site}}', baseUrl.split('.').slice(-2).join('.')); for (const [key, value] of Object.entries(pathParams)) { url = url.replace(`:${key}`, encodeURIComponent(String(value))); } return url; } function buildQueryString(params) { if (!params || Object.keys(params).length === 0) return ''; const searchParams = new URLSearchParams(); for (const [key, value] of Object.entries(params)) { if (value !== undefined && value !== null) { searchParams.append(key, String(value)); } } const queryString = searchParams.toString(); return queryString ? `?${queryString}` : ''; } function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } export class DatadogClient { constructor(config) { this.config = config; this.baseUrl = `https://${config.subdomain}.${config.site}`; } async request({ method, rawUrlTemplate, pathParams = {}, query = {}, body, headers = {}, timeoutMs, }) { const url = buildUrl(this.baseUrl, rawUrlTemplate, pathParams) + buildQueryString(query); const requestHeaders = { 'DD-API-KEY': this.config.credentials.apiKey, 'DD-APPLICATION-KEY': this.config.credentials.appKey, 'User-Agent': this.config.userAgent, 'Accept': 'application/json', ...headers, }; if (body && method !== 'GET' && method !== 'HEAD') { if (typeof body === 'object') { requestHeaders['Content-Type'] = 'application/json'; } } const requestOptions = { method, headers: requestHeaders, bodyTimeout: timeoutMs || this.config.timeoutMs, headersTimeout: (timeoutMs || this.config.timeoutMs) / 2, }; if (body && method !== 'GET' && method !== 'HEAD') { requestOptions.body = typeof body === 'string' ? body : JSON.stringify(body); } let lastError; for (let attempt = 0; attempt <= this.config.maxRetries; attempt++) { try { const response = await request(url, requestOptions); const responseText = await response.body.text(); let data; try { data = responseText ? JSON.parse(responseText) : null; } catch { data = responseText; } const result = { ok: response.statusCode >= 200 && response.statusCode < 300, status: response.statusCode, statusText: response.statusMessage || '', url, method, data, headers: Object.fromEntries(Object.entries(response.headers)), }; if (!result.ok && response.statusCode >= 400) { throw new DatadogHttpError( `HTTP ${response.statusCode}: ${responseText || response.statusMessage}`, response.statusCode, result ); } return result; } catch (error) { lastError = error; if (attempt === this.config.maxRetries) break; if (error.status && error.status < 500 && error.status !== 429) { break; } let delayMs = this.config.retryBaseMs * Math.pow(2, attempt); if (error.status === 429 && this.config.respectRetryAfter) { const retryAfter = error.response?.headers?.['retry-after']; if (retryAfter) { delayMs = parseInt(retryAfter, 10) * 1000; } } delayMs = Math.min(delayMs, 30000); await sleep(delayMs); } } throw lastError; } } export { DatadogHttpError };

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/ClaudioLazaro/mcp-datadog-server'

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