使用说明
AppDynamics MCP Server
A Model Context Protocol server that gives LLM clients (Cursor, Claude Desktop, etc.) full access to your AppDynamics monitoring data — plus the ability to create and manage dashboards and health rules.
Features
30 tools across 8 categories:
- Discovery: List and search applications by name
- Health Monitoring: Full health rule CRUD, violations, and anomaly detection
- Application Performance: Business transactions, service endpoints, and their metrics
- Infrastructure: Tiers, nodes, and backend/remote service dependencies
- Diagnostics: Transaction snapshots and error events
- Root Cause Analysis: Automated composite diagnosis across all signal types
- Metrics: Browse the metric tree and query any metric with rollup support
- Dashboards: Full CRUD — list, view, create, update, add widgets, clone, delete, export, import, auto-build, per-rule health status widgets
Key capabilities
- Natural language friendly: Accept application names, not just IDs
- Historical time ranges: Query any past window, not just "the last N minutes" — see Time Ranges
- Metric tree browser: Discover available metrics interactively, including custom/machine-agent metrics
- Rollup control: Per-widget rollup for time-series vs. aggregate metric views
- Dashboard auto-builder: Create full multi-section dashboards from a single prompt
- HealthListWidget scoping: Each widget can be pinned to a specific health rule (not "all rules")
- Health rule CRUD: Create, update, enable/disable, and delete health rules — including custom metrics scoped to a specific tier or node
- Smart defaults: Sensible time ranges and result limits out of the box
Time Ranges
Every time-aware tool accepts durationInMins, startTime, and endTime. Timestamps
may be ISO 8601 (2026-08-03T14:00:00Z) or epoch milliseconds; bare epoch-seconds
values are detected and converted.
| Arguments supplied | Window queried | AppDynamics range type |
|---|---|---|
| (none) | The tool's default lookback, ending now | BEFORE_NOW |
durationInMins |
Last N minutes | BEFORE_NOW |
startTime + endTime |
Exactly that window | BETWEEN_TIMES |
endTime + durationInMins |
N minutes before that point | BEFORE_TIME |
startTime + durationInMins |
N minutes after that point | AFTER_TIME |
// "What did response time look like during yesterday's incident?"
{
"application": "Checkout",
"metricPath": "Overall Application Performance|Average Response Time (ms)",
"startTime": "2026-08-02T12:00:00Z",
"endTime": "2026-08-02T15:00:00Z"
}
Contradictory input is rejected with an actionable message rather than silently
guessing — supplying durationInMins together with both endpoints, an inverted
window (endTime before startTime), or an unparseable timestamp all return an error.
Tools supporting time ranges: appd_get_metric_data, appd_get_health_violations,
appd_get_anomalies, appd_get_errors, appd_get_snapshots, appd_get_bt_performance,
appd_get_service_endpoint_performance, appd_diagnose_issue.
Note: AppDynamics rolls older data into coarser buckets. A narrow window far in the past may return nothing even though a wider window over the same period returns an aggregate — this is controller-side retention granularity, not a query error.
Quick Start
1. Install dependencies
npm install
2. Configure environment
Copy .env.example to .env and fill in your credentials:
cp .env.example .env
Required variables:
| Variable | Description |
|---|---|
APPD_URL |
Controller base URL (e.g., https://mycompany.saas.appdynamics.com) |
APPD_CLIENT_NAME |
OAuth client name or API key |
APPD_CLIENT_SECRET |
OAuth client secret |
APPD_ACCOUNT_NAME |
Account name (for clientName@accountName format) |
3. Add to your MCP client
Cursor (~/.cursor/mcp.json):
{
"mcpServers": {
"appdynamics": {
"command": "npx",
"args": ["tsx", "src/index.ts"],
"cwd": "/path/to/appdynamics-mcp-server",
"env": {
"APPD_URL": "https://your-controller.saas.appdynamics.com",
"APPD_CLIENT_NAME": "your-client-name",
"APPD_CLIENT_SECRET": "your-client-secret",
"APPD_ACCOUNT_NAME": "your-account-name"
}
}
}
}
Claude Desktop (claude_desktop_config.json):
{
"mcpServers": {
"appdynamics": {
"command": "npx",
"args": ["tsx", "/path/to/appdynamics-mcp-server/src/index.ts"],
"env": {
"APPD_URL": "https://your-controller.saas.appdynamics.com",
"APPD_CLIENT_NAME": "your-client-name",
"APPD_CLIENT_SECRET": "your-client-secret",
"APPD_ACCOUNT_NAME": "your-account-name"
}
}
}
}
Tools Reference
Discovery
| Tool | Description |
|---|---|
appd_get_applications |
List all monitored applications (with optional name filter) |
Health Monitoring
| Tool | Description |
|---|---|
appd_get_health_rules |
List health rules or get details of a specific rule |
appd_create_health_rule |
Create a new health rule with warning and/or critical conditions. Supports OVERALL_APPLICATION_PERFORMANCE, BUSINESS_TRANSACTION_PERFORMANCE, TIER_NODE_HEALTH, and CUSTOM entity types. Use affectedTier or affectedNode to scope rules to a specific tier/node for custom metrics. |
appd_update_health_rule |
Update an existing health rule's name, conditions, thresholds, or scope |
appd_delete_health_rule |
Permanently delete a health rule |
appd_enable_health_rule |
Enable or disable a health rule |
appd_get_health_violations |
Get health rule violations for one or all apps |
appd_get_anomalies |
Get anomaly events (open-only by default) |
Application Performance
| Tool | Description |
|---|---|
appd_get_business_transactions |
List BTs for an application |
appd_get_bt_performance |
Get response time, throughput, errors for a BT |
appd_get_service_endpoints |
List service endpoints (API-level granularity) |
appd_get_service_endpoint_performance |
Get performance metrics for a service endpoint |
Infrastructure
| Tool | Description |
|---|---|
appd_get_tiers_and_nodes |
Get tiers with their nodes (agents, machines, IPs) |
appd_get_backends |
List backend dependencies (databases, APIs, caches, queues) |
Diagnostics
| Tool | Description |
|---|---|
appd_get_snapshots |
Get transaction snapshots (deep diagnostic captures) |
appd_get_errors |
Get error and exception events |
Root Cause Analysis
| Tool | Description |
|---|---|
appd_diagnose_issue |
Automated root cause analysis — fetches violations, anomalies, error events, and snapshots in parallel, then returns ranked candidates, a merged timeline, error breakdown, and investigation steps. Accepts a historical window; the baseline automatically becomes the equivalent window immediately before it |
Metrics
| Tool | Description |
|---|---|
appd_browse_metric_tree |
Browse the metric hierarchy to discover available metrics, including custom machine-agent metrics |
appd_get_metric_data |
Query any metric by path, over any time range. Supports rollup control: true returns a single aggregated value, false returns individual time-series data points |
Dashboards
| Tool | Description |
|---|---|
appd_get_dashboards |
List all custom dashboards |
appd_get_dashboard |
Get full dashboard definition with widgets |
appd_create_dashboard |
Create a new dashboard with optional widgets |
appd_update_dashboard |
Update dashboard properties and/or widgets |
appd_add_widget_to_dashboard |
Add a single widget without replacing existing ones |
appd_clone_dashboard |
Clone a dashboard with a new name |
appd_delete_dashboard |
Delete a dashboard (permanent) |
appd_export_dashboard |
Export dashboard as portable JSON |
appd_import_dashboard |
Create a new dashboard from a saved JSON definition |
appd_save_dashboard_file |
Build a complete dashboard JSON file locally without creating anything in AppDynamics — ready to edit and import |
appd_auto_build_dashboard |
Auto-discover tiers, BTs, and health rules, then create a complete multi-section dashboard in one shot |
Dashboard widget types
| Widget type | Description |
|---|---|
TIMESERIES_GRAPH |
Time-series line chart for one or more metrics |
METRIC_VALUE |
Single aggregated number (gauge tile) — stored as METRIC_LABEL in AppDynamics |
GAUGE |
Gauge dial |
PIE |
Pie chart |
HEALTH_LIST |
Health rule status (green/yellow/red circles). Set healthRuleIds: [id] to pin a widget to specific health rules; omit to show all rules for the application. Display options: showPie: true renders a pie chart, add innerRadius: 30-40 for a donut, showList: false hides the rule list under the chart. |
TEXT |
Static text / label — stored as LABEL in AppDynamics |
Widgets are saved first, then their metric bindings are attached in a second pass using
the server-assigned widget ids — this is what makes graphs actually render data.
Metric paths are bound in one of three forms (each verified against the dashboard
rendering API): Business Transaction metrics with btIds use BT criteria; app-scope
metrics (Overall Application Performance, Backends, Service Endpoints, …) use the
application-aggregate criteria, optionally scoped per tier via tierIds; node metrics
(JVM, Hardware Resources, or Application Infrastructure Performance|Tier|… paths) use
node-level criteria with the node-relative path.
Example Conversations
"What's the health status of my production apps?"
→ Uses appd_get_applications + appd_get_health_violations + appd_get_anomalies
"Show me the slowest business transactions for the Orders app"
→ Uses appd_get_business_transactions + appd_get_bt_performance
"What databases does the Payment service connect to?"
→ Uses appd_get_backends with typeFilter="JDBC"
"Create a health rule that fires when Custom Metrics|RequestCount > 1000 on the WebTier"
→ Uses appd_create_health_rule with affectedEntityType="TIER_NODE_HEALTH", affectedTier="WebTier", metricPath="Custom Metrics|RequestCount"
"Create a dashboard for the Checkout app with response time and error rate"
→ Uses appd_get_applications → appd_browse_metric_tree → appd_create_dashboard
"Build me a full monitoring dashboard for the Orders app"
→ Uses appd_auto_build_dashboard — auto-discovers all tiers, BTs, and health rules, creates a complete dashboard in one shot
"Create one health widget per URL Monitor service, each scoped to its own rule"
→ Uses appd_create_health_rule (one per service) + appd_create_dashboard with healthRuleIds on each HEALTH_LIST widget
"Clone the production monitoring dashboard for staging"
→ Uses appd_get_dashboards → appd_clone_dashboard
"Why is my Payment app slow? Diagnose the last hour"
→ Uses appd_diagnose_issue with application="Payment", durationInMins=60 — returns ranked root cause candidates, merged event timeline, error class breakdown, and step-by-step investigation guide
"Are there any errors spiking in the Orders app right now?"
→ Uses appd_diagnose_issue with application="Orders", focus="errors"
"What went wrong during yesterday's outage between 14:00 and 15:00?"
→ Uses appd_diagnose_issue with startTime/endTime — degradation is measured against
the 14:00-preceding hour, so the report reflects that incident rather than current state
"Pull the snapshots captured during last Tuesday's slowdown"
→ Uses appd_get_snapshots with startTime/endTime
Health Rules — Custom Metrics
Custom metrics reported by machine agents are stored per-node under:
Application Infrastructure Performance|{Tier}|Individual Nodes|{Node}|Custom Metrics|{MetricName}
When creating health rules for custom metrics, use affectedEntityType=TIER_NODE_HEALTH and provide the relative metric path (not the full absolute path):
affectedEntityType: "TIER_NODE_HEALTH"
affectedNode: "my-server-hostname" # scope to specific node
metricPath: "Custom Metrics|MyMetric" # relative path only
Architecture
src/
├── index.ts # Entry point, registers all tools
├── types.ts # TypeScript interfaces
├── constants.ts # Shared constants
├── services/
│ ├── auth.ts # OAuth2 token management
│ └── api-client.ts # Authenticated HTTP client
├── utils/
│ ├── error-handler.ts # Error → MCP response
│ ├── app-resolver.ts # App name → ID resolution
│ ├── time-range.ts # Shared time-range parsing → AppD query params
│ ├── concurrency.ts # Bounded fan-out across apps/tiers
│ └── formatting.ts # Response formatting
└── tools/ # One file per tool domain
├── applications.ts
├── health-rules.ts # CRUD + enable/disable
├── health-violations.ts
├── anomalies.ts
├── business-transactions.ts
├── bt-performance.ts
├── service-endpoints.ts
├── tiers-nodes.ts
├── backends.ts
├── snapshots.ts
├── errors.ts
├── metrics.ts # browse + query with rollup
├── dashboards.ts # full CRUD + auto-build + HealthListWidget scoping
└── root-cause.ts
Development
# Run in dev mode (auto-reload)
npm run dev
# Build TypeScript
npm run build
# Run built version
npm start
# Unit tests — payload builders vs. ground-truth fixtures, plus time-range
# resolution, response truncation, token caching, bounded concurrency,
# and error handling
npm test
# End-to-end verification: drives the MCP server against the live controller,
# creates test dashboards, and asserts the persisted widget shapes.
# Requires APPD_* env vars.
node scripts/verify-dashboard-fixes.mjs
Authentication
The server supports two authentication modes:
-
OAuth2 Client Credentials (recommended): Set
APPD_CLIENT_NAME,APPD_CLIENT_SECRET, and optionallyAPPD_ACCOUNT_NAME. The server acquires and caches tokens automatically. -
API Key: Set only
APPD_CLIENT_NAME(as the API key). No secret needed.
Token handling details:
- Tokens are cached until 5 minutes before expiry.
- Concurrent callers share a single in-flight token request, so a cold start issues one OAuth exchange rather than one per parallel tool call.
- A
401invalidates the cached token and retries the request once with a fresh one — a token revoked before its advertised expiry recovers automatically instead of failing every call until the cache times out. - Credentials are never written to logs or error messages; OAuth failures log only the HTTP status code.
Never commit credentials. Keep them in .env (gitignored) or your MCP client's
env block. If a secret is ever committed, rotate it in the AppDynamics controller —
removing it from git history alone does not invalidate it.
Reliability
- Bounded fan-out: tools that sweep every application or tier cap simultaneous
requests (
MAX_CONCURRENT_REQUESTS, default 6) instead of firing one request per entity at once, which trips controller rate limiting on large accounts. - Budgeted truncation: oversized responses are trimmed to the largest prefix that
fits
CHARACTER_LIMIT, and the note reports how many of the total items were kept. - Capped error bodies: upstream error payloads (including HTML error pages) are collapsed to a single line and truncated before being surfaced.
License
ISC