Repository navigation
Description
Proposal
I'd like us to support the Skills over MCP extension so our MCP servers can publish workflow instructions alongside their tools. Start with skills bundled and versioned with Azure MCP Server, with the protocol support structured for reuse by other servers in this repo.
The server supplies the skill. The host discovers, verifies, and loads it. We should not require the server to install files into a client's skills directory or introduce a custom download tool for functionality the extension already defines.
Problem
Tools expose individual operations, but they do not always provide enough guidance for a workflow that spans several operations. Maintaining that guidance separately from the server creates another installation step and allows instructions to drift from the tools they describe.
Shipping skills with the server keeps the instructions and tool implementations aligned. A compatible host can discover the available workflows and load the relevant instructions when needed.
Proposed behavior
The server would declare Resources support and the io.modelcontextprotocol/skills extension, then implement:
skills/listto expose skill frontmatter and complete file manifests, including SHA-256 digests and byte sizes.skills/getto retrieve a skill entry directly by URI, including skills not returned by the listing.resources/readto returnSKILL.mdand supporting files on demand.
Directory reading is optional in the extension and can remain out of the initial implementation unless a supported client requires it.
For example, a deployment diagnostics skill could describe the investigation sequence, reference troubleshooting guidance, and direct the agent to the appropriate MCP tools. The host retrieves the instructions first and supporting files only as needed. Reading a skill does not activate it or execute its scripts.
Local MCP behavior
This should work over stdio as well as HTTP. A locally running server reads bundled skill content and returns it through MCP. It does not need an HTTP endpoint or a shared filesystem with the host, so the same approach works when the server runs in a container or WSL.
Retrieving bundled skills should not require network access. The operations described by a skill may still require Azure connectivity and authorization.
The host owns skill activation, approval, and caching. The server should not write into the user's repository or client-specific skill directories. MCP resource URIs identify published content, not arbitrary paths on the server's filesystem.
Scope and boundaries
Start with static, bundled skills and manifests generated from the exact bytes served. Defer upstream catalogs, independently updated skills, dynamic content, and a separate installation or export experience.
Follow the extension's integrity and origin requirements rather than inventing a parallel trust model. Hosts must retain server identity and skill URI, verify retrieved content, and apply the required approvals. Serving a script does not authorize its execution, and a skill does not grant additional tool permissions.
Client support is a dependency. Confirm the protocol revision, SDK support, and intended host's implementation before committing to the integration. Clients without Skills support must continue to use existing tools normally; exposing resources alone does not provide native skill activation.
Acceptance criteria
- A packaged example skill can be discovered and retrieved through the extension over stdio and HTTP.
- Direct lookup works without a preceding list request.
- Manifests include every published skill file, with digests and byte sizes matching the served content.
- Resource reads are limited to explicitly published content. Unknown skills and files return the specified protocol errors.
- Bundled skill retrieval works without network access and does not write to client or repository skill directories.
- Tests cover discovery, direct lookup, content retrieval, manifest consistency, and rejection of unpublished paths.
- Existing tool behavior remains unchanged for clients that do not support the extension.
- Documentation identifies the supported protocol and client prerequisites, local behavior, and the boundary between retrieving, activating, and executing skill content.
Activity
github-actions commentedon Sep 14, 2026
Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc Alan Zimmer (@alzimmermsft) Vinay Gera (@g2vinay) @microsoft/azure-mcp.
tmeschter commentedon Sep 15, 2026
Per the client support matrix there is very little support for skills-over-MCP at the moment. We would be able to use verification tools to check that we are implementing the standard, but for the clients we currently target with skills there would be no way to test the end-to-end experience.
tmeschter commentedon Sep 17, 2026
Also, the C# MCP SDK does not yet support the proposed spec. The work is being tracked by modelcontextprotocol/csharp-sdk#1863, with a proposed implementation in modelcontextprotocol/csharp-sdk#1864.
RickWinter commentedon Oct 16, 2026
Here is an implementation and testing plan for supporting
io.modelcontextprotocol/skills(SEP-2640) in Azure MCP Server and aligning with the client runtime support in https://github.com/github/copilot-agent-runtime/pull/25177.1. Specification & Client (
github/copilot-agent-runtime#25177) RequirementsProtocol Contract (
io.modelcontextprotocol/skills/ SEP-2640)initializein2025-11-25andserver/discoverin2026-07-28):io.modelcontextprotocol/skillsignore the extension key and continue using tools as normal.skill://<skill-path>/SKILL.md, with supporting files atskill://<skill-path>/<relative-path>.<skill-path>must matchfrontmatter.name(^[a-z0-9]+(-[a-z0-9]+)*$, 1 to 64 characters).skills/list,skills/get):skills/list(cursor-paginated) returnsSkillentries without downloading full markdown bodies:uri:"skill://<skill-path>/SKILL.md"frontmatter: verbatim JSON object parsed fromSKILL.mdYAML frontmatter (at minimumnameanddescription<= 1024 chars).resources: static array of{ uri, digest: "sha256:<64-lowercase-hex>", size: <raw-byte-length> }coveringSKILL.mdand every supporting file.skills/get({ uri }) returns{ skill }directly bySKILL.mdURI without requiring a priorskills/listcall, or JSON-RPC-32602(InvalidParams) if unknown.resources.length <= 512) and <= 16 MiB (16,777,216bytes) total size.2026-07-28,skills/listandskills/getincludeCacheableResultmetadata (resultType: "complete",ttlMs,cacheScope: "public").resources/read,resources/list):SKILL.mdand supporting files on demand asTextResourceContents(mimeType: "text/markdown"for.md) orBlobResourceContents. Unknown URIs return-32602(InvalidParams).Client Runtime Expectations (
github/copilot-agent-runtime#25177)"resources": "dynamic"because dynamic skills cannot be integrity-pinned before user consent. Publishing staticSkillResource[]manifests is required and allows the client to synthesize directory listings locally fromentry.resourceswithout requiringresources/directory/read.(serverName, uri)and the manifest's{ uri, digest }set.SKILL.mdviaresources/readand verifies:manifest.size.sha256:<lowercase-hex>of raw UTF-8 bytes equalsmanifest.digest.SKILL.mddeep-equalsentry.frontmatterfromskills/list/skills/get.read_resourcetool for supporting files that rejects any URI not listed inentry.resourcesand verifiessize+digeston every read.2. Implementation Plan
Phase 1: Core Models, Validator & Frontmatter Parser (
Microsoft.Mcp.Core)core/Microsoft.Mcp.Core/src/Areas/Server/Skills/McpSkillsJsonContext:McpSkillCapability,McpSkill,McpSkillResource,ListSkillsRequestParams,ListSkillsResult(inheritsPaginatedResult),GetSkillRequestParams,GetSkillResult(inheritsCacheableResult).SkillPackageBuilder/SkillFrontmatterParser):JsonObjectdirectly from the in-memorySKILL.mdUTF-8 bytes.sizeandsha256:<lowercase-hex>from the exact in-memory UTF-8byte[]served byresources/read(preventing CRLF/LF mismatches between digest calculation and content delivery).nameregex,<skill-path>leaf matchesfrontmatter.name, non-emptydescription<= 1024 chars, <= 512 files, <= 16 MiB per skill.Phase 2: Secure-by-Default Runtime Handlers & Options (
Microsoft.Mcp.Core)ISkillProvider&McpSkillsRuntime(core/Microsoft.Mcp.Core/src/Areas/Server/Skills/):Dictionary<string, SkillPackage>andDictionary<string, SkillFileContent>withStringComparer.Ordinal).skill://scheme, or path-traversal sequence (..,\, percent-encoded segments) inskills/getorresources/readimmediately throwsMcpProtocolExceptionwithMcpErrorCode.InvalidParams(-32602).SkillPackagecan optionally declare its owning service namespace(s) (for example,azurebackup), so--namespacefiltering onazmcp server startfilters skills consistently with tools while retaining global/cross-service skills.--disable-skillstoServerStartOptions(defaultfalse) so operators can disable skill publishing when needed.ServiceCollectionExtensions.ConfigureMcpServerOptions:options.Capabilities.Resources ??= new ResourcesCapability()andoptions.Capabilities.Extensions["io.modelcontextprotocol/skills"] = new JsonObject().skills/listandskills/getviaoptions.RequestHandlers.Set(...)withCacheScope.PublicandTimeToLive = TimeSpan.FromHours(1).options.Handlers.ListResourcesHandlerandoptions.Handlers.ReadResourceHandler.ActivityName.ListSkills,ActivityName.GetSkill,ActivityName.ReadSkillResource) with W3C trace context capture matchingMcpRuntime.Phase 3: Bundled Skills in
Azure.Mcp.ServerEmbeddedSkillProvider:SKILL.md+references/+scripts/) as assembly resources inAzure.Mcp.Serverand registers the provider inservers/Azure.Mcp.Server/src/Program.cs.3. Testing Strategy
Microsoft.Mcp.Core.Tests&Azure.Mcp.Core.Tests):frontmatter.namemismatch, missingname/description,description> 1024 chars, > 512 files limit, > 16 MiB size limit, and YAML frontmatter edge cases (quotes, multiline blocks, nested objects/arrays).github/copilot-agent-runtime#25177across every registered skill and supporting file:Encoding.UTF8.GetByteCount(text) == resource.SizeSHA256(Encoding.UTF8.GetBytes(text)) == resource.DigestParseYamlFrontmatter(skillMdText)deep-equalsskill.Frontmatterskills/listdeterministic ordering andcursor/nextCursorpagination; invalid cursor returns-32602.skills/getworks without priorskills/list; returns-32602for missinguri, unknown skill, supporting-file URI instead ofSKILL.md, or traversal attempts (skill://foo/../bar/SKILL.md,skill://foo/%2e%2e/SKILL.md,skill://foo\bar/SKILL.md).resources/readserves exact UTF-8 text (text/markdownfor.md) and binary blobs; returns-32602for unlisted/unknown URIs.--disable-skills(or zero registered skills) omitsio.modelcontextprotocol/skillsfrom capabilities.--namespacefilters skills appropriately and all server modes (namespace,all,single,consolidated) preserve existing tool behavior for clients that ignore skills.Azure.Mcp.Server.Tests):2025-11-25and2026-07-28:initialize(2025-11-25) and statelessserver/discover(2026-07-28) advertiseresourcesandextensions["io.modelcontextprotocol/skills"].2026-07-28HTTP routing headers (ValidateMcpRoutingHeadersMiddleware):skills/listandskills/getsucceed withMcp-Methodalone;resources/readsucceeds withMcp-Method: resources/read+Mcp-Name: skill://...and is rejected (400) whenMcp-Nameis missing.McpAccessauthorization onskills/list,skills/get, andresources/read../eng/scripts/Build-Local.ps1 -BuildNativeto verify zero AOT/trim warnings.COPILOT_MCP_SKILLS=1discovering, consenting to, integrity-checking, and activating a skill fromazmcp server start.