Skip to content

feat(oab-mcp): add deploy_events — ECS control-plane event history - #16

Merged
brettchien merged 1 commit into
mainfrom
feat/oab-mcp-deploy-events
Aug 11, 2026
Merged

feat(oab-mcp): add deploy_events — ECS control-plane event history#16
brettchien merged 1 commit into
mainfrom
feat/oab-mcp-deploy-events

Conversation

@brettchien

Copy link
Copy Markdown
Contributor

What

Adds a 7th, read-only MCP tool — deploy_events — to oab-mcp, so an agent can read the ECS lifecycle timeline that DescribeTasks (a point-in-time snapshot) cannot show: task stops + stoppedReason, service-impairment, and deployment transitions.

Why / design

oab-mcp is a short-lived stdio server spawned per session — it has nowhere to receive a live push. So "receive ECS events" is implemented as event-sourcing: an EventBridge rule archives ECS events into a CloudWatch Logs group, and this tool reads that store on demand. The MCP boundary stays pull; what changes is that you can now query history (a timeline), not just now.

ECS ──event──▶ EventBridge rule ──▶ CloudWatch Logs (/oab/ecs-events)
                                          │
        deploy_events(service?, since_minutes?, limit?) ──reads──┘

Tool

deploy_events(service?, since_minutes=1440, limit=50, log_group?, cluster?)
→ { cluster, log_group, since_minutes, count,
    events: [{ time, type, service, last_status, desired_status, stop_code, reason }] }

log_group defaults to $OAB_EVENTS_LOG_GROUP, else /oab/ecs-events.

Changes (3 crates, additive, read-only)

  • oabctl src/events.rs (new): CloudWatch Logs FilterLogEvents + normalize each EventBridge envelope → EcsEvent; newest-first; bounded pagination; per-service / per-cluster filtering. 4 unit tests (parse task-stop, parse service-action via resources[] ARN, skip non-ECS/garbage, name normalization).
  • studio-cp: observe_events() passthrough + re-exports EcsEvent / DEFAULT_EVENTS_LOG_GROUP.
  • oab-mcp: deploy_events tool registration + t_events handler + dispatch + event_json; catalog test updated 6 → 7, plus an event_json test.

Caveat (documented in the tool description + module docs)

A container healthStatus flip while a task stays RUNNING (e.g. an agent going Unhealthy without restarting) is not emitted by ECS as an event — the field is absent from Task State Change events. That signal remains poll-only via DescribeTasks; only lifecycle/stop/service/deployment transitions land here.

Requires (separate — infra, not in this PR)

  1. EventBridge rule on the default bus (source: aws.ecs, scoped to the oab cluster) → target the CloudWatch Logs group /oab/ecs-events.
  2. logs:FilterLogEvents (+ GetLogEvents) on the oab-mcp task role.

Until that exists, the tool returns cleanly against an empty/absent group (it surfaces the read error rather than crashing the server).

Test status

Full workspace cargo test (oabctl 83 + studio-cp 5 + oab-mcp 3 + new events 4) passed green locally before a small clippy autofix (split_once / sort_by_key); cargo clippy is clean after the fix (which compiles the whole crate). The post-fix test binary re-link hit a local disk-space wall (the statically-linked test binary pulls the full AWS SDK); the fix is a mechanical, semantics-preserving clippy suggestion, so I'm relying on CI here for the authoritative test+clippy+fmt run.

🤖 Generated with Claude Code

A 7th, read-only MCP tool that surfaces the ECS lifecycle timeline
DescribeTasks cannot show: task stops + stoppedReason, service
impairment, and deployment transitions.

Events are read back (pull) from a CloudWatch Logs group that an
EventBridge rule archives ECS events into. The MCP server is a
short-lived stdio process with nowhere to receive a live push, so the
event source is decoupled into a store and this tool queries it — the
MCP boundary stays pull.

- oabctl: new `events` module — CloudWatch Logs FilterLogEvents +
  EventBridge-envelope normalization into EcsEvent (4 unit tests)
- studio-cp: observe_events() passthrough + re-exports
- oab-mcp: deploy_events tool + handler + dispatch + event_json
  (+ catalog/event_json tests; catalog assertion 6 -> 7)

Caveat (documented in the tool + module docs): a container healthStatus
flip while a task stays RUNNING is NOT emitted by ECS as an event (the
field is absent from Task State Change events); that signal stays
poll-only via DescribeTasks.

Infra (separate, work-block B): an EventBridge rule -> CloudWatch Logs
group (default /oab/ecs-events, override $OAB_EVENTS_LOG_GROUP) plus
logs:FilterLogEvents on the oab-mcp task role.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@brettchien
brettchien merged commit 72ba56c into main Aug 11, 2026
3 checks passed
@brettchien
brettchien deleted the feat/oab-mcp-deploy-events branch August 11, 2026 06:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant