# Remote MCP tools that run long: what your agent actually gets back

> Source: <https://dev.to/zebudata/remote-mcp-tools-that-run-long-what-your-agent-actually-gets-back-4gf6>
> Published: 2026-10-02 17:22:01+00:00

Most MCP demos show a tool that answers in a second. Real tools often don't: a scraper, a crawl or a report job can take minutes. We build web scrapers on Apify, so this is a problem we run into daily. We wanted to know what an agent actually receives when a remote MCP tool runs longer than one call, so we traced the raw JSON-RPC traffic against Apify's hosted MCP server (`mcp.apify.com`, version 0.17.1 at the time) on Oct 2, 2026. The job: a YellowPages scraper reading one results page, which takes about 35 seconds.

After `initialize`, `tools/list` returned one tool per scraper we had allowed through the server URL, plus four helper tools that only make sense for long-running work:

`get-actor-run` checks a run's status and can wait for it,`get-dataset-items` reads the results in pages,`get-key-value-store-record` reads a stored file or record,`abort-actor-run` stops a run.
The helpers are the first hint: the server expects the agent to come back for results.

The agent calls the scraper tool with ordinary arguments:

```
{ "searchKeyword": ["plumbers"], "location": "Austin, TX", "maxPages": 1 }
```

The response arrived after about 30 seconds, while the job was still running. It had two content parts. The first is structured:

```
{
  "runId": "…",
  "status": "RUNNING",
  "storages": { "datasets": { "default": { "id": "…", "itemCount": 23 } } }
}
```

The second is plain text written for the model:

```
RUNNING for 30s. In progress. 23 results so far.
Use get-actor-run with runId=… and waitSecs=30 to poll for completion.
```

That second part is the interesting design choice. The server returns machine-readable state and also tells the model, in plain English, what to do next. An agent that only parses the JSON still works. An agent that only reads text also knows to poll.

We first asked `get-actor-run` to wait 60 seconds and then 120. Both came back as a JSON-RPC error, not a tool result:

```
MCP error -32602: Invalid arguments for tool "get-actor-run".
Validation errors: /waitSecs: must be <= 45.
```

With `waitSecs: 30` the call returned `SUCCEEDED`, the run time (about 35 seconds) and the dataset item count (37). The result also carried a `_meta` block with the run's platform usage, which a client can show the user before it starts anything bigger.

Two things to handle here:

`-32602`), not as tool results with `isError`. If your client only checks `get-dataset-items` takes the dataset ID plus `offset` and `limit`, and returns:

```
{ "datasetId": "…", "items": [ … ], "itemCount": 37, "totalItemCount": 37, "offset": 0, "limit": 100 }
```

For a big job, page through with `offset` instead of pulling everything into the model's context at once.

The same evening a second test job, a Google Maps scraper, ran for about 157 seconds and finished with status `SUCCEEDED`, but `get-dataset-items` came back empty:

```
{ "items": [], "itemCount": 0, "totalItemCount": 0, "offset": 0, "limit": 100 }
```

An upstream dependency was failing, and the job ended cleanly with nothing to show. If your agent treats `SUCCEEDED` as "done, report success", it will tell the user everything worked. Check the item count, and treat "succeeded but empty" as a result the user needs to hear about.

How does your MCP client deal with tools that outlive one call: polling, progress notifications, or something else? We're curious what holds up in production.

*Written with AI assistance. Every request and response above comes from real calls we made on Oct 2, 2026.*
