incident-assistant
by gmgalvan
README.md
# incident-assistant — MCP "Hello World"
A test MCP (Model Context Protocol) server, built following the "incident response"
exercise from the MCP book/course — with the difference that here it's wired up to
**Claude Code** as the client instead of Gemini CLI.
The server simulates an alert dashboard for a production system and exposes:
- A **resource** (`resource://incidents/active`) with the list of active alerts (mock data).
- A **tool** (`resolve_incident`) that "restarts" a service to resolve an alert, with an
80% simulated success rate (so you can also see the failure path).
Source: [src/index.ts](src/index.ts)
## Stack
- [`@modelcontextprotocol/sdk`](https://www.npmjs.com/package/@modelcontextprotocol/sdk) — official MCP SDK for TypeScript/Node.
- **stdio** transport (the client spawns the server as a subprocess and they talk over stdin/stdout).
- TypeScript compiled to `dist/` (see [tsconfig.json](tsconfig.json)).
## 1. Install and build
```bash
npm install
npx tsc
```
This compiles [src/index.ts](src/index.ts) → `dist/index.js` (the entry point that
starts the server).
> Note: `console.error` is used for logging inside the server on purpose — `stdout` is
> reserved for the MCP JSON-RPC protocol, so any `console.log` there would break
> communication with the client.
## 2. Register the server with Claude Code
Unlike the book (which uses Gemini CLI's `settings.json`), in Claude Code a local MCP
server is registered with the `claude mcp add` command:
```bash
cd /absolute/path/to/incident-assistant
claude mcp add --scope project incident-assistant -- node /absolute/path/to/incident-assistant/dist/index.js
```
Key points:
- The `--` separates `claude mcp add`'s own flags from the actual command that starts
the server.
- An **absolute path** to `dist/index.js` is used (a relative path would resolve
against the directory `claude` was launched from, not against `.mcp.json`'s location).
- `--scope project` stores the config in [.mcp.json](.mcp.json) at the repo root
(version-controllable in git). Alternatives: `--scope local` (private to me, not
shared) or `--scope user` (available across all my projects, stored in `~/.claude.json`).
This generates a local `.mcp.json` with your machine's absolute path baked in. Since
that path is specific to your setup, `.mcp.json` itself is gitignored — the repo ships
[.mcp.json.example](.mcp.json.example) instead, showing the expected shape with a
placeholder path:
```json
{
"mcpServers": {
"incident-assistant": {
"type": "stdio",
"command": "node",
"args": ["/absolute/path/to/incident-assistant/dist/index.js"]
}
}
}
```
## 3. Approve the server
Since `.mcp.json` is a project file (it could come from a shared repo), Claude Code
asks for explicit approval the first time:
```bash
claude
```
On startup it shows a trust prompt for `incident-assistant` — accept it once per
project (unless the server's command/args later change).
## 4. Verify
```bash
claude mcp list
claude mcp get incident-assistant
```
Expected output once approved:
```
incident-assistant: node /absolute/path/to/incident-assistant/dist/index.js - ✔ Connected
```
Inside a `claude` session, `/mcp` lists the server's available tools/resources.
## 5. Demo — real result
Prompt to the agent: **"are there any critical alerts? If so, try to fix them and let
me know the result"**
The agent:
1. Listed the available MCP resources (`listMcpResources`) and found
`resource://incidents/active`.
2. Read that resource (`readMcpResource`) and got the mock alerts:
| ID | Service | Status | Message |
|----------|-----------------|--------------------------|------------------------|
| ALRT-001 | auth-api | 🔴 CRITICAL | Memory leak detected |
| ALRT-002 | payment-gateway | 🟡 WARNING (not critical) | Latency > 500ms |
3. Identified that only `ALRT-001` is critical and called the `resolve_incident` tool
with `serviceName: "auth-api"`.
4. Result:
> ✅ Fixed: auth-api was gracefully restarted to clear the memory leak (ALRT-001,
> CRITICAL). Restart succeeded.
>
> ⚠️ Not touched: payment-gateway still shows a WARNING (latency > 500ms), but that's
> not critical, so it was left as-is.
Agent's note: a restart clears the symptom, not necessarily the root cause — worth
keeping an eye on `auth-api` memory to confirm the leak doesn't recur.
5. When explicitly asked *"restart payment-gateway too"*, the agent calls
`resolve_incident` again with `serviceName: "payment-gateway"` (the exact outcome
isn't recorded here since it depends on the 80% simulated success rate — it can come
back ✅ or ❌ FAILURE).
This confirms the full loop: **MCP client (Claude Code) → resource/tool discovery →
reading a resource → decision → tool invocation → result**.
## Credits
This exercise is based on / learned from
[maliksahil/mcp-incident-assistant](https://github.com/maliksahil/mcp-incident-assistant/tree/main).
The original walkthrough uses Gemini CLI as the MCP client; this repo adapts the same
server to be used with Claude Code instead.
## Notes / gotchas
- The server runs under WSL; since Claude Code is also launched from a WSL terminal in
this setup, paths in `.mcp.json` are native Linux paths (e.g. `/home/<user>/...`), not
Windows UNC paths (`\\wsl.localhost\...`).
- If [src/index.ts](src/index.ts) is edited, it needs to be rebuilt (`npx tsc`) before
the change takes effect — the server starts from `dist/index.js`, not the `.ts` file
directly.
- `resolve_incident` has a deliberately simulated 80% success rate
(`Math.random() > 0.2`), so you can observe how the agent handles both the success and
the failure (`isError: true`) case.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues