Skip to main content
Glama
Rajendertyagi

MCPEvent

README.md
# EventHub — MCP Event Server

Generic self-hosted MCP event server foundation (`python -m app.server`).

## Layout

```
app/      application composition: Starlette+Uvicorn host, entrypoint,
          lifespan presentation helpers, canonical config + paths
core/     generic services: events, alerts, runtime/background tasks,
          SSE broker, persistence (core/persistence/store.py + modules/)
mcp_server/  MCP surface: contract identifiers, tools/, resources,
          services bundle, metrics   (named mcp_server so it can never
          shadow the installed `mcp` SDK distribution)
sources/  external source subsystem (registry, HTTP poller, test source)
test/     feature-focused regression suite (see below)
```

## Layout

```
test/
  run_all.py            # regression driver: isolated subprocess per file, hard 300s/file timeout
  helpers/              # lifecycle, mcp, wait, mock_http, runner — shared test support
  mcp_result.py         # SDK result normalization + safe teardown
  test_*.py             # one feature per file (the units of the suite)
  config.json           # base server config (overwritten per-test, restored after)
TEST_RUNTIME_MAP.md     # per-file server usage, harness behavior, run guidance
```

Production source under `test/` is **frozen** — do not edit `server.py`, `events.py`,
`store.py`, `runtime.py`, `errors.py`, `client.py`, `config.json`, `requirements.txt`,
or `sources/*` as part of test work.

## Run

```bash
# Focused (preferred while debugging one feature):
python test/test_acknowledgement.py
python test/run_all.py --group fast

# Full regression (CI / release only — slow path):
python test/run_all.py
python test/run_all.py --timeout 300
```

See `TEST_RUNTIME_MAP.md` for the server-usage matrix, the bounded-wait strategy, and
why you should run focused, not full, during development.

## Principles

- **No server unless the test needs the MCP/HTTP boundary.** Application logic
  (store, events, routing, checkpoint/ack, background tasks, source lifecycle, dedup)
  is tested directly against the real objects with an in-memory stub bus.
- **One server per D-level file** (exceptions: restart tests in `test_errors.py` /
  `test_reconnect.py`, and `test_subscriptions.py` whose tests need different source
  configs).
- **Bounded waits, no long fixed sleeps.** Readiness/counts are polled with timeouts.
- **Hard timeout (300 s/file) + parent-owned cleanup** — the runner terminates the child's
  process group, so a hung file fails fast (reported as **TIMEOUT**) and any `server.py`
  it spawned is killed with it. No reliance on the child's `atexit` (which can't run after
  a hard kill).

## Deleted (do not recreate)

`test/test_phase8.py`, `test/integrate_test.py` — replaced by the per-feature files above.