observability-mcp
by dev-hops
README.md
# Azure Incident Investigation
A two-part portfolio project: a **read-only MCP server** exposing Azure
observability tools, and an **autonomous agent** that drives those tools to
investigate incidents and produce a synthesised root-cause report. A free,
self-built, minimal take on the idea behind Microsoft's Azure SRE Agent — and,
like that tool's "Reader mode", strictly read-only throughout.
```
you ──"symptom"──▶ incident-agent ──MCP (stdio/HTTP)──▶ observability-mcp ──▶ Azure
(Claude Agent SDK) (9 read-only tools) (App Insights,
│ App Service,
└── streams its reasoning + tool calls live, Activity Log)
then emits a Markdown root-cause report
```
## The two components
| Directory | What it is |
| --- | --- |
| [`observability-mcp/`](observability-mcp/) | The **tool layer**. A [Model Context Protocol](https://modelcontextprotocol.io) server (TypeScript, stdio **or** Streamable HTTP) exposing 9 read-only tools over Application Insights telemetry, App Service deployment history, App Service Plan metrics, and the Azure Activity Log — all correlated on `operation_Id`. Auth via `DefaultAzureCredential` (no secrets in code). |
| [`incident-agent/`](incident-agent/) | The **investigator**. A standalone agent ([Claude Agent SDK](https://www.npmjs.com/package/@anthropic-ai/claude-agent-sdk)) that connects to the MCP server as a client and autonomously drives its tools — starting narrow, widening the time window, localising the onset, identifying what changed, and confirming on a trace — before writing an evidence-backed report. Read-only by construction. |
Each directory is a self-contained npm project with its own README covering
setup, configuration, and how to run it. Start with
[`observability-mcp/`](observability-mcp/README.md) (the tools), then
[`incident-agent/`](incident-agent/README.md) (the agent that drives them).
## Design principles
- **Read-only, always.** Every tool calls only `list*` / `get*` / query APIs;
the agent routes every tool call through a single deny-by-default gate. Nothing
in this project can modify, restart, scale, or delete anything.
- **No secrets in code or config.** Azure access is `DefaultAzureCredential`
(your `az login` locally; a managed identity when deployed). See each
component's README for the auth and security model.
- **Runs locally or hosted.** The MCP server speaks stdio for local use and
Streamable HTTP for hosting (e.g. Azure Container Apps); the agent connects to
either.
> This is a lab / portfolio project — safe to run and read, but deliberately not
> production-hardened. See each component's "Security model" notes before
> deploying anywhere reachable.
## Infrastructure & deployment
[`Infrastructure/`](Infrastructure/) holds the Bicep that deploys the MCP server to
**Azure Container Apps** — the managed environment, the user-assigned identity, and
its **discrete, per-resource RBAC** (Reader on exactly the allowlisted App
Services / Container Apps / Log Analytics workspaces, never RG-wide except the
deliberate Activity Log exception). The identity's access is defined once, here, at
deploy time; it is never expanded at runtime from an alert payload.
- **Image:** built by [`.github/workflows/build-image.yml`](.github/workflows/build-image.yml)
and pushed to **GitHub Container Registry** (`ghcr.io/<owner>/observability-mcp-server`).
The package is **public**, so the Container App pulls it anonymously — no registry
credentials. (After the first workflow run, set the package visibility to Public
and link it to the repo.)
- **Parameters:** copy [`Infrastructure/main.parameters.example.json`](Infrastructure/main.parameters.example.json)
to `main.parameters.local.json` (gitignored) and fill in your real subscription /
resource IDs. **Never commit real values** — the example is the only parameters
file in git.
- **Deploy:** `az deployment group create -g <rg> -f Infrastructure/main.bicep -p Infrastructure/main.parameters.local.json`.
The three `allowed*` params also drive the agent's resource-scope gate: they're
emitted as Bicep outputs for the agent job / trigger Function (not yet built) to
consume as `ALLOWED_*` env vars — same source, defined once. See the
[incident-agent README](incident-agent/README.md#resource-scoping-allowlist-gate).
## License
[MIT](LICENSE).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues