Skip to content

Expose async cross-app polling handles to MCP callers - #2486

Merged
3mdistal merged 7 commits into
mainfrom
codex/a2a-route-continuity-refresh
Jul 29, 2026
Merged

Expose async cross-app polling handles to MCP callers#2486
3mdistal merged 7 commits into
mainfrom
codex/a2a-route-continuity-refresh

Conversation

@3mdistal

@3mdistal 3mdistal commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Problem

When the Framework cross-app ask action returns an asynchronous task, callers must receive its opaque task handle and exact polling arguments to retrieve the result. The builtin action already produced that envelope, but the generic MCP text fallback reduced mutating action results to their message field. Callers therefore saw instructions to poll with a handle they had never received, making the original task unreachable and encouraging duplicate submissions.

Approach

Preserve the full JSON response only for the Framework builtin ask_app action. A private marker identifies the actual builtin entry, rather than matching the public action name, so an app-defined action that overrides ask_app retains the normal concise-output and data-exposure boundary. This does not make ask_app read-only and does not broaden output visibility for other mutating actions.

What changed

  • Mark the freshly constructed Framework ask_app builtin as requiring its complete MCP object result.
  • Teach the generic text fallback to honor that private marker alongside the existing read-only behavior.
  • Add regression coverage for both the polling envelope and an app-defined ask_app name collision.
  • Add a patch changeset for @agent-native/core.

Safety and operations

This changes response serialization only; it adds no database migration, credential, permission, or new network behavior. The returned handle was already part of the builtin result and is intentionally opaque. Existing apps that define their own ask_app action do not inherit the marker. After merge and package rollout, the original Calendar-to-Content production acceptance story still needs to be rerun once to prove the hosted path end to end.

Verification

  • After reconciling the branch with current main and its MCP 2026 handler, the focused MCP server suite passed all 71 tests, proving the polling envelope and name-collision boundary on the prospective merge tree.
  • The broader MCP slice excluding oauth-store.spec.ts passed 34 files and 527 tests. The excluded local file could not load this checkout’s better-sqlite3 native binding; clean-runner CI covered the repository surface instead.
  • Exact-head clean-runner gates passed, including build, typecheck, lint, fast core tests, integration tests, security guards, the trusted acceptance substrate, scaffold generation, and Chat template end-to-end coverage.
  • Formatting and diff checks passed. Targeted lint exited successfully with pre-existing equality-style and unbound-method warnings in build-server.ts.
  • Independent read-only review of the reconciled head found no actionable issue and confirmed that current main’s MCP 2026 behavior and this PR’s visibility boundary are both preserved.

Review focus

  • Does the private marker remain confined to the freshly constructed Framework builtin under template-action precedence?
  • Is preserving the complete ask_app envelope the narrowest compatible way to keep asynchronous tasks reachable?
  • Do the collision test and existing concise formatter behavior adequately prevent unrelated mutating results from becoming visible?

@github-actions

github-actions Bot commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Here's a visual recap of what changed:

Visual recap

Open the full interactive recap

builder-io-integration[bot]

This comment was marked as outdated.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

@netlify

This comment has been minimized.

…nuity-refresh

# Conflicts:
#	packages/core/src/mcp/build-server.ts

@builder-io-integration builder-io-integration Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Builder reviewed your changes — looks good ✅

Review Details

Incremental Code Review Summary

I reviewed the latest head of PR #2486 against the previously reviewed implementation. The update retains the same narrow behavior: only the freshly constructed Framework ask_app builtin receives the private marker that enables lossless MCP object serialization, while template/app actions still take precedence and app-defined ask_app overrides remain concise. The latest diff also preserves the regression coverage for the async polling envelope and the non-leak boundary for an app-defined name collision.

Both independent incremental reviews found no new confirmed bugs, security issues, or performance regressions. The marker remains confined to the builtin entry, survives the merge, and is not inherited by an overriding app action. The added tests pass in isolation, including the polling metadata and override cases. No previous review comments required resolution because the prior review had no actionable findings.

Risk assessment: Standard. No actionable findings to submit.

🧪 Browser testing: Skipped — PR only modifies backend/package MCP behavior and tests, no UI impact

@3mdistal
3mdistal merged commit 21e33c7 into main Jul 29, 2026
100 checks passed
@3mdistal
3mdistal deleted the codex/a2a-route-continuity-refresh branch July 29, 2026 16:45
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.

2 participants