Skip to content

MCP server: a request-modifying Scripting rule causes duplicate flow IDs → colliding flows are silently dropped from MCP results #2687

Description

@amarcadet

Description

When a request-modifying Scripting rule is active, Proxyman can assign the same flow id to two distinct, concurrent flows. The built-in MCP server then exposes only one of the two: the other is missing from get_flows / filter_flows (by url, host or requestBody) and cannot be fetched via get_flow_detail (the shared id resolves to the sibling). Both flows remain visible, with the same id, in the macOS app UI.

Disabling the request-modifying Scripting rule removes the collision — the same user action then yields unique ids and all flows are exposed by the MCP.

The triggering rule simply reassigns the request body and overrides a header in onRequest:

async function onRequest(context, url, request) {
  var body = JSON.parse(request.rawBody);
  request.headers["Content-Type"] = "application/json";
  request.body = body;
  return request;
}

Consequence for MCP consumers (important). The collision is undetectable from the MCP side: a masked flow is indistinguishable from a flow that never happened, and a returned flow gives no hint that a sibling is hidden behind the same id. An automated MCP client / AI agent therefore cannot trust absence or counts and may confidently assert "the app did not send request X" when it actually did — this caused real misdiagnoses on our side before we noticed the duplicate ids in the UI.

Steps to Reproduce

  1. Add a Scripting rule with a request script (like the one above) scoped to host A.
  2. Run an app that fires, at nearly the same instant, a request to host A (scripted) and another request to a different host B (not scripted).
  3. In the macOS app, observe two rows sharing the same flow id (the host-A and host-B flows).
  4. From an MCP client, query get_flows / filter_flows (e.g. by host B) and get_flow_detail(<shared id>) — the host-B flow is absent / unfetchable. Then disable the Scripting rule and repeat → the collision disappears and the flow is exposed normally.

Current Behavior

  • Two different concurrent flows are assigned the same id when a request-modifying Scripting rule is active.
  • The MCP server returns only one of them; the other is silently omitted from get_flows / filter_flows (all keys: url, host, requestBody) and unreachable via get_flow_detail (which returns the sibling).
  • The loss is invisible to the MCP client (no error, plausible non-empty results), making it impossible to detect from the MCP alone.

Expected Behavior

  • Every captured flow has a unique id, even when modified by a Scripting rule.
  • get_flows / filter_flows return all matching flows.
  • get_flow_detail(id) unambiguously returns the requested flow.

Environment

  • App version: Proxyman 6.9.0 (build 60900), built-in MCP server
  • macOS version: macOS 26.5 (build 25F71), Apple Silicon
  • Traffic captured from an iOS Simulator app with SSL proxying enabled

Metadata

Metadata

Assignees

Labels

bugSomething isn't working✅ DoneTicket is addressed and fixed.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions