Skip to content

Python: Make foundry toolbox MCP skills sample self-contained#7099

Open
giles17 wants to merge 2 commits into
microsoft:mainfrom
giles17:toolbox-mcp-skills-selfcontained
Open

Python: Make foundry toolbox MCP skills sample self-contained#7099
giles17 wants to merge 2 commits into
microsoft:mainfrom
giles17:toolbox-mcp-skills-selfcontained

Conversation

@giles17

@giles17 giles17 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Motivation & Context

The 12_foundry_toolbox_mcp_skills sample was not self-contained and did not work end-to-end:

  • It assumed a Foundry toolbox with skills already existed and gave no way to build one, unlike sample 04_foundry_toolbox (bundles a toolbox.yaml) and sample 09_foundry_skills (bundles SKILL.md sources). A user starting from zero was stuck.
  • The README documented a stale API (SkillsProvider(MCPSkillsSource(...))) that did not match main.py (FoundryToolbox(...).as_skills_provider()), and used the fragile TOOLBOX_NAME (unversioned) env var instead of a versioned endpoint.
  • Even with a toolbox, the agent stalled: SkillsProvider registers load_skill with approval required by default, but ResponsesHostServer runs the agent without an AgentSession, so the default approval flow (and ToolApprovalMiddleware) cannot complete — every skill-loading request returned an unanswered mcp_approval_request.

This makes the sample a complete, from-zero, azd-native walkthrough and lets it run unattended behind the Responses host.

Description & Review Guide

  • What are the major changes?

    • Sample rewrite (self-contained): bundle two single-file SKILL.md skills (support-style, escalation-policy, reused from sample 09) and a toolbox.yaml that references them. The toolbox includes one connectionless code_interpreter tool because azd ai toolbox create rejects a skills-only toolbox; load_tools=False keeps it hidden from the model, so it stays effectively skills-only. Add .azdignore and update .dockerignore so authoring inputs are excluded from the deployed container.
    • README: rewritten as an azd-native, from-zero guide (create skills → create toolbox → set TOOLBOX_ENDPOINT → run), fixing the stale MCPSkillsSource description and documenting the two progressive-disclosure stages this path supports (advertise + load). Config switched from TOOLBOX_NAME to the versioned TOOLBOX_ENDPOINT across .env.example, agent.yaml, and agent.manifest.yaml.
    • Package (agent-framework-foundry-hosting): FoundryToolbox.as_skills_provider() now forwards disable_load_skill_approval / disable_read_skill_resource_approval / disable_run_skill_script_approval to the underlying SkillsProvider. main.py uses as_skills_provider(disable_load_skill_approval=True) so the hosted agent loads skills without an approval round-trip. Adds unit tests for the default and overridden behaviour.
  • What is the impact of these changes?

    • The sample now works end-to-end. Verified against a live Foundry project: advertise lists both skills; a routine prompt loads support-style (canary STYLE-CANARY-3318); an escalation prompt loads both skills (canary ESC-CANARY-7742). The package change is purely additive (new keyword-only args defaulting to False), so existing callers are unaffected.
    • Note: the third Agent Skills stage (read resources) is intentionally not demonstrated — Foundry serves ZIP/multi-file skills as type: archive, which the Python MCPSkillsSource does not currently discover (it only handles type: skill-md). The README explains this.
  • What do you want reviewers to focus on?

    • Whether forwarding the approval-disabling kwargs on as_skills_provider() is the preferred fix for the ResponsesHostServer (no AgentSession) scenario, vs. an alternative.

Related Issue

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 is linked to an issue and there is no other open PR for this issue (see Related Issue above).
  • 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.

Rework sample 12 (foundry_toolbox_mcp_skills) so users can build it from
zero with azd, mirroring samples 04 and 09:

- Bundle two single-file SKILL.md skills (support-style, escalation-policy)
  and a skills-only toolbox.yaml (with one connectionless code_interpreter
  tool, required by `azd ai toolbox create`).
- Rewrite the README as an azd-native, from-zero guide (create skills ->
  create toolbox -> set TOOLBOX_ENDPOINT -> run) and fix the stale
  MCPSkillsSource API description to match main.py.
- Switch config from TOOLBOX_NAME to the versioned TOOLBOX_ENDPOINT
  (.env.example, agent.yaml, agent.manifest.yaml); add .azdignore.

Also enable the sample to run unattended behind ResponsesHostServer:

- Forward disable_load_skill_approval / disable_read_skill_resource_approval
  / disable_run_skill_script_approval from FoundryToolbox.as_skills_provider()
  to the underlying SkillsProvider, so load_skill needs no approval round-trip
  (the Responses host runs without an AgentSession, which the default approval
  flow requires). main.py now uses as_skills_provider(disable_load_skill_approval=True).
- Add unit tests covering the default and overridden approval behaviour.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 4f14f83d-1868-45c1-be1a-12f49a58ac36
Copilot AI review requested due to automatic review settings July 14, 2026 03:43
@giles17 giles17 added documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python labels Jul 14, 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.

Pull request overview

Updates the Python 12_foundry_toolbox_mcp_skills Responses-hosted sample so it can be run end-to-end starting from an empty Foundry project (bundled skill sources + toolbox definition), and extends FoundryToolbox.as_skills_provider() to optionally disable skill-tool approval requirements for unattended hosting scenarios.

Changes:

  • Bundles two single-file SKILL.md skills and a toolbox.yaml, and rewrites the sample README into an azd-native “from zero” walkthrough using TOOLBOX_ENDPOINT.
  • Updates the sample’s config assets (agent.yaml, agent.manifest.yaml, .env.example) to use a versioned toolbox endpoint instead of TOOLBOX_NAME, and excludes authoring inputs from deployment via .azdignore / .dockerignore.
  • Extends FoundryToolbox.as_skills_provider() to forward disable_*_skill_*_approval options to SkillsProvider, and adds unit tests validating default/override behavior.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
python/samples/04-hosting/foundry-hosted-agents/responses/12_foundry_toolbox_mcp_skills/toolbox.yaml Adds a toolbox definition referencing the bundled skills (plus a placeholder tool to satisfy CLI constraints).
python/samples/04-hosting/foundry-hosted-agents/responses/12_foundry_toolbox_mcp_skills/skills/support-style/SKILL.md Adds bundled “support-style” skill source.
python/samples/04-hosting/foundry-hosted-agents/responses/12_foundry_toolbox_mcp_skills/skills/escalation-policy/SKILL.md Adds bundled “escalation-policy” skill source.
python/samples/04-hosting/foundry-hosted-agents/responses/12_foundry_toolbox_mcp_skills/README.md Rewrites docs to a from-zero azd walkthrough and explains progressive disclosure stages/constraints.
python/samples/04-hosting/foundry-hosted-agents/responses/12_foundry_toolbox_mcp_skills/main.py Uses as_skills_provider(disable_load_skill_approval=True) for unattended hosting.
python/samples/04-hosting/foundry-hosted-agents/responses/12_foundry_toolbox_mcp_skills/agent.yaml Switches configuration from TOOLBOX_NAME to TOOLBOX_ENDPOINT.
python/samples/04-hosting/foundry-hosted-agents/responses/12_foundry_toolbox_mcp_skills/agent.manifest.yaml Switches manifest parameterization from TOOLBOX_NAME to TOOLBOX_ENDPOINT.
python/samples/04-hosting/foundry-hosted-agents/responses/12_foundry_toolbox_mcp_skills/.env.example Documents and switches to TOOLBOX_ENDPOINT.
python/samples/04-hosting/foundry-hosted-agents/responses/12_foundry_toolbox_mcp_skills/.dockerignore Excludes bundled skill/toolbox authoring inputs from container builds.
python/samples/04-hosting/foundry-hosted-agents/responses/12_foundry_toolbox_mcp_skills/.azdignore Excludes authoring inputs and local env files from azd packaging/deploy context.
python/packages/foundry_hosting/tests/test_toolbox.py Adds tests for approval override forwarding behavior.
python/packages/foundry_hosting/agent_framework_foundry_hosting/_toolbox.py Adds approval-disabling kwargs to as_skills_provider() and forwards them into SkillsProvider.

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

Automated Code Review

Reviewers: 5 | Confidence: 91% | Result: All clear

Reviewed: Correctness, Security Reliability, Test Coverage, Failure Modes, Design Approach


Automated review by giles17's agents

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/foundry_hosting/agent_framework_foundry_hosting
   _toolbox.py620100% 
TOTAL44431524388% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
8967 33 💤 0 ❌ 0 🔥 2m 8s ⏱️

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

Automated Code Review

Reviewers: 5 | Confidence: 92% | Result: All clear

Reviewed: Correctness, Security Reliability, Test Coverage, Failure Modes, Design Approach


Automated review by giles17's agents

@giles17 giles17 requested a review from TaoChenOSU July 14, 2026 15:03
@giles17 giles17 enabled auto-merge July 14, 2026 15:18
Comment on lines +85 to +86
azd ai skill create support-style --file ./skills/support-style/SKILL.md --no-prompt
azd ai skill create escalation-policy --file ./skills/escalation-policy/SKILL.md --no-prompt

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.

Are these verified? Shouldn't we provide the entire skill folder instead of just the md file?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I ran both  azd ai skill create … --file …/SKILL.md commands against a live Foundry project and confirmed the skills upload and load end-to-end.

Single-file is intentional because providing the folder requires zipping it and foundry serves it as type: archive and this is not handled yet in our framework. Issue tracked here: #6088

```

When the agent connects to the toolbox MCP endpoint, skills are advertised through a well-known `skill://index.json` discovery resource. The `MCPSkillsSource` in this sample reads `skill://index.json` the first time the agent runs to discover all attached skills, then fetches each `SKILL.md` body on demand via `resources/read`.
> **Why single files (not ZIPs)?** Uploading a skill as a `.zip` (to bundle supplementary resource files) makes Foundry serve it as `type: archive` in the toolbox's `skill://index.json`. The Python `MCPSkillsSource` only discovers `type: skill-md` entries, so archive skills are silently dropped. Keeping each skill as a single `SKILL.md` ensures both are discovered.

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.

We are not using the MCPSkillsSource, do we? The _FoundryToolboxSkillsSource derives only from SkillsSource

@giles17 giles17 disabled auto-merge July 14, 2026 15:47
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.

5 participants