Get AppDynamics alerting configuration
appd_get_alerting_configRetrieve all alerting configuration for an AppDynamics application, including health rules, policies, actions, and schedules, to inventory who gets notified and under what conditions.
Instructions
Composite read: parallel-fetches health rules + policies + actions + schedules for one application via the Alerting REST v1 API. Use this for "what alerts and to whom" inventories.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| application | Yes |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| summary | Yes | ||
| evidence | No | ||
| entities | Yes | ||
| timeRange | No | ||
| sourceEndpoints | Yes | ||
| pagination | No | ||
| warnings | Yes | ||
| truncated | Yes |
Implementation Reference
- src/tools/getAlertingConfig.ts:20-74 (handler)The tool registration and handler for 'appd_get_alerting_config'. It registers the tool with MCP server, resolves the application ID, then parallel-fetches health rules, policies, actions, and schedules from the Alerting REST v1 API with concurrency limit of 4, and returns the results in a structured envelope.
export const getAlertingConfigTool: ToolRegistration = { name: 'appd_get_alerting_config', profile: 'read', register(server, services) { server.registerTool( 'appd_get_alerting_config', { title: 'Get AppDynamics alerting configuration', description: 'Composite read: parallel-fetches health rules + policies + actions + schedules for one application via the Alerting REST v1 API. Use this for "what alerts and to whom" inventories.', inputSchema: inputShape, outputSchema: envelopeOutputShape, }, wrapHandler<{ application: AppRef }, AlertingConfigEvidence>( services.log, 'appd_get_alerting_config', async (input) => { const appId = await services.alerting.resolveAppId(input.application); const limit = pLimit(4); const sourceEndpoints: string[] = []; const fetchList = async (segment: string): Promise<unknown[]> => { const path = `applications/${appId}/${segment}`; sourceEndpoints.push(`GET /controller/alerting/rest/v1/${path}`); const res = await services.alerting.get<unknown>(path); return Array.isArray(res.body) ? (res.body as unknown[]) : []; }; const [healthRules, policies, actions, schedules] = await Promise.all([ limit(() => fetchList('health-rules')), limit(() => fetchList('policies')), limit(() => fetchList('actions')), limit(() => fetchList('schedules')), ]); return toToolResult( buildEnvelope({ summary: `Alerting config for app ${appId}: ${healthRules.length} rules, ${policies.length} policies, ${actions.length} actions, ${schedules.length} schedules.`, evidence: { application: input.application, applicationId: appId, healthRules, policies, actions, schedules, } as AlertingConfigEvidence, entities: [{ kind: 'application', id: appId }], sourceEndpoints, }), ); }, ), ); }, }; - src/tools/getAlertingConfig.ts:7-9 (schema)Input schema for the tool: accepts an 'application' reference (either string name or numeric id).
const inputShape = { application: appRefSchema, }; - src/tools/index.ts:18-39 (registration)Central registration array that imports getAlertingConfigTool and includes it in the ALL_TOOLS array so it gets registered with the MCP server.
export const ALL_TOOLS: ToolRegistration[] = [ listApplicationsTool, getApplicationModelTool, getMetricHierarchyTool, queryMetricsTool, getTransactionSnapshotsTool, getHealthRuleViolationsTool, getAnomalyViolationsTool, getEventsTool, listHealthRulesTool, getAlertingConfigTool, queryAnalyticsEventsTool, getDependencyMapTool, ]; export function registerAllTools( server: McpServer, services: Services, ): { registered: string[]; skipped: string[] } { return registerTools(server, services, ALL_TOOLS); } - src/http/alertingClient.ts:31-68 (helper)Helper method in AlertingClient that resolves an application name or ID to a numeric ID, used by the tool handler to look up the application.
async resolveAppId(appNameOrId: string | number): Promise<number> { if (typeof appNameOrId === 'number') return appNameOrId; const trimmed = appNameOrId.trim(); if (/^\d+$/.test(trimmed)) return Number.parseInt(trimmed, 10); const cached = this.caches.appNameToId.get(trimmed); if (cached !== undefined) return cached; const res = await this.controller.get<AppListEntry[]>('applications'); const list = Array.isArray(res.body) ? res.body : []; // Build a complete Map first. Do not look up via the LRU during/after // the iteration — if the response has more entries than `appNameToId.max` // (real tenants commonly have hundreds-to-thousands of apps), early // entries get evicted mid-loop and the post-iteration LRU.get() misses // even though the name was definitely in the response. // Verified bug repro on 2026-05-05 against an 841-app SaaS tenant. const fullIndex = new Map<string, number>(); for (const app of list) { if (typeof app?.name === 'string' && typeof app?.id === 'number') { fullIndex.set(app.name, app.id); } } const found = fullIndex.get(trimmed); if (found === undefined) { throw new HttpError({ kind: 'not_found', sourceEndpoint: 'GET /controller/rest/applications', message: `Application "${trimmed}" not found in this account`, hint: 'Pass a numeric application id, or verify the name with appd_list_applications.', }); } // Best-effort write to the bounded LRU so subsequent same-name lookups // hit cache. The lookup result above is already authoritative regardless. this.caches.appNameToId.set(trimmed, found); return found;