title: agentskills-mcp-server description: MCP tools and resources for Agent Skills registries.
MCP server integration for the Agent Skills SDK - expose a skill registry as an MCP server.
Creates a Model Context Protocol server from a SkillRegistry, exposing skills through ordinary MCP tools and resources. v0.6.0 also provides an opt-in native Skills server backed by immutable file captures.
The MCP server remains maintained. Only AgentSkillsMcpContextProvider and the
[agentframework] extra are deprecated and maintenance-only in v0.6. Existing
bridge APIs remain available during the migration window. See the
migration guide and feature-gap matrix
for framework-owned replacements and removal gates.
Installation
pip install agentskills-mcp-server
With provider extras:
pip install agentskills-mcp-server[fs] # filesystem provider
pip install agentskills-mcp-server[http] # HTTP provider
With Agent Framework integration:
pip install agentskills-mcp-server[agentframework] # MCP context provider for Agent Framework
Requires Python 3.12 or newer. Installs agentskills-core, mcp, and pydantic as dependencies.
MCP SDK Compatibility
v0.6.0 accepts MCP SDK 1.28.1 or newer in the 1.x line, or 2.2.0 or
newer in the 2.x line. SDK 2.0 and 2.1 are excluded. The repository lock keeps
1.29.0, while a separate CI job exercises 2.2.0 and the unlocked job checks the
latest permitted dependencies. Direct server tests and real legacy stdio sessions
cover the same eight tools and three static skills:// resources.
create_mcp_server() returns the installed SDK's server class: FastMCP on 1.x
and MCPServer on 2.x. SDK-level Python APIs follow that SDK's version. For
example, direct call_tool() calls return a tuple on 1.x and CallToolResult on
2.x. Protocol clients receive standard MCP results in either case. This support
does not imply that a host supports the Skills extension. Native mode is a separate
opt-in and does not establish host-specific certification.
Agent Framework's upstream MCP client still declares an MCP 1.x constraint. Keep that client and the existing context-provider bridge in a 1.x environment:
pip install "agentskills-mcp-server[agentframework]" "mcp>=1.28.1,<2"
Run a 2.x server in a separate environment or process when using that client. Do not force incompatible framework extras into the server environment. The native integrations and context-provider bridge remain available during the planned deprecation window.
Tested Client Matrix
The development checkout was verified with the official Python MCP SDK clients and mcpc on 2026-10-06. These are protocol and client checks, not model-host activation or production deployment certifications.
| Server mode and SDK | Client SDK and API | Transport | Verified behavior |
|---|---|---|---|
| Legacy 1.29.0 | 1.29.0 ClientSession |
stdio | Eight tools, three static resources, tool errors |
| Legacy 2.2.0 | 2.2.0 ClientSession |
stdio | Same legacy contract |
| Legacy 2.2.0 | 1.29.0 ClientSession |
stdio | Same contract across separate environments |
| Legacy 1.29.0 | 2.2.0 ClientSession |
stdio | Same contract across separate environments |
| Native 2.2.0 | 2.2.0 Client |
In-process, stdio, loopback HTTP | Native discovery, lookup, and original-byte resources |
| Native 2.2.0 | @apify/mcpc 0.7.0 |
stdio | Direct lookup before listing, paginated discovery, aliases, exact instructions/reference/binary reads with sizes and SHA-256 digests |
| Native 2.2.0 | 1.29.0 or 2.2.0 ClientSession |
stdio | Canonical resources only, native discovery rejected with -32601 |
SDK 2's ClientSession is its legacy-protocol compatibility API. Use Client
for the native protocol. The HTTP checks use a real listener and both values of
the server's json_response option. They verify resource bytes against the source
and advertised size and digest, plus required result/cache fields. They do not
certify remote authentication, TLS, reverse proxies, or a host's approval policy.
The modern-SDK CI job creates an isolated 1.29.0 environment and runs both
mixed-SDK stdio directions. Locally, AGENTSKILLS_TEST_MCP_SERVER_PYTHON selects
the legacy server interpreter for test_config.py -k stdio, and
AGENTSKILLS_TEST_NATIVE_MCP_SERVER_PYTHON selects a 2.2+ native server interpreter.
Without overrides, tests use the current interpreter and skip native publication
when SDK 2.2+ is unavailable. Each interpreter needs this checkout's core, provider,
and MCP packages. The client also needs pytest and pytest-asyncio.
The same CI job installs pinned @apify/mcpc@0.7.0 and runs the real-client test.
To repeat it locally with Node 22.12 or later and MCP SDK 2.2, set
AGENTSKILLS_TEST_MCPC to the installed package's bin/mcpc JavaScript entry
point and run pytest packages/integrations/agentskills-mcp-server/tests/test_config.py -k mcpc.
The test isolates its session state and closes the session in a cleanup block.
It does not call a model, execute skill scripts, or test remote authentication.
Discovery and Delivery Benchmarks
The development checkout includes a model-free benchmark for catalogs of 1, 10, and 100 skills. It records actual request counts, payload sizes, token estimates, and in-process timings for native Skills and the retained legacy API. Native publication reads are separated from client delivery, and discovery prefetch is rejected. See the benchmark guide and measured trade-offs. Synthetic ranking scores are not production accuracy or host certification.
Native Skills
Install agentskills-mcp-server>=0.6.0 with mcp>=2.2,<3. Released 0.5.0
packages do not contain this API. The native server implements the official
Skills extension
against protocol revision 2026-07-28:
server/discoverdeclaresio.modelcontextprotocol/skillsand resources.skills/listreturns complete manifests with opaque, server-scoped pagination.skills/getreturns the same entry directly by its canonicalSKILL.mdURI.resources/readreturns captured original bytes, including BOMs and line endings.- Results carry the required result type, cache fields, and SDK-generated metadata.
Native mode does not register legacy tools or inject a catalog. It does not
advertise directoryRead. The providers cannot enumerate empty directories, so
the optional directory method is deliberately unavailable.
Native CLI
{
"name": "Native Skills",
"mode": "native",
"skills": [
{
"id": "incident-response",
"provider": "fs",
"options": {"root": "./skills"}
}
]
}
Run it with python -m agentskills_mcp_server --config server.json. Omitted
mode retains legacy behavior. HTTP providers require "file_manifest": true
and complete per-skill file indexes. The CLI closes its provider clients after
capture. The programmatic builder does not close caller-owned providers.
Check configured providers and publication without starting a listener:
python -m agentskills_mcp_server --config server.json --check
The JSON success report includes the installed MCP SDK version, selected mode,
provider types, skill count, and native client requirements. It excludes provider
options, including credential-bearing URLs. Its localServerConstruction scope
does not claim a transport connection, authentication check, or host verification.
Provider reads do occur during preflight. Native mode reads and verifies every
file, while legacy mode validates registration. Provider clients opened by a
preflight are closed before it returns, including when construction fails.
For a filesystem source, the companion tools can inspect canonical manifests and run the same native builder without a config file:
agentskills inspect ./skills --native --format json
agentskills serve ./skills --native --check
Those tools default to a 16 MiB per-file bound. To compare a config-driven source
with that inspection, set its max_file_bytes filesystem option or
max_response_bytes HTTP option to the intended bound. HTTP native publication
also requires file_manifest: true. A lower provider limit can reject a skill
that fits the extension's total limit.
Native Python API
import asyncio
from pathlib import Path
from agentskills_core import Skill
from agentskills_fs import LocalFileSystemSkillProvider
from agentskills_mcp_server import create_native_mcp_server
provider = LocalFileSystemSkillProvider(Path("./skills"))
server = asyncio.run(create_native_mcp_server(
[Skill("incident-response", provider)], name="Native Skills"
))
server.run()
The builder also accepts an existing SkillRegistry. Raw Skill handles avoid
legacy metadata parsing, including its BOM and ASCII-name restrictions. Native
validation accepts current-spec Unicode lowercase names and preserves every
JSON-compatible author field. Known optional fields retain their specified types.
For example, metadata values must be strings. SDK-specific list-valued tags in
that mapping require an authored format change before native publication.
Duplicate YAML keys, non-JSON values such as unquoted dates, non-finite numbers, and recursive values fail publication. Valid YAML merges retain their resolved values. Expanded frontmatter JSON is bounded at 16 MiB.
Publication Boundaries
Each skill is limited to 512 files and 16 MiB. By default, the builder retains at
most 128 skills and 64 MiB of captured file bytes. max_skills and
max_total_bytes control those aggregate limits. Provider per-file limits apply
as well. Publication fails without returning a server when a capture, manifest,
limit, or URI conflict is invalid. Use trusted, immutable sources during capture
and restart the server to publish changes.
skill_paths maps handle IDs to unescaped paths ending in the declared skill
name, such as {"refunds": "billing/refunds"}. Without an override, a differing
handle ID becomes a prefix, so an alias cannot replace the final name segment.
Names may repeat at distinct canonical URIs. Register nested skills explicitly
and map their paths under the parent, such as {"child": "parent/child"}.
Their files remain in the parent manifest too. Overlapping captures must agree
on both directory membership and every shared file's bytes.
page_size defaults to 100 complete entries. listed_skill_ids can select a
partial or empty listing, but never restricts direct lookup or resource access.
It is not an authorization control. All supplied skills must be appropriate for
the server's audience.
Canonical reads use standard base64 blob resources, including for SKILL.md.
Decode the blob before checking byte size, SHA-256 digest, and frontmatter.
There are no SDK envelopes, truncation, image conversion, or script execution.
Cache hints are ttlMs: 0 and cacheScope: "private". Captured bytes remain
unchanged for the server instance, but cache hints are not an integrity guarantee.
Hosts remain responsible for origin-scoped identity and reads, lazy retrieval,
digest and frontmatter verification, and explicit per-skill consent. Reading is
not activation. Parent approval does not approve nested skills, and
allowed-tools grants no host permissions automatically. Digests establish
consistency, not publisher trust. Remote HTTP deployments also need authenticated
transport, TLS, and audience isolation beyond this builder.
The tested matrix above distinguishes native Skills support from ordinary resources access. Native checks now cover in-process, real stdio, and loopback Streamable HTTP. Host-specific Skills certification remains a separate release gate, including consent, origin isolation, and verification before activation.
Quick Start (CLI)
Create a server.json config file:
{
"name": "My Skills Server",
"skills": [
{
"id": "incident-response",
"provider": "fs",
"options": {"root": "./skills"}
}
]
}
Start the server:
python -m agentskills_mcp_server --config server.json
With Streamable HTTP transport:
python -m agentskills_mcp_server --config server.json --transport streamable-http
The server listens on http://127.0.0.1:8000/mcp.
Remote HTTP Deployment Boundaries
Keep the backend listener private. A remote deployment needs a TLS-terminating, authenticated endpoint in front of it, or an equivalent secured ASGI deployment. The local CLI commands do not configure a public OAuth resource server.
Before exposing /mcp, validate these deployment controls:
- Use MCP-compatible authorization discovery and validate issuer, audience, expiry, and required scopes for the public resource identifier
- Enforce the intended server audience and skill access policy, not
listed_skill_ids, which only filters enumeration - Restrict accepted hosts and browser origins, including forwarded-header trust at the proxy boundary
- Preserve streaming responses and supported HTTP methods without proxy buffering or unintended timeouts
- Route stateful sessions consistently when the deployment uses session state
- Keep bearer tokens out of public MCP URLs, and redact provider credentials from logs and published configuration
- Test rejected and expired credentials, cross-origin requests, disconnect cleanup, and exact native bytes through the public endpoint
The authentication component must validate credentials before traffic reaches
the private backend. Forwarding an unchecked Authorization header is not
authentication. Account for the backend's host and origin protections when
configuring the trusted proxy, rather than disabling them without a replacement.
Real loopback HTTP and stdio interoperability are tested. A production gateway,
TLS setup, authorization server, and host-specific approval workflow are not
certified by those tests or by --check. A host must still verify manifests and
obtain per-skill consent before activation. Use legacy mode when its client lacks
native Skills support.
MCP Client Integration
Use a client that supports the selected MCP transport. Ordinary legacy tools/resources connectivity does not establish native Skills support.
Stdio (local):
{
"command": "python",
"args": ["-m", "agentskills_mcp_server", "--config", "server.json"]
}
Streamable HTTP (remote):
{
"url": "http://127.0.0.1:8000/mcp"
}
Config Reference
The server.json file supports the following structure:
| Field | Type | Required | Description |
|---|---|---|---|
name |
str |
Yes | Display name shown to MCP clients |
instructions |
str |
No | Server-level instructions sent during handshake |
skills |
list |
Yes | One or more skill definitions (see below) |
mode |
str |
No | legacy by default, or native for the official Skills extension |
skill_paths |
dict |
No | Native handle-ID to canonical skill-path mapping |
listed_skill_ids |
list |
No | Native listing selection only, not access control |
page_size |
int |
No | Native entries per page, default 100 |
max_skills |
int |
No | Native captured skill count, default 128 |
max_total_bytes |
int |
No | Native aggregate captured byte limit, default 64 MiB |
Each skill entry:
| Field | Type | Required | Description |
|---|---|---|---|
id |
str |
Yes | Skill identifier |
provider |
str |
Yes | Provider type: "fs" or "http" |
options |
dict |
No | Provider-specific options |
Provider options:
fsacceptsroot(default".") andmax_file_bytes.httpacceptsbase_url,headers,params,resource_manifest,file_manifest, andmax_response_bytes.
Only "fs" and "http" are supported as provider types.
Environment Variable Substitution
String values in the config file may contain ${VAR} placeholders that are resolved from environment variables at load time:
{
"name": "My Skills Server",
"skills": [
{
"id": "cloud-runbooks",
"provider": "http",
"options": {
"base_url": "https://cdn.example.com/skills",
"headers": { "Authorization": "Bearer ${API_TOKEN}" },
"params": { "sig": "${SAS_TOKEN}" }
}
}
]
}
Unset variables resolve to an empty string and a warning is logged.
Programmatic Usage
For custom providers or advanced setups, use the Python API directly:
from agentskills_core import SkillRegistry
from agentskills_mcp_server import create_mcp_server
registry = SkillRegistry()
await registry.register("incident-response", my_custom_provider) # any SkillProvider
server = create_mcp_server(registry, name="My Skills Server")
server.run() # stdio by default
Agent Framework Context Provider
If you're using Microsoft Agent Framework, AgentSkillsMcpContextProvider bridges an MCP session into the Agent Framework lifecycle. It reads the skills catalog and usage-instruction resources from the MCP server and injects them as session instructions on every agent.run() call.
Note: This adapter only injects instructions, not tools. Agent Framework's MCP tool classes (
MCPStdioTool,MCPStreamableHttpTool, etc.) handle tool registration natively.
pip install agentskills-mcp-server[agentframework]
from agent_framework import Agent, MCPStdioTool
from agentskills_mcp_server import AgentSkillsMcpContextProvider
mcp_skills = MCPStdioTool(
name="skills",
command="python",
args=["-m", "agentskills_mcp_server", "--config", "server.json"],
)
async with mcp_skills:
skills_context = AgentSkillsMcpContextProvider(
session=mcp_skills.session,
)
agent = Agent(
client=client, # any Agent Framework chat client
name="SREAssistant",
instructions="You are an SRE assistant.",
tools=mcp_skills,
context_providers=[skills_context],
)
response = await agent.run("What severity is a full DB outage?")
See examples/agent-framework/ for full working demos including client setup.
| Parameter | Default | Description |
|---|---|---|
session |
(required) | An MCP ClientSession, typically from mcp_tool.session |
skills_instruction_prompt |
Built-in template | Custom prompt template. Must contain {skills_catalog} and {tools_usage_instructions} placeholders. |
skills_catalog_format |
"xml" |
Skills catalog format — "xml" or "markdown". |
source_id |
"agentskills_mcp" |
Unique identifier for this provider instance. |
Tools
The server exposes tools that let the LLM agent access skill content:
| Tool | Parameters | Description |
|---|---|---|
get_skill_metadata |
skill_id |
Read frontmatter (name, description, etc.) |
get_skill_body |
skill_id |
Load full skill instructions |
get_skill_outline |
skill_id |
List the body's sections, keys and token costs |
get_skill_section |
skill_id, key |
Load one section of the body |
list_skill_resources |
skill_id |
List bundled references, scripts and assets |
get_skill_reference |
skill_id, name |
Read a reference document |
get_skill_script |
skill_id, name |
Read a script |
get_skill_asset |
skill_id, name |
Read an asset |
get_skill_outline exists so a large skill is not all-or-nothing. Its rendered text carries the whole-body cost alongside the per-section costs and says outright when get_skill_body is the cheaper call — a section fetch is not free, it costs a tool call and a model turn on top of the outline. Section keys are flat slugs and sections do not nest, so fetching a parent does not include what is indented under it in the outline.
list_skill_resources returns a JSON object keyed by resource kind. Not every backend can enumerate resources — a plain static HTTP host cannot. Rather than surfacing an exception, the tool returns {"supported": false, "note": "..."} in that case: "this cannot be listed" is something the model can act on by falling back to the names in the skill body, not an error worth retrying.
Resources
The server provides resources for system-prompt context:
| URI | Description |
|---|---|
skills://catalog/xml |
XML catalog of all registered skills |
skills://catalog/markdown |
Markdown catalog of all registered skills |
skills://tools-usage-instructions |
Workflow instructions for using the tools |
skills://{skill_id}/resources |
Resource listing for a single skill |
The MCP client reads these resources and injects them into the system prompt, giving the agent both what skills exist and how to interact with them.
Single-Skill Fast Path
A server exposing one skill makes the client pay the whole discovery apparatus — a catalog listing one entry, eight tool definitions, usage instructions describing a selection workflow, and a model round trip while the agent calls get_skill_body — to reach content there was never a choice about.
from agentskills_core import resolve_fast_path
fast_path = await resolve_fast_path(registry)
server = create_mcp_server(registry, name="my-skills", fast_path=fast_path)
resolve_fast_path returns None unless the effective skill set is exactly one and its body fits under a token ceiling, and fast_path=None is the normal path — so the call above is safe unconditionally. When it fires:
- Both
skills://catalog/*resources serve the skill's body directly, so an existing client that already injects the catalog needs no change. skills://tools-usage-instructionsdrops the selection workflow, which would otherwise point the model at a catalog that is no longer there and at tools that are no longer registered.- The four body-access tools are never registered. MCP has no way to hide a registered tool later, so they are omitted at construction rather than declined at call time.
- The four resource tools remain.
The ceiling, the arithmetic behind its default, and why resource tools stay are documented in the core README. Because tools are fixed at construction, rebuild the server if the registry changes.
API
AgentSkillsMcpContextProvider(session, *, skills_instruction_prompt=None, skills_catalog_format="xml", source_id=None)
A ContextProvider that reads the skills catalog and tools-usage-instructions from an MCP session and injects them as session instructions via before_run(). Requires the [agentframework] extra.
create_mcp_server(registry, *, name, instructions=None, max_inline_binary_bytes=65536, fast_path=None, vision=False, max_inline_image_bytes=5242880)
| Parameter | Type | Description |
|---|---|---|
registry |
SkillRegistry |
The registry whose skills are exposed |
name |
str |
Display name for the MCP server (required) |
instructions |
str | None |
Optional server-level instructions sent to clients |
max_inline_binary_bytes |
int |
Size ceiling for inlining binary resources as base64 |
fast_path |
FastPath | None |
From resolve_fast_path; inlines a lone skill's body and drops the body-access tools |
vision |
bool |
Return bundled images as native ImageContent instead of a base64 envelope |
max_inline_image_bytes |
int |
Size ceiling for native images; only consulted when vision is on |
Returns the installed SDK's configured server instance, ready for server.run().
Supported transport modes: stdio (default), streamable-http.
Binary Resources
Skill resources may be arbitrary files. Valid UTF-8 is returned as-is; anything else is returned as a JSON envelope, so a binary payload is never silently mangled into replacement characters:
{
"name": "architecture.png",
"media_type": "image/png",
"size_bytes": 20481,
"encoding": "base64",
"content": "iVBORw0KGgo..."
}
Base64 costs roughly 1.37 characters per byte, so binaries above 64 KiB are described rather than inlined - "encoding": "none" plus a note explaining the omission. Adjust the ceiling with create_mcp_server(..., max_inline_binary_bytes=256 * 1024).
Images
A base64 envelope is the right answer for an opaque binary and the wrong one for
a diagram: the model gets a wall of characters where a picture was. Pass
vision=True and bundled images come back as native ImageContent instead:
server = create_mcp_server(registry, name="skills", vision=True)
It is off by default because handing an image to a text-only model is an API error from the provider, not a degraded answer, and there is no reliable way to ask a model whether it can see. The client knows which model is on the other end; the server does not.
PNG, JPEG, GIF and WebP qualify, and only when the leading bytes say so - a name
is a claim, bytes are evidence. PDF is excluded because support varies by model,
and SVG because it is already text the model can read. Everything else keeps the
JSON envelope exactly as above, including images past max_inline_image_bytes
(5 MiB by default, against 64 KiB for opaque binaries - base64 in a text field is
billed per byte, while a native image is billed by tile count).
See ADR 0009.
License
MIT
Metadata
Release files for agentskills-mcp-server 0.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| agentskills_mcp_server-0.6.0.tar.gz | 31.0 kB | With provenance | Details for agentskills_mcp_server-0.6.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| agentskills_mcp_server-0.6.0-py3-none-any.whl | Python 3 | none | any | Details for agentskills_mcp_server-0.6.0-py3-none-any.whl |
Total release size: 58.2 kB
Release files / agentskills_mcp_server-0.6.0.tar.gz
| Download URL | agentskills_mcp_server-0.6.0.tar.gz |
|---|---|
| Size | 31.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
5e7638af779fa7ae7b311a3dd3c5bc8cc4f24344cbdc929bac41d1da50c1f4ec
|
|
BLAKE2b-256 checksum How to use checksums |
e0139617ed81b8a7a0675f946a6afdf4608b703f6ea567bec0a631ea023f40de
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logRelease files / agentskills_mcp_server-0.6.0-py3-none-any.whl
| Download URL | agentskills_mcp_server-0.6.0-py3-none-any.whl |
|---|---|
| Size | 27.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
65e050eefc085353983f26edc072c6e236f156fadbf5cc579b7a1691077d4b62
|
|
BLAKE2b-256 checksum How to use checksums |
a76a8865027a858a525d1f8146e71399b3c7325806dd81747bcd68aa24947900
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logSecurity for agentskills-mcp-server 0.6.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for agentskills_mcp_server-0.6.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.