skills-mcp-server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@skills-mcp-serverlist all available skills"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
skills-mcp-server
An MCP server, built with FastMCP, that serves a directory of
SKILL.md-based "skills" over the network — as both MCP resources and MCP tools.
How it works
Resources come from FastMCP's built-in
fastmcp.server.providers.skills.SkillsDirectoryProvider. It scans a root directory, and treats every subdirectory containing aSKILL.mdfile as one skill, exposing:skill://{name}/SKILL.md— the skill's main fileskill://{name}/_manifest— a synthetic JSON file listing (path/size/hash) for the skillskill://{name}/{relative/path}— every other file in the skill folder (e.g.references/*.md)
This server configures the provider with
supporting_files="resources", so every supporting file is individually listed bylist_resources()up front (not hidden behind a lazy URI template) — good for upfront discoverability by clients that just calllist_resources()once.Tools (
list_skills,get_skill,get_skill_reference) are hand-written on top of the same skills directory, since the provider only exposes resources, not tools. They parse full YAML frontmatter (interface:blocks, nested lists, etc.) rather than relying on the provider's internal simplified line-based frontmatter parser, so nested metadata (e.g.risk_level,confirmation_points) comes through correctly.list_skills()→ name, description, argument hint, risk level, and path for every skill.get_skill(name)→ full parsed frontmatter, the markdown body, and a list of that skill's supporting reference files.get_skill_reference(skill_name, path)→ the text content and MIME type of one reference file within a skill (e.g.references/infoblox/procedure.md), for clients that want a specific reference file's content without walkinglist_resources().pathmust be one of the paths in that skill'sreference_fileslist; anything else (including path traversal attempts) is rejected.
Transport: streamable-HTTP (
mcp.run(transport="http", ...)), since this is meant to run in a container and be reached by remote MCP clients rather than over stdio.Skills directory is never baked into the image. The Dockerfile only ships the server code; the actual skills live on the host and are mounted as a read-only volume at container runtime (
docker-compose.ymlmounts them to/skills). Swap in a different skills directory by changing the compose volume mount or theSKILLS_DIRenv var — no rebuild needed.
Related MCP server: skills-mcp-server
Configuration
All configuration is via environment variables (see .env.example):
Variable | Default | Meaning |
| (unset) | Multiple named skill sources — see Multiple skills directories below. Takes precedence over |
|
| Legacy single-directory config. Root directory to scan for skill folders. Still fully supported for backward compatibility when |
|
| Host/interface the HTTP transport binds to |
|
| Port the HTTP transport binds to |
|
| If |
|
|
|
|
| Standard Python logging level |
A GET /health route is also registered for container/orchestrator liveness checks. It reports
every configured skill source by name.
Multiple skills directories
This server can merge more than one skills collection behind a single MCP endpoint. Configure
SKILLS_DIRS as a comma-separated list of name=path pairs, one per source:
SKILLS_DIRS=agent-skills=/skills/agent-skills,automation-skills=/skills/automation-skillsEach source is identified by an explicit, stable name — this is what drives collision
resolution (below), not the order the sources are listed in.
Collision policy: agent-skills always wins. If the same skill directory name exists under
more than one configured source, the source literally named agent-skills always wins,
regardless of where it appears in SKILLS_DIRS. This is enforced by an explicit name check
(source.name == "agent-skills") in discovery._resolve_skill_dirs, not by "whichever directory
happens to be scanned first" — reordering SKILLS_DIRS in your .env file later will not
silently flip precedence. If neither colliding source is named agent-skills, the
first-configured source wins (list order only matters as a tiebreaker in that case).
Every time a collision is resolved, the server logs a WARNING naming the skill, every source
that defines it, the winning source, and the shadowed source(s) — so shadowing is never silent.
This applies identically to both the tool layer (list_skills/get_skill/get_skill_reference)
and the resource layer (skill://... URIs): a shadowed source's own files are never served under
the winning skill's name, even if you ask for one of its supporting files by path directly.
SKILLS_DIR (singular) keeps working unchanged if you only need one source — it's treated as one
source named "default". If both SKILLS_DIRS and SKILLS_DIR are set, SKILLS_DIRS wins and
SKILLS_DIR is ignored.
Local development quickstart
Requires Python 3.11+ and uv.
uv venv .venv
source .venv/bin/activate
uv pip install -e .
# Point at any skills directory you like — this repo bundles a minimal
# example under ./example-skills:
export SKILLS_DIR=./example-skills
skills-mcp-server
# -> Starting MCP server 'Skills MCP Server' with transport 'http' on http://0.0.0.0:8010/mcp(pip install -e . in a plain venv works too, if you'd rather not use uv.)
To run locally against a real, richer skills set instead of the bundled example (e.g. for manual
testing), just point SKILLS_DIR elsewhere — nothing else needs to change:
export SKILLS_DIR=/path/to/agent-skills/skills
skills-mcp-serverThis only affects your local shell session — it does not touch docker-compose.yml, the
project's .env.example default, or the test suite (which always uses its own fixtures under
tests/fixtures/, independent of both example-skills/ and whatever SKILLS_DIR you export).
Quick smoke test with the FastMCP client
import asyncio
from fastmcp import Client
async def main():
async with Client("http://127.0.0.1:8010/mcp") as client:
tools = await client.list_tools()
print([t.name for t in tools])
resources = await client.list_resources()
print([str(r.uri) for r in resources])
result = await client.call_tool("list_skills", {})
print(result.data)
asyncio.run(main())Or with curl against the health route:
curl http://127.0.0.1:8010/health
# {"status": "ok", "skill_sources": {"default": "./example-skills"}}Docker quickstart
docker compose up --buildThis builds the image (server code only — no skills baked in), mounts the bundled
./example-skills directory from the repo to /skills inside the container read-only, and
serves on http://localhost:8010/mcp. No configuration is required for this to work on a fresh
clone.
Pointing at a different skills directory
Copy docker-compose.override.yml.example to docker-compose.override.yml (untracked — see
.gitignore) and edit the path:
services:
skills-mcp-server:
volumes:
- /path/to/your/skills:/skills:roCompose automatically merges docker-compose.override.yml over docker-compose.yml, so your
own skills directory is used without editing the tracked file.
Or, if running the container directly instead of via compose:
docker run --rm -p 8010:8010 \
-v /path/to/your/skills:/skills:ro \
-e SKILLS_DIR=/skills \
skills-mcp-server:localConnecting an MCP client
Any MCP client that supports streamable-HTTP transport can connect directly to
http://<host>:8010/mcp. Example generic client config:
{
"mcpServers": {
"skills": {
"url": "http://localhost:8010/mcp",
"transport": "http"
}
}
}Project layout
skills-mcp-server/
├── pyproject.toml
├── Dockerfile
├── docker-compose.yml
├── docker-compose.override.yml.example # template for pointing at your own skills dir
├── .env.example
├── .gitignore
├── LICENSE
├── README.md
├── example-skills/ # bundled fixture so the server works out of the box
│ └── hello-world/
│ ├── SKILL.md
│ └── references/
│ └── greeting-styles.md
├── tests/ # pytest suite — uses its own fixtures/, never example-skills/
│ ├── conftest.py
│ ├── fixtures/skills/
│ ├── fixtures/multi/ # two-source fixtures for collision-policy tests
│ ├── test_config.py
│ ├── test_discovery.py
│ ├── test_server.py
│ └── test_tools.py
└── src/skills_mcp_server/
├── __init__.py
├── config.py # env-driven Settings; SKILLS_DIRS / SKILLS_DIR parsing, SkillSource
├── discovery.py # full YAML frontmatter parsing, multi-source merge + collision policy
├── tools.py # list_skills / get_skill / get_skill_reference MCP tool definitions
└── server.py # FastMCP app wiring, multi-provider root ordering, health route, entrypointRunning tests
uv pip install -e ".[dev]" --python .venv/bin/python
.venv/bin/python -m pytestLicense
Apache License 2.0 — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Remote MCP server exposing SMI Aware tools, resources, and skills over Streamable HTTP.
- UnifAPIOAuthcom.unifapi
Hosted MCP server for live public-data APIs and Skills for AI agents.
Search and discover Agent Skills from the skills.sh registry. Powered by HAPI MCP server.
MCP server for skill documentation, generated by doc2mcp.
Related MCP Servers
- AlicenseAqualityCmaintenanceConverts AI Skills (following Claude Skills format) into MCP server resources, enabling LLM applications to discover, access, and utilize self-contained skill directories through the Model Context Protocol. Provides tools to list available skills, retrieve skill details and content, and read supporting files with security protections.329Apache 2.0
- AlicenseAqualityDmaintenanceExposes Cursor-style skill packs (SKILL.md trees) via MCP resources, tools, and prompts, enabling any MCP client to list, get, search skills, and retrieve skill context.311 npmISC
- AlicenseNot gradedqualityDmaintenanceA minimal MCP server that resolves skill names to filesystem paths + metadata, enabling on-demand skill retrieval without loading full content into context.MIT
- AlicenseAqualityCmaintenanceMCP server that serves agent skills (SKILL.md bundles) to any MCP client, exposing them via tools and resources for tool-oriented and resource-aware clients.311 npmISC