Draft: Feature: Support Skills over MCP (#3585951)

Related to #3585951.

Feature: Support Skills over MCP

Status: Draft for initial discussion — blocked on an SDK release with Skills support and SDK collision handling. Not ready to merge.

The accompanying MR proposes a thin integration with the PHP SDK's planned Skills support. The goal is for enabled Drupal modules to define skills in .agents/skills and have MCP Server serve them as Skills over MCP through the SDK.

Problem

Modules can expose tools through MCP Server, but tool descriptions alone cannot explain multi-step workflows. Agent Skills provide that guidance in SKILL.md files with optional supporting references. Canvas Tools, for example, ships workflows for building pages and configuring templates. These should be available alongside its tools without putting all instructions into the initial handshake.

Specification

SEP-2640: Skills Extension is Final. Its Dependencies section states:

This extension has no dependencies beyond the base MCP Resources primitive.

Its Resource Mapping section states:

Each file within a skill directory is exposed as an MCP resource.

Full support includes skills/list, skills/get, file resources, and manifests containing frontmatter, digests and sizes for static skills. Host verification and activation are separate responsibilities. The SEP does not prescribe how Drupal locates directories. Exposing Markdown through ordinary resources alone is not full Skills extension support. See also the maintained specification.

PHP SDK and Symfony Mate

PHP SDK PR #372 proposes Builder::addSkillsFromDirectory(). The application supplies directories; the SDK handles scanning, parsing, resources, manifests and extension methods. This integration targets the API tested at commit 616c4dd on 7 November 2026. It cannot merge until an SDK release provides that API, cross-directory URI collisions cannot silently replace content, and MCP Server's dependency constraint and CI floor are updated for the selected release.

Symfony AI Mate PR #2213 takes a complementary approach: packages declare directories through extra.ai-mate.skills, and Mate installs their skills into local agent folders. That merged implementation addresses filesystem consumption, not MCP transport. The Symfony bridge proposal #2132 provides skill content alongside its tools. The relevant precedent for Drupal is explicit module-owned content with a thin integration layer.

Proposed resolution

Use .agents/skills as the module directory convention, with each skill in its own directory containing SKILL.md and optional supporting files:

my_module/
  .agents/
    skills/
      my-workflow/
        SKILL.md
        references/

MCP Server should use Drupal's enabled-module list to locate each module's .agents/skills directory and register existing directories through the SDK's Builder::addSkillsFromDirectory(). Module authors should not need a service provider merely to expose skills in the conventional location. Disabling a module must remove its skills when Drupal rebuilds the container.

Drupal's responsibility is locating module roots and registering their skill directories. The SDK owns recursive scanning, frontmatter parsing, resources, manifests and protocol behavior. This does not require a Drupal skill scanner or changes to the SDK in this MR. The directory convention is a Drupal integration choice; SEP-2640 does not mandate that filesystem location.

The accompanying patch calls addSkillsFromDirectory() once for each existing module directory. It does not instantiate a provider or registry, enable the extension manually, or inspect manifests. The SDK owns these responsibilities.

Collision handling is an unresolved merge blocker. At the tested SDK commit, two roots containing the same relative skill path silently overwrite each other; reversing registration order changes the content served. This patch deliberately removes the Drupal-side collision workaround to use the public builder API. It therefore does not currently protect against that overwrite. The SDK must reject collisions or provide a namespace mechanism that lets Drupal preserve both modules' content before this integration can merge.

Before merging, add an integration test for the agreed SDK collision behavior (including reversed registration order), alongside the existing enabled-module discovery/removal tests. The old test for Drupal's custom exception has been removed with that implementation; its removal is not evidence that the collision requirement has been met. Also verify empty-directory capabilities through the builder and the newer protocol's manifest and caching envelopes.

Protocol probes against real module files passed for all four Canvas Tools skills and an editorial skill with supporting content. A dedicated Drupal HTTP fixture also passed 16 authenticated checks across two non-admin accounts plus anonymous denial. These validate the SDK and per-request directory selection; the MR's full /mcp integration still needs testing against the selected release.

Open questions for discussion

  • Alignment with AI Best Practices: Its skill discovery recognizes .agents/skills, .claude/skills, and skills, and its Composer workflow copies discovered skills into a project-level output directory (default .agents/skills). MCP Server should reuse module-owned source files in .agents/skills, so authors maintain one copy for local installation and MCP delivery. It should not scan the aggregated output as well: that would duplicate content and lose the enabled-module boundary. We propose sharing the source convention, while leaving MCP parsing and serving with the SDK. Should exposure selection or source metadata be coordinated between projects?
  • Suitability of the instructions: Sharing a format does not mean every skill can run with the tools available over MCP. Skills that require shell access or source edits should state those requirements. Canvas Tools' build-canvas-page skill already explains that its Drush examples map to MCP tools with the same IDs and inputs, making it a concrete reuse candidate. Its publication workflow still needs to respect the user's requested outcome. Should authors declare execution requirements, and should site builders select the skills exposed?
  • Discovery and overrides: The patch checks conventional directories during server creation using Drupal's enabled-module list. Should modules or site builders be able to override that location?
  • Exposure and configuration: Is enabling a module that supplies skills sufficient to expose that content to authorized MCP clients, or should site builders be able to select or exclude registered directories? How should that interact with any endpoint-specific configuration? This also includes developer-oriented skills shipped in a module's .agents/skills directory, including MCP Server's own repository skills.
  • Module identity and collisions (merge blocker): Should the SDK reject duplicate URIs, offer a directory URI prefix, or support both? A module prefix would let modules serve identical relative paths without changing their skill layout. Drupal should consume that SDK behavior through the builder API.
  • Failure handling: Should an invalid registered directory prevent server creation, or should the contributing module's skills be omitted with a logged error? Which behavior belongs in the SDK rather than MCP Server?

Validation

Patch replay, PHP syntax and isolated SDK protocol checks passed. Full MR kernel/HTTP integration remains to be verified against the SDK release; the two-account HTTP checks used a dedicated Drupal fixture endpoint.

AI Disclosure

AI-Generated: Yes. OpenAI Codex was used to investigate, implement and validate this draft.

Edited by Ronald te Brake

Merge request reports

Loading
Loading