Skip to content

Python: Add a default approval mode to MCP approval policies - #9828

Open
Eduard van Valkenburg (eavanvalkenburg) wants to merge 3 commits into
microsoft:mainfrom
eavanvalkenburg:mcp-approval-defaults
Open

Eduard van Valkenburg (eavanvalkenburg) wants to merge 3 commits into
microsoft:mainfrom
eavanvalkenburg:mcp-approval-defaults

Conversation

@eavanvalkenburg

Copy link
Copy Markdown
Member

Motivation & Context

Per-tool approval policies for local MCP tools (MCPSpecificApproval) let callers list the tools that always or never require approval. They did not let callers state the approval mode for tools and prompts named in neither list. Those silently used the framework default, which does not require approval. Hosted MCP services apply their own default to unnamed tools, so the same policy shape could mean different things for local and hosted tools.

This change adds an explicit default so callers can state the intent, and it flags the implicit fallback ahead of a possible future change.

Description & Review Guide

  • What are the major changes?
    • Add an optional default key ("always_require" or "never_require") to MCPSpecificApproval. A tool or prompt resolves in this order: always_require_approval, never_require_approval, default, then the existing fallback (no approval). default also applies to tools and prompts discovered later, for example after tools/list_changed. It is validated when the MCP tool is constructed and is read only by local MCP tools (the hosted get_mcp_tool helpers are unchanged).
    • Emit a FutureWarning once at construction when never_require_approval is set without default. Behavior is unchanged in that case. The warning points at the code that constructs the tool, including through subclass constructors such as FoundryToolbox.
    • Treat a name list given as a single string as one name instead of a substring pattern, in both approval matching and the ambiguous-name validation.
    • Document the resolution order in the MCPSpecificApproval and constructor docstrings and in python/packages/core/AGENTS.md. Add tests, and add default to existing test policies that would otherwise emit the new warning.
  • What is the impact of these changes? No behavior change unless a caller sets default or passes a name list as a single string. Callers who set never_require_approval without default see a FutureWarning. Setting default silences it: "never_require" keeps today's behavior and "always_require" requires approval for tools and prompts named in neither list.
  • What do you want reviewers to focus on? The resolution order and the unchanged fallback, the warning stack level through subclass constructors, and the single-string name handling.

Related Issue

N/A - trivial change. It is a small, additive option on an existing parameter, and behavior is unchanged unless the new key is set.

AI Assistance

  • No material AI assistance was used.
  • This is an AI-assisted contribution. I reviewed, understood, and verified all submitted content and accept responsibility for it.

AI assistance details: Implementation, tests, documentation, and this PR description were drafted with GitHub Copilot.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR links to an agreed issue with no competing open PR, or the Related Issue section documents a trivial-change or repository-automation exception.
  • This is not a breaking change. If it is a breaking change, add the breaking change label (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.

Add an optional `default` key to `MCPSpecificApproval` that sets the approval
mode for tools and prompts named in neither list.

- Resolve a policy in order: always list, never list, `default`, then the
  existing fallback (no approval).
- Validate `default` when the MCP tool is constructed.
- Warn once at construction when `never_require_approval` is set without
  `default`, because that fallback may change in a future release.
- Treat a name list given as a single string as one name instead of a
  substring pattern.
- Document the resolution order and add tests.
Copilot AI balanced review requested due to automatic review settings October 29, 2026 13:46
@agent-framework-automation agent-framework-automation Bot added documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python labels Oct 29, 2026

Copilot AI 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.

🟡 Changes recommended

The new non-fixture test helpers violate the coding standard and must move to explicitly imported helper modules, with captured test state passed as arguments.

1 open issue
What changed in this PR

Adds an explicit default approval policy for local Python MCP tools and prompts while preserving the existing fallback when no default is set.

Changes:

  • Adds and validates MCPSpecificApproval.default, with explicit name lists taking precedence.
  • Warns about implicit fallback policies and treats bare-string approval names as exact names.
  • Documents policy behavior and tests precedence, warning locations, discovery refreshes, and streaming/non-streaming approval gating.
File Description
python/​packages/​core/​tests/​core/​test_mcp.py Adds approval-policy coverage and updates existing policies to avoid unintended warnings.
python/​packages/​core/​AGENTS.md Documents resolution order, warnings, and local-only default behavior.
python/​packages/​core/​agent_framework/​_mcp.py Implements default validation and resolution, exact-name handling, and caller-targeted warnings.

Review effort: Balanced

Comment thread python/packages/core/tests/core/test_mcp.py Outdated

@github-actions github-actions 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.

MAF Automated Review — Iteration 1

Result: No findings
Scope: full PR (1 commit(s)): 558f4d578260
Model: gpt-5.6-sol

Overview

The change adds an explicit fallback to local MCP approval policies while preserving the current implicit no-approval behavior when no default is supplied. Construction-time validation, explicit precedence, exact handling of single-string names, and coverage across prompts, progressive disclosure, reloads, and streaming/non-streaming approval flows provide strong guardrails. No Critical, High, or Medium defect is supported by the reviewed evidence.

Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
No publishable findings remained after source verification for this scope.

Move the non-fixture helpers added for the approval-policy tests out of
`test_mcp.py` into `mcp_approval_helpers.py`, import them explicitly, and pass
the test state to them as arguments, as the Python coding standard requires.
Comment thread python/packages/core/agent_framework/_mcp.py Outdated
`_mcp_approval_default` now owns both the validation of `default` and the
warning for a `never_require_approval` list without `default`.

Constructors opt in to the warning with `warn_stacklevel`, so it still fires
once per construction and points at the calling code. The per-tool resolver
calls the same function without it, so discovery and reloads stay silent.

Add a test that discovery and reloads do not repeat the warning.

@github-actions github-actions 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.

MAF Automated Review — Iteration 2

Result: No findings
Scope: 2 net-new commit(s): 75377872f993, ee2d1ff69abb
Model: gpt-5.6-sol

Overview

This incremental update centralizes construction-time warning emission in _mcp_approval_default while keeping discovery-time resolution silent, and moves reusable test code into a standards-compliant helper module. Constructor validation, explicit stack-level handling, and tests covering exact caller attribution and repeated discovery provide concrete guardrails. No supported Critical, High, or Medium defect remains after reconciling the four perspectives against the previous head and current source.

Reviewed the supplied incremental change set across correctness, security/reliability, architecture, and failure behavior.
No publishable findings remained after source verification for this scope.

This branch was successfully deployed

1 active deployment
github-app-auth — ee2d1ff6 Deployed Oct 29, 2026 by eavanvalkenburg via team_check #8022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants