feat: add dynamic tool loading for official models and per-server MCP deferred disclosure - #3667
Conversation
🦋 Changeset detectedLatest commit: 154056b The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 279e72ed39
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| // catalogModelToCapability reads it; stripping it here would silently | ||
| // disable tool-select for catalog-imported aliases. | ||
| "dynamically_loaded_tools", | ||
| "dynamic_tools", |
There was a problem hiding this comment.
Preserve the models.dev capability field
The models.dev catalog schema and compatible mirrors expose this as dynamically_loaded_tools; replacing that wire key with the internal dynamic_tools name causes stripModel() to discard the capability from fetched catalogs. Consequently, catalog-imported models that previously advertised support are emitted without the bit and tool selection remains disabled; retain the wire key here and translate it while normalizing the catalog.
Useful? React with 👍 / 👎.
| dynamic_tools: | ||
| declared.has('dynamic_tools') || | ||
| detected.dynamic_tools === true, |
There was a problem hiding this comment.
Continue recognizing the existing config capability
For users whose existing config.toml model aliases declare dynamically_loaded_tools, this resolver now silently ignores that declaration, so enabling the tool-select flag no longer activates progressive disclosure after upgrading. Since this is being released as a patch rather than a confirmed major change, accept both spellings during resolution and normalize to dynamic_tools internally.
AGENTS.md reference: AGENTS.md:L64-L64
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e274157fc7
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| }); | ||
| const disposable = this._register(this.registry.register(tool, { source: 'mcp' })); | ||
| const disposable = this._register( | ||
| this.registry.register(tool, { source: 'mcp', disclosure: 'deferred' }), |
There was a problem hiding this comment.
Honor deferred:false for MCP authentication tools
When a remote MCP server configured with deferred: false initially enters needs-auth while the tool-select gate is active, this branch still marks its synthetic authentication tool as deferred. AgentToolSelectService consequently hides that tool from the top-level tool list until it is selected dynamically, so the server's explicit inline-disclosure opt-out is not honored during authentication; propagate the server's configured disclosure setting here as the connected-server path does.
Useful? React with 👍 / 👎.
…icial models endpoint
f791d9a to
154056b
Compare
Related Issue
No linked issue — internal feature request.
Problem
The official Kimi Code
/modelsendpoint returnssupports_dynamic_tools: boolper model, but the refresh/provisioning flow drops the field, so config.toml never records which models accept message-level tool declarations — and thetool-selectprogressive-disclosure gate therefore never opens for official models. Separately,select_tools(the tool that loads deferred tool definitions) was never registered: agent profiles do not list it in their tool allowlists and the activation path filtered it out, so even with the capability declared and the flag enabled, models had no way to load deferred (e.g. MCP) tools.What changed
packages/oauth): parsesupports_dynamic_toolsfrom the/modelsresponse intoModelInfo; models declaring support getdynamically_loaded_toolsappended to their config.tomlcapabilitiesvia the existingcapabilitiesForModel()mapping — the same translation layer that already mapssupports_reasoning→thinking,supports_image_in→image_in, etc. The internal capability vocabulary is unchanged.packages/agent-core-v2,packages/klient): MCP server configuration gains a per-serverdeferredfield. Servers default to deferred disclosure when the model supports dynamic tool loading;deferred: falsekeeps a server's tools in the top-level tool list. The synthesized needs-auth MCP tool honors the same per-server setting.select_toolsregistration fix (packages/agent-core-v2):AgentToolActivationServicenow registersselect_toolsregardless of the profile tool allowlist, matching the disclosure-aware call guard inAgentToolPolicyService; profiledisallowedToolsstill vetoes it.Note: the
tool-selectexperimental flag stays default-off. The capability declaration lands in config.toml with this PR, but the progressive-disclosure gate remains flag-controlled until a separate release flip.Checklist
/approve).gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update.