Skip to content

AgentToolProvider MCP probe: no byte-size cap on rmcp's JSON tools/list response before parsing #98

Description

@jordigilh

Follow-up from grid#56 review (nerdalert): grid#56 landed bounds on the tool
catalog we persist to status.discoveredTools (name length + entry count),
but not on the raw HTTP response rmcp/reqwest buffer into memory before
parsing it into a tools/list result.

Problem

operator::resources::mcp_probe::run_probe_session calls into rmcp's
Streamable HTTP client (rmcp::transport::streamable_http_client). Its SSE
path honors a configured max_sse_event_size limit, but the plain-JSON
tools/list response path
(response.json::<ServerJsonRpcMessage>() in
rmcp::transport::common::reqwest::streamable_http_client) reads the entire
response body into memory with no size cap in the rmcp version this
workspace depends on (3.1.2).

A fast MCP endpoint returning an implausibly large JSON body could exhaust
operator memory before parsing ever completes, even though the outer probe
timeout (PROBE_TIMEOUT) still bounds elapsed time.

Options

  • Upstream fix: check whether/when rmcp adds a body-size cap for the
    JSON response path (may already be tracked upstream -- worth checking
    their issue tracker before doing anything else here).
  • Bypass rmcp's session API: bound bytes ourselves via a raw reqwest
    streamed read (bytes_stream() + running total check) before handing off
    to JSON parsing. This means not using rmcp::ServiceExt::serve()/
    list_tools() for this call, which undermines this module's "reuse
    rmcp's transport, don't reimplement MCP protocol detection" design intent
    (see the module doc comment).
  • Accept the gap for now: this is a controller-initiated discovery probe
    against operator-declared endpoints, not a request-time data-plane path,
    and the operator process itself has its own resource limits. Revisit if/
    when rmcp closes the gap upstream.

Not blocking grid#56

The count/name-length bounds that landed in grid#56 already narrow the
practical blast radius once a response is read; this issue is specifically
about bounding the read itself.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions