Skip to content

Adopt MCP Tasks for long-running tools (blocked on MCP Java SDK and Spring AI support) #274

Open

Description

@adityamparikh

Summary

Why Tasks, and why wait

Backup, restore and URL indexing can run for minutes. The current SDK gives the server two options:

  • block the call, risking the client's tool-call timeout with no progress feedback, since the stateless HTTP transport cannot send progress notifications;
  • return a home-grown request handle plus a status tool that only this server understands.

Tasks is the protocol's answer to this problem. The server returns a durable task handle, the client polls tasks/get, and the final result or error comes back in the same shape a synchronous call would have. A custom mechanism built now would have to be maintained alongside Tasks, or deprecated, once Tasks arrives.

The HTTP transport already runs with spring.ai.mcp.server.protocol=stateless, the model the Tasks extension assumes, so no transport rework is expected.

Blocked work

Work Why it waits
#224 backup-collection, list-backups, restore-collection (all three) Solr runs backup and restore as async jobs that can take minutes. list-backups waits too, so the three tools land together.
#208 / #210 index-url (URL and local-file routes) A transfer runs for up to solr.index-url.total-timeout (default 5 min). #210 stays a draft.

Not affected: the four inline-payload indexing tools. The model's output budget caps their payload size, and their time goes into token generation, not Solr. For the 61-record shows.json sample, Solr and the server take under 1 s of roughly 2 minutes (#208).

Upstream status (2026-10-20)

MCP spec 2026-07-28 + ext-tasks schema ........ done (SEP-2663 merged 2026-05-15)
MCP Java SDK: modern stateless server ......... done, 2.2.0-M1 (modelcontextprotocol/java-sdk#1170)
MCP Java SDK: modern client ................... not started (part of modelcontextprotocol/java-sdk#1011)
MCP Java SDK: Tasks extension ................. not started (modelcontextprotocol/java-sdk#1013, milestone 2.2.0-M2)
Spring AI: adopt SDK 2.2 modern server ........ no tracking issue found
Spring AI: tasks for @McpTool methods ......... no tracking issue found
MCP hosts declaring the tasks extension ....... none in the official extension client matrix

Design notes for when it is unblocked

Backup and restore (#224) fit Tasks well, because Solr already keeps the job record:

 MCP client                       solr-mcp                         Solr (ZK)
     |  tools/call backup-collection  |                                |
     |  (_meta: tasks extension)      |-- BACKUP async=solr-mcp-<id> ->| status stored
     |<- CreateTaskResult ------------|                                |  in ZooKeeper
     |   taskId=solr-mcp-<id>         |                                |
     |  tasks/get taskId              |-- REQUESTSTATUS -------------->|
     |<- working / completed+result --|<- state, exception.msg --------|
     |   / failed+error               |-- DELETESTATUS (terminal) ---->|
     |  tasks/cancel                  |  ack only; Solr cannot cancel  |
     |<- {} --------------------------|  a running BACKUP/RESTORE      |
  • Task id and storage: use the Solr async id as the task id. If Spring AI lets the application supply the task store, back it with REQUESTSTATUS, so task state survives a server restart and works across stateless replicas. Otherwise use Spring AI's own store. Do not build a parallel one.
  • Polling Solr: keep backup: add backup-collection, list-backups and restore-collection tools #224's finding and poll REQUESTSTATUS by hand. SolrJ's processAndWait deletes the stored status, and with it the failure detail, before the caller can read it (CollectionAdminRequest.java:1862-1876 in SolrJ 10.0.0).
  • Cancel: acknowledge only. The spec makes cancellation cooperative, and Solr has no cancel for a running BACKUP or RESTORE.
  • Authorization: tasks/get and tasks/cancel need the same scope as the tool that created the task (McpAuthorities.ADMIN once Have specific security roles #66 lands). Use whatever task-to-caller binding Spring AI provides.

index-url (#208 / #210)

  • Storage: Solr keeps no job record for an update request, so task state lives in the store Spring AI or the SDK provides. Under http, check that the store works across replicas before enabling tasks.
  • Progress: report bytes and documents sent so far in the task's status message.
  • Cancel and failure: in SolrCloud an uncommitted batch cannot be rolled back. Documents already streamed become visible at the next autoCommit or the next caller's commit, so a cancelled or failed task must say the collection may be partially indexed.
  • Concurrency: keep feat(indexing): index-url — index a document set into Solr from an http(s) URL, or from a local file path under STDIO #208's limit of 4 concurrent transfers. A task holds its slot until it reaches a terminal state.

Both: under the 2026-07-28 spec, a server must not return a task to a client that did not declare the extension. When implementing, decide what those clients get: block until finished, or refuse the call. If blocking stays, measure the target clients' tool-call timeouts first.

Unblock checklist

Then unblock #224 first, then #208 / #210, rewriting each issue's async section along these lines.

Out of scope

  • A custom status tool, job registry or handle-and-poll protocol, in place of Tasks or alongside it.
  • Tasks for search, schema, collection or alias tools, which return in well under a second.
  • input_required / tasks/update. No tool needs to pause for input today.

References

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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