Protocol-level middleware: hooks at MCP layer with built-in implementations #3

Closed
opened 2026-05-23 20:53:53 +00:00 by coilysiren · 0 comments
Owner

Originally filed by @coilysiren on 2026-05-13T14:23:42Z - https://github.com/coilysiren/cli-mcp/issues/40

FastMCP ships a middleware system with a hook hierarchy distinct from any argv-level wrapping:

  • Message level: on_message
  • Type level: on_request, on_notification
  • Operation level: on_call_tool, on_read_resource, on_get_prompt, on_list_tools, on_list_resources, on_list_prompts, on_initialize

Each receives a MiddlewareContext and a call_next continuation, bidirectional pipeline shape. Built-in middlewares include: LoggingMiddleware, StructuredLoggingMiddleware, TimingMiddleware, ResponseCachingMiddleware, RateLimitingMiddleware, SlidingWindowRateLimitingMiddleware, ErrorHandlingMiddleware, RetryMiddleware, PingMiddleware, ResponseLimitingMiddleware.

cli-mcp today has no protocol-layer middleware. cli-guard covers argv-level validation and audit, but several concerns are MCP-protocol-shaped and don't belong in cli-guard:

  • Response size capping (ResponseLimitingMiddleware) - prevent a tool dumping 50MB into an agent context. Critical, not currently solvable.
  • Per-tool rate limiting at the MCP transport.
  • Response caching for idempotent tools.
  • Tool-list filtering dynamically based on caller identity (on_list_tools).
  • Timing / structured logging at the protocol layer for observability.

Proposal: add a middleware surface to Options, with the hook set narrowed to what cli-mcp actually has (tools-only for v1, no resources/prompts):

type Middleware interface {
    OnCallTool(ctx, req, next) (CallToolResult, error)
    OnListTools(ctx, req, next) (ListToolsResult, error)
}

Ship the high-value built-ins:

  • ResponseLimitMiddleware(maxBytes int)
  • TimingMiddleware()
  • RateLimitMiddleware(perTool int, window time.Duration)
  • Maybe ResponseCacheMiddleware(ttl) if there's demand

The cli-guard relationship stays clean: guard wraps the Action (argv truth), middleware wraps the MCP call (protocol truth). Compose both.

_Originally filed by @coilysiren on 2026-05-13T14:23:42Z - [https://github.com/coilysiren/cli-mcp/issues/40](https://github.com/coilysiren/cli-mcp/issues/40)_ [FastMCP][fastmcp] ships a middleware system with a hook hierarchy distinct from any argv-level wrapping: - Message level: `on_message` - Type level: `on_request`, `on_notification` - Operation level: `on_call_tool`, `on_read_resource`, `on_get_prompt`, `on_list_tools`, `on_list_resources`, `on_list_prompts`, `on_initialize` Each receives a `MiddlewareContext` and a `call_next` continuation, bidirectional pipeline shape. Built-in middlewares include: `LoggingMiddleware`, `StructuredLoggingMiddleware`, `TimingMiddleware`, `ResponseCachingMiddleware`, `RateLimitingMiddleware`, `SlidingWindowRateLimitingMiddleware`, `ErrorHandlingMiddleware`, `RetryMiddleware`, `PingMiddleware`, `ResponseLimitingMiddleware`. cli-mcp today has no protocol-layer middleware. [cli-guard] covers *argv-level* validation and audit, but several concerns are MCP-protocol-shaped and don't belong in cli-guard: - **Response size capping** (`ResponseLimitingMiddleware`) - prevent a tool dumping 50MB into an agent context. Critical, not currently solvable. - **Per-tool rate limiting** at the MCP transport. - **Response caching** for idempotent tools. - **Tool-list filtering** dynamically based on caller identity (`on_list_tools`). - **Timing / structured logging** at the protocol layer for observability. Proposal: add a middleware surface to `Options`, with the hook set narrowed to what cli-mcp actually has (tools-only for v1, no resources/prompts): ```go type Middleware interface { OnCallTool(ctx, req, next) (CallToolResult, error) OnListTools(ctx, req, next) (ListToolsResult, error) } ``` Ship the high-value built-ins: - `ResponseLimitMiddleware(maxBytes int)` - `TimingMiddleware()` - `RateLimitMiddleware(perTool int, window time.Duration)` - Maybe `ResponseCacheMiddleware(ttl)` if there's demand The cli-guard relationship stays clean: guard wraps the Action (argv truth), middleware wraps the MCP call (protocol truth). Compose both. [fastmcp]: https://github.com/jlowin/fastmcp [cli-guard]: https://github.com/coilysiren/cli-guard
coilysiren 2026-05-30 05:44:18 +00:00
  • closed this issue
  • added the
    icebox
    label
Commenting is not possible because the repository is archived.
No milestone
No project
No assignees
1 participant
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
coilysiren/cli-mcp#3
No description provided.