Skip to main content
Glama
swapnilbabladkar

mcp-aws-observability-server

README.md
# mcp-aws-observability-server

A small, **dependency-free** MCP (Model Context Protocol) server that
exposes AWS CloudWatch Logs and Alarms as tools an LLM client (Claude
Desktop, an agent runtime, a custom MCP client) can call — `list_log_groups`,
`search_logs`, and `get_active_alarms`.

This is a reference implementation modelled on the kind of MCP server
I've built and deployed to AWS at Equal Experts for centralized
logging/monitoring/observability across a shared GenAI platform: the
same tool surface, but standing on a mock backend here instead of a
real account, so anyone can clone and run it in under a minute.

## Why no SDK dependency

The official `mcp` SDK is great, but for a reference/demo repo I wanted
zero install friction and the transport mechanics to be visible rather
than hidden behind a library. `src/mcp_observability/protocol.py`
implements the newline-delimited JSON-RPC 2.0 stdio transport and the
`initialize` / `tools/list` / `tools/call` lifecycle directly from the
[MCP specification](https://modelcontextprotocol.io/specification). It's
~200 lines and fully tested — a good place to actually read how MCP
works under the hood.

## Quickstart

```bash
git clone https://github.com/swapnilbabladkar/mcp-aws-observability-server.git
cd mcp-aws-observability-server

# run the test suite (stdlib unittest, no install required)
PYTHONPATH=src python3 -m unittest discover -s tests -v

# run the full stdio flow against a real subprocess
python3 examples/demo_client.py

# or run the server directly (reads JSON-RPC from stdin, writes to stdout)
PYTHONPATH=src python3 -m mcp_observability
```

## Using it from Claude Desktop

Add to your MCP client config (e.g. Claude Desktop's
`claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "aws-observability": {
      "command": "python3",
      "args": ["-m", "mcp_observability"],
      "env": { "PYTHONPATH": "/absolute/path/to/mcp-aws-observability-server/src" }
    }
  }
}
```

Restart Claude Desktop and ask it something like *"any active alarms on
the platform right now?"* or *"search the mcp-server log group for
errors in the last two hours."*

## Switching to real AWS data

By default the server runs on `MockObservabilityBackend`, which returns
realistic canned data (log groups/events/alarms shaped like a real
EKS-hosted MCP server + RAG pipeline platform) so the whole tool-call
flow works with zero AWS setup.

To point it at a real account, install the optional AWS extra and swap
the backend in `server.py`:

```bash
pip install -e ".[aws]"
```

```python
# server.py
from .backends import AWSObservabilityBackend

def default_server() -> MCPServer:
    return build_server(AWSObservabilityBackend(region_name="eu-west-1"))
```

`AWSObservabilityBackend` (in `backends.py`) implements the same
interface via `boto3`'s `logs` and `cloudwatch` clients — real
`describe_log_groups` / `filter_log_events` / `describe_alarms` calls,
paginated. It needs a role/profile with `logs:Describe*`,
`logs:FilterLogEvents`, and `cloudwatch:DescribeAlarms`.

## Project layout

```
src/mcp_observability/
  protocol.py   # MCP JSON-RPC/stdio transport — the actual protocol implementation
  backends.py   # ObservabilityBackend interface + Mock and AWS implementations
  server.py     # registers the 3 tools against a backend
  __main__.py   # `python -m mcp_observability` entrypoint
tests/          # unittest coverage for protocol + mock backend
examples/
  demo_client.py  # spawns the server as a subprocess and drives it end-to-end
```

## Running the tests

```bash
PYTHONPATH=src python3 -m unittest discover -s tests -v
```

16 tests, covering the JSON-RPC error cases (parse errors, unknown
methods, unknown tools, tool-level failures vs. protocol failures) as
well as the mock backend's filtering logic.

## License

MIT — see [LICENSE](LICENSE).