resolveToolAvailability function
- required Map<
String, ToolCapability> capabilities, - required List<
(ToolScope, ToolsConfig)> scopes, - Set<
String> ? essentialToolIds, - Iterable<
String> mcpServerIds = const [],
Resolves the scope stack against the host's capabilities.
scopes lists (scope, config) pairs shallow→deep (global, project,
session, runtime); the deepest scope mentioning a key wins. Capability
absence is the hard floor: such ids stay disabled at ToolScope.builtin
even when a scope force-enables them. Present capabilities are on by
default and only config can turn them off. Unknown ids are collected in
ToolAvailabilityResolution.unknownIds without failing.
essentialToolIds is the active load-mode preset (issue #680): when
set, every ENABLED id outside it — static tool ids AND enabled
mcp:<server> families — demotes to discoverable (see
ToolAvailabilityResolution.discoverableIds). mcpServerIds names
the live MCP servers (the manager's connected set): servers no scope
declares are enabled by default, so the resolver cannot see them
without this — they demote like everyone else.
Implementation
ToolAvailabilityResolution resolveToolAvailability({
required Map<String, ToolCapability> capabilities,
required List<(ToolScope, ToolsConfig)> scopes,
Set<String>? essentialToolIds,
Iterable<String> mcpServerIds = const [],
}) {
final (:intent, :intentScope, :unknownIds, :mcpServers) = _collectToolIntents(
scopes,
);
final byId = <String, ResolvedToolAvailability>{
for (final id in knownToolIds)
id: _resolveKnownTool(id, capabilities[id], intent, intentScope),
};
if (intent['mcp'] == false) {
for (final server in mcpServers.keys.toList()) {
mcpServers[server] = false;
}
}
// Load-mode demotion (issue #680): under a preset, an enabled id
// outside the essential set becomes discoverable — UNLESS a scope
// explicitly enabled it (`tools: {id: on}` is a standing mount: the
// user asked for the tool, the preset only curates the default). The
// essential set is pinned: nothing in the scope stack can demote it,
// and an explicit `off` still disables it exactly as before.
final discoverable = essentialToolIds == null
? const <String>{}
: {
for (final entry in byId.entries)
if (entry.value.enabled &&
!essentialToolIds.contains(entry.key) &&
intent[entry.key] != true)
entry.key,
// MCP families demote too (issue #680 — the card lists mcp__*
// among the discoverable): the heaviest tool schemas are the
// feature's whole point. The same standing-mount rule applies:
// an explicit per-server `tools: {mcp:<server>: on}` or an
// aggregate `tools: {mcp: on}` keeps the family in the schema.
// Presets never carry mcp ids, and a disabled family (declared
// off, or the mcp:false kill-switch above) fails the enabled
// check — disable stays disable, not demotion.
if (intent['mcp'] != true)
for (final server in {...mcpServerIds, ...mcpServers.keys})
if ((mcpServers[server] ?? byId['mcp']?.enabled ?? true) &&
mcpServers[server] != true)
'mcp:$server',
};
return ToolAvailabilityResolution(
byId: byId,
unknownIds: unknownIds,
mcpServers: mcpServers,
discoverableIds: discoverable,
);
}