stateless-mcp-incident-lab-typescript-sdk
by maximalfocus
README.md
# Stateless MCP Incident Lab — TypeScript SDK
Official `@modelcontextprotocol/sdk` implementation of the Stateless MCP Incident Lab.
## Requirements
- Node.js 24+
- The external conformance repository checked out as `../stateless-mcp-incident-lab-conformance` (or set `CONFORMANCE_PATH`)
## Development
```sh
npm ci
npm run format
npm run lint
npm run typecheck
npm run test:architecture
npm test
npm run test:coverage
npm run test:conformance
npm run test:mutation
```
The external suite holds 197 golden contracts; the SDK lane selects and runs 159 of them. Conformance fixtures remain in the external repository and are never copied into this implementation.
## Runtime
```sh
npm run build
npm start
```
The server listens on port `3102` by default (`PORT` overrides it). Every request crosses an official `@modelcontextprotocol/sdk` `Server`/`Client` pair over `InMemoryTransport` before application dispatch, carrying the request's real JSON-RPC method, its params, and the negotiated protocol version for the SDK's own request schema to validate. The lab's 2026-07-28 wire revision — the `_meta` protocol-version envelope, `resultType`/`requestState`/`inputRequests` results, and `Mcp-Method`/`Mcp-Name` header mirroring — is not representable by the pinned SDK's HTTP transport, so HTTP framing and header validation remain in this adapter:
- MCP: `POST /sdk/mcp`
- Health: `GET /sdk/healthz`
The same executable is the network client; the command group comes first, with no `client` prefix:
```sh
node dist/src/main.js discover http://localhost:3102/sdk/mcp
node dist/src/main.js tools list http://localhost:3102/sdk/mcp
node dist/src/main.js tools call http://localhost:3102/sdk/mcp get_incident '{"incident_id":"..."}'
```
## Configuration
- `PORT` (default `3102`) and `HOST` (default `127.0.0.1`; the image sets `0.0.0.0`).
- `REPLICA_ID` — the replica identity reported in `_meta` on discovery, catalog, MRTR, and
streamed diagnostic results, and in telemetry records. Falls back to `HOSTNAME` (the container
ID when running in Docker) and then to `sdk-local-1`; the same value is used on every surface.
- `MCP_REQUEST_STATE_SECRET` — at least 32 bytes. Required when `NODE_ENV=production`: without it
`/sdk/healthz` reports 503 and signing `requestState` fails. Outside production a per-process
random key is used, so signed state does not survive a restart or span replicas.
- `EFFECT_STORE` — `memory` for explicit local, per-replica state, or `dynamodb` for durable shared state.
- `DYNAMODB_TABLE` — required with `EFFECT_STORE=dynamodb`. Create this table with string partition and sort keys named `PK` and `SK`; enable DynamoDB TTL on the numeric attribute `ttl` so expired incident rows are eventually reaped. The single-table adapter uses strongly consistent reads, conditional lifecycle writes, and an atomic effect-claim/incident-mitigation transaction. Its health probe performs one non-mutating strongly consistent read when the same store instance backs both persistence interfaces.
## Container
```sh
docker build -t incident-lab-sdk .
docker run --rm -p 3102:3102 \
-e EFFECT_STORE=memory \
-e MCP_REQUEST_STATE_SECRET=0123456789abcdef0123456789abcdef \
incident-lab-sdk
curl http://localhost:3102/sdk/healthz
```
The Docker `test` target accepts the conformance repository as a named build context, as demonstrated by CI.
## Quality gates
CI enforces formatting, lint, type checking, standalone architecture verification against the sdk-provider assertion files in the external suite, unit tests, overall coverage thresholds (90% statements/functions/lines, 80% branches) plus 100% statement/branch/function/line coverage for the protocol codec and validator, the complete SDK conformance lane, production dependency audit, build, mutation score ≥80%, the charter invariants (197 external contracts, zero vendored fixtures, the architecture contract directories, and no suppression pragmas in `src/`), the container `test` target, and a build-and-probe of the production image against `/sdk/healthz` and a live `server/discover`.
The mutation gate is scoped to the decision-dense modules listed in `stryker.config.mjs`: the incident lifecycle and state machine, MRTR and request-state signing, the client cache and cache-key laws, the domain transition table, header codec, protocol validation, the capability scanner, version recovery, the official SDK dispatch boundary (`sdk-registry.ts:59-107`), and the complete DynamoDB adapter. The ≥80% score speaks only to those modules. It deliberately excludes the HTTP framing in `server.ts` and the request-metadata validation in `http.ts`, whose behaviour is covered instead by the live-server integration tests in `test/unit/main.test.ts` and by the external conformance lane. The implementation stub scan stays a local step because it is supplied by the separate `cdd-skills` tooling repository, which CI does not check out.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues