middleware

ToolCallLoggingMiddleware — logs every tool call with its duration, appends a per-route audit record while model routing is active, and gates the experimental tool surface. It never alters the result and never swallows an exception.

See also

Architecture

Cross-cutting middleware for the NovelAI MCP server.

ToolCallLoggingMiddleware observes every tool call: it times it, writes a line to a route-derived logger, appends one record to the append-only audit trail while model-routing is active, and gates the experimental tool surface. It never rewrites a result and never swallows an exception.

The gate is deliberately two-sided. on_list_tools hides insiders-tagged tools from a client that has not opted in, and on_call_tool rejects a call to one by name, so guessing the name is not a way around the listing filter.

No tool shipped today carries the tag. The mechanism is opt-in by design: tagging an existing tool would remove it from every client that does not send the insiders header, which would break the promise that a request without the header behaves exactly as it did before.

novelai_image_mcp.middleware.AUDIT_LOGGER_PREFIX = 'novelai_image_mcp.audit'

Prefix of the per-route audit loggers (novelai_image_mcp.audit.<route>).

novelai_image_mcp.middleware.INSIDERS_TAG = 'insiders'

Tag that marks a tool as part of the experimental insiders surface.

class novelai_image_mcp.middleware.ToolCallLoggingMiddleware[source]

Bases: Middleware

Log every tool call, audit routed calls, and gate experimental tools.

Middleware keeps these concerns out of the tool bodies: the hooks observe the call, never rewrite the result, and never swallow an exception.

async on_list_tools(context, call_next)[source]

Hide insiders-tagged tools unless the client opted in.

Parameters:
  • context (MiddlewareContext[mt.ListToolsRequest])

  • call_next (CallNext[mt.ListToolsRequest, Sequence[Tool]])

Return type:

Sequence[Tool]

async on_call_tool(context, call_next)[source]

Time the call, audit it, and refuse a gated tool called by name.

Parameters:
  • context (MiddlewareContext[mt.CallToolRequestParams])

  • call_next (CallNext[mt.CallToolRequestParams, ToolResult])

Return type:

ToolResult