Skip to content

Python: Add MCP-based skills discovery (McpSkillsSource)#6169

Merged
semenshi merged 10 commits into
microsoft:mainfrom
semenshi:feature/mcp-skills-source
Jun 3, 2026
Merged

Python: Add MCP-based skills discovery (McpSkillsSource)#6169
semenshi merged 10 commits into
microsoft:mainfrom
semenshi:feature/mcp-skills-source

Conversation

@semenshi
Copy link
Copy Markdown
Contributor

@semenshi semenshi commented May 29, 2026

Motivation and Context

Python port of the .NET MCP skills discovery added in #6108.

Description

Adds McpSkillsSource, McpSkill, and McpSkillResource — enabling Agent Skills discovery over MCP following the SEP-2640 convention (skill://index.json → lazy SKILL.md fetch via resources/read).

Includes samples for standalone MCP and Foundry Toolbox integration, plus comprehensive unit tests.

Contribution Checklist

  • The code builds clean without any errors or warnings
  • The PR follows the Contribution Guidelines
  • All unit tests pass, and I have added new tests where possible
  • Is this a breaking change? If yes, add "[BREAKING]" prefix to the title of the PR.

Closes: #6087

…source)

Implement Agent Skills discovery over MCP following the SEP-2640 convention:
- McpSkillsSource: reads skill://index.json to discover skills served by an MCP server
- McpSkill: lazily fetches SKILL.md content via resources/read on demand
- McpSkillResource: wraps MCP resource results (text and binary)
- Path traversal protection in get_resource for defense in depth
- Samples for Foundry Toolbox and standalone MCP skills server
- Comprehensive unit tests (514 lines)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 29, 2026 09:30
@moonbox3 moonbox3 added documentation Improvements or additions to documentation python labels May 29, 2026
@moonbox3
Copy link
Copy Markdown
Contributor

moonbox3 commented May 29, 2026

Python Test Coverage

Python Test Coverage Report •
FileStmtsMissCoverMissing
packages/core/agent_framework
   _feature_stage.py1671094%108, 154, 209, 220, 240, 278, 289, 295, 326, 354
   _skills.py10213796%294, 541, 1007, 1022, 1024–1025, 1381–1382, 1394–1395, 1625, 1654, 2117, 2573–2574, 2709, 2714, 2717, 2722, 2749, 2754, 2808, 2817, 2822, 2825, 2830, 2854, 2859, 3101–3102, 3451, 3684–3685, 3712–3713, 3720–3721
TOTAL37980442688% 

Python Unit Test Overview

Tests Skipped Failures Errors Time
7577 34 💤 0 ❌ 0 🔥 1m 59s ⏱️

@semenshi semenshi self-assigned this May 29, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR extends the Python skills system to support discovery and consumption of Agent Skills served over the Model Context Protocol (MCP), following the SEP-2640 skill://index.json convention, and adds samples and tests to demonstrate/validate the behavior.

Changes:

  • Add McpSkillsSource, McpSkill, and McpSkillResource to enable MCP-based skill discovery and lazy SKILL.md/resource loading.
  • Add two new samples showing generic MCP skills discovery and Foundry Toolbox-hosted skills discovery with AAD auth.
  • Add a comprehensive new unit test suite covering index parsing, caching, text/binary resources, and traversal rejection.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
python/samples/02-agents/skills/README.md Adds the MCP-based skills sample to the skills samples index.
python/samples/02-agents/skills/mcp_based_skill/README.md Documents how to run the new MCP-based skills sample.
python/samples/02-agents/skills/mcp_based_skill/mcp_based_skill.py New sample that discovers MCP skills and injects them via McpSkillsSource.
python/samples/02-agents/providers/foundry/README.md Adds the Foundry Toolbox skills discovery sample to the Foundry samples index.
python/samples/02-agents/providers/foundry/foundry_chat_client_with_toolbox_skills.py New sample that authenticates to a Foundry Toolbox MCP endpoint and discovers skills.
python/packages/core/tests/core/test_mcp_skills.py New unit tests covering MCP skills discovery and resource loading behaviors.
python/packages/core/agent_framework/_skills.py Implements MCP-based skills discovery and resource/content loading.
python/packages/core/agent_framework/init.py Exposes the new MCP skills classes as part of the public API.

Comment thread python/packages/core/agent_framework/_skills.py
Comment thread python/packages/core/agent_framework/_skills.py Outdated
Comment thread python/samples/02-agents/skills/mcp_based_skill/mcp_based_skill.py Outdated
Comment thread python/packages/core/tests/core/test_mcp_skills.py Outdated
Comment thread python/packages/core/agent_framework/_skills.py
Comment thread python/packages/core/agent_framework/_skills.py Outdated
Comment thread python/samples/02-agents/skills/mcp_based_skill/mcp_based_skill.py Outdated
Comment thread python/packages/core/tests/core/test_mcp_skills.py Outdated
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Automated Code Review

Reviewers: 4 | Confidence: 88%

✓ Correctness

The implementation of McpSkillsSource, McpSkill, and McpSkillResource is well-structured and correct. Path traversal protection is sound, caching logic is straightforward, error handling gracefully degrades, and the test suite comprehensively covers edge cases. No correctness issues found.

✓ Security Reliability

The MCP skills implementation is well-structured from a security and reliability perspective. Path traversal protection in _validate_resource_name correctly handles literal traversal patterns (../, backslash variants, absolute paths, URI schemes). Exception handling is fail-closed (returns None on errors). The broad except Exception in get_resource correctly allows asyncio.CancelledError and KeyboardInterrupt to propagate since they inherit from BaseException. The caching in get_content is straightforward and idempotent. No blocking security issues found.

✓ Test Coverage

Test coverage is strong overall (514 lines covering parsing, caching, text/binary resources, path traversal rejection, and end-to-end discovery flows). The main gap is that two explicit exception-handling branches in the production code — the non-McpError exception path in McpSkill.get_resource and the non-McpError exception path in McpSkillsSource._try_read_index — have no corresponding test coverage. These are defensive code paths with distinct behavior (different log levels, different messaging) that warrant at least minimal testing to prevent regression.

✓ Design Approach

The core MCP-skills shape looks reasonable, but there is one blocking design issue: McpSkill.get_resource() currently masks every MCP/transport failure as a missing resource, so higher layers will tell the model "resource not found" for session/auth/server errors instead of surfacing a read failure.


Automated review by semenshi's agents

Comment thread python/packages/core/agent_framework/_skills.py
semenshi and others added 2 commits May 29, 2026 11:23
…ling and samples

- Rename McpSkill/McpSkillResource/McpSkillsSource to MCPSkill/MCPSkillResource/MCPSkillsSource
- Add data-URI prefix stripping for blob resource decoding
- Let non-McpError exceptions propagate from get_resource()
- Fix contradictory test comment
- Use interactive input() in mcp_based_skill sample
- Remove misleading sample output block

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@semenshi semenshi force-pushed the feature/mcp-skills-source branch from 6113cc3 to f37ddb5 Compare May 29, 2026 10:39
@semenshi semenshi marked this pull request as ready for review May 29, 2026 10:47
@semenshi semenshi moved this to In Review in Agent Framework May 29, 2026
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

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

Automated Code Review

Reviewers: 4 | Confidence: 90%

✓ Correctness

The MCP-based skills discovery implementation is well-structured and correct. MCPSkillsSource properly reads the index, validates entries, and constructs MCPSkill instances with lazy content loading. Path traversal prevention in get_resource is sound. Error handling in _try_read_index gracefully degrades (returning empty list) on failures. The MCPSkillResource.read() method correctly prioritizes binary over text content and handles the data-URI prefix edge case. All abstract method contracts from SkillsSource, Skill, and SkillResource are satisfied. The previously resolved review comments (broad McpError catch, data-URI normalization, naming consistency) are either addressed in the current diff or accepted by reviewers.

✓ Security Reliability

The MCP skills implementation is well-designed from a security and reliability standpoint. Path traversal validation in _validate_resource_name is thorough and well-tested (rejects .. segments, absolute paths, URI schemes, backslash-normalized traversals). The data-URI normalization in MCPSkillResource.read() handles the prefix-strip correctly. Error handling follows a defensible pattern: discovery (_try_read_index) gracefully degrades to empty on any failure, while get_resource swallows only MCP errors and re-raises unexpected exceptions. No secrets in code, no unsafe deserialization, no resource leaks identified.

✓ Test Coverage

The test suite is comprehensive for the happy path and many edge cases (path traversal, invalid names, malformed JSON, etc.). However, three distinct code branches in the production code lack any test coverage: (1) the data-URI prefix stripping logic in MCPSkillResource.read(), (2) the re-raise of non-McpError exceptions in MCPSkill.get_resource(), and (3) the non-McpError exception handling path in MCPSkillsSource._try_read_index(). These are all explicitly coded behaviors that could silently regress without tests.

✗ Design Approach

I found one design issue in the new MCP skill resource path: MCPSkill.get_resource() currently converts every McpError into None, which makes unrelated MCP/session/auth failures look like a normal missing resource to the rest of the skills stack.

Flagged Issues

  • MCPSkill.get_resource() swallows all McpErrors and returns None, but SkillsProvider._read_skill_resource() treats None as "resource not found" (line 2316-2318). Non-not-found MCP failures (session/auth/transport) will be silently misreported as missing resources instead of surfacing a real read error.

Automated review by semenshi's agents

Comment thread python/samples/02-agents/skills/mcp_based_skill/mcp_based_skill.py
Comment thread python/packages/core/agent_framework/_skills.py Outdated
Comment thread python/packages/core/agent_framework/_skills.py Outdated
Comment thread python/packages/core/tests/core/test_mcp_skills.py
semenshi and others added 4 commits June 2, 2026 10:31
Replace DefaultAzureCredential with AzureCliCredential to match the
credential convention used in all other samples.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Replace raw mcp library imports (ClientSession, streamable_http_client)
with the framework's MCPStreamableHTTPTool to keep MCP server connections
consistent regardless of whether skills are enabled.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Previously _try_read_index() and get_resource() swallowed every McpError
as 'no skills available', making auth failures, server crashes, and
connection drops indistinguishable from a server that simply has no
skills.

Now only two codes are treated as not-found:
- -32002 (MCP-spec Resource not found)
- -32601 (METHOD_NOT_FOUND — server lacks resources/read)

All other McpError codes and non-McpError exceptions propagate with a
warning log, surfacing real failures visibly.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
… skills

Cover the re-raise branch in MCPSkill.get_resource for plain
ConnectionError/TimeoutError, the generic McpError (code 0) propagation
on get_resource, and TimeoutError propagation in _try_read_index.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread python/samples/02-agents/skills/mcp_based_skill/mcp_based_skill.py Outdated
This reverts commit f31ed0d.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Comment thread python/packages/core/agent_framework/_skills.py Outdated
Add a separate MCP_SKILLS feature ID to ExperimentalFeature enum and
use it for MCPSkillResource, MCPSkill, and MCPSkillsSource, since their
promotion timeline is partly outside of our control.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@semenshi semenshi enabled auto-merge June 3, 2026 15:19
@semenshi semenshi added this pull request to the merge queue Jun 3, 2026
Merged via the queue into microsoft:main with commit c6951c2 Jun 3, 2026
50 of 60 checks passed
@github-project-automation github-project-automation Bot moved this from In Review to Done in Agent Framework Jun 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation python

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Python: Support MCP skills of skill-md type

5 participants