Trace viewer

Debug how your agent reads every tool

Mockd captures the full conversation between your agent and its tools. Inspect each call, replay the session, and find exactly where the model misreads a tool — before it ever touches production.

sessionses_h7Qf…3a1
  • crm.contacts.searchquery: "acme"200142ms
    crm.contacts.search
    ok · 200
    started 12:04:01.221 · took 142 ms · 3 fields

    Full-text search across CRM contacts; returns matching records.

    From the tool catalog — what the agent read.

    Agent inputrequired 1/1 · 0 unknown
    I'm calling crm.contacts.search with 3 values:
    querystringrequired

    Search term — e.g. a company name or email address.

    "acme"
    propertiesarrayoptional

    Which contact fields to include in the result.

    emailcompanylifecyclestage
    limitnumberoptional

    Maximum number of matches.

    10
    Exactly the data the agent sent (JSON)
    {
      "query": "acme",
      "properties": ["email", "company", "lifecyclestage"],
      "limit": 10
    }
    Server response
    what the tool returned
    200 ok
    {
      "total": 2,
      "results": [
        { "id": "5512", "company": "Acme Inc.", "email": "ops@acme.io" },
        { "id": "5513", "company": "Acme Labs", "email": "hi@acmelabs.dev" }
      ]
    }
  • crm.contacts.getid: 551220088ms
    crm.contacts.get
    ok · 200
    started 12:04:01.402 · took 88 ms · 2 fields

    Loads a single contact by its unique ID.

    From the tool catalog — what the agent read.

    Agent inputrequired 1/1 · 0 unknown
    I'm calling crm.contacts.get with 2 values:
    contactIdstringrequired

    Unique ID of the contact.

    "5512"
    propertiesarrayoptional

    Which fields to load.

    emailcompanyownerlifecyclestage
    Exactly the data the agent sent (JSON)
    {
      "contactId": "5512",
      "properties": ["email", "company", "owner", "lifecyclestage"]
    }
    Server response
    what the tool returned
    200 ok
    {
      "id": "5512",
      "company": "Acme Inc.",
      "email": "ops@acme.io",
      "owner": "rep_42",
      "lifecyclestage": "opportunity"
    }
  • crm.deals.createname: "Acme – Q3 Expansion"201196ms
    crm.deals.create
    ok · 201
    started 12:04:01.690 · took 196 ms · 4 fields

    Creates a new deal in the CRM pipeline.

    From the tool catalog — what the agent read.

    Agent inputrequired 1/1 · 0 unknown
    I'm calling crm.deals.create with 4 values:
    dealnamestringrequired

    Display name of the deal.

    "Acme – Q3 Expansion"
    amountnumberoptional

    Deal value in the account's currency.

    48000
    pipelinestringoptional

    ID of the pipeline the deal sits in.

    "default"
    dealstagestringoptional

    Current stage in the sales process.

    "qualifiedtobuy"
    Exactly the data the agent sent (JSON)
    {
      "dealname": "Acme – Q3 Expansion",
      "amount": 48000,
      "pipeline": "default",
      "dealstage": "qualifiedtobuy"
    }
    Server response
    what the tool returned
    201 ok
    {
      "id": "deal_9981",
      "dealname": "Acme – Q3 Expansion",
      "amount": 48000,
      "createdAt": "2026-06-19T12:04:01Z"
    }
  • crm.associations.createdeal_9981 ↔ 551220074ms
    crm.associations.create
    ok · 200
    started 12:04:01.871 · took 74 ms · 3 fields

    Links two CRM records together, e.g. a deal with a contact.

    From the tool catalog — what the agent read.

    Agent inputrequired 3/3 · 0 unknown
    I'm calling crm.associations.create with 3 values:
    fromobjectrequired

    Record the association starts from — type (e.g. "deal") and id.

    {object with 2 fieldstype:"deal"id:"deal_9981"}
    toobjectrequired

    Record being linked to — also type and id.

    {object with 2 fieldstype:"contact"id:"5512"}
    associationTypestringrequired

    Type of link (e.g. deal_to_contact).

    "deal_to_contact"
    Exactly the data the agent sent (JSON)
    {
      "from": { "type": "deal", "id": "deal_9981" },
      "to": { "type": "contact", "id": "5512" },
      "associationType": "deal_to_contact"
    }
    Server response
    what the tool returned
    200 ok
    { "status": "ASSOCIATED", "from": "deal_9981", "to": "5512" }
  • crm.notes.createinjectedrate limit — injected42931ms
    crm.notes.create
    429 errorinjected: 429 burst
    started 12:04:02.005 · took 31 ms · 2 fields

    Creates a note and attaches it to one or more CRM records.

    From the tool catalog — what the agent read.

    Agent inputrequired 1/1 · 0 unknown
    I'm calling crm.notes.create with 2 values:
    bodystringrequired

    Text content of the note.

    "Logged Q3 expansion deal from agent."
    associationsarrayoptional

    IDs of the records the note is attached to.

    deal_9981
    Exactly the data the agent sent (JSON)
    {
      "body": "Logged Q3 expansion deal from agent.",
      "associations": ["deal_9981"]
    }
    Server response
    what the tool returned
    429 error

    Rate limited — injected on purpose by the Mockd scenario 429 burst". Your agent waited 250 ms and the retry came back with 201 — from the mock, not the real tool.

    {
      "error": "RATE_LIMITED",
      "message": "Too many requests. Injected by Mockd scenario 'burst'.",
      "retryAfterMs": 250
    }
  • crm.notes.create↻ retry okretried after 250ms backoff201110ms
    crm.notes.create
    ok · 201
    started 12:04:02.379 · took 110 ms · 2 fields

    Creates a note and attaches it to one or more CRM records.

    From the tool catalog — what the agent read.

    Agent inputrequired 1/1 · 0 unknown
    I'm calling crm.notes.create with 2 values:
    bodystringrequired

    Text content of the note.

    "Logged Q3 expansion deal from agent."
    associationsarrayoptional

    IDs of the records the note is attached to.

    deal_9981
    Exactly the data the agent sent (JSON)
    {
      "body": "Logged Q3 expansion deal from agent.",
      "associations": ["deal_9981"]
    }
    Server response
    what the tool returned
    201 ok
    { "id": "note_4471", "createdAt": "2026-06-19T12:04:02Z" }
6 calls1 injectedtotal 641ms
Anatomy of a call

Everything captured, for every call

Each tool call your agent makes is recorded in full — so you see not just what happened, but why.

crm.deals.create
dealname: "Acme – Q3"
amount: 48000
pipeline: "default"
01

Tool & arguments

The exact tool the model picked and the arguments it filled in.

response
id: "deal_9981"
amount: 48000
createdAt: "…01Z"
02

Response

The synthetic payload Mockd returned — shaped like the real thing.

201 created196ms
0msbudget 300ms
03

Latency & status

How long the call took, and whether it succeeded, failed or was throttled.

forcedscenario: burst
429RATE_LIMITED
04

Injected scenario

Whether the response was forced by a scenario — a 429, a timeout, an empty set.

How it works

From config to first trace in under five minutes

No SDK to install, no code to change. Mockd looks exactly like a real MCP server to your agent — it just answers with synthetic data and records everything.

011 / 4

Pick a mock

Choose a server from the catalog — start with HubSpot — or bring your own MCP. You get a ready-to-paste connection config.

mock catalog8 servers
  • HubSpot24 tools
  • Salesforce31 toolssoon
  • Slack18 toolssoon
  • Stripe27 toolssoon
  • Notion15 toolssoon
022 / 4

Paste it into your agent

Drop the config into Claude, Cursor, the OpenAI Agents SDK or any MCP client. No code changes, no SDK to install.

mcp.json
{
  "mcpServers": {
    "mockd": {
      "url": "https://mock-d.com/hubspot/mcp"
    }
  }
}
033 / 4

Run your agent

Let it work. Every tool call is routed to the Mockd endpoint and answered with realistic, deterministic data.

agentmockd /mcpstreaming
  • crm.contacts.search200142ms
  • crm.contacts.get20088ms
  • crm.deals.create201196ms
  • crm.associations.create20074ms
044 / 4

Watch, then tune

Inspect each call in the live trace viewer, spot where the model misreads a tool, and fix your system prompt until it's right.

crm.deals.createmisread
model filled "name" — tool expects "dealname"
system prompt
− be a helpful CRM agent
+ use dealname (not name) when creating deals
re-run · 201 created
Under the hood

A control room for your agent's tools

The pieces that turn 'it seemed to work' into a tight, observable feedback loop.

Full-fidelity trace viewer

Every tool call captured with arguments, response, latency and status — a LangSmith-style timeline built for MCP.

crm.contacts.search142ms
crm.deals.create196ms
crm.notes.create429

Error & latency injection

Flip a switch to return 429s, empty sets or slow responses and prove your agent recovers.

inject errors
429timeoutempty

Latency you control

Simulate real-world response times to see how your agent paces itself.

latency+250ms

Prompt diffing

Compare two system prompts across the same tool calls, side by side.

be helpful
+prefer contactId over name

Stays in your sandbox

Nothing leaves to a third party. Mocked data is synthetic by design.

synthetic data
no egress

Bring your own MCP

Point Mockd at any custom MCP server. We render its tool descriptions, capture every call, and let you tune prompts against your own tools.

your-server.com/mcpconnected
tickets.listorders.getusers.search· 12 tools

See your agent's first trace

Point your agent at a Mockd endpoint and watch every tool call land in real time.

Start testing — free
sessionlive
crm.contacts.search142ms
crm.deals.create196ms
crm.notes.create110ms