Patch Changes
-
db62d66: Fix
frameworkToolssilently ignoring eight of its own switches.sharing,review,history,featureFlags,localization,contextXray,userProfile, andauditare removed byfilterFrameworkToolGroups, which matched onActionEntry.frameworkGroup. That tag is written in exactly one place —mergeCoreSharingActions— and the plugin calls it againsthttpActions, the registry documented as deliberately ungated so the UI keeps working. So the tag never reached the agent registry: any app loading core kits throughloadActionsFromStaticRegistryor its own actions directory held untagged entries, and setting those eight groups tofalsedid nothing. The other groups (database,extensions,automation,docs,resources,web,workspaceApps,chat,email) were unaffected — they are gated at construction, where the registry is built empty.Group membership now resolves by name first and tag second (
resolveFrameworkGroup), so a switch works no matter how the action was registered.CORE_ACTION_GROUPSmoves toframework-tools.ts(still re-exported fromaction-discovery.ts) so the filter can read it without an import cycle; theframeworkGroupstamp stays as a pre-resolved copy but nothing depends on it any more.The same tag dependency broke
resolveInitialToolNames, which excludes framework kits from the DEFAULT first-request tool list — untagged apps were promoting ~45 framework schemas into every first request. Fixed by the same change.Guard tests cover both consumers using deliberately untagged fixtures built from
CORE_ACTION_GROUPS, since the previous tests hand-stampedframeworkGroupand so passed against inputs no real app produced. They also assert an app action that merely resembles a kit name (share-portfolioundersharing: false) is left alone. -
db62d66: Accept Client ID Metadata documents that advertise grant types beyond
authorization_code/refresh_token. The MCP OAuth client-metadata validator rejected the whole document when it listed any other grant — so Claude.ai, whose CIMD document also listsurn:ietf:params:oauth:grant-type:jwt-bearer, could not connect at all. Only the length/shape ofgrant_typesis validated now; the token endpoint already honors justauthorization_codeandrefresh_tokenregardless of what the document declares. -
db62d66: Consolidate every MCP setting on
createAgentChatPluginunder onemcp: {}option, and addmcp.catalog: "app".mcpacceptsenabled,catalog,connectorCatalog,externalAgents,builtinCrossAppTools,title,description,websiteUrl, andicons. The top-leveldisableMcp,mcpServerInfo,connectorCatalog, andexternalAgentsstay accepted for one minor and are deprecated; the nested value wins, and setting both forms to disagreeing values throws at plugin init rather than booting an app with an MCP surface nobody chose (same contract asresolveFrameworkTools).disableMcp: trueandmcp.enabled: falseare normalized as inverses, so a correctly migrated app is not read as a conflict.Two behavior fixes come with it:
builtinCrossAppToolshad no route through the plugin at all — it was reachable only by callingmountMCPdirectly. That is whyframeworkTools: "minimal"andworkspaceApps: falsecould never remove the cross-app builtins (list_apps,open_app,ask_app,ask_app_status,create_embed_session,create_workspace_app,list_templates) from an app using the normal plugin entry point: the MCP layer merges them downstream of theframeworkToolsfilter.mcp.builtinCrossAppTools: falseis now the switch.- A2A read the connector policy straight off the raw plugin options, so
mcp.connectorCatalogwould have narrowed the MCP surface while A2A kept serving the old one.filterDirectA2AActions/buildAuthenticatedAgentA2ASkillsnow take the resolved shape, so the two external surfaces cannot diverge.
mcp.catalog: "app"serves external callers exactly the app's own tool registry, flat — the same actions the in-app agent holds, with no cross-app builtins, noask-agent, notool-search, and no compact/connector trimming.externalAgents.denyActionsand the OAuth scope filter still apply, since both are explicit removals rather than catalog tiering, and the dev-open surface split is unchanged (an unauthenticated loopback probe still getsactions, notproductionActions). Weigh the token cost before setting it: an app registering ~100 actions puts every schema in the caller's context ontools/list, which is what the compact default exists to avoid.Also folds the per-tier
tools/callgate into one rule — the advertised set is the callable surface on every tier except the explicit--full-catalogopt-in — so adding a tier can no longer default to "everything callable" by omission.tool-searchis fixed on both ends over MCP. It is dropped entirely from every flat catalog (mcp.catalog: "app"and the--full-catalogopt-in), where every tool is already listed beside it and it could only describe its own neighbours. On the trimmed catalogs, where it does earn its place, it is now scoped to the advertised set: previously it closed over the app's whole registry whiletools/callaccepted only the advertised subset, so it answered with names that came straight back as "Unknown tool".attachToolSearch,searchToolRegistry,createToolSearchEntry,TOOL_SEARCH_ACTION_NAME,resolveFrameworkTools,filterFrameworkToolGroups, andframeworkGroupEnabledare now exported from@agent-native/core/server, so a standalonemountMCPplugin can compose the same surface the agent-chat plugin does instead of hand-rolling a copy that drifts.