Skip to content

feat: expose ARS querying on the MCP and CLI surfaces - #66

Open
SkyeAv wants to merge 19 commits into
query-arsfrom
query-ars-mcp
Open

SkyeAv wants to merge 19 commits into
query-arsfrom
query-ars-mcp

Conversation

@SkyeAv

@SkyeAv SkyeAv commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Third of three stacked PRs for ARS querying. Puts @gloriachin's ARS finder flow in front of agents on the MCP and CLI surfaces. It also adds query_ars, which runs the whole flow as an MCP background task (SEP-1686).

Stacked on #65.

What changed

  • Five shared tools in TCT/interfaces/tools.py, available on both MCP and CLI (tct ARS-neighborhood-finder, tct submit-ars-query, and so on):
    • ARS_neighborhood_finder and ARS_pathfinder: the blocking finders from Guangrong's branch, including json_file passthrough of uploaded TRAPI queries. They return resolved inputs plus the top 20 ranked rows, or the full merged message for uploads.
    • submit_ars_query(node, neighbor_categories, predicates) returns a pk immediately. get_ars_status(pk) reports parent status, the merged pk, and per-ARA status. get_ars_results(pk, top_n=20) returns ranked rows, or the full merged TRAPI message with top_n=0.
  • query_ars, MCP-only, in TCT/interfaces/ars_task.py, registered with task=TaskConfig(mode="optional"). Task-aware clients get a task ID immediately and poll; task-unaware clients get an ordinary blocking call (SEP-1686 graceful degradation). It reports progress in two steps (ARS finished, merged answer fetched). The polling wait and merged-message fetch run in a worker thread.
  • query_ars lives in its own module because mcp.py uses PEP 563 string annotations, and FastMCP could not resolve the Progress dependency through them. Plain calls failed until the move.
  • None of the ARS submitters carries readOnlyHint: submit_ars_query, ARS_neighborhood_finder, ARS_pathfinder, and query_ars each create an ARS submission. Status and results lookups stay read-only.
  • TCT/server.py re-exports the six new names. The shared registry grows from 16 to 21 tools; MCP lists 22 with query_ars.
  • FastMCP 2.14.7 test-transport quirk: with the in-memory transport, once a server instance has run a task call, a second client session on that instance fails. The same session keeps working, and a real HTTP server handled task and plain calls across five separate sessions, so production is unaffected. The in-process tests reload the adapter to get a fresh server per session.

Stats (for audit)

  • 19 commits, 23 files, +2731/-14.
  • Offline suite: 171 passed, 7 skipped (157 before this PR; +14 in tests/test_ars_tools.py).
  • New offline coverage in tests/test_ars_tools.py: tool shaping (TRAPI construction, predicate forwarding, ranked rows, ready flags, json_file passthrough), plus the MCP surface through an in-process FastMCP client (submit/poll/fetch, task flow, graceful degradation, task metadata).
  • Contract tests extended with the new names, signatures, input schemas, and annotation sets. The unstructured-output contract still holds for all 22 tools.
  • Live tests: 3 to 6. Added the submit, poll, fetch flow; query_ars as a task; and query_ars through a task-unaware client.

Verification

  • uv run pytest: 171 passed, 7 skipped.
  • Live run 1: TCT_LIVE_ARS=1 uv run pytest tests/test_ars_live.py -v: 6 passed in 846.56 s.
  • Live run 2, same command: 6 passed in 760.28 s.
  • Performance figures for the underlying client are in feat: ARS neighborhood finder and pathfinder #65.

gloriachin and others added 4 commits September 29, 2026 15:13
The node_normalizer CI hostname returns 404; resolve every environment to
the production URL unless an explicit override is set.

Co-authored-by: Guangrong Qin <2994757+gloriachin@users.noreply.github.com>
Carry the status code, URL, and response into the raised requests.HTTPError
so callers see what failed instead of a bare exception.

Co-authored-by: Guangrong Qin <2994757+gloriachin@users.noreply.github.com>
When the CI and dev multiomics URLs 404, try the test deployment before
warning, so the Plover API registry still loads in restricted environments.

Co-authored-by: Guangrong Qin <2994757+gloriachin@users.noreply.github.com>
SkyeAv and others added 14 commits September 30, 2026 11:19
Reshape TCT.Query_ARS around Guangrong Qin's feat/ars-query-support module:
shared requests.Session transport, deadline-based merge-aware polling
(Relay#621), frozen ARSStatus with an O(1) child index, and an ARSResult that
extends FinderResult so both finders behave like the other TCT finders.
format_query_json_forARS_pathfinder reuses the shared pathfinder query-graph
builder.

Co-authored-by: Guangrong Qin <2994757+gloriachin@users.noreply.github.com>
Co-authored-by: Frankie Hodges <hodgesf@oregonstate.edu>
Co-authored-by: Frankie Hodges <129905251+hodgesf@users.noreply.github.com>
Re-executed Test_ARS.ipynb end to end (neighborhood, raw submit/poll flow,
and the new pathfinder cells) against the CI ARS.

Co-authored-by: Guangrong Qin <2994757+gloriachin@users.noreply.github.com>
… URL change

Guangrong's nodenorm fix was written against an older base that predated the
constant; keep his endpoint change but preserve the constant.

Co-authored-by: Guangrong Qin <2994757+gloriachin@users.noreply.github.com>
Ported from Guangrong Qin's feat/ars-query-support tool layer, reshaped onto
the ARSResult API: ranked summary rows for built queries, the full merged
message for uploaded json_file queries.

Co-authored-by: Guangrong Qin <2994757+gloriachin@users.noreply.github.com>
Async wrapper over the ARS finder flow with per-poll progress reporting.
Task-aware clients get a task ID immediately; task-unaware clients get a
plain blocking call per SEP-1686 graceful degradation.
ARS_neighborhood_finder, ARS_pathfinder, submit_ars_query, get_ars_status,
get_ars_results, and the query_ars background task join the server namespace.
FastMCP resolves the Progress dependency from real annotations, and PEP 563
string annotations in the adapter module defeat that resolution, which broke
task-unaware clients. The task tool now lives in a module without the future
import; the adapter registers it after the shared tools.
Tool shaping for the finder pair and the submit/status/results trio, plus the
MCP surface: SEP-1686 task flow (task ID, status, ranked results) and graceful
degradation for task-unaware clients.
Covers the sync trio (submit, poll, fetch) and query_ars through an
in-process MCP client both as a background task and as a blocking call.
The finder and submit tools now return plain status strings, and
submit_ars_query is marked non-read-only: submitting a query creates ARS
state, so readOnlyHint was wrong. The polling and fetch tools keep it.
@SkyeAv
SkyeAv added this pull request to stack #67 October 2, 2026 17:28
@Santoshkumarpuppala

Copy link
Copy Markdown

8fe83ee takes submit_ars_query out of the read-only set because "submitting a query creates ARS state", but three tools that stay in _READ_ONLY_TOOLS (TCT/interfaces/mcp.py:30-37) make the same submission. ARS_neighborhood_finder and ARS_pathfinder call submit_ARS (TCT/Query_ARS.py:701, :767), which does the POST {ars}/submit at :294, and query_ars calls it too (TCT/interfaces/ars_task.py:58) while hardcoding readOnlyHint: True (:92). tests/test_server.py:189-196 pins that split.

The MCP spec defines readOnlyHint as "the tool does not modify its environment". It's a hint, and the spec says clients should never base tool use decisions on annotations from untrusted servers, but a client that skips confirmation for read-only tools from a server it does trust would prompt for submit_ars_query and not for the other three. So either those three drop the hint alongside submit_ars_query (for query_ars that's ars_task.py:92, not the set), or the comment at mcp.py:34 and the test should say why their submission differs from submit_ars_query's. Read at 8fe83ee, not run.

ARS_neighborhood_finder, ARS_pathfinder, and query_ars each create an
ARS submission through submit_ARS, so readOnlyHint is now False for
them as it already was for submit_ars_query. Removes the inert
query_ars entry from _READ_ONLY_TOOLS and updates the annotation pins.
@SkyeAv

SkyeAv commented Oct 5, 2026 •

Copy link
Copy Markdown
Member Author

@Santoshkumarpuppala Good catch, all four ARS submitters now carry readOnlyHint: False on query-ars-mcp (commit 94eefb7), thanks for the detailed review.

This branch has not been deployed

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants