skill-mcp
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., "@skill-mcpwhat skills do you have?"
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.
skill-mcp
An MCP server that serves a directory of Agent Skills. Point it at skills; it lists them, hands out their instructions and their bundled files, and runs only the scripts a skill declares.
It is a generic adapter, not a curated set: the skills are content it reads, and the same build serves whatever it is pointed at.
npx @chrischall/skill-mcp # serves the example skill bundled here
SKILLS_DIR=~/my-skills npx @chrischall/skill-mcpThe npm package is @chrischall/skill-mcp (unscoped skill-mcp is taken by
someone else on npm). Everything else — the repo, the binary, the registry
identity io.github.chrischall/skill-mcp — is unscoped.
What a skill is
A directory holding SKILL.md: YAML frontmatter (name, description, and
optionally the mcp-host: block below) followed by instructions, plus whatever
files those instructions refer to. Three layouts are found under each root:
<root>/SKILL.md # the root IS one skill
<root>/<name>/SKILL.md # a directory of skills
<root>/skills/<name>/SKILL.mdA skill is served under its DIRECTORY name, never under the name in its
own frontmatter (a frontmatter name that disagrees is reported and otherwise
ignored; where the root itself is the skill, the root directory names it). That
is a security rule, not a tidiness one: the owner's grant names a skill, so a
bundle that could choose its own name could claim its neighbour's and be handed
the neighbour's granted script and granted variables. For the same reason, two
directories that really do contribute one name — only possible across two roots
— have both refused and reported, rather than one of them winning by scan
order.
Related MCP server: MCP Skills Server
The tools
tool | arguments | returns |
| — | every skill found: name, description, when to use it, file count, whether it declares runnable scripts and exactly which; plus |
|
| the SKILL.md body verbatim, plus a manifest of the bundle's files. Referenced files are not inlined — that is what |
|
| one file from that skill's directory: text, or base64 with its media type. At most 1 MiB, |
|
|
|
skill_file takes one path. The design of record specifies a paths[]
batch (8 paths per call, 1 MiB per entry, 4 MiB per call, one bad path failing
only its own slot); shipping the singular form is a deliberate deferral, not an
oversight, and those three bounds are what a later batching change has to
honour. Read the caps as bounds on this server's own heap: they cap the
allocation, not only the answer, because a hosted child has a hard 256 MiB
data limit and a bundle may be larger than that.
Each skill is also registered as an MCP prompt (its body is the message) and
each bundled file as a resource (skill://<name>/<path>), because a client that
supports those surfaces presents a skill better than a tool call does. It is a
second door, never the only one: when this server runs on
mcp-host and a registration narrows
enabledTools, prompts/list and resources/list come back empty and the
handshake stops advertising those capabilities — so the tools carry the whole
experience.
Discovery reports, it never goes quiet
Anything that keeps a directory from being served comes back in skill_list's
problems, with the path and the reason: no SKILL.md, frontmatter that will
not parse, a name two directories both claim (both refused), a declared script that is not in
the bundle, a symlink leading out of the root or out of a skill, a filename the
read tools could not address. One bad skill costs itself and never the listing,
and there is no third outcome where something is dropped in silence — a
symlinked skill directory is served when it stays inside the root (so
skills/foo -> ../shared/foo works) and reported when it does not.
The execution fence
skill_run executes third-party code. Every rule below narrows which code
runs and what it is handed; each has its own test.
Only a script the skill DECLARES. Not "any file under
scripts/", not "anything executable". An undeclared path is refused, saying it must be declared and listing the ones that are.Only inside that skill's own directory. The path is checked as a string first (plain segments; no leading
/, no.or.., no backslash, no percent escape, no NUL) and then again after resolution: the real path, with symlinks followed, must still be inside the skill's real directory, and it must be a regular file. Both checks, because a string check alone misses a symlink planted inside the bundle and a resolved check alone accepts shapes that should never have been joined. The same discipline governsskill_file: a read out of a skill directory is another skill's bundle at best.An argv array, never a shell string.
spawnwithshell: false, no interpolation, nosh -c. Arguments are passed through verbatim.An interpreter from a closed set, named by the declaration — never inferred from the extension and never taken from the file's own shebang, since a file that can choose its own interpreter has already chosen its own program. v1 runs
nodeand nothing else (see What v1 cannot run).Bounded, and the call always returns. A wall-clock timeout (60 s default, per-script override, hard 300 s ceiling), 1 MiB captured per stream with
truncated: truerather than a silent cut, and oneskill_runat a time. On timeout the process group is signalled, which reaches the script and any child that stayed in its group. It does not reach a grandchild that detached into a group of its own, and such a grandchild also holds the stdio pipes open — so the run settles on the process exiting plus a short drain, under a hard deadline, rather than on the pipes closing. That is what guarantees the tool call returns within its budget and frees the one-at-a-time lock; it is not a guarantee that a deliberately detached grandchild is dead. Bounding that is the tier's job (an unprivileged uid,prlimitNPROC, and a machine that stops), not this adapter's.An env allowlist. A script gets
PATH,HOME,LANG,TZ,TMPDIR,MCP_DATA_DIRwhen the host set one, and exactly the variables that script asked for and the owner granted — never this server's own environment. The fixed half mirrors mcp-host'sINSTALL_ALLOWLIST(packages/runner-node/src/spawn-env.ts), for the reason that file gives: a host constant a hosted declaration cannot widen by one name.A non-zero exit is a normal, reported outcome — exit code, stdout and stderr all come back. It is never an exception that loses the output.
skill_runis confirm-gated. Withoutconfirm: trueit starts no process and returns a dry-run preview of exactly what would run: the interpreter, the argv, the working directory, the timeout, and the names of the variables the script would be handed.
Why the confirm gate is blanket
The fleet convention gates mutating tools. Whether a given script mutates anything is something this server cannot know: it never reads a script, and it deliberately does not analyse one — a machine-generated verdict about somebody else's code gets trusted in a way an author's declaration does not. Unknown effects are therefore treated as mutating.
The obvious softening — let a skill mark a script read-only and skip the gate for it — is refused because it is circular: the same author wrote the script and the sentence describing it, so a self-declared "read-only" authorizes nothing. That leaves a blanket gate. Its cost is one extra round-trip on a read-only helper; its benefit is that the preview is the one place a caller sees the exact call before any of it happens.
What the fence does NOT buy
A declared script is still arbitrary code. These rules narrow which code
runs and with what; none of them makes the code safe. A script you allow can
read the whole skills tree, spend the machine's CPU, and send whatever it holds
anywhere its network permits. skill_run's output caps are truncation, not
confidentiality: nothing redacts a script's stdout, and nothing could.
This is not a sandbox. Run it against skills you have read, or run it
somewhere that fences it — under mcp-host that means the isolated tier
(fly-machine): a microVM per registration, an unprivileged uid, prlimit
bounds, and nftables default-deny with a declared egress allowlist. This server
is a narrowing on top of such a fence, not a replacement for one.
What v1 cannot run
The set of interpreters is node, one entry, and that is a measured decision
rather than an oversight: mcp-host's runner image is Node + git + tar +
util-linux + nftables, with no python3, curl or jq, while real skills are
overwhelmingly Python (70 .py against 1 .js in anthropics/skills at
3b3fad96).
So a skill declaring a Python script is reported by skill_list under
unavailableScripts, with the interpreter and this deployment's set named, and
skill_run refuses it in the same words. Its instructions still serve —
an instructions-only skill is a useful skill, and most published skills are
exactly that. A pinned interpreter is a follow-up that arrives as a dependency,
never as an image change.
The mcp-host: declaration block
Optional, inside SKILL.md's frontmatter:
---
name: weather
description: Forecasts and geocoding.
mcp-host:
version: 1
run:
- script: scripts/forecast.js
interpreter: node
env: [WEATHER_API_KEY] # variables this SCRIPT asks for
timeout: 30 # seconds; clamped to 300
env: # fields proposed for the SERVER's environment
- name: WEATHER_API_KEY
secret: true
egress: [api.weather.example] # hosts this skill reaches; a proposal
---A declaration narrows; it never grants. The author of the scripts also wrote the block naming them, so nothing in it is an authorization — it says which files are entry points and what each wants. What makes a script runnable, and a variable reach it, is somebody else accepting it.
Read strictly: YAML 1.2 core schema, anchors and aliases refused, a 64 KiB cap, an unknown MAJOR version refused wholesale, unknown keys ignored and reported by name, and a block that does not parse reported with the parser's position rather than treated as absent. A broken block costs a skill its scripts, never its instructions, and never the rest of the listing.
Configuration
variable | meaning |
|
|
| the same thing for local use. Read only when |
| optional JSON |
(neither set) | this package's own |
MCP_SKILL_RUN deserves the emphasis. When it is present, what may run is the
declaration intersected with it — a row naming a script the skill did not
declare grants nothing (and is reported), and a row naming a variable the script
did not ask for grants nothing. There is no spelling of it that makes something
runnable which a skill did not declare, which is what makes it safe to read from
an environment that also carries a registration's own variables.
When it is absent, the default depends on whether a host started this child, and the hosted half is fail-closed.
Hosted — any variable mcp-host's runner injects is present (
MCP_SKILLS_PATH,MCP_HOST_METER_FILE,MCP_DATA_DIR,MCP_BLOB_BASE_URL): nothing is granted and nothing runs. Every skill's instructions and files are still served — that is a working, useful connector. The reason is that one child holds one environment holding every credential the owner set, so a skill whose frontmatter named its neighbour's variable would otherwise be handed the neighbour's credential with nobody having decided to give it. It deliberately does not key onMCP_SKILLS_PATHalone: mcp-host does not inject that variable yet, so today's only hosted channel isSKILLS_DIRin a registration's plainenv, and that must not land on the open default. The marker check can only ever move the default in the fail-closed direction.Standalone — no injected marker at all: the skill's own declaration stands. Nothing is injecting anything, and the person who pointed the server at a directory is the owner.
skill_list reports which case it is (grantFrom, plus a grantNote in the
hosted one) and lists a skill's declared-but-ungranted scripts, so "nothing
runs" is never indistinguishable from "nothing was declared".
Trust posture
This server's code is the operator's; the skills are yours. It reads a fixed set of directories handed to it, fetches nothing, installs nothing, and has no tool that takes a path outside a skill's own directory.
It vets nothing. There is no badge, no publisher allowlist, no scan. A skill's instructions and its scripts are exactly as trustworthy as whoever wrote them.
A read is treated as dangerously as an execution, because the directory it reads from sits beside everything else on the machine.
It caches nothing and stores nothing. The catalog is scanned once at boot and held in memory; no file is written anywhere.
Hosting on mcp-host
mint.yaml at the repo root says how this MCP wants to be registered. Four
things it deliberately does not propose, because only a registration can
decide them:
The runtime — and it could not, by rule. A manifest may never name one (docs/MINT-MANIFEST.md §5): which tier a registration lands on is decided by who is asking, not by the package, since a file that could ask for
fly-sharedwould be a stranger's package requesting a seat on the operator's own machine. A hosted skill server belongs on the isolated tier (fly-machine) with a declared egress policy, and that is the registration's choice to make.The skills themselves. They arrive as a pinned dependency (a
github-archivenaming a repository and an exact commit) and land in a read-only slot the runner names throughMCP_SKILLS_PATH. This package cannot know which ones a given registration carries.state.dataDir. The adapter needs no persistence. Turn it on when a registration's skills have scripts that need somewhere to write — the slot is read-only, soMCP_DATA_DIR(with it on) orTMPDIR(without) is where a script's output goes — and give the reason there.The real egress allowlist.
mint.yamlproposesallow: [], which is what the adapter itself needs: it reaches nothing. The hosts a registration needs are the ones its SKILLS declare, shown at the preview with who declared them and accepted by the owner. On the isolated tier a host that is not on the list appears either as an HTTP 403 from the loopback proxy or as a plain timeout — the two are indistinguishable from inside a script, soskill_runattaches a note saying so whenever a call fails on a machine that looks fenced.
Narrowing enabledTools to [skill_list, skill_load, skill_file] is the
non-executable switch, enforced at the gateway rather than here — a stronger
statement than this server refusing skill_run, and it costs the prompt and
resource surfaces entirely.
Development
npm install
npm run build # tsc → dist/, esbuild → dist/bundle.js
npm test # tsc typecheck + vitestThis project was developed and is maintained by AI. Use at your own discretion.
Available Tools
4 toolsskill_fileARead-onlyIdempotent
Read files a skill bundles. Paths are relative to that skill's own directory; text comes back as text, anything else as base64 with its media type. Ask for every file you need in ONE call — a SKILL.md usually points at several.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The skill's name, exactly as skill_list reports it. | |
| paths | Yes | Up to 8 paths relative to the skill's own directory, as skill_load lists them. Reading a SKILL.md's referenced files in one call costs one round trip instead of one each. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint and idempotentHint, so the description carries a lighter burden. It adds valuable behavior beyond annotations: relative-path scoping and type-dependent return encoding (text as text, non-text as base64 with media type). No contradiction with the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each adding distinct information: the operation, path resolution and return encoding, and batching guidance. The purpose is front-loaded and there is no filler or redundant restatement.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only, two-parameter tool with no output schema, the description covers purpose, path scope, return encoding, and batching, while the schema covers parameter details. The only notable gap is that the response shape for multiple requested paths is not spelled out.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and the parameter descriptions already document provenance ('exactly as skill_list reports it', 'as skill_load lists it') and the batching/round-trip rationale. The description mostly repeats the relative-path constraint, so it adds little parameter meaning beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb and resource ('Read files a skill bundles') and clarifies that paths are resolved relative to the skill's directory, so the tool's role is clear. It does not explicitly distinguish itself from skill_load, but the read-file intent is unambiguous among the sibling tools.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit batching guidance: 'Ask for every file you need in ONE call' and explains why with 'a SKILL.md usually points at several.' It provides clear context for efficient use, though it relies on the schema's parameter descriptions to point the agent to skill_list and skill_load rather than stating alternatives directly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
skill_listARead-onlyIdempotent
List every Agent Skill this server found: name, description, when to use it, how many files it bundles, and the exact scripts (if any) that may be executed with skill_run. Also reports anything that could not be read, so an empty list is never a mystery.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnly and idempotent annotations, the description discloses failure behavior: it reports anything that could not be read, so an empty list is meaningful. It also surfaces safety-relevant metadata by revealing the exact executable scripts that skill_run may run.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler: the first states the main purpose and contents, the second adds the important error-reporting behavior. Everything earns its place and the key verb 'List' is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-parameter list tool with no output schema, the description fully specifies what will be returned (name, description, usage guidance, file count, scripts) and how failures are reported. No critical information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters and the schema is empty with 100% coverage, so there are no parameter semantics to explain. The description appropriately spends its effort on listing the output fields instead.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb ('List') and resource ('every Agent Skill this server found'), and clearly distinguishes this discovery tool from the executing/loading siblings skill_run, skill_load, and skill_file. It also states exactly what entries the list contains.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description makes clear this is the tool for enumerating all available skills and their metadata, including when to use each skill and what scripts may run. It doesn't explicitly state when not to use it or point to alternatives, but the listing scope and mention of skill_run imply the intended discovery use case.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
skill_loadARead-onlyIdempotent
Load one skill's SKILL.md instructions verbatim, plus a manifest of the files it bundles. Referenced files are NOT inlined — read them by name with skill_file.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | The skill's name, exactly as skill_list reports it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the readOnlyHint and idempotentHint annotations, the description adds critical behavioral detail: content is returned verbatim, a file manifest is included, and referenced files are not inlined. This tells the agent exactly what to expect and how to handle file references.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no wasted words. The primary action is front-loaded, and the important non-inlining caveat is stated immediately after, making the most critical usage note prominent.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Completely sufficient for a simple, one-parameter read-only tool. The description covers the return contents, the non-inlining behavior, and points to the relevant sibling for file access. No output schema is needed given the verbatim-loading nature.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the parameter 'name' is already well-documented with guidance to use the exact name from skill_list. The tool description adds no further parameter detail, which is acceptable given the baseline of 3 for full schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: loads one skill's SKILL.md instructions verbatim plus a manifest of bundled files. Clearly distinguishes from sibling tools by explicitly noting referenced files are not inlined and should be read via skill_file.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit when-to-use context (loading a skill's instructions and manifest) and provides a direct alternative for referenced files: 'read them by name with skill_file.' The input schema further references skill_list for obtaining the exact name, which reinforces routing.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
skill_runADestructive
Execute a script the skill DECLARES as runnable, with an argument array. Returns the exit code and the captured output; a non-zero exit is a normal, reported outcome. Mutating: call it once without confirm to see exactly what would run, then again with confirm: true.
| Name | Required | Description | Default |
|---|---|---|---|
| args | No | Arguments passed as an argv array. There is no shell: nothing here is interpreted. | |
| name | Yes | The skill's name, exactly as skill_list reports it. | |
| script | Yes | The exact script path skill_list reports for this skill. | |
| confirm | No | Must be true to proceed. Without this, the tool returns a preview. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description explicitly labels the tool as 'Mutating' and explains the confirm gate, going beyond the annotations (readOnlyHint=false, destructiveHint=true). It also discloses that a non-zero exit is a normal, reported outcome, and that a no-confirm call returns a preview of what would run. This gives the agent meaningful behavioral context not present in the schema or annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences with no filler. It front-loads the core action ('Execute a script'), then the return type, then the critical mutating/confirm behavior. Every sentence earns its place and the length is appropriate for the tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the absence of an output schema, the description sufficiently covers return values (exit code and captured output) and normalizes non-zero exits. It also explains the destructive nature and the preview/confirm workflow, and points the agent to skill_list for valid name/script values. No essential calling information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description mentions 'argument array' and the confirm flow, but the input schema already documents each parameter thoroughly (name from skill_list, script path, no-shell args, confirm preview behavior). The description adds no significant per-parameter semantics beyond what the schema provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb-resource pairing: 'Execute a script the skill DECLARES as runnable, with an argument array.' It clearly distinguishes skill_run from the sibling tools skill_list, skill_load, and skill_file by focusing on running a declared script rather than listing, loading, or reading files. The inclusion of return behavior (exit code and captured output) further pins down the tool's role.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear operational guidance on how to call the tool safely: first without confirm to preview, then with confirm: true to actually run. It does not explicitly name sibling alternatives or state when-not-to-use, but the two-step preview/execute pattern and the reference to skill_list's reporting ('exactly as skill_list reports it') give an agent enough context to use it correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
v0.3.0- Changed
skill_file1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
skill_list1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
skill_load1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
skill_run1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
4 tool updates
v0.1.0- First observed
skill_file - First observed
skill_list - First observed
skill_load - First observed
skill_run
TDQS
Scored across 4 tools
Each tool has a clearly distinct role: listing skills, loading the main SKILL.md, reading bundled files, and executing declared scripts. There is no functional overlap between any pair, so an agent can reliably select the right tool.
All tools share the skill_ prefix and use lower_snake_case, making the set visually consistent. skill_file is slightly less verb-oriented than the others (list, load, run), but the pattern is still predictable and readable.
With only four tools, the server is tightly scoped to its purpose: discovering, reading, and executing Agent Skills. Every tool contributes a necessary capability without redundancy or bloat.
The tool set covers the full lifecycle for consuming skills: enumerate available skills, load instructions, read referenced files, and execute declared scripts. There are no obvious dead ends—each action an agent needs from a skill server is represented.
Maintenance
Related MCP Connectors
The governed runtime for agent skills. Search the catalog and inspect a skill before running it.
Search and discover Agent Skills from the skills.sh registry. Powered by HAPI MCP server.
Governed AI agent skills — one library, distributed to devs and exposed to remote agents over MCP.
- UnifAPIOAuthcom.unifapi
Hosted MCP server for live public-data APIs and Skills for AI agents.
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.328Apache 2.0
- AlicenseNot gradedqualityCmaintenanceDynamically loads and exposes skills from a directory with hot-reloading support, enabling users to manage and query skill content via MCP resources and tools.13MIT
- FlicenseNot gradedqualityCmaintenanceServes Agent Skills over MCP using the SEP-2640 Skills Extension, enabling skills discovery, retrieval, and resource reading via MCP.-
- AlicenseNot gradedqualityCmaintenanceServes SKILL.md-based skills as MCP resources and tools over streamable HTTP, enabling remote discovery and retrieval of skill files with full YAML frontmatter parsing.Apache 2.0