Skip to content

Add mcpTool and important to defineAction - #3454

Open
manucorporat wants to merge 2 commits into
mainfrom
claude/define-action-tool-config-d0go2b
Open

Add mcpTool and important to defineAction#3454
manucorporat wants to merge 2 commits into
mainfrom
claude/define-action-tool-config-d0go2b

Conversation

@manucorporat

Copy link
Copy Markdown
Contributor

Two configurations lived in plugin-level name lists that an action could not
see: mcp.connectorCatalog decided which actions external agents get served,
and initialToolNames decided which schemas ride the first model request.
Both drift the moment an action is renamed, and neither is visible where the
action is written.

  • mcpTool: false is a hard veto on every MCP tier, filtered from actions
    rather than the advertised listing so the --full-catalog tier — where
    actions IS the callable surface — cannot leave it callable by name. It
    also drops the action from both direct-A2A projections.
  • mcpTool: true is connector-catalog membership declared on the action, and
    activates the connector tier on its own, so a template can retire its
    connectorCatalog array. It feeds the A2A local-capability set too, so
    both surfaces keep serving the same curated list.
  • important: true puts an action in the first-request tool list and narrows
    the derived default from "every app action" to the marked ones — otherwise
    the annotation would be decorative and the array would stay. important: false drops an action from the derived set only; a name a template still
    lists explicitly is never silently deleted.

Both name lists keep working unchanged, so an app migrates one action at a
time.

Two configurations lived in plugin-level name lists that an action could not
see: `mcp.connectorCatalog` decided which actions external agents get served,
and `initialToolNames` decided which schemas ride the first model request.
Both drift the moment an action is renamed, and neither is visible where the
action is written.

- `mcpTool: false` is a hard veto on every MCP tier, filtered from `actions`
  rather than the advertised listing so the `--full-catalog` tier — where
  `actions` IS the callable surface — cannot leave it callable by name. It
  also drops the action from both direct-A2A projections.
- `mcpTool: true` is connector-catalog membership declared on the action, and
  activates the connector tier on its own, so a template can retire its
  `connectorCatalog` array. It feeds the A2A local-capability set too, so
  both surfaces keep serving the same curated list.
- `important: true` puts an action in the first-request tool list and narrows
  the derived default from "every app action" to the marked ones — otherwise
  the annotation would be decorative and the array would stay. `important:
  false` drops an action from the derived set only; a name a template still
  lists explicitly is never silently deleted.

Both name lists keep working unchanged, so an app migrates one action at a
time.
@github-actions

github-actions Bot commented Aug 23, 2026

Copy link
Copy Markdown
Contributor

Here's a visual recap of what changed:

Visual recap

Open the full interactive recap

@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 and found 2 potential issues 🔴

Review Details

Code Review Summary

PR #3454 adds action-owned mcpTool and important metadata, preserves the declarations through action discovery, derives first-request tools from important, and merges action declarations with the existing MCP connector catalog. The core approach is sound: omitted values remain distinguishable from explicit booleans, the full-catalog callable set is filtered rather than merely hiding schemas, and the focused tests cover the main connector and A2A paths. This is a standard-risk change because it modifies shared action exposure and agent-surface policy.

Key Findings

  • 🔴 HIGH: An action can combine agentTool: false with mcpTool: true and still be added to the MCP connector catalog. This violates the documented “mcpTool never widens agentTool” contract and can expose an action that should be hidden from all agent surfaces.
  • 🟡 MEDIUM: Public A2A skill discovery does not apply the new mcpTool: false veto, so a supposedly external-hidden action can remain advertised in the public agent card.

The implementation has good backward-compatibility intent for existing name-based configuration and includes useful regression coverage for full-catalog callability.

🧪 Browser testing: Skipped — PR only modifies backend/config/docs, no UI impact

Comment thread packages/core/src/mcp/build-server.ts
Comment on lines +156 to +159
rawQueryAllowed &&
!denied.has(name) &&
entry.agentTool !== false &&
entry.mcpTool !== false &&

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.

🟡 Apply the mcpTool veto to public A2A skills

mcpTool: false is enforced for authenticated direct and delegated A2A actions, but filterPublicAgentActions() still includes every anonymously exposed publicAgent action. An action with publicAgent.expose: true and mcpTool: false remains advertised in the public A2A skills card, exposing its name, description, and schema despite the hard-veto contract; apply the veto to the public projection and add a regression test.

Additional Info
Found independently by 3 of 3 parallel code-review agents.

Fix in Builder

`mcpTool` defaulted to a flat `true`, so an `agentTool: false` action was
hidden from the agent but still described as externally exposed. One flag
should stay one decision: an undeclared `mcpTool` now inherits `agentTool`,
and declaring it overrides that inheritance in both directions — including
`agentTool: false` with `mcpTool: true`, an MCP-only action that outside
agents get and the app's own agent never sees.

`isActionExposedToExternalAgents` in `action.ts` is the single resolver; no
surface re-derives it from the two raw fields.

Making MCP-only reachable took three gates that all tested `agentTool` alone:

- `filterAgentTools` drops these actions before the MCP and A2A mounts, which
  is right for every in-app surface. The plugin now re-merges exactly the
  MCP-only set into those two mounts through `filterMcpOnlyActions`, and
  nowhere else: an `ask_app` run is the app's own agent, which `agentTool:
  false` already answered.
- `executeAgentToolCall` and `searchToolRegistry` are backstops behind a
  surface-scoped registry, so they now refuse only what no surface may run.
  Testing `agentTool` alone made them reject the MCP-only actions their own
  caller had just handed them — advertised over MCP, then "unknown tool" on
  call, and invisible to `tool-search` on a trimmed catalog.

The boundary filter also closes a smaller gap: the standalone stdio server
builds its surface from `autoDiscoverActions` and was serving `agentTool:
false` actions to external clients.

@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 and found 1 potential issue 🟡

Review Details

Incremental Code Review Summary

The latest commit adds the intended MCP-only model: actions with agentTool: false, mcpTool: true are re-merged into external MCP/A2A registries while remaining absent from the app’s own agent surface. It also centralizes the external-exposure inheritance rule and updates the tests and documentation to describe mcpTool inheriting agentTool. The previously reported MCP connector widening issue is fixed and its review thread was resolved. The public A2A-card issue remains open and was intentionally not reposted.

New Finding

  • 🟡 MEDIUM: The secondary dev/test filesystem discovery path reconstructs action entries without retaining mcpTool or important. As a result, actions loaded through that path cannot become MCP-only and their important annotation does not affect first-request tool selection.

The main architecture and compatibility behavior otherwise look sound, including explicit support for MCP-only actions and preserving the existing name-based configuration. This remains a standard-risk shared-core exposure change.

🧪 Browser testing: Skipped — PR only modifies backend/config/docs, no UI impact

Comment on lines +1117 to +1118
const mcpOnlyActions = filterFrameworkToolGroups(
filterMcpOnlyActions({

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.

🟡 Preserve MCP metadata in the dev discovery registry

The secondary filesystem discovery path that feeds discoveredActionsAll reconstructs imported entries with tool, run, http, and agentTool, but drops mcpTool and important. An action declared { agentTool: false, mcpTool: true } is therefore omitted from the new mcpOnlyActions merge instead of being available externally, and important: true is ignored for initial-tool selection. Carry both flags through the direct-import and shell-wrapper fallback paths, with an integration test for a filesystem-discovered action.

Additional Info
Found independently by 2 of 3 parallel incremental code-review agents.

Fix in Builder

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