datadog-mcp 2.0.2 → 4.0.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
@@ -37,12 +37,12 @@ var configSchema = z.object({
37
37
  host: z.string().default("localhost")
38
38
  }).default({}),
39
39
  limits: z.object({
40
- maxResults: z.number().default(100),
41
- maxLogLines: z.number().default(100),
42
- // Reduced from 500 for token efficiency
43
- defaultLimit: z.number().default(25),
44
- // Default limit for initial queries
45
- maxMetricDataPoints: z.number().default(1e3),
40
+ defaultLimit: z.number().default(50),
41
+ // Fallback when AI doesn't specify limit
42
+ defaultLogLines: z.number().default(200),
43
+ // Fallback when AI doesn't specify log limit
44
+ defaultMetricDataPoints: z.number().default(1e3),
45
+ // Fallback for timeseries data points
46
46
  defaultTimeRangeHours: z.number().default(24)
47
47
  }).default({}),
48
48
  features: z.object({
@@ -115,9 +115,9 @@ function loadConfig() {
115
115
  host: args.strings.host ?? process.env.MCP_HOST ?? "localhost"
116
116
  },
117
117
  limits: {
118
- maxResults: Number.parseInt(process.env.MCP_MAX_RESULTS ?? "100", 10),
119
- maxLogLines: Number.parseInt(process.env.MCP_MAX_LOG_LINES ?? "500", 10),
120
- maxMetricDataPoints: Number.parseInt(process.env.MCP_MAX_METRIC_POINTS ?? "1000", 10),
118
+ defaultLimit: Number.parseInt(process.env.MCP_DEFAULT_LIMIT ?? "50", 10),
119
+ defaultLogLines: Number.parseInt(process.env.MCP_DEFAULT_LOG_LINES ?? "200", 10),
120
+ defaultMetricDataPoints: Number.parseInt(process.env.MCP_DEFAULT_METRIC_POINTS ?? "1000", 10),
121
121
  defaultTimeRangeHours: Number.parseInt(process.env.MCP_DEFAULT_TIME_RANGE ?? "24", 10)
122
122
  },
123
123
  features: {
@@ -394,7 +394,7 @@ var InputSchema = {
394
394
  groupStates: z2.array(z2.string()).optional().describe(
395
395
  "Filter multi-alert monitors by group states (e.g., alert by host). Does NOT filter by overall monitor status. Values: alert, warn, no data, ok"
396
396
  ),
397
- limit: z2.number().optional().describe("Maximum number of monitors to return"),
397
+ limit: z2.number().min(1).optional().describe("Maximum number of monitors to return (default: 50)"),
398
398
  config: z2.record(z2.unknown()).optional().describe("Monitor configuration (for create/update)"),
399
399
  message: z2.string().optional().describe("Mute message (for mute action)"),
400
400
  end: z2.number().optional().describe("Mute end timestamp (for mute action)")
@@ -415,7 +415,7 @@ function formatMonitor(m, site = "datadoghq.com") {
415
415
  };
416
416
  }
417
417
  async function listMonitors(api, params, limits, site) {
418
- const effectiveLimit = Math.min(params.limit ?? limits.maxResults, limits.maxResults);
418
+ const effectiveLimit = params.limit ?? limits.defaultLimit;
419
419
  const response = await api.listMonitors({
420
420
  name: params.name,
421
421
  tags: params.tags?.join(","),
@@ -451,7 +451,7 @@ async function getMonitor(api, id, site) {
451
451
  }
452
452
  async function searchMonitors(api, query, limits, site) {
453
453
  const response = await api.searchMonitors({ query });
454
- const monitors = (response.monitors ?? []).slice(0, limits.maxResults).map((m) => ({
454
+ const monitors = (response.monitors ?? []).map((m) => ({
455
455
  id: m.id ?? 0,
456
456
  name: m.name ?? "",
457
457
  status: String(m.status ?? "unknown"),
@@ -632,7 +632,7 @@ var InputSchema2 = {
632
632
  id: z3.string().optional().describe("Dashboard ID (required for get/update/delete)"),
633
633
  name: z3.string().optional().describe("Filter by name"),
634
634
  tags: z3.array(z3.string()).optional().describe("Filter by tags"),
635
- limit: z3.number().optional().describe("Maximum number of dashboards to return"),
635
+ limit: z3.number().min(1).optional().describe("Maximum number of dashboards to return (default: 50)"),
636
636
  config: z3.record(z3.unknown()).optional().describe("Dashboard configuration (for create/update)")
637
637
  };
638
638
  function formatDashboardSummary(d) {
@@ -648,7 +648,7 @@ function formatDashboardSummary(d) {
648
648
  };
649
649
  }
650
650
  async function listDashboards(api, params, limits) {
651
- const effectiveLimit = Math.min(params.limit ?? limits.maxResults, limits.maxResults);
651
+ const effectiveLimit = params.limit ?? limits.defaultLimit;
652
652
  const response = await api.listDashboards({
653
653
  filterShared: false
654
654
  });
@@ -914,7 +914,7 @@ var InputSchema3 = {
914
914
  host: z4.string().optional().describe("Filter by host"),
915
915
  status: z4.enum(["error", "warn", "info", "debug"]).optional().describe("Filter by log status/level"),
916
916
  indexes: z4.array(z4.string()).optional().describe("Log indexes to search"),
917
- limit: z4.number().optional().describe("Maximum number of logs to return"),
917
+ limit: z4.number().min(1).optional().describe("Maximum number of logs to return (default: 200)"),
918
918
  sort: z4.enum(["timestamp", "-timestamp"]).optional().describe("Sort order"),
919
919
  sample: z4.enum(["first", "spread", "diverse"]).optional().describe(
920
920
  "Sampling mode: first (chronological, default), spread (evenly across time range), diverse (distinct message patterns)"
@@ -1009,6 +1009,7 @@ function diverseSample(items, limit) {
1009
1009
  patterns: seen.size
1010
1010
  };
1011
1011
  }
1012
+ var SAMPLE_DIVERSITY_MULTIPLIER = 4;
1012
1013
  function buildLogQuery(params) {
1013
1014
  const parts = [];
1014
1015
  if (params.query) {
@@ -1050,10 +1051,10 @@ async function searchLogs(api, params, limits, site) {
1050
1051
  host: params.host,
1051
1052
  status: params.status
1052
1053
  });
1053
- const requestedLimit = params.limit ?? limits.defaultLimit;
1054
+ const requestedLimit = params.limit ?? limits.defaultLogLines;
1054
1055
  const sampleMode = params.sample ?? "first";
1055
- const fetchMultiplier = sampleMode === "first" ? 1 : 4;
1056
- const fetchLimit = Math.min(requestedLimit * fetchMultiplier, limits.maxLogLines);
1056
+ const fetchMultiplier = sampleMode === "first" ? 1 : SAMPLE_DIVERSITY_MULTIPLIER;
1057
+ const fetchLimit = requestedLimit * fetchMultiplier;
1057
1058
  const body = {
1058
1059
  filter: {
1059
1060
  query: fullQuery,
@@ -1226,7 +1227,10 @@ var InputSchema4 = {
1226
1227
  to: z5.string().optional().describe('End time (ONLY for query action). Same formats as "from".'),
1227
1228
  metric: z5.string().optional().describe("Metric name (for metadata action)"),
1228
1229
  tag: z5.string().optional().describe("Filter by tag"),
1229
- limit: z5.number().optional().describe("Maximum number of results (for search/list)")
1230
+ limit: z5.number().min(1).optional().describe("Maximum number of results (for search/list, default: 50)"),
1231
+ pointLimit: z5.number().min(1).optional().describe(
1232
+ "Maximum data points per timeseries (for query action). AI controls resolution vs token usage (default: 1000)."
1233
+ )
1230
1234
  };
1231
1235
  async function queryMetrics(api, params, limits, site) {
1232
1236
  const defaultFrom = hoursAgo(limits.defaultTimeRangeHours);
@@ -1242,7 +1246,7 @@ async function queryMetrics(api, params, limits, site) {
1242
1246
  });
1243
1247
  const series = (response.series ?? []).map((s) => ({
1244
1248
  metric: s.metric ?? "",
1245
- points: (s.pointlist ?? []).slice(0, limits.maxMetricDataPoints).map((p) => ({
1249
+ points: (s.pointlist ?? []).slice(0, params.pointLimit ?? limits.defaultMetricDataPoints).map((p) => ({
1246
1250
  timestamp: p[0] ?? 0,
1247
1251
  value: p[1] ?? 0
1248
1252
  })),
@@ -1269,20 +1273,20 @@ async function searchMetrics(api, params, limits) {
1269
1273
  });
1270
1274
  const allMetrics = response.metrics ?? [];
1271
1275
  const lowerQuery = params.query.toLowerCase();
1272
- const filtered = allMetrics.filter((name) => name.toLowerCase().includes(lowerQuery)).slice(0, params.limit ?? limits.maxResults);
1276
+ const filtered = allMetrics.filter((name) => name.toLowerCase().includes(lowerQuery)).slice(0, params.limit ?? limits.defaultLimit);
1273
1277
  return {
1274
1278
  metrics: filtered,
1275
1279
  total: filtered.length,
1276
1280
  searchedFrom: allMetrics.length
1277
1281
  };
1278
1282
  }
1279
- async function listMetrics(api, params, limits) {
1283
+ async function listMetrics(api, params, _limits) {
1280
1284
  const response = await api.listActiveMetrics({
1281
1285
  from: hoursAgo(24),
1282
1286
  host: void 0,
1283
1287
  tagFilter: params.query
1284
1288
  });
1285
- const metrics = (response.metrics ?? []).slice(0, limits.maxResults);
1289
+ const metrics = response.metrics ?? [];
1286
1290
  return {
1287
1291
  metrics,
1288
1292
  total: response.metrics?.length ?? 0
@@ -1315,7 +1319,7 @@ APM METRICS (auto-generated from traces):
1315
1319
  - trace.{service}.duration - Latency (use avg:, p95:, max:)
1316
1320
  Example: max:trace.{service}.request.duration{*}`,
1317
1321
  InputSchema4,
1318
- async ({ action, query, from, to, metric, limit }) => {
1322
+ async ({ action, query, from, to, metric, limit, pointLimit }) => {
1319
1323
  try {
1320
1324
  switch (action) {
1321
1325
  case "query": {
@@ -1326,7 +1330,8 @@ Example: max:trace.{service}.request.duration{*}`,
1326
1330
  {
1327
1331
  query: metricsQuery,
1328
1332
  from,
1329
- to
1333
+ to,
1334
+ pointLimit
1330
1335
  },
1331
1336
  limits,
1332
1337
  site
@@ -1401,7 +1406,7 @@ var InputSchema5 = {
1401
1406
  ),
1402
1407
  errorType: z6.string().optional().describe('Filter by error type (grep-like). Example: "TimeoutError", "ConnectionRefused"'),
1403
1408
  errorMessage: z6.string().optional().describe('Filter by error message (grep-like). Example: "timeout", "connection refused"'),
1404
- limit: z6.number().optional().describe("Maximum number of results"),
1409
+ limit: z6.number().min(1).optional().describe("Maximum number of results (default: 50)"),
1405
1410
  sort: z6.enum(["timestamp", "-timestamp"]).optional().describe("Sort order"),
1406
1411
  groupBy: z6.array(z6.string()).optional().describe('Fields to group by (for aggregate). Example: ["resource_name", "status"]')
1407
1412
  };
@@ -1541,7 +1546,7 @@ async function searchTraces(api, params, limits, site) {
1541
1546
  },
1542
1547
  sort: params.sort === "timestamp" ? "timestamp" : "-timestamp",
1543
1548
  page: {
1544
- limit: Math.min(params.limit ?? limits.maxResults, limits.maxResults)
1549
+ limit: params.limit ?? limits.defaultLimit
1545
1550
  }
1546
1551
  }
1547
1552
  }
@@ -1633,7 +1638,7 @@ async function listApmServices(api, params, limits) {
1633
1638
  groupBy: [
1634
1639
  {
1635
1640
  facet: "service",
1636
- limit: limits.maxResults
1641
+ limit: limits.defaultLimit
1637
1642
  }
1638
1643
  ]
1639
1644
  }
@@ -1756,7 +1761,8 @@ var ActionSchema6 = z7.enum([
1756
1761
  "aggregate",
1757
1762
  "top",
1758
1763
  "timeseries",
1759
- "incidents"
1764
+ "incidents",
1765
+ "discover"
1760
1766
  ]);
1761
1767
  var InputSchema6 = {
1762
1768
  action: ActionSchema6.describe("Action to perform"),
@@ -1767,7 +1773,7 @@ var InputSchema6 = {
1767
1773
  priority: z7.enum(["normal", "low"]).optional().describe("Event priority"),
1768
1774
  sources: z7.array(z7.string()).optional().describe("Filter by sources"),
1769
1775
  tags: z7.array(z7.string()).optional().describe("Filter by tags"),
1770
- limit: z7.number().optional().describe("Maximum number of events to return"),
1776
+ limit: z7.number().min(1).optional().describe("Maximum number of events to return (default: 50)"),
1771
1777
  title: z7.string().optional().describe("Event title (for create)"),
1772
1778
  text: z7.string().optional().describe("Event text (for create)"),
1773
1779
  alertType: z7.enum(["error", "warning", "info", "success"]).optional().describe("Alert type (for create)"),
@@ -1778,7 +1784,14 @@ var InputSchema6 = {
1778
1784
  // Phase 2: Incidents deduplication
1779
1785
  dedupeWindow: z7.string().optional().describe("Deduplication window for incidents: 5m, 15m, 1h (default: 5m)"),
1780
1786
  // Phase 3: Monitor enrichment
1781
- enrich: z7.boolean().optional().describe("Enrich events with monitor metadata (slower, adds monitor details)")
1787
+ enrich: z7.boolean().optional().describe("Enrich events with monitor metadata (slower, adds monitor details)"),
1788
+ // Context tag extraction for top action
1789
+ contextTags: z7.array(z7.string()).optional().describe(
1790
+ "Tag prefixes for context breakdown in top action (default: queue, service, ingress, pod_name, kube_namespace, kube_container_name)"
1791
+ ),
1792
+ maxEvents: z7.number().min(1).max(1e4).optional().describe(
1793
+ "Maximum events to fetch for grouping in top action (default: 10000). Higher = more accurate but slower"
1794
+ )
1782
1795
  };
1783
1796
  function extractMonitorInfo(title) {
1784
1797
  const priorityMatch = title.match(/^\[P(\d+)\]\s*/);
@@ -1901,8 +1914,50 @@ function formatEventV2(e) {
1901
1914
  } : void 0
1902
1915
  };
1903
1916
  }
1917
+ function findFirstContextTag(tags, prefixes) {
1918
+ for (const tag of tags) {
1919
+ const colonIndex = tag.indexOf(":");
1920
+ if (colonIndex > 0) {
1921
+ const prefix = tag.substring(0, colonIndex);
1922
+ if (prefixes.has(prefix)) {
1923
+ return tag;
1924
+ }
1925
+ }
1926
+ }
1927
+ return null;
1928
+ }
1929
+ async function discoverTagsV2(api, params, limits, site) {
1930
+ const result = await searchEventsV2(
1931
+ api,
1932
+ {
1933
+ ...params,
1934
+ limit: 200
1935
+ },
1936
+ limits,
1937
+ site
1938
+ );
1939
+ const prefixSet = /* @__PURE__ */ new Set();
1940
+ for (const event of result.events) {
1941
+ for (const tag of event.tags) {
1942
+ if (tag.includes(":")) {
1943
+ const prefix = tag.split(":")[0];
1944
+ if (prefix) {
1945
+ prefixSet.add(prefix);
1946
+ }
1947
+ }
1948
+ }
1949
+ }
1950
+ return {
1951
+ tagPrefixes: Array.from(prefixSet).sort((a, b) => a.localeCompare(b)),
1952
+ sampleSize: result.events.length,
1953
+ meta: {
1954
+ from: result.meta.from,
1955
+ to: result.meta.to
1956
+ }
1957
+ };
1958
+ }
1904
1959
  async function listEventsV1(api, params, limits) {
1905
- const effectiveLimit = Math.min(params.limit ?? limits.defaultLimit, limits.maxResults);
1960
+ const effectiveLimit = params.limit ?? limits.defaultLimit;
1906
1961
  const defaultFrom = hoursAgo(limits.defaultTimeRangeHours);
1907
1962
  const defaultTo = now();
1908
1963
  const response = await api.listEvents({
@@ -1986,7 +2041,7 @@ async function searchEventsV2(api, params, limits, site) {
1986
2041
  tags: params.tags,
1987
2042
  priority: params.priority
1988
2043
  });
1989
- const effectiveLimit = Math.min(params.limit ?? limits.defaultLimit, limits.maxResults);
2044
+ const effectiveLimit = params.limit ?? limits.defaultLimit;
1990
2045
  const body = {
1991
2046
  filter: {
1992
2047
  query: fullQuery,
@@ -2090,34 +2145,79 @@ async function aggregateEventsV2(api, params, limits, site) {
2090
2145
  };
2091
2146
  }
2092
2147
  async function topEventsV2(api, params, limits, site) {
2148
+ if (params.contextTags !== void 0) {
2149
+ if (!Array.isArray(params.contextTags)) {
2150
+ throw new Error("contextTags must be an array");
2151
+ }
2152
+ if (params.contextTags.some((tag) => typeof tag !== "string" || tag.trim() === "")) {
2153
+ throw new Error("contextTags must be an array of non-empty strings");
2154
+ }
2155
+ }
2093
2156
  const effectiveQuery = params.query ?? "source:alert";
2094
2157
  const effectiveTags = params.tags ?? ["source:alert"];
2095
- const result = await aggregateEventsV2(
2158
+ const result = await searchEventsV2(
2096
2159
  api,
2097
2160
  {
2098
- ...params,
2099
2161
  query: effectiveQuery,
2162
+ from: params.from,
2163
+ to: params.to,
2164
+ sources: params.sources,
2100
2165
  tags: effectiveTags,
2101
- groupBy: params.groupBy ?? ["monitor_name"],
2102
- limit: params.limit ?? 10
2166
+ limit: params.maxEvents ?? 1e4
2103
2167
  },
2104
2168
  limits,
2105
2169
  site
2106
2170
  );
2107
- return {
2108
- top: result.buckets.map((bucket, index) => ({
2109
- rank: index + 1,
2110
- name: bucket.key,
2111
- monitorId: bucket.sample.monitorId,
2112
- alertCount: bucket.count,
2113
- lastAlert: bucket.sample.timestamp,
2114
- sample: {
2115
- title: bucket.sample.title,
2116
- source: bucket.sample.source,
2117
- alertType: bucket.sample.alertType
2171
+ const monitorGroups = /* @__PURE__ */ new Map();
2172
+ for (const event of result.events) {
2173
+ const monitorName = event.monitorInfo?.name ?? event.title;
2174
+ const monitorId = event.monitorId ?? 0;
2175
+ const key = `${monitorId}|${monitorName}`;
2176
+ let monitorGroup = monitorGroups.get(key);
2177
+ if (!monitorGroup) {
2178
+ monitorGroup = { name: monitorName, monitorId, events: [] };
2179
+ monitorGroups.set(key, monitorGroup);
2180
+ }
2181
+ monitorGroup.events.push(event);
2182
+ }
2183
+ const contextPrefixes = new Set(
2184
+ params.contextTags ?? [
2185
+ "queue",
2186
+ "service",
2187
+ "ingress",
2188
+ "pod_name",
2189
+ "kube_namespace",
2190
+ "kube_container_name"
2191
+ ]
2192
+ );
2193
+ const monitors = Array.from(monitorGroups.values()).map((monitor) => {
2194
+ const contextGroups = /* @__PURE__ */ new Map();
2195
+ for (const event of monitor.events) {
2196
+ const contextTag = findFirstContextTag(event.tags, contextPrefixes);
2197
+ if (contextTag) {
2198
+ contextGroups.set(contextTag, (contextGroups.get(contextTag) || 0) + 1);
2118
2199
  }
2119
- })),
2120
- meta: result.meta
2200
+ }
2201
+ return {
2202
+ name: monitor.name,
2203
+ monitor_id: monitor.monitorId,
2204
+ total_count: monitor.events.length,
2205
+ by_context: Array.from(contextGroups.entries()).map(([context, count]) => ({ context, count })).sort((a, b) => b.count - a.count)
2206
+ // Sort by count desc
2207
+ };
2208
+ }).filter((monitor) => monitor.by_context.length > 0);
2209
+ const topMonitors = monitors.sort((a, b) => b.total_count - a.total_count).slice(0, params.limit ?? 10).map((m, i) => ({ rank: i + 1, ...m }));
2210
+ return {
2211
+ top: topMonitors,
2212
+ meta: {
2213
+ query: effectiveQuery,
2214
+ from: result.meta.from,
2215
+ to: result.meta.to,
2216
+ totalMonitors: monitorGroups.size,
2217
+ totalEvents: result.events.length,
2218
+ contextPrefixes,
2219
+ datadog_url: result.meta.datadog_url
2220
+ }
2121
2221
  };
2122
2222
  }
2123
2223
  function parseIntervalToMs(interval) {
@@ -2388,6 +2488,7 @@ async function enrichWithMonitorMetadata(events, monitorsApi) {
2388
2488
  if (monitor) {
2389
2489
  enriched.monitorMetadata = {
2390
2490
  id: monitor.id ?? 0,
2491
+ name: monitor.name ?? "",
2391
2492
  type: String(monitor.type ?? ""),
2392
2493
  message: monitor.message ?? "",
2393
2494
  tags: monitor.tags ?? [],
@@ -2405,16 +2506,15 @@ async function enrichWithMonitorMetadata(events, monitorsApi) {
2405
2506
  function registerEventsTool(server, apiV1, apiV2, monitorsApi, limits, readOnly = false, site = "datadoghq.com") {
2406
2507
  server.tool(
2407
2508
  "events",
2408
- `Track Datadog events. Actions: list, get, create, search, aggregate, top, timeseries, incidents.
2409
- IMPORTANT: For monitor alert history, use tags: ["source:alert"] to find all triggered monitors.
2410
- Filters: query (text search), sources, tags, priority, time range.
2411
- Use for: monitor alerts, deployments, incidents, change tracking.
2509
+ `Track Datadog events. Actions: list, get, create, search, aggregate, top, timeseries, incidents, discover.
2510
+ For monitor alerts, use tags: ["source:alert"].
2412
2511
 
2413
- Use action:"top" with from:"7d" to find the noisiest monitors.
2414
- Use action:"aggregate" with groupBy:["monitor_name"] for alert counts per monitor.
2415
- Use action:"timeseries" with interval:"1h" to see alert trends over time.
2416
- Use action:"incidents" with dedupeWindow:"5m" to deduplicate alerts into incidents.
2417
- Use enrich:true with search to get monitor metadata (slower).`,
2512
+ top: Returns monitors with context breakdown. Example: {name, monitor_id, total_count, by_context: [{context: "queue:X", count: 30}]}
2513
+ discover: Returns available tag prefixes from events.
2514
+ aggregate: Custom groupBy, returns pipe-delimited keys.
2515
+ search: Full event details.
2516
+ timeseries: Time-bucketed trends with interval.
2517
+ incidents: Deduplicate alerts with dedupeWindow.`,
2418
2518
  InputSchema6,
2419
2519
  async ({
2420
2520
  action,
@@ -2433,7 +2533,8 @@ Use enrich:true with search to get monitor metadata (slower).`,
2433
2533
  cursor,
2434
2534
  interval,
2435
2535
  dedupeWindow,
2436
- enrich
2536
+ enrich,
2537
+ contextTags
2437
2538
  }) => {
2438
2539
  try {
2439
2540
  checkReadOnly(action, readOnly);
@@ -2520,8 +2621,23 @@ Use enrich:true with search to get monitor metadata (slower).`,
2520
2621
  to,
2521
2622
  sources,
2522
2623
  tags,
2523
- groupBy,
2524
- limit
2624
+ limit,
2625
+ contextTags
2626
+ },
2627
+ limits,
2628
+ site
2629
+ )
2630
+ );
2631
+ case "discover":
2632
+ return toolResult(
2633
+ await discoverTagsV2(
2634
+ apiV2,
2635
+ {
2636
+ query,
2637
+ from,
2638
+ to,
2639
+ sources,
2640
+ tags
2525
2641
  },
2526
2642
  limits,
2527
2643
  site
@@ -2580,7 +2696,7 @@ var InputSchema7 = {
2580
2696
  id: z8.string().optional().describe("Incident ID (required for get/update/delete)"),
2581
2697
  query: z8.string().optional().describe("Search query (for search action)"),
2582
2698
  status: z8.enum(["active", "stable", "resolved"]).optional().describe("Filter by status (for list)"),
2583
- limit: z8.number().optional().describe("Maximum number of incidents to return"),
2699
+ limit: z8.number().min(1).optional().describe("Maximum number of incidents to return (default: 50)"),
2584
2700
  config: z8.record(z8.unknown()).optional().describe(
2585
2701
  "Incident configuration (for create/update). Create requires: title. Update can modify: title, status, severity, fields."
2586
2702
  )
@@ -2610,7 +2726,7 @@ function formatIncident(i) {
2610
2726
  };
2611
2727
  }
2612
2728
  async function listIncidents(api, params, limits) {
2613
- const effectiveLimit = Math.min(params.limit ?? limits.maxResults, limits.maxResults);
2729
+ const effectiveLimit = params.limit ?? limits.defaultLimit;
2614
2730
  const response = await api.listIncidents({
2615
2731
  pageSize: effectiveLimit
2616
2732
  });
@@ -2633,7 +2749,7 @@ async function getIncident(api, id) {
2633
2749
  async function searchIncidents(api, query, limits) {
2634
2750
  const response = await api.searchIncidents({
2635
2751
  query,
2636
- pageSize: limits.maxResults
2752
+ pageSize: limits.defaultLimit
2637
2753
  });
2638
2754
  const incidents = (response.data?.attributes?.incidents ?? []).map(
2639
2755
  (i) => ({
@@ -2732,7 +2848,7 @@ var InputSchema8 = {
2732
2848
  ids: z9.array(z9.string()).optional().describe("Multiple SLO IDs (for list with specific IDs)"),
2733
2849
  query: z9.string().optional().describe("Search query (for list)"),
2734
2850
  tags: z9.array(z9.string()).optional().describe("Filter by tags (for list)"),
2735
- limit: z9.number().optional().describe("Maximum number of SLOs to return"),
2851
+ limit: z9.number().min(1).optional().describe("Maximum number of SLOs to return (default: 50)"),
2736
2852
  config: z9.record(z9.unknown()).optional().describe("SLO configuration (for create/update). Must include type, name, thresholds."),
2737
2853
  from: z9.string().optional().describe('Start time for history (ISO 8601 or relative like "7d", "1w")'),
2738
2854
  to: z9.string().optional().describe("End time for history (ISO 8601 or relative, default: now)")
@@ -2759,7 +2875,7 @@ function formatSlo(s) {
2759
2875
  };
2760
2876
  }
2761
2877
  async function listSlos(api, params, limits) {
2762
- const effectiveLimit = Math.min(params.limit ?? limits.maxResults, limits.maxResults);
2878
+ const effectiveLimit = params.limit ?? limits.defaultLimit;
2763
2879
  const response = await api.listSLOs({
2764
2880
  ids: params.ids?.join(","),
2765
2881
  query: params.query,
@@ -2910,7 +3026,7 @@ var InputSchema9 = {
2910
3026
  testType: z10.enum(["api", "browser"]).optional().describe("Test type filter (for list) or type for create"),
2911
3027
  locations: z10.array(z10.string()).optional().describe("Filter by locations (for list)"),
2912
3028
  tags: z10.array(z10.string()).optional().describe("Filter by tags (for list)"),
2913
- limit: z10.number().optional().describe("Maximum number of tests to return"),
3029
+ limit: z10.number().min(1).optional().describe("Maximum number of tests to return (default: 50)"),
2914
3030
  config: z10.record(z10.unknown()).optional().describe(
2915
3031
  "Test configuration (for create/update). Includes: name, type, config, options, locations, message."
2916
3032
  )
@@ -2929,7 +3045,7 @@ function formatTest(t) {
2929
3045
  };
2930
3046
  }
2931
3047
  async function listTests(api, params, limits) {
2932
- const effectiveLimit = Math.min(params.limit ?? limits.maxResults, limits.maxResults);
3048
+ const effectiveLimit = params.limit ?? limits.defaultLimit;
2933
3049
  const response = await api.listTests({
2934
3050
  pageSize: effectiveLimit
2935
3051
  });
@@ -3129,7 +3245,7 @@ var InputSchema10 = {
3129
3245
  action: ActionSchema10.describe("Action to perform"),
3130
3246
  filter: z11.string().optional().describe('Filter hosts by name, alias, or tag (e.g., "env:prod")'),
3131
3247
  from: z11.number().optional().describe("Starting offset for pagination"),
3132
- count: z11.number().optional().describe("Number of hosts to return"),
3248
+ count: z11.number().min(1).optional().describe("Number of hosts to return"),
3133
3249
  sortField: z11.string().optional().describe('Field to sort by (e.g., "apps", "cpu", "name")'),
3134
3250
  sortDir: z11.enum(["asc", "desc"]).optional().describe("Sort direction"),
3135
3251
  hostName: z11.string().optional().describe("Host name (required for mute/unmute)"),
@@ -3158,7 +3274,7 @@ async function listHosts(api, params, limits) {
3158
3274
  const response = await api.listHosts({
3159
3275
  filter: params.filter,
3160
3276
  from: params.from,
3161
- count: Math.min(params.count ?? limits.maxResults, limits.maxResults),
3277
+ count: params.count ?? limits.defaultLimit,
3162
3278
  sortField: params.sortField,
3163
3279
  sortDir: params.sortDir
3164
3280
  });
@@ -3252,7 +3368,7 @@ var InputSchema11 = {
3252
3368
  id: z12.string().optional().describe("Downtime ID (required for get/update/cancel)"),
3253
3369
  monitorId: z12.number().optional().describe("Monitor ID (required for listByMonitor)"),
3254
3370
  currentOnly: z12.boolean().optional().describe("Only return active downtimes (for list)"),
3255
- limit: z12.number().optional().describe("Maximum number of downtimes to return"),
3371
+ limit: z12.number().min(1).optional().describe("Maximum number of downtimes to return (default: 50)"),
3256
3372
  config: z12.record(z12.unknown()).optional().describe("Downtime configuration (for create/update). Must include scope and schedule.")
3257
3373
  };
3258
3374
  function extractMonitorIdentifier(mi) {
@@ -3281,7 +3397,7 @@ function formatDowntime(d) {
3281
3397
  };
3282
3398
  }
3283
3399
  async function listDowntimes(api, params, limits) {
3284
- const effectiveLimit = Math.min(params.limit ?? limits.maxResults, limits.maxResults);
3400
+ const effectiveLimit = params.limit ?? limits.defaultLimit;
3285
3401
  const response = await api.listDowntimes({
3286
3402
  currentOnly: params.currentOnly
3287
3403
  });
@@ -3386,9 +3502,9 @@ function formatMonitorDowntime(d) {
3386
3502
  end: attrs?.end ? new Date(attrs.end).toISOString() : null
3387
3503
  };
3388
3504
  }
3389
- async function listMonitorDowntimes(api, monitorId, limits) {
3505
+ async function listMonitorDowntimes(api, monitorId, _limits) {
3390
3506
  const response = await api.listMonitorDowntimes({ monitorId });
3391
- const downtimes = (response.data ?? []).slice(0, limits.maxResults).map(formatMonitorDowntime);
3507
+ const downtimes = (response.data ?? []).map(formatMonitorDowntime);
3392
3508
  return {
3393
3509
  downtimes,
3394
3510
  monitorId,
@@ -3447,7 +3563,7 @@ var InputSchema12 = {
3447
3563
  to: z13.string().optional().describe('End time (ISO 8601, relative like "now", or precise timestamp)'),
3448
3564
  type: z13.enum(["all", "view", "action", "error", "long_task", "resource"]).optional().describe("RUM event type filter"),
3449
3565
  sort: z13.enum(["timestamp", "-timestamp"]).optional().describe("Sort order for events"),
3450
- limit: z13.number().optional().describe("Maximum number of events to return"),
3566
+ limit: z13.number().min(1).optional().describe("Maximum number of events to return (default: 50)"),
3451
3567
  groupBy: z13.array(z13.string()).optional().describe('Fields to group by for aggregation (e.g., ["@view.url_path", "@session.type"])'),
3452
3568
  compute: z13.object({
3453
3569
  aggregation: z13.enum(["count", "cardinality", "avg", "sum", "min", "max", "percentile"]).optional(),
@@ -3549,7 +3665,7 @@ async function searchEvents(api, params, limits, site) {
3549
3665
  filterFrom: new Date(fromTime * 1e3),
3550
3666
  filterTo: new Date(toTime * 1e3),
3551
3667
  sort: params.sort === "timestamp" ? "timestamp" : "-timestamp",
3552
- pageLimit: Math.min(params.limit ?? limits.maxResults, limits.maxResults)
3668
+ pageLimit: params.limit ?? limits.defaultLimit
3553
3669
  });
3554
3670
  const events = (response.data ?? []).map(formatEvent);
3555
3671
  return {
@@ -3766,7 +3882,7 @@ async function getSessionWaterfall(api, params, limits, site) {
3766
3882
  const response = await api.listRUMEvents({
3767
3883
  filterQuery: queryParts.join(" "),
3768
3884
  sort: "timestamp",
3769
- pageLimit: Math.min(limits.maxResults, 1e3)
3885
+ pageLimit: limits.defaultLimit
3770
3886
  });
3771
3887
  const events = (response.data ?? []).map(formatWaterfallEvent);
3772
3888
  const summary = {
@@ -3852,7 +3968,7 @@ var InputSchema13 = {
3852
3968
  to: z14.string().optional().describe('End time (ISO 8601, relative like "now")'),
3853
3969
  severity: z14.enum(["info", "low", "medium", "high", "critical"]).optional().describe("Filter by severity"),
3854
3970
  status: z14.enum(["open", "under_review", "archived"]).optional().describe("Filter signals by status"),
3855
- pageSize: z14.number().optional().describe("Number of results to return"),
3971
+ pageSize: z14.number().min(1).optional().describe("Number of results to return"),
3856
3972
  pageCursor: z14.string().optional().describe("Cursor for pagination")
3857
3973
  };
3858
3974
  function formatRule(rule) {
@@ -3894,7 +4010,7 @@ function formatSignal(signal) {
3894
4010
  }
3895
4011
  async function listRules(api, params, limits) {
3896
4012
  const response = await api.listSecurityMonitoringRules({
3897
- pageSize: Math.min(params.pageSize ?? limits.maxResults, limits.maxResults),
4013
+ pageSize: params.pageSize ?? limits.defaultLimit,
3898
4014
  pageNumber: 0
3899
4015
  });
3900
4016
  const rules = (response.data ?? []).map(formatRule);
@@ -3931,7 +4047,7 @@ async function searchSignals(api, params, limits) {
3931
4047
  to: new Date(toTime * 1e3)
3932
4048
  },
3933
4049
  page: {
3934
- limit: Math.min(params.pageSize ?? limits.maxResults, limits.maxResults),
4050
+ limit: params.pageSize ?? limits.defaultLimit,
3935
4051
  cursor: params.pageCursor
3936
4052
  },
3937
4053
  sort: "timestamp"
@@ -3960,7 +4076,7 @@ async function listFindings(api, params, limits) {
3960
4076
  to: /* @__PURE__ */ new Date()
3961
4077
  },
3962
4078
  page: {
3963
- limit: Math.min(params.pageSize ?? limits.maxResults, limits.maxResults),
4079
+ limit: params.pageSize ?? limits.defaultLimit,
3964
4080
  cursor: params.pageCursor
3965
4081
  }
3966
4082
  }
@@ -4037,7 +4153,7 @@ var InputSchema14 = {
4037
4153
  end: z15.number().optional()
4038
4154
  }).optional().describe("Time configuration for notebook"),
4039
4155
  status: z15.enum(["published"]).optional().describe("Notebook status"),
4040
- pageSize: z15.number().optional().describe("Number of notebooks to return"),
4156
+ pageSize: z15.number().min(1).optional().describe("Number of notebooks to return"),
4041
4157
  pageNumber: z15.number().optional().describe("Page number for pagination")
4042
4158
  };
4043
4159
  function formatNotebookSummary(nb) {
@@ -4092,8 +4208,8 @@ async function listNotebooks(api, params, limits) {
4092
4208
  authorHandle: params.authorHandle,
4093
4209
  excludeAuthorHandle: params.excludeAuthorHandle,
4094
4210
  includeCells: params.includeCells ?? false,
4095
- count: Math.min(params.pageSize ?? limits.maxResults, limits.maxResults),
4096
- start: (params.pageNumber ?? 0) * (params.pageSize ?? limits.maxResults)
4211
+ count: params.pageSize ?? limits.defaultLimit,
4212
+ start: (params.pageNumber ?? 0) * (params.pageSize ?? limits.defaultLimit)
4097
4213
  });
4098
4214
  const notebooks = (response.data ?? []).map(formatNotebookSummary);
4099
4215
  return {
@@ -4310,7 +4426,7 @@ var InputSchema15 = {
4310
4426
  id: z16.string().optional().describe("User ID (required for get action)"),
4311
4427
  filter: z16.string().optional().describe("Filter users by name or email"),
4312
4428
  status: z16.enum(["Active", "Pending", "Disabled"]).optional().describe("Filter by user status"),
4313
- pageSize: z16.number().optional().describe("Number of users to return per page"),
4429
+ pageSize: z16.number().min(1).optional().describe("Number of users to return per page"),
4314
4430
  pageNumber: z16.number().optional().describe("Page number for pagination")
4315
4431
  };
4316
4432
  function formatUser(user) {
@@ -4338,7 +4454,7 @@ async function listUsers(api, params, limits) {
4338
4454
  const response = await api.listUsers({
4339
4455
  filter: params.filter,
4340
4456
  filterStatus: params.status,
4341
- pageSize: Math.min(params.pageSize ?? limits.maxResults, limits.maxResults),
4457
+ pageSize: params.pageSize ?? limits.defaultLimit,
4342
4458
  pageNumber: params.pageNumber ?? 0
4343
4459
  });
4344
4460
  const users = (response.data ?? []).map(formatUser);
@@ -4392,7 +4508,7 @@ var InputSchema16 = {
4392
4508
  action: ActionSchema16.describe("Action to perform"),
4393
4509
  id: z17.string().optional().describe("Team ID (required for get/members actions)"),
4394
4510
  filter: z17.string().optional().describe("Filter teams by name"),
4395
- pageSize: z17.number().optional().describe("Number of teams to return per page"),
4511
+ pageSize: z17.number().min(1).optional().describe("Number of teams to return per page"),
4396
4512
  pageNumber: z17.number().optional().describe("Page number for pagination")
4397
4513
  };
4398
4514
  function formatTeam(team) {
@@ -4426,7 +4542,7 @@ function formatTeamMember(member) {
4426
4542
  async function listTeams(api, params, limits) {
4427
4543
  const response = await api.listTeams({
4428
4544
  filterKeyword: params.filter,
4429
- pageSize: Math.min(params.pageSize ?? limits.maxResults, limits.maxResults),
4545
+ pageSize: params.pageSize ?? limits.defaultLimit,
4430
4546
  pageNumber: params.pageNumber ?? 0
4431
4547
  });
4432
4548
  const teams = (response.data ?? []).map(formatTeam);
@@ -4449,7 +4565,7 @@ async function getTeam(api, teamId) {
4449
4565
  async function getTeamMembers(api, teamId, limits) {
4450
4566
  const response = await api.getTeamMemberships({
4451
4567
  teamId,
4452
- pageSize: limits.maxResults
4568
+ pageSize: limits.defaultLimit
4453
4569
  });
4454
4570
  const members = (response.data ?? []).map(formatTeamMember);
4455
4571
  return {