Skip to content

MCP v2 Audit Middleware Decision

Decision

MCP-for-Stata uses MCPServer middleware for generic tools/call lifecycle auditing, an AuditStore for local append-only persistence, and tool-specific artifact hooks for Stata do-file snapshots.

Architecture

MCP client
  -> MCPServer
  -> AuditMiddleware
  -> tool handler
  -> StataDo snapshot hook when applicable

AuditMiddleware owns run IDs, client and protocol metadata, redacted arguments, timing, and terminal status. StataDo owns exact source snapshots, hashes, and log artifacts. A ContextVar carries one AuditExecutionContext through concurrent and worker-thread execution so both layers write the same run ID.

Alternatives

  • Per-tool wrappers were rejected because every new tool would duplicate audit lifecycle code.
  • Snapshot creation inside middleware was rejected because it would couple raw protocol rewriting to Stata-specific path and security behavior.
  • OpenTelemetry-only auditing was rejected because traces are operational data, not durable, human-inspectable research evidence.

Failure Behavior

If the initial audit event or snapshot cannot be persisted, execution fails closed. If the terminal event cannot be persisted after a tool runs, the caller receives the audit failure; existing artifacts remain on disk for diagnosis.

Security

Client identity is self-reported and never authorizes access. Credential-like argument keys are redacted recursively. Audit paths remain under the configured project artifact root and are ignored by Git.

Deferred Work

Audit v1 does not configure or export OpenTelemetry traces. Observability work must be designed separately and remain optional. If adopted, trace/span IDs may be correlated with the durable run_id, but traces must not replace or mutate the JSONL audit trail.

Timeout classification, snapshot replay/recovery, and audit retention are also deferred. Replay must require an explicit user action, verify the content hash, create a new run, and keep the original audit events immutable.