Auditing and Logging
This SDK provides default implementations for many components (e.g., ConsoleAuditLogStore
, ConsoleLogger
) to simplify initial setup and development. However, many of these defaults are NOT suitable for production environments due to limitations in persistence, performance, or security. Always review the defaults mentioned in this document and others (like Authorization) and provide production-ready implementations for critical components before deployment.
The @ithena-one/mcp-governance
SDK provides robust mechanisms for observing the behavior of your MCP server through auditing and structured logging.
Auditing
Auditing creates a detailed, structured record of each significant operation (primarily requests, optionally notifications) processed by the GovernedServer
. This is crucial for security monitoring, compliance, and debugging.
Key Components & Concepts
-
AuditRecord
(Type): (src/types.ts
)- Defines the structure for audit events.
- Key Fields:
eventId
,timestamp
,serviceIdentifier
,transport
(connection details),mcp
(message details),identity
(resolved, possibly sanitized),trace
(tracing IDs),outcome
(status, error?, mcpResponse?),authorization?
(RBAC details),credentialResolution?
,durationMs
.
-
AuditLogStore
(Interface): (src/interfaces/audit.ts
)- Your implementation receives
AuditRecord
objects and sends them to storage/analysis (SIEM, DB, etc.). - Requires
async log(record: AuditRecord): Promise<void>
(must handle own errors). - Defaults:
NoOpAuditLogStore
: Does nothing (safe default).ConsoleAuditLogStore
: Logs JSON to console (Dev/Debug ONLY).
- Your implementation receives
-
sanitizeForAudit
(Function): (GovernedServerOptions
)- A function you provide:
(record: AuditRecord) => AuditRecord
. - Processes the
AuditRecord
before it’s sent to theAuditLogStore
. - Purpose: Remove, mask, or transform sensitive data (PII, secrets, etc.).
- Default (
defaultSanitizeForAudit
): Provided insrc/defaults/sanitization.ts
. Uses regex to match common secret key names (e.g.,apiKey
,secret
,password
,token
) and masks values. Also truncates long strings.
- A function you provide:
The default key-based sanitizer is a basic starting point and likely insufficient for production. Relying solely on key names is brittle. You MUST review its logic and limitations and implement your own sanitizeForAudit
function tailored to your specific data structures, sensitivity requirements, and compliance needs. Failure to do so can lead to severe security vulnerabilities.
- Configuration Options:
auditStore
: Provide yourAuditLogStore
implementation.sanitizeForAudit
: Provide your custom sanitization function.auditDeniedRequests
(defaulttrue
): Log audits even if RBAC denied the request.auditNotifications
(defaultfalse
): Log audits for incoming notifications.
Structured Logging
The SDK uses structured logging, capturing messages with context (like eventId
, traceId
, userId
).
Key Components & Concepts
-
Logger
(Interface): (src/interfaces/logger.ts
)- Standard methods (
debug
,info
,warn
,error
). - Accepts optional
context
object. - Optional
child(bindings: LogContext): Logger
method enables request-scoped logging context.
- Standard methods (
-
ConsoleLogger
(Default): (src/defaults/logger.ts
)- Logs JSON objects to the console.
- Supports
child
loggers.
ConsoleLogger
is suitable for development and debugging only; do not use in production.
-
Usage:
- Provide your
Logger
via thelogger
option inGovernedServerOptions
. - SDK creates request-scoped loggers passed to components (
OperationContext.logger
) and handlers (GovernedRequestHandlerExtra.logger
). - Use the provided logger instance within your code.
Handler Logging Example// Example within a request handler governedServer.setRequestHandler(mySchema, async (request, extra) => { extra.logger.info("Handler started", { customData: "value" }); try { // ... handler logic ... extra.logger.debug("Intermediate step successful"); return { success: true }; } catch (err) { extra.logger.error("Handler failed", err as Error, { input: request.params }); throw err; // Re-throw for pipeline error handling } } );
- Provide your
-
Integration: Create an adapter for your preferred Node.js logging library (e.g., Pino, Winston) that implements the
Logger
interface (includingchild
).
Tracing
The SDK facilitates distributed tracing by extracting trace context.
Key Components & Concepts
-
TraceContext
(Type): (src/types.ts
)- Holds standard tracing identifiers (e.g.,
traceId
,spanId
,traceFlags
,traceState
).
- Holds standard tracing identifiers (e.g.,
-
TraceContextProvider
(Type): (src/interfaces/tracing.ts
)- Function signature:
(transportContext, mcpMessage) => TraceContext | undefined
.
- Function signature:
-
defaultTraceContextProvider
(Default): (src/defaults/tracing.ts
)- Looks for W3C Trace Context headers (
traceparent
,tracestate
) intransportContext.headers
.
- Looks for W3C Trace Context headers (
-
Usage:
GovernedServer
calls the configuredtraceContextProvider
.- Resulting
TraceContext
is added toOperationContext
, handler extras,AuditRecord
, and logger context. - Use this context for cross-service correlation. Provide a custom provider for different standards.