Python: Make foundry toolbox MCP skills sample self-contained#7099
Open
giles17 wants to merge 2 commits into
Open
Python: Make foundry toolbox MCP skills sample self-contained#7099giles17 wants to merge 2 commits into
giles17 wants to merge 2 commits into
Conversation
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
Contributor
There was a problem hiding this comment.
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.mdskills and atoolbox.yaml, and rewrites the sample README into an azd-native “from zero” walkthrough usingTOOLBOX_ENDPOINT. - Updates the sample’s config assets (
agent.yaml,agent.manifest.yaml,.env.example) to use a versioned toolbox endpoint instead ofTOOLBOX_NAME, and excludes authoring inputs from deployment via.azdignore/.dockerignore. - Extends
FoundryToolbox.as_skills_provider()to forwarddisable_*_skill_*_approvaloptions toSkillsProvider, 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. |
Contributor
Python Test Coverage Report •
Python Unit Test Overview
|
||||||||||||||||||||||||||||||
4 tasks
moonbox3
approved these changes
Jul 14, 2026
eavanvalkenburg
approved these changes
Jul 14, 2026
TaoChenOSU
reviewed
Jul 14, 2026
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 |
Contributor
There was a problem hiding this comment.
Are these verified? Shouldn't we provide the entire skill folder instead of just the md file?
| ``` | ||
|
|
||
| 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. |
Contributor
There was a problem hiding this comment.
We are not using the MCPSkillsSource, do we? The _FoundryToolboxSkillsSource derives only from SkillsSource
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation & Context
The
12_foundry_toolbox_mcp_skillssample was not self-contained and did not work end-to-end:04_foundry_toolbox(bundles atoolbox.yaml) and sample09_foundry_skills(bundlesSKILL.mdsources). A user starting from zero was stuck.SkillsProvider(MCPSkillsSource(...))) that did not matchmain.py(FoundryToolbox(...).as_skills_provider()), and used the fragileTOOLBOX_NAME(unversioned) env var instead of a versioned endpoint.SkillsProviderregistersload_skillwith approval required by default, butResponsesHostServerruns the agent without anAgentSession, so the default approval flow (andToolApprovalMiddleware) cannot complete — every skill-loading request returned an unansweredmcp_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?
SKILL.mdskills (support-style,escalation-policy, reused from sample 09) and atoolbox.yamlthat references them. The toolbox includes one connectionlesscode_interpretertool becauseazd ai toolbox createrejects a skills-only toolbox;load_tools=Falsekeeps it hidden from the model, so it stays effectively skills-only. Add.azdignoreand update.dockerignoreso authoring inputs are excluded from the deployed container.TOOLBOX_ENDPOINT→ run), fixing the staleMCPSkillsSourcedescription and documenting the two progressive-disclosure stages this path supports (advertise + load). Config switched fromTOOLBOX_NAMEto the versionedTOOLBOX_ENDPOINTacross.env.example,agent.yaml, andagent.manifest.yaml.agent-framework-foundry-hosting):FoundryToolbox.as_skills_provider()now forwardsdisable_load_skill_approval/disable_read_skill_resource_approval/disable_run_skill_script_approvalto the underlyingSkillsProvider.main.pyusesas_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?
support-style(canarySTYLE-CANARY-3318); an escalation prompt loads both skills (canaryESC-CANARY-7742). The package change is purely additive (new keyword-only args defaulting toFalse), so existing callers are unaffected.type: archive, which the PythonMCPSkillsSourcedoes not currently discover (it only handlestype: skill-md). The README explains this.What do you want reviewers to focus on?
as_skills_provider()is the preferred fix for theResponsesHostServer(noAgentSession) scenario, vs. an alternative.Related Issue
Contribution Checklist
breaking changelabel (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.