datadog-mcp 5.4.0 → 5.5.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/dist/index.js CHANGED
@@ -134929,7 +134929,7 @@ var require_InputSchema = __commonJS({
134929
134929
  "use strict";
134930
134930
  Object.defineProperty(exports, "__esModule", { value: true });
134931
134931
  exports.InputSchema = void 0;
134932
- var InputSchema21 = class _InputSchema {
134932
+ var InputSchema24 = class _InputSchema {
134933
134933
  constructor() {
134934
134934
  }
134935
134935
  /**
@@ -134939,8 +134939,8 @@ var require_InputSchema = __commonJS({
134939
134939
  return _InputSchema.attributeTypeMap;
134940
134940
  }
134941
134941
  };
134942
- exports.InputSchema = InputSchema21;
134943
- InputSchema21.attributeTypeMap = {
134942
+ exports.InputSchema = InputSchema24;
134943
+ InputSchema24.attributeTypeMap = {
134944
134944
  parameters: {
134945
134945
  baseName: "parameters",
134946
134946
  type: "Array<InputSchemaParameters>"
@@ -281731,10 +281731,10 @@ var require_object_inspect = __commonJS({
281731
281731
  }
281732
281732
  if (!isDate(obj) && !isRegExp(obj)) {
281733
281733
  var ys = arrObjKeys(obj, inspect);
281734
- var isPlainObject3 = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object;
281734
+ var isPlainObject4 = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object;
281735
281735
  var protoTag = obj instanceof Object ? "" : "null prototype";
281736
- var stringTag = !isPlainObject3 && toStringTag && Object(obj) === obj && toStringTag in obj ? $slice.call(toStr(obj), 8, -1) : protoTag ? "Object" : "";
281737
- var constructorTag = isPlainObject3 || typeof obj.constructor !== "function" ? "" : obj.constructor.name ? obj.constructor.name + " " : "";
281736
+ var stringTag = !isPlainObject4 && toStringTag && Object(obj) === obj && toStringTag in obj ? $slice.call(toStr(obj), 8, -1) : protoTag ? "Object" : "";
281737
+ var constructorTag = isPlainObject4 || typeof obj.constructor !== "function" ? "" : obj.constructor.name ? obj.constructor.name + " " : "";
281738
281738
  var tag = constructorTag + (stringTag || protoTag ? "[" + $join.call($concat.call([], stringTag || [], protoTag || []), ": ") + "] " : "");
281739
281739
  if (ys.length === 0) {
281740
281740
  return tag + "{}";
@@ -302583,7 +302583,10 @@ function createDatadogClients(config2) {
302583
302583
  usage: new import_datadog_api_client.v1.UsageMeteringApi(configuration),
302584
302584
  spans: new import_datadog_api_client.v2.SpansApi(configuration),
302585
302585
  services: new import_datadog_api_client.v2.ServiceDefinitionApi(configuration),
302586
- auth: new import_datadog_api_client.v1.AuthenticationApi(configuration)
302586
+ auth: new import_datadog_api_client.v1.AuthenticationApi(configuration),
302587
+ logsPipelines: new import_datadog_api_client.v1.LogsPipelinesApi(configuration),
302588
+ logsIndexes: new import_datadog_api_client.v1.LogsIndexesApi(configuration),
302589
+ logsArchives: new import_datadog_api_client.v2.LogsArchivesApi(configuration)
302587
302590
  };
302588
302591
  }
302589
302592
 
@@ -302661,7 +302664,8 @@ var WRITE_ACTIONS = /* @__PURE__ */ new Set([
302661
302664
  "unmute",
302662
302665
  "cancel",
302663
302666
  "add",
302664
- "trigger"
302667
+ "trigger",
302668
+ "reorder"
302665
302669
  ]);
302666
302670
  function checkReadOnly(action, readOnly) {
302667
302671
  if (readOnly && WRITE_ACTIONS.has(action)) {
@@ -303905,6 +303909,98 @@ var InputSchema2 = {
303905
303909
  ),
303906
303910
  maxEvents: external_exports.number().min(1).max(5e3).optional().describe("Maximum events to fetch for top action (default: 5000, max: 5000)")
303907
303911
  };
303912
+ var MonitorThresholdsSchema = external_exports.object({
303913
+ critical: external_exports.number().optional(),
303914
+ warning: external_exports.number().optional(),
303915
+ ok: external_exports.number().optional(),
303916
+ criticalRecovery: external_exports.number().optional(),
303917
+ warningRecovery: external_exports.number().optional(),
303918
+ unknown: external_exports.number().optional()
303919
+ }).passthrough();
303920
+ var MonitorThresholdWindowsSchema = external_exports.object({
303921
+ triggerWindow: external_exports.string().optional(),
303922
+ recoveryWindow: external_exports.string().optional()
303923
+ }).passthrough();
303924
+ var SchedulingOptionsSchema = external_exports.object({
303925
+ evaluationWindow: external_exports.record(external_exports.unknown()).optional(),
303926
+ customSchedule: external_exports.record(external_exports.unknown()).optional()
303927
+ }).passthrough();
303928
+ var MonitorOptionsSchema = external_exports.object({
303929
+ // Notification
303930
+ notifyNoData: external_exports.boolean().optional(),
303931
+ noDataTimeframe: external_exports.number().optional(),
303932
+ notifyAudit: external_exports.boolean().optional(),
303933
+ notificationPresetName: external_exports.string().optional(),
303934
+ // Evaluation / delay
303935
+ newHostDelay: external_exports.number().optional(),
303936
+ newGroupDelay: external_exports.number().optional(),
303937
+ evaluationDelay: external_exports.number().optional(),
303938
+ requireFullWindow: external_exports.boolean().optional(),
303939
+ onMissingData: external_exports.string().optional(),
303940
+ // Renotification
303941
+ renotifyInterval: external_exports.number().nullable().optional(),
303942
+ renotifyOccurrences: external_exports.number().optional(),
303943
+ renotifyStatuses: external_exports.array(external_exports.string()).optional(),
303944
+ escalationMessage: external_exports.string().optional(),
303945
+ // Lifecycle
303946
+ timeoutH: external_exports.number().nullable().optional(),
303947
+ includeTags: external_exports.boolean().optional(),
303948
+ locked: external_exports.boolean().optional(),
303949
+ silenced: external_exports.record(external_exports.number().nullable()).optional(),
303950
+ groupRetentionDuration: external_exports.string().optional(),
303951
+ // Thresholds & scheduling
303952
+ thresholds: MonitorThresholdsSchema.optional(),
303953
+ thresholdWindows: MonitorThresholdWindowsSchema.optional(),
303954
+ schedulingOptions: SchedulingOptionsSchema.optional()
303955
+ }).passthrough();
303956
+ var MonitorConfigSchema = external_exports.object({
303957
+ name: external_exports.string().optional(),
303958
+ type: external_exports.string().optional(),
303959
+ query: external_exports.string().optional(),
303960
+ message: external_exports.string().optional(),
303961
+ tags: external_exports.array(external_exports.string()).optional(),
303962
+ priority: external_exports.number().int().min(1).max(5).nullable().optional(),
303963
+ restrictedRoles: external_exports.array(external_exports.string()).nullable().optional(),
303964
+ multi: external_exports.boolean().optional(),
303965
+ options: MonitorOptionsSchema.optional()
303966
+ }).passthrough();
303967
+ var KNOWN_TOP_LEVEL_KEYS = new Set(
303968
+ Object.keys(MonitorConfigSchema.shape).filter((key) => key !== "options")
303969
+ );
303970
+ var KNOWN_OPTIONS_KEYS = new Set(
303971
+ Object.keys(MonitorOptionsSchema.shape)
303972
+ );
303973
+ function collectUnknownKeyWarnings(config2) {
303974
+ const warnings = [];
303975
+ for (const key of Object.keys(config2)) {
303976
+ if (!KNOWN_TOP_LEVEL_KEYS.has(key) && key !== "options") {
303977
+ warnings.push(`unknown top-level key '${key}' under config forwarded without validation`);
303978
+ }
303979
+ }
303980
+ const options = config2.options;
303981
+ if (isPlainObject3(options)) {
303982
+ for (const key of Object.keys(options)) {
303983
+ if (!KNOWN_OPTIONS_KEYS.has(key)) {
303984
+ warnings.push(
303985
+ `unknown option key '${key}' under config.options forwarded without validation`
303986
+ );
303987
+ }
303988
+ }
303989
+ }
303990
+ return warnings;
303991
+ }
303992
+ function isPlainObject3(value) {
303993
+ return typeof value === "object" && value !== null && !Array.isArray(value);
303994
+ }
303995
+ function summarizeZodIssue(error2) {
303996
+ const issue2 = error2.issues[0];
303997
+ if (!issue2) {
303998
+ return "validation failed";
303999
+ }
304000
+ const path = issue2.path.length > 0 ? issue2.path.join(".") : "<root>";
304001
+ const expected = issue2.code === "invalid_type" && "expected" in issue2 ? `expected ${String(issue2.expected)}` : issue2.message;
304002
+ return `${path}: ${expected}`;
304003
+ }
303908
304004
  function formatMonitor(m, site = "datadoghq.com") {
303909
304005
  const monitorId = m.id ?? 0;
303910
304006
  return {
@@ -304012,6 +304108,11 @@ function normalizeMonitorConfig(config2, isUpdate = false) {
304012
304108
  ["include_tags", "includeTags"],
304013
304109
  ["require_full_window", "requireFullWindow"],
304014
304110
  ["escalation_message", "escalationMessage"],
304111
+ ["notification_preset_name", "notificationPresetName"],
304112
+ ["on_missing_data", "onMissingData"],
304113
+ ["group_retention_duration", "groupRetentionDuration"],
304114
+ ["threshold_windows", "thresholdWindows"],
304115
+ ["scheduling_options", "schedulingOptions"],
304015
304116
  ["locked", "locked"],
304016
304117
  ["silenced", "silenced"]
304017
304118
  ];
@@ -304043,21 +304144,49 @@ function normalizeMonitorConfig(config2, isUpdate = false) {
304043
304144
  return normalized;
304044
304145
  }
304045
304146
  async function createMonitor(api, config2, site = "datadoghq.com") {
304046
- const body = normalizeMonitorConfig(config2);
304147
+ const normalized = normalizeMonitorConfig(config2);
304148
+ try {
304149
+ MonitorConfigSchema.parse(normalized);
304150
+ } catch (error2) {
304151
+ if (error2 instanceof external_exports.ZodError) {
304152
+ throw new Error(`EINVALID_MONITOR_CONFIG: ${summarizeZodIssue(error2)}`);
304153
+ }
304154
+ throw error2;
304155
+ }
304156
+ const warnings = collectUnknownKeyWarnings(normalized);
304157
+ const body = normalized;
304047
304158
  const monitor = await api.createMonitor({ body });
304048
- return {
304159
+ const result = {
304049
304160
  success: true,
304050
304161
  monitor: formatMonitorDetail(monitor, site)
304051
304162
  };
304163
+ if (warnings.length > 0) {
304164
+ result.warnings = warnings;
304165
+ }
304166
+ return result;
304052
304167
  }
304053
304168
  async function updateMonitor(api, id, config2, site = "datadoghq.com") {
304054
304169
  const monitorId = Number.parseInt(id, 10);
304055
- const body = normalizeMonitorConfig(config2, true);
304170
+ const normalized = normalizeMonitorConfig(config2, true);
304171
+ try {
304172
+ MonitorConfigSchema.parse(normalized);
304173
+ } catch (error2) {
304174
+ if (error2 instanceof external_exports.ZodError) {
304175
+ throw new Error(`EINVALID_MONITOR_CONFIG: ${summarizeZodIssue(error2)}`);
304176
+ }
304177
+ throw error2;
304178
+ }
304179
+ const warnings = collectUnknownKeyWarnings(normalized);
304180
+ const body = normalized;
304056
304181
  const monitor = await api.updateMonitor({ monitorId, body });
304057
- return {
304182
+ const result = {
304058
304183
  success: true,
304059
304184
  monitor: formatMonitorDetail(monitor, site)
304060
304185
  };
304186
+ if (warnings.length > 0) {
304187
+ result.warnings = warnings;
304188
+ }
304189
+ return result;
304061
304190
  }
304062
304191
  async function deleteMonitor(api, id) {
304063
304192
  const monitorId = Number.parseInt(id, 10);
@@ -304212,7 +304341,21 @@ function registerMonitorsTool(server, api, eventsApi, limits, readOnly = false,
304212
304341
  "monitors",
304213
304342
  `Manage Datadog monitors. Actions: list, get, search, create, update, delete, mute, unmute, top.
304214
304343
  Filters: name, tags, groupStates (alert/warn/ok/no data).
304215
- get/create/update return the full options object (notify_no_data, renotify_interval, thresholds, etc.) so callers can safely read-then-patch.
304344
+ get/create/update return the full options object so callers can safely read-then-patch.
304345
+
304346
+ create/update accept a config object validated against a typed schema covering the documented Datadog Monitor fields:
304347
+ - Top-level: name, type, query, message, tags, priority (1-5, nullable), restrictedRoles, multi, options.
304348
+ - options.* validated keys grouped by category:
304349
+ - notification: notifyNoData, noDataTimeframe, notifyAudit, notificationPresetName.
304350
+ - evaluation/delay: newHostDelay, newGroupDelay, evaluationDelay, requireFullWindow, onMissingData.
304351
+ - renotification: renotifyInterval (nullable), renotifyOccurrences, renotifyStatuses, escalationMessage.
304352
+ - lifecycle: timeoutH (nullable), includeTags, locked, silenced (record of timestamps/null), groupRetentionDuration.
304353
+ - thresholds: thresholds (critical/warning/ok/criticalRecovery/warningRecovery/unknown), thresholdWindows.
304354
+ - scheduling: schedulingOptions.
304355
+ Unknown keys (top-level or under options) are forwarded to Datadog as-is and surfaced via an optional warnings array on the response, so the schema does not lag the API.
304356
+ snake_case aliases are accepted on input and normalized to camelCase before validation.
304357
+ Validation errors short-circuit before any HTTP call and surface as 'EINVALID_MONITOR_CONFIG: <path>: <expected>'.
304358
+ Reference: https://docs.datadoghq.com/api/latest/monitors/
304216
304359
 
304217
304360
  top: Ranked monitors by alert frequency with real monitor names and context breakdown.
304218
304361
  - Returns: {rank, monitor_id, name (with {{template.vars}}), message (template), total_count, by_context}
@@ -305584,6 +305727,22 @@ function registerIncidentsTool(server, api, limits, readOnly = false, _site = "d
305584
305727
  );
305585
305728
  }
305586
305729
 
305730
+ // src/utils/normalize.ts
305731
+ function snakeToCamel2(str) {
305732
+ return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
305733
+ }
305734
+ function normalizeConfigKeys(obj) {
305735
+ if (obj === null || obj === void 0) return obj;
305736
+ if (Array.isArray(obj)) return obj.map(normalizeConfigKeys);
305737
+ if (typeof obj !== "object") return obj;
305738
+ const normalized = {};
305739
+ for (const [key, value] of Object.entries(obj)) {
305740
+ const camelKey = snakeToCamel2(key);
305741
+ normalized[camelKey] = normalizeConfigKeys(value);
305742
+ }
305743
+ return normalized;
305744
+ }
305745
+
305587
305746
  // src/tools/slos.ts
305588
305747
  var ActionSchema8 = external_exports.enum(["list", "get", "create", "update", "delete", "history"]);
305589
305748
  var InputSchema8 = {
@@ -305599,7 +305758,7 @@ var InputSchema8 = {
305599
305758
  };
305600
305759
  function formatSlo(s) {
305601
305760
  const primaryThreshold = s.thresholds?.[0];
305602
- return {
305761
+ const summary = {
305603
305762
  id: s.id ?? "",
305604
305763
  name: s.name ?? "",
305605
305764
  description: s.description ?? null,
@@ -305617,11 +305776,24 @@ function formatSlo(s) {
305617
305776
  createdAt: s.createdAt ? new Date(s.createdAt * 1e3).toISOString() : "",
305618
305777
  modifiedAt: s.modifiedAt ? new Date(s.modifiedAt * 1e3).toISOString() : ""
305619
305778
  };
305779
+ if (s.query?.numerator && s.query.denominator) {
305780
+ summary.query = { numerator: s.query.numerator, denominator: s.query.denominator };
305781
+ }
305782
+ if (Array.isArray(s.monitorIds) && s.monitorIds.length > 0) {
305783
+ summary.monitorIds = s.monitorIds;
305784
+ }
305785
+ if (Array.isArray(s.monitorTags) && s.monitorTags.length > 0) {
305786
+ summary.monitorTags = s.monitorTags;
305787
+ }
305788
+ if (Array.isArray(s.groups) && s.groups.length > 0) {
305789
+ summary.groups = s.groups;
305790
+ }
305791
+ return summary;
305620
305792
  }
305621
305793
  function formatSearchSlo(slo) {
305622
305794
  const attrs = slo.data?.attributes;
305623
305795
  const primaryThreshold = attrs?.thresholds?.[0];
305624
- return {
305796
+ const summary = {
305625
305797
  id: slo.data?.id ?? "",
305626
305798
  name: attrs?.name ?? "",
305627
305799
  description: attrs?.description ?? null,
@@ -305645,6 +305817,16 @@ function formatSearchSlo(slo) {
305645
305817
  createdAt: attrs?.createdAt ? new Date(attrs.createdAt * 1e3).toISOString() : "",
305646
305818
  modifiedAt: attrs?.modifiedAt ? new Date(attrs.modifiedAt * 1e3).toISOString() : ""
305647
305819
  };
305820
+ if (attrs?.query?.numerator && attrs.query.denominator) {
305821
+ summary.query = { numerator: attrs.query.numerator, denominator: attrs.query.denominator };
305822
+ }
305823
+ if (Array.isArray(attrs?.monitorIds) && attrs.monitorIds.length > 0) {
305824
+ summary.monitorIds = attrs.monitorIds;
305825
+ }
305826
+ if (Array.isArray(attrs?.groups) && attrs.groups.length > 0) {
305827
+ summary.groups = attrs.groups;
305828
+ }
305829
+ return summary;
305648
305830
  }
305649
305831
  function buildSearchQuery(query, tags) {
305650
305832
  const parts = [];
@@ -305680,20 +305862,6 @@ async function getSlo(api, id) {
305680
305862
  slo: response.data ? formatSlo(response.data) : null
305681
305863
  };
305682
305864
  }
305683
- function snakeToCamel2(str) {
305684
- return str.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
305685
- }
305686
- function normalizeConfigKeys(obj) {
305687
- if (obj === null || obj === void 0) return obj;
305688
- if (Array.isArray(obj)) return obj.map(normalizeConfigKeys);
305689
- if (typeof obj !== "object") return obj;
305690
- const normalized = {};
305691
- for (const [key, value] of Object.entries(obj)) {
305692
- const camelKey = snakeToCamel2(key);
305693
- normalized[camelKey] = normalizeConfigKeys(value);
305694
- }
305695
- return normalized;
305696
- }
305697
305865
  function normalizeSloConfig(config2) {
305698
305866
  const normalized = normalizeConfigKeys(config2);
305699
305867
  if (!normalized.name) {
@@ -307944,6 +308112,488 @@ function registerSchemaTool(server) {
307944
308112
  );
307945
308113
  }
307946
308114
 
308115
+ // src/tools/logs_pipelines.ts
308116
+ var ActionSchema20 = external_exports.enum(["list", "get", "create", "update", "delete", "reorder", "get_order"]);
308117
+ var InputSchema21 = {
308118
+ action: ActionSchema20.describe("Action to perform"),
308119
+ id: external_exports.string().optional().describe("Pipeline ID (required for get/update/delete)"),
308120
+ config: external_exports.record(external_exports.unknown()).optional().describe(
308121
+ "Pipeline configuration (for create/update). Requires name and filter.query. Processors are forwarded unchanged."
308122
+ ),
308123
+ pipeline_ids: external_exports.array(external_exports.string()).optional().describe("Ordered pipeline ID list (required for reorder)"),
308124
+ verbose: external_exports.boolean().optional().describe("Return full SDK payload alongside summary (default false)")
308125
+ };
308126
+ function formatPipeline(p, verbose = false) {
308127
+ const summary = {
308128
+ id: p.id ?? "",
308129
+ name: p.name ?? "",
308130
+ filterQuery: p.filter?.query ?? null,
308131
+ isEnabled: p.isEnabled ?? false,
308132
+ isReadOnly: p.isReadOnly ?? false,
308133
+ type: p.type ?? null,
308134
+ processorsCount: p.processors?.length ?? 0
308135
+ };
308136
+ if (verbose && p.processors) {
308137
+ summary.processors = p.processors;
308138
+ }
308139
+ return summary;
308140
+ }
308141
+ function normalizePipelineConfig(config2) {
308142
+ const normalized = normalizeConfigKeys(config2);
308143
+ if (!normalized.name) {
308144
+ throw new Error("Pipeline config requires 'name' field");
308145
+ }
308146
+ const filter = normalized.filter;
308147
+ if (!filter || typeof filter.query !== "string" || filter.query.length === 0) {
308148
+ throw new Error("Pipeline config requires 'filter.query' field");
308149
+ }
308150
+ return normalized;
308151
+ }
308152
+ async function listPipelines(api, verbose = false) {
308153
+ const response = await api.listLogsPipelines();
308154
+ const pipelines = (response ?? []).map((p) => formatPipeline(p, verbose));
308155
+ const result = { pipelines, total: pipelines.length };
308156
+ if (verbose) {
308157
+ result.raw = response;
308158
+ }
308159
+ return result;
308160
+ }
308161
+ async function getPipeline(api, id, verbose = false) {
308162
+ const response = await api.getLogsPipeline({ pipelineId: id });
308163
+ const result = { pipeline: formatPipeline(response, verbose) };
308164
+ if (verbose) {
308165
+ result.raw = response;
308166
+ }
308167
+ return result;
308168
+ }
308169
+ async function createPipeline(api, config2, verbose = false) {
308170
+ const body = normalizePipelineConfig(config2);
308171
+ const response = await api.createLogsPipeline({ body });
308172
+ const result = {
308173
+ success: true,
308174
+ pipeline: formatPipeline(response, verbose)
308175
+ };
308176
+ if (verbose) {
308177
+ result.raw = response;
308178
+ }
308179
+ return result;
308180
+ }
308181
+ async function updatePipeline(api, id, config2, verbose = false) {
308182
+ const body = normalizePipelineConfig(config2);
308183
+ const response = await api.updateLogsPipeline({ pipelineId: id, body });
308184
+ const result = {
308185
+ success: true,
308186
+ pipeline: formatPipeline(response, verbose)
308187
+ };
308188
+ if (verbose) {
308189
+ result.raw = response;
308190
+ }
308191
+ return result;
308192
+ }
308193
+ async function deletePipeline(api, id) {
308194
+ await api.deleteLogsPipeline({ pipelineId: id });
308195
+ return {
308196
+ success: true,
308197
+ message: `Pipeline ${id} deleted`
308198
+ };
308199
+ }
308200
+ async function reorderPipelines(api, pipelineIds) {
308201
+ const body = { pipelineIds };
308202
+ const response = await api.updateLogsPipelineOrder({ body });
308203
+ return {
308204
+ success: true,
308205
+ order: {
308206
+ pipelineIds: response.pipelineIds ?? []
308207
+ }
308208
+ };
308209
+ }
308210
+ async function getPipelineOrder(api) {
308211
+ const response = await api.getLogsPipelineOrder();
308212
+ return {
308213
+ order: {
308214
+ pipelineIds: response.pipelineIds ?? []
308215
+ }
308216
+ };
308217
+ }
308218
+ function registerLogsPipelinesTool(server, api, _limits, readOnly = false, _site = "datadoghq.com") {
308219
+ server.tool(
308220
+ "logs_pipelines",
308221
+ "Manage Datadog Logs pipelines (parsing & processor chains). Actions: list, get, create, update, delete, reorder, get_order. Pipelines run sequentially on incoming logs; reorder changes the structure of downstream data. Mutations are blocked when the server is in read-only mode. Unknown processor types in 'config.processors' are forwarded to Datadog unchanged.",
308222
+ InputSchema21,
308223
+ async ({ action, id, config: config2, pipeline_ids, verbose }) => {
308224
+ try {
308225
+ checkReadOnly(action, readOnly);
308226
+ const isVerbose = verbose ?? false;
308227
+ switch (action) {
308228
+ case "list":
308229
+ return toolResult(await listPipelines(api, isVerbose));
308230
+ case "get": {
308231
+ const pipelineId = requireParam(id, "id", "get");
308232
+ return toolResult(await getPipeline(api, pipelineId, isVerbose));
308233
+ }
308234
+ case "create": {
308235
+ const pipelineConfig = requireParam(config2, "config", "create");
308236
+ return toolResult(await createPipeline(api, pipelineConfig, isVerbose));
308237
+ }
308238
+ case "update": {
308239
+ const pipelineId = requireParam(id, "id", "update");
308240
+ const pipelineConfig = requireParam(config2, "config", "update");
308241
+ return toolResult(await updatePipeline(api, pipelineId, pipelineConfig, isVerbose));
308242
+ }
308243
+ case "delete": {
308244
+ const pipelineId = requireParam(id, "id", "delete");
308245
+ return toolResult(await deletePipeline(api, pipelineId));
308246
+ }
308247
+ case "reorder": {
308248
+ const ids = requireParam(pipeline_ids, "pipeline_ids", "reorder");
308249
+ return toolResult(await reorderPipelines(api, ids));
308250
+ }
308251
+ case "get_order":
308252
+ return toolResult(await getPipelineOrder(api));
308253
+ default:
308254
+ throw new Error(`Unknown action: ${String(action)}`);
308255
+ }
308256
+ } catch (error2) {
308257
+ handleDatadogError(error2);
308258
+ }
308259
+ }
308260
+ );
308261
+ }
308262
+
308263
+ // src/tools/logs_indexes.ts
308264
+ var ActionSchema21 = external_exports.enum(["list", "get", "update", "reorder", "get_order"]);
308265
+ var InputSchema22 = {
308266
+ action: ActionSchema21.describe("Action to perform"),
308267
+ name: external_exports.string().optional().describe("Index name (required for get/update). Datadog identifies indexes by name, not id."),
308268
+ config: external_exports.record(external_exports.unknown()).optional().describe(
308269
+ "Index configuration (for update). Requires filter.query and numRetentionDays. Exclusion filters are forwarded unchanged."
308270
+ ),
308271
+ index_names: external_exports.array(external_exports.string()).optional().describe("Ordered index name list (required for reorder)"),
308272
+ verbose: external_exports.boolean().optional().describe("Return full SDK payload alongside summary (default false)")
308273
+ };
308274
+ function formatIndex(idx, verbose = false) {
308275
+ const summary = {
308276
+ name: idx.name ?? "",
308277
+ filterQuery: idx.filter?.query ?? null,
308278
+ exclusionFiltersCount: idx.exclusionFilters?.length ?? 0,
308279
+ numRetentionDays: idx.numRetentionDays ?? null,
308280
+ numFlexLogsRetentionDays: idx.numFlexLogsRetentionDays ?? null,
308281
+ dailyLimit: idx.dailyLimit ?? null,
308282
+ isRateLimited: idx.isRateLimited ?? false
308283
+ };
308284
+ if (verbose && idx.exclusionFilters) {
308285
+ summary.exclusionFilters = idx.exclusionFilters;
308286
+ }
308287
+ return summary;
308288
+ }
308289
+ function normalizeIndexConfig(config2) {
308290
+ const normalized = normalizeConfigKeys(config2);
308291
+ const filter = normalized.filter;
308292
+ if (!filter || typeof filter.query !== "string" || filter.query.length === 0) {
308293
+ throw new Error("Index config requires 'filter.query' field");
308294
+ }
308295
+ if (typeof normalized.numRetentionDays !== "number") {
308296
+ throw new Error("Index config requires 'numRetentionDays' field");
308297
+ }
308298
+ return normalized;
308299
+ }
308300
+ async function listIndexes(api, verbose = false) {
308301
+ const response = await api.listLogIndexes();
308302
+ const indexes = (response.indexes ?? []).map((idx) => formatIndex(idx, verbose));
308303
+ const result = { indexes, total: indexes.length };
308304
+ if (verbose) {
308305
+ result.raw = response;
308306
+ }
308307
+ return result;
308308
+ }
308309
+ async function getIndex(api, name, verbose = false) {
308310
+ const response = await api.getLogsIndex({ name });
308311
+ const result = { index: formatIndex(response, verbose) };
308312
+ if (verbose) {
308313
+ result.raw = response;
308314
+ }
308315
+ return result;
308316
+ }
308317
+ async function updateIndex(api, name, config2, verbose = false) {
308318
+ const body = normalizeIndexConfig(config2);
308319
+ const response = await api.updateLogsIndex({ name, body });
308320
+ const result = {
308321
+ success: true,
308322
+ index: formatIndex(response, verbose)
308323
+ };
308324
+ if (verbose) {
308325
+ result.raw = response;
308326
+ }
308327
+ return result;
308328
+ }
308329
+ async function reorderIndexes(api, indexNames) {
308330
+ const body = { indexNames };
308331
+ const response = await api.updateLogsIndexOrder({ body });
308332
+ return {
308333
+ success: true,
308334
+ order: {
308335
+ indexNames: response.indexNames ?? []
308336
+ }
308337
+ };
308338
+ }
308339
+ async function getIndexOrder(api) {
308340
+ const response = await api.getLogsIndexOrder();
308341
+ return {
308342
+ order: {
308343
+ indexNames: response.indexNames ?? []
308344
+ }
308345
+ };
308346
+ }
308347
+ function registerLogsIndexesTool(server, api, _limits, readOnly = false, _site = "datadoghq.com") {
308348
+ server.tool(
308349
+ "logs_indexes",
308350
+ "Manage Datadog Logs indexes (filters, retention, exclusion filters, daily limits). Actions: list, get, update, reorder, get_order. Datadog identifies indexes by 'name', not 'id'. Note: create/delete are UI-only per Datadog and not supported through the API. Mutations (update, reorder) are blocked when the server is in read-only mode.",
308351
+ InputSchema22,
308352
+ async ({ action, name, config: config2, index_names, verbose }) => {
308353
+ try {
308354
+ checkReadOnly(action, readOnly);
308355
+ const isVerbose = verbose ?? false;
308356
+ switch (action) {
308357
+ case "list":
308358
+ return toolResult(await listIndexes(api, isVerbose));
308359
+ case "get": {
308360
+ const indexName = requireParam(name, "name", "get");
308361
+ return toolResult(await getIndex(api, indexName, isVerbose));
308362
+ }
308363
+ case "update": {
308364
+ const indexName = requireParam(name, "name", "update");
308365
+ const indexConfig = requireParam(config2, "config", "update");
308366
+ return toolResult(await updateIndex(api, indexName, indexConfig, isVerbose));
308367
+ }
308368
+ case "reorder": {
308369
+ const names = requireParam(index_names, "index_names", "reorder");
308370
+ return toolResult(await reorderIndexes(api, names));
308371
+ }
308372
+ case "get_order":
308373
+ return toolResult(await getIndexOrder(api));
308374
+ default:
308375
+ throw new Error(`Unknown action: ${String(action)}`);
308376
+ }
308377
+ } catch (error2) {
308378
+ handleDatadogError(error2);
308379
+ }
308380
+ }
308381
+ );
308382
+ }
308383
+
308384
+ // src/tools/logs_archives.ts
308385
+ var ActionSchema22 = external_exports.enum(["list", "get", "create", "update", "delete", "reorder", "get_order"]);
308386
+ var InputSchema23 = {
308387
+ action: ActionSchema22.describe("Action to perform"),
308388
+ id: external_exports.string().optional().describe("Archive ID (required for get/update/delete)"),
308389
+ config: external_exports.record(external_exports.unknown()).optional().describe(
308390
+ "Archive configuration (for create/update). Requires name, query, and destination with type \u2208 { s3, gcs, azure_storage }. Provider credential / integration fields are forwarded unchanged."
308391
+ ),
308392
+ archive_ids: external_exports.array(external_exports.string()).optional().describe("Ordered archive ID list (required for reorder)"),
308393
+ verbose: external_exports.boolean().optional().describe("Return full SDK payload alongside summary (default false)")
308394
+ };
308395
+ var VALID_DESTINATION_TYPES = ["s3", "gcs", "azure_storage"];
308396
+ function extractDestinationContainer(destination) {
308397
+ if (!destination || typeof destination !== "object") return null;
308398
+ const dest = destination;
308399
+ if (typeof dest.bucket === "string") return dest.bucket;
308400
+ if (typeof dest.container === "string") return dest.container;
308401
+ return null;
308402
+ }
308403
+ function formatArchive(archive, verbose = false) {
308404
+ const attrs = archive.attributes;
308405
+ const destination = attrs?.destination ?? null;
308406
+ const destinationType = destination && typeof destination === "object" && "type" in destination ? String(destination.type ?? "") : "";
308407
+ const summary = {
308408
+ id: archive.id ?? "",
308409
+ name: attrs?.name ?? "",
308410
+ query: attrs?.query ?? null,
308411
+ destinationType,
308412
+ destinationContainer: extractDestinationContainer(destination),
308413
+ includeTags: attrs?.includeTags ?? false,
308414
+ rehydrationTags: attrs?.rehydrationTags ?? [],
308415
+ state: attrs?.state ?? null
308416
+ };
308417
+ if (verbose && destination) {
308418
+ summary.destination = destination;
308419
+ }
308420
+ return summary;
308421
+ }
308422
+ function normalizeArchiveConfig(config2) {
308423
+ const normalized = normalizeConfigKeys(config2);
308424
+ if (typeof normalized.name !== "string" || normalized.name.length === 0) {
308425
+ throw new Error("Archive config requires 'name' field");
308426
+ }
308427
+ if (typeof normalized.query !== "string" || normalized.query.length === 0) {
308428
+ throw new Error("Archive config requires 'query' field");
308429
+ }
308430
+ const destination = normalized.destination;
308431
+ if (!destination || typeof destination !== "object") {
308432
+ throw new Error("Archive config requires 'destination' object");
308433
+ }
308434
+ const destinationType = destination.type;
308435
+ if (typeof destinationType !== "string" || !VALID_DESTINATION_TYPES.includes(destinationType)) {
308436
+ throw new Error("destination.type must be one of: s3, gcs, azure_storage");
308437
+ }
308438
+ if (destinationType === "azure_storage") {
308439
+ ;
308440
+ destination.type = "azure";
308441
+ }
308442
+ return normalized;
308443
+ }
308444
+ function buildArchiveRequestBody(normalizedConfig) {
308445
+ const { name, query, destination, includeTags, rehydrationTags, rehydrationMaxScanSizeInGb } = normalizedConfig;
308446
+ const attributes = {
308447
+ name,
308448
+ query,
308449
+ destination
308450
+ };
308451
+ if (includeTags !== void 0) attributes.includeTags = includeTags;
308452
+ if (rehydrationTags !== void 0) attributes.rehydrationTags = rehydrationTags;
308453
+ if (rehydrationMaxScanSizeInGb !== void 0) {
308454
+ attributes.rehydrationMaxScanSizeInGb = rehydrationMaxScanSizeInGb;
308455
+ }
308456
+ return {
308457
+ data: {
308458
+ type: "archives",
308459
+ attributes
308460
+ }
308461
+ };
308462
+ }
308463
+ async function listArchives(api, verbose = false) {
308464
+ const response = await api.listLogsArchives();
308465
+ const archives = (response.data ?? []).map((archive) => formatArchive(archive, verbose));
308466
+ const result = { archives, total: archives.length };
308467
+ if (verbose) {
308468
+ result.raw = response;
308469
+ }
308470
+ return result;
308471
+ }
308472
+ async function getArchive(api, id, verbose = false) {
308473
+ const response = await api.getLogsArchive({ archiveId: id });
308474
+ const archive = response.data;
308475
+ if (!archive) {
308476
+ throw new Error(`Archive ${id} returned an empty payload`);
308477
+ }
308478
+ const result = { archive: formatArchive(archive, verbose) };
308479
+ if (verbose) {
308480
+ result.raw = response;
308481
+ }
308482
+ return result;
308483
+ }
308484
+ async function createArchive(api, config2, verbose = false) {
308485
+ const normalized = normalizeArchiveConfig(config2);
308486
+ const body = buildArchiveRequestBody(normalized);
308487
+ const response = await api.createLogsArchive({ body });
308488
+ const archive = response.data;
308489
+ if (!archive) {
308490
+ throw new Error("Archive creation returned an empty payload");
308491
+ }
308492
+ const result = {
308493
+ success: true,
308494
+ archive: formatArchive(archive, verbose)
308495
+ };
308496
+ if (verbose) {
308497
+ result.raw = response;
308498
+ }
308499
+ return result;
308500
+ }
308501
+ async function updateArchive(api, id, config2, verbose = false) {
308502
+ const normalized = normalizeArchiveConfig(config2);
308503
+ const body = buildArchiveRequestBody(normalized);
308504
+ const response = await api.updateLogsArchive({ archiveId: id, body });
308505
+ const archive = response.data;
308506
+ if (!archive) {
308507
+ throw new Error(`Archive ${id} update returned an empty payload`);
308508
+ }
308509
+ const result = {
308510
+ success: true,
308511
+ archive: formatArchive(archive, verbose)
308512
+ };
308513
+ if (verbose) {
308514
+ result.raw = response;
308515
+ }
308516
+ return result;
308517
+ }
308518
+ async function deleteArchive(api, id) {
308519
+ await api.deleteLogsArchive({ archiveId: id });
308520
+ return {
308521
+ success: true,
308522
+ message: `Archive ${id} deleted`
308523
+ };
308524
+ }
308525
+ async function reorderArchives(api, archiveIds) {
308526
+ const body = {
308527
+ data: {
308528
+ type: "archive_order",
308529
+ attributes: {
308530
+ archiveIds
308531
+ }
308532
+ }
308533
+ };
308534
+ const response = await api.updateLogsArchiveOrder({ body });
308535
+ const resultIds = response.data?.attributes?.archiveIds ?? [];
308536
+ return {
308537
+ success: true,
308538
+ order: {
308539
+ archiveIds: resultIds
308540
+ }
308541
+ };
308542
+ }
308543
+ async function getArchiveOrder(api) {
308544
+ const response = await api.getLogsArchiveOrder();
308545
+ const resultIds = response.data?.attributes?.archiveIds ?? [];
308546
+ return {
308547
+ order: {
308548
+ archiveIds: resultIds
308549
+ }
308550
+ };
308551
+ }
308552
+ function registerLogsArchivesTool(server, api, _limits, readOnly = false, _site = "datadoghq.com") {
308553
+ server.tool(
308554
+ "logs_archives",
308555
+ "Manage Datadog Logs archives (long-term log retention to S3 / GCS / Azure Blob). Actions: list, get, create, update, delete, reorder, get_order. Archives accept destinations of type 's3', 'gcs', or 'azure_storage'; per-provider credential and integration fields (S3 IAM role ARN, GCS service account, Azure tenant/secret) are forwarded unchanged. Mutations (create, update, delete, reorder) are blocked when the server is in read-only mode.",
308556
+ InputSchema23,
308557
+ async ({ action, id, config: config2, archive_ids, verbose }) => {
308558
+ try {
308559
+ checkReadOnly(action, readOnly);
308560
+ const isVerbose = verbose ?? false;
308561
+ switch (action) {
308562
+ case "list":
308563
+ return toolResult(await listArchives(api, isVerbose));
308564
+ case "get": {
308565
+ const archiveId = requireParam(id, "id", "get");
308566
+ return toolResult(await getArchive(api, archiveId, isVerbose));
308567
+ }
308568
+ case "create": {
308569
+ const archiveConfig = requireParam(config2, "config", "create");
308570
+ return toolResult(await createArchive(api, archiveConfig, isVerbose));
308571
+ }
308572
+ case "update": {
308573
+ const archiveId = requireParam(id, "id", "update");
308574
+ const archiveConfig = requireParam(config2, "config", "update");
308575
+ return toolResult(await updateArchive(api, archiveId, archiveConfig, isVerbose));
308576
+ }
308577
+ case "delete": {
308578
+ const archiveId = requireParam(id, "id", "delete");
308579
+ return toolResult(await deleteArchive(api, archiveId));
308580
+ }
308581
+ case "reorder": {
308582
+ const ids = requireParam(archive_ids, "archive_ids", "reorder");
308583
+ return toolResult(await reorderArchives(api, ids));
308584
+ }
308585
+ case "get_order":
308586
+ return toolResult(await getArchiveOrder(api));
308587
+ default:
308588
+ throw new Error(`Unknown action: ${String(action)}`);
308589
+ }
308590
+ } catch (error2) {
308591
+ handleDatadogError(error2);
308592
+ }
308593
+ }
308594
+ );
308595
+ }
308596
+
307947
308597
  // src/tools/index.ts
307948
308598
  function registerAllTools(server, clients, limits, features, site = "datadoghq.com", datadogConfig) {
307949
308599
  const { readOnly, disabledTools } = features;
@@ -307958,6 +308608,12 @@ function registerAllTools(server, clients, limits, features, site = "datadoghq.c
307958
308608
  if (enabled("dashboards"))
307959
308609
  registerDashboardsTool(server, clients.dashboards, limits, readOnly, credentials);
307960
308610
  if (enabled("logs")) registerLogsTool(server, clients.logs, limits, site);
308611
+ if (enabled("logs_pipelines"))
308612
+ registerLogsPipelinesTool(server, clients.logsPipelines, limits, readOnly, site);
308613
+ if (enabled("logs_indexes"))
308614
+ registerLogsIndexesTool(server, clients.logsIndexes, limits, readOnly, site);
308615
+ if (enabled("logs_archives"))
308616
+ registerLogsArchivesTool(server, clients.logsArchives, limits, readOnly, site);
307961
308617
  if (enabled("metrics"))
307962
308618
  registerMetricsTool(server, clients.metricsV1, clients.metricsV2, limits, site);
307963
308619
  if (enabled("traces")) registerTracesTool(server, clients.spans, clients.services, limits, site);