Skip to content

mcp: add compact run and result navigation#330

Merged
arybchik merged 3 commits into
ts-factory:mainfrom
okt-limonikas:mcp-improve-run
Jun 26, 2026
Merged

mcp: add compact run and result navigation#330
arybchik merged 3 commits into
ts-factory:mainfrom
okt-limonikas:mcp-improve-run

Conversation

@okt-limonikas

@okt-limonikas okt-limonikas commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Stacked on top of #324


Replace the fragmented run metadata tools and the ambiguous direct-child
list_results interface with two validated Markdown workflows for MCP clients.

What changed

This PR introduces two higher-level run navigation tools:

  • get_run_overview
  • get_run_leaf_results

Together they replace the previous flow where clients had to call separate run
metadata/stat/source tools and manually reconstruct how to navigate from a run
tree node to concrete test executions.

New tools

get_run_overview

Returns a complete Markdown overview for a run, including:

  • run metadata
  • status and conclusion
  • source URL
  • compromised details
  • recursive result statistics tree
  • aggregate Result IDs for test leaves

The tool also supports:

  • requirements: semicolon-separated requirement filter
  • unexpected_only: return only leaf tests containing unexpected or abnormal results

Each test row includes a Result ID that can be passed directly to
get_run_leaf_results.

get_run_leaf_results

Returns paginated concrete executions represented by one test leaf from
get_run_overview.

The input is intentionally an aggregate test Result ID from the overview, not an
individual execution ID. The tool validates that the ID points to a real test
leaf before resolving executions.

It supports two usage modes:

  • unexpected_only=true: common failure-investigation mode, returning only
    unexpected or abnormal executions
  • advanced filters:
    • requirements
    • results, for example PASSED;FAILED;SKIPPED;KILLED;CORED;FAKED;INCOMPLETE
    • result_properties, for example expected;unexpected;not_run

unexpected_only is mutually exclusive with the advanced filters.

Why this is better

The old MCP interface exposed lower-level pieces of the UI model. Clients had to
combine run details, source, stats, and direct-child result listing themselves,
while also knowing how Bublik lazy-loads the run tree.

The new flow is explicit:

  1. Call get_run_overview(run_id) to inspect the run and find interesting test leaves.
  2. Pick a test row Result ID.
  3. Call get_run_leaf_results(leaf_result_id) to inspect concrete executions.

This makes MCP usage more reliable and cheaper for large runs because clients no
longer need to fetch or reason over unrelated execution details.

Token impact

Estimated token count changes:

  • Full run stats: ~26,000 tokens -> ~10,000 tokens
  • Unexpected-only run stats leaves: ~26,000 tokens -> ~2,000 tokens

Validation and rendering

The new run payloads are validated with strict Pydantic models before Markdown
rendering. This keeps the MCP output compact and human-readable while still
catching unexpected service payload changes early.

Issue: #326
Issue: #327

@okt-limonikas okt-limonikas force-pushed the mcp-improve-run branch 6 times, most recently from 158c578 to 9693777 Compare June 16, 2026 01:02
@okt-limonikas okt-limonikas marked this pull request as ready for review June 16, 2026 01:02
Comment thread bublik/mcp/run/models.py Outdated
@okt-limonikas okt-limonikas force-pushed the mcp-improve-run branch 3 times, most recently from 34daf38 to 5eb5350 Compare June 16, 2026 17:59

@ol-nata ol-nata left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use a more goal-oriented commit summary: replace mcp: add compact run and result navigation with something like mcp: enforce structured run/result navigation workflow to prevent incorrect tool usage

Comment thread bublik/mcp/models.py
@okt-limonikas okt-limonikas force-pushed the mcp-improve-run branch 4 times, most recently from 1bf28e6 to 4551d96 Compare June 18, 2026 01:10
@okt-limonikas

okt-limonikas commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator Author

Please use a more goal-oriented commit summary: replace mcp: add compact run and result navigation with something like mcp: enforce structured run/result navigation workflow to prevent incorrect tool usage

Changed to mcp: enforce run/result navigation to reduce context usage
Also rebased

@okt-limonikas okt-limonikas force-pushed the mcp-improve-run branch 3 times, most recently from 2550b81 to 9f45117 Compare June 24, 2026 15:03
@ol-nata ol-nata self-requested a review June 25, 2026 13:21
Comment thread bublik/mcp/run/helpers.py
meta_results__meta__type='result',
meta_results__meta__value__in=abnormal_statuses,
),
)

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This duplicates the existing Meta.abnormal / abnormal() helper in core/run/stats.py, which already encodes the same status set. Could we reuse Meta.abnormal here instead of resolving the statuses independently via discover_statuses? Otherwise the two definitions can drift apart over time.

Comment thread bublik/mcp/run/markdown.py Outdated

page = 1
if pagination.previous:
page = int(pagination.previous.split('=')[1]) + 1

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this recovers the current page by parsing pagination.previous ("page=N") back into an int. The resolved page is already computed in _get_run_leaf_results/PaginatedResult.paginate_queryset, just not passed along. Could it be threaded through as an explicit field on RunLeafResultsPayload/RunLeafPagination instead, so this doesn't depend on the string format of previous?

@okt-limonikas okt-limonikas force-pushed the mcp-improve-run branch 2 times, most recently from c815906 to f213ba6 Compare June 25, 2026 14:24
Comment thread bublik/core/pagination_helpers.py
PaginatedResult.paginate_queryset already resolves the current page number
but discarded it, leaving consumers to recover it from the 'next'/'previous'
URL strings. Add it as an explicit 'page' field on the returned pagination
dict so callers can read it directly.

Signed-off-by: Danil Kostromin <danil.kostromin@icloud.com>
@okt-limonikas okt-limonikas force-pushed the mcp-improve-run branch 2 times, most recently from ec992ea to 04bfb84 Compare June 25, 2026 17:59
The previous commit added a 'page' field to the dict returned by
PaginatedResult.paginate_queryset, but RunListPagination is a
fixed-field dataclass built from that dict via RunService.list_runs
(RunListPagination(**paginated_runs['pagination'])). Without a matching
field it raises TypeError on the unexpected 'page' keyword. Add 'page'
to keep the DTO consistent with the shared pagination shape.

Follow-up to: f8bb70e
Signed-off-by: Danil Kostromin <danil.kostromin@icloud.com>
@okt-limonikas okt-limonikas force-pushed the mcp-improve-run branch 2 times, most recently from 5640030 to 39da14b Compare June 25, 2026 18:51
@okt-limonikas okt-limonikas requested a review from ol-nata June 25, 2026 18:57
Comment thread bublik/mcp/run/markdown.py
Comment thread bublik/mcp/tools.py
Replace the fragmented run metadata tools and the ambiguous
direct-child `list_results` interface with two validated Markdown
workflows.

`get_run_overview` combines run metadata with the recursive statistics
tree and can reduce it to unexpected leaves. `get_run_leaf_results`
accepts an aggregate test result ID from that overview and delegates
concrete execution filtering and pagination to the existing result
service.

This gives MCP clients a compact way to inspect large run trees without
reconstructing UI lazy-loading semantics, while preserving strict
payload validation before rendering.

Issue: ts-factory#326
Issue: ts-factory#327
Signed-off-by: Danil Kostromin <danil.kostromin@icloud.com>
@arybchik arybchik merged commit 3617b55 into ts-factory:main Jun 26, 2026
2 checks passed
@okt-limonikas okt-limonikas deleted the mcp-improve-run branch June 26, 2026 10:31
@okt-limonikas okt-limonikas restored the mcp-improve-run branch June 26, 2026 10:55
@okt-limonikas okt-limonikas deleted the mcp-improve-run branch June 26, 2026 10:59
@okt-limonikas okt-limonikas restored the mcp-improve-run branch June 26, 2026 18:59
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