Skip to Content
DocsSDKsAuditing & Logging

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

  1. 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.
  2. 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).
  3. sanitizeForAudit (Function): (GovernedServerOptions)

    • A function you provide: (record: AuditRecord) => AuditRecord.
    • Processes the AuditRecord before it’s sent to the AuditLogStore.
    • Purpose: Remove, mask, or transform sensitive data (PII, secrets, etc.).
    • Default (defaultSanitizeForAudit): Provided in src/defaults/sanitization.ts. Uses regex to match common secret key names (e.g., apiKey, secret, password, token) and masks values. Also truncates long strings.
🚫

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.

  1. Configuration Options:
    • auditStore: Provide your AuditLogStore implementation.
    • sanitizeForAudit: Provide your custom sanitization function.
    • auditDeniedRequests (default true): Log audits even if RBAC denied the request.
    • auditNotifications (default false): Log audits for incoming notifications.

Structured Logging

The SDK uses structured logging, capturing messages with context (like eventId, traceId, userId).

Key Components & Concepts

  1. 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.
  2. 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.

  1. Usage:

    • Provide your Logger via the logger option in GovernedServerOptions.
    • 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 } } );
  2. Integration: Create an adapter for your preferred Node.js logging library (e.g., Pino, Winston) that implements the Logger interface (including child).

Tracing

The SDK facilitates distributed tracing by extracting trace context.

Key Components & Concepts

  1. TraceContext (Type): (src/types.ts)

    • Holds standard tracing identifiers (e.g., traceId, spanId, traceFlags, traceState).
  2. TraceContextProvider (Type): (src/interfaces/tracing.ts)

    • Function signature: (transportContext, mcpMessage) => TraceContext | undefined.
  3. defaultTraceContextProvider (Default): (src/defaults/tracing.ts)

    • Looks for W3C Trace Context headers (traceparent, tracestate) in transportContext.headers.
  4. Usage:

    • GovernedServer calls the configured traceContextProvider.
    • Resulting TraceContext is added to OperationContext, handler extras, AuditRecord, and logger context.
    • Use this context for cross-service correlation. Provide a custom provider for different standards.
Last updated on