How to inspect MCP / AI-agent traffic with a hosted proxy

Updated 2026-08-14

AI agents are getting good at calling tools, and MCP (Model Context Protocol) is becoming the wire format for how they do it. The moment your agent starts calling a real MCP server, the debugging question is the same one you've always had with any integration: what did it actually send, what came back, and where did it break? Except now the "request" is a JSON-RPC call like tools/call and the interesting part is buried in a POST body.

This guide shows how to route an AI client's MCP traffic through Proxycept (a hosted, shared HTTP(S) proxy) and read those calls decoded: method, tool name, session id, JSON-RPC request id, and error, surfaced first-class in the Sessions view instead of as an opaque blob.

We're going to be precise about what decodes today and what doesn't, because a half-honest answer here wastes your afternoon. The short version:

  • Decodes today: MCP JSON-RPC 2.0 over HTTP. That means the request (method, tool, request id, session id) and non-streaming JSON responses between an MCP client and a remote / HTTP-transport MCP server routed through the proxy.
  • Does not decode yet: streaming responses sent as text/event-stream (the Streamable-HTTP / SSE transport). The call is still badged from its request, but the response body isn't parsed. So a JSON-RPC error inside a stream doesn't register and the call counts as a success unless the HTTP status is ≥ 400. It's on the roadmap; it isn't here.
  • Can't see at all: MCP servers a host launches over local stdio. That traffic never touches an HTTP proxy, so no proxy sees it. Proxycept sees HTTP-transport MCP only.

If your setup is an agent talking to a remote MCP server over HTTP that replies with JSON, you're in the sweet spot. Let's do it.


What MCP-over-HTTP actually looks like on the wire

MCP is JSON-RPC 2.0. Over the HTTP transport, an MCP client POSTs a JSON-RPC message to the server's endpoint (commonly /mcp) with Content-Type: application/json, and the server replies with either application/json or text/event-stream. A header called Mcp-Session-Id ties the conversation together across calls.

A tool call on the wire is roughly:

POST /mcp HTTP/1.1
Host: mcp.example.com
Content-Type: application/json
Mcp-Session-Id: 5f3a9c2e-...

{"jsonrpc":"2.0","id":7,"method":"tools/call",
 "params":{"name":"get_weather","arguments":{"city":"Amman"}}}

and the (non-streaming) response:

HTTP/1.1 200 OK
Content-Type: application/json

{"jsonrpc":"2.0","id":7,"result":{"content":[{"type":"text","text":"31°C, clear"}]}}

In a plain HTTP capture, all you see is POST 200 mcp.example.com/mcp and two JSON bodies you have to open and read by eye. The useful facts (this was a tools/call, the tool was get_weather, it belonged to session 5f3a9c2e, and it succeeded) are in there, but you're doing the parsing in your head. That's the job Proxycept's decode does for you.


Step 1: Point the MCP client at the proxy

Proxycept is a hosted proxy, so there's nothing to install as a data plane. You route the MCP client's outbound HTTP(S) through one authenticated endpoint:

  • Endpoint: the Proxycept edge at proxycept.com:8443.
  • Auth: your profile's Basic-auth credentials (issued when the profile starts).
  • How you point at it: the same way you'd send any HTTP client through a proxy. Use the client's system proxy setting, or the standard HTTPS_PROXY environment variable for a process, or the device's proxy configuration. Whatever routes that client's HTTP traffic.

This is the exact same connect flow as any other Proxycept client. There is no MCP-specific switch. If you've pointed an emulator or a CI runner at Proxycept before, you already know this step. (New to it? The in-app /docs quick-start has the copy-paste version for your platform.)

Because the endpoint is a hostname and port rather than a laptop on your LAN, the same credentials work whether the agent runs on your machine, on a teammate's machine, or in CI. No 10.0.2.2-style translation, no "works on my box."

Step 2: Trust the CA so HTTPS can be decrypted

MCP servers are almost always HTTPS. To read (and decode) the JSON-RPC inside a TLS connection, the proxy has to terminate TLS, which means the client must trust the proxy's certificate authority. Install your profile's CA on the machine or environment running the MCP client. It's the same CA install you'd do for any HTTPS interception.

Heads up on two honest details: the CA's certificate subject reads Proxy Control CA, not "Proxycept". That's the name you'll see in a trust dialog. And certificate pinning still wins: if the MCP client pins its server's certificate, no proxy (this one included) will get in the middle on a stock setup. For a client you control in development, neither is usually a problem.

Step 3: Make an MCP call and watch Sessions

Trigger a tool call from your agent: anything that makes the client talk to the remote MCP server. Open Sessions in the Proxycept console. The flow shows up live, and if it's MCP, it's badged.

On the flow row you get:

  • an MCP badge (it reads MCP, or MCP • error when the call carried a JSON-RPC error), and
  • a compact summary of the call, e.g. tools/call → get_weather.

Open the flow drawer and the MCP detail panel shows the decoded fields:

  • Method: initialize, tools/call, tools/list, resources/read, and so on.
  • Tool: the called tool name (params.name) for a tools/call.
  • Mcp-Session-Id: the session header tying the conversation together.
  • Request id: the JSON-RPC request id, so you can line up a response with its call.
  • Error: the JSON-RPC error code and message when the call failed.

Non-MCP flows in the same session render exactly as they always have. The badge only appears when the decode is confident it's MCP.

Group a whole conversation with the "MCP only" filter

A single agent run can scatter dozens of tool calls through a session, interleaved with whatever other HTTP traffic the client makes. Flip the "MCP only" toggle on the flow list and two things happen:

  • the list filters to MCP flows (the non-MCP noise drops away), and
  • the remaining flows group by Mcp-Session-Id into collapsible per-session sections, so one conversation's tool calls collapse into a single readable trace. Flows without a session header fall into a "No session id" bucket rather than disappearing.

That's the "see everything one agent run asked its tools to do, in order" view: expand a session and read its tools/call → … sequence top to bottom.

Per-tool stats: counts, latency, error rate

When a session has MCP traffic, Sessions shows an MCP stats panel that aggregates the decoded calls per tool:

  • Count: how many times each tool was called.
  • Error rate: the share of calls to that tool that came back a JSON-RPC error (or an HTTP status ≥ 400).
  • p50 / p95 latency: the median and tail response time per tool, measured on live capture from the moment the proxy reads your request to the moment the upstream response is complete. That's what your agent actually waited for, response-body transfer included. Honest caveat: a tool shows a dash instead of a number when there was nothing to measure. That happens when every call to it was answered by a mock, held for intercept (that clock would be your own thinking time), or failed before any response arrived. A dash means unknown, never fast.

It turns a flat call log into something you can act on (which tool is slow or flaky) without exporting anything. The panel only appears when the session actually contains MCP traffic; a plain HTTP session doesn't grow an empty stats table. (The same numbers are available from the API at GET /api/sessions/{id}/mcp_stats.)

How the decode decides something is MCP

So it doesn't slap an MCP badge on every JSON API, the detection is deliberately conservative. A flow is treated as MCP only when both hold:

  1. the request Content-Type is JSON and the body parses as a JSON-RPC 2.0 message (a request with a method, or a result/error response carrying an id); and
  2. there's an actual MCP fingerprint: either an Mcp-Session-Id header (on the request or the response) or a recognized MCP method (initialize, tools/*, resources/*, prompts/*, notifications/*).

A generic JSON-RPC service that isn't MCP won't get mislabeled. And a truncated or non-JSON body simply doesn't decode. You still see the raw flow, just without the badge.


What this does not do yet (read this before you rely on it)

This is a focused capability, not an "AI observability platform," and it's worth being blunt about the edges so nothing surprises you:

  • No streaming (SSE) response decode, and the failure mode is subtler than "nothing shows up". If your MCP server replies with text/event-stream (the Streamable-HTTP transport), the call itself still decodes: detection reads the request, so you get the MCP badge, the summary, the method, the tool name, the request id and the Mcp-Session-Id. What is lost is the response: the data: frames aren't parsed, so a JSON-RPC error returned inside the stream is never seen. And because SSE-transported MCP errors usually ride an HTTP 200, that call is counted as a success. So the per-tool error rate is a floor, not a total, whenever your server streams. Decoding SSE frames is on the roadmap, not shipped. A server configured to return application/json gives you the full picture, errors included.
  • No stdio capture. A locally-launched stdio MCP server never crosses an HTTP proxy. There's nothing to point at the endpoint, so there's nothing to see. This is a transport fact, not a setting.
  • No MCP mocking and no token/cost decode. Proxycept mocks and injects faults on ordinary HTTP routes, but there's no MCP-server mocking, and it doesn't decode model or token usage out of LLM-API bodies.

None of that is hidden. It's just the honest boundary of the feature as it stands today. What you do get is the thing that was actually annoying: an AI agent's HTTP MCP calls, readable at a glance, in a shared console your whole team can open.


Why do this through a hosted, shared proxy

You could read one agent's traffic on your own laptop. The reason to do it through a hosted endpoint is the same reason the rest of Proxycept exists:

  • One endpoint, many clients. The agent on your machine, an agent in CI, and a teammate's run all point at the same proxycept.com:8443 with per-profile credentials, and every call lands in one shared Sessions view.
  • Team-shared, not screenshot-shared. A colleague can open the exact tools/call you're staring at instead of you pasting a screenshot into Slack. On paid tiers you get workspaces, roles (RBAC), and an audit trail over it.
  • Intercept and edit, not just watch. Beyond reading MCP calls, Proxycept can hold a request or response by host/path/method and edit it in flight. That's useful for poking at how an agent handles a changed tool result or an injected error.

That's the wedge: MCP decode is one more thing that shows up first-class in a proxy your whole team and CI already share, rather than a tap you run on one laptop.


Try it on your own agent

Proxycept has a free tier: one workspace, live capture, intercept/edit, and a per-profile mock server. It's enough to point an MCP client at a shared endpoint and watch tools/call → … decode in Sessions for yourself. No card required.

If you're weighing Proxycept specifically against a local-first MCP inspector, the Proxycept vs Inspectr comparison lays out the honest trade-offs, including where the local tool is the better fit.

Try Proxycept free

One hosted proxy endpoint for every device, emulator, and CI runner. Shared captures, no per-machine install.

Start free