Skip to main content
Glama

lazy-skills-mcp

An MCP server that lets a coding agent search your Agent Skills and load one only when a request needs it, instead of loading every skill's description into every session.

An agent that loads skills natively pays for each skill's description in every session, even for specialized skills that few sessions use. Behind this server, those skills cost two tool definitions, find_skills and load_skill, and the agent reads a skill's full text only when it asks for it. It was built for Codex and GitHub Copilot CLI. An agent that already defers skill loading itself, such as Claude Code, gains nothing from it.

The server only reads. It serves the skills it finds in the folders you name, over stdio, and never writes, installs, or syncs skills; put them there with whatever tool you already use. Point it at a whole skills checkout, grouped into subfolders or flat, and tell it which folders your agent already loads natively: it serves only the rest.

What the Agent Sees

Given /srv/skills holding the skills nix-flakes and python-testing, a find_skills call with the query flake lockfile returns:

{
  "skills": [
    {
      "name": "nix-flakes",
      "description": "Write and debug Nix flakes, inputs, and lockfiles."
    }
  ]
}

The agent then calls load_skill with nix-flakes and gets the skill's text, its directory, and its other files, which it reads with its own tools:

{
  "content": "---\nname: nix-flakes\ndescription: Write and debug Nix flakes, inputs, and lockfiles.\n---\n\n# Nix flakes\n",
  "directory": "/srv/skills/nix-flakes",
  "files": [
    "references/inputs.md"
  ]
}

Related MCP server: skill-retrieval-mcp

Quick Start

This walk-through installs the server, gives it one skill, and registers it with Codex. It needs uv.

  1. Install the latest release, which puts lazy-skills-mcp on PATH:

    uv tool install git+https://github.com/jonatsu/lazy-skills-mcp@v0.2.0
  2. Create a skill in the default skills folder:

    mkdir -p ~/.local/share/lazy-skills-mcp/skills/hello-skill
    cat > ~/.local/share/lazy-skills-mcp/skills/hello-skill/SKILL.md <<'EOF'
    ---
    name: hello-skill
    description: Say hello. Use when asked to test that lazy-skills-mcp serves skills.
    ---
    
    # Hello
    
    Reply with a friendly greeting that names lazy-skills-mcp.
    EOF
  3. Register the server in ~/.codex/config.toml:

    [mcp_servers.lazy-skills-mcp]
    command = "lazy-skills-mcp"
  4. Tell the agent when to search, with a line in ~/.codex/AGENTS.md:

    Some skills are not preloaded: the lazy-skills-mcp server holds them. When a request touches testing
    lazy-skills-mcp, call its find_skills tool first, then load the best match with load_skill.
  5. Start a new Codex session and ask it to test that lazy-skills-mcp serves skills. It calls find_skills and load_skill, then replies with the greeting.

Then point the server at your real skills, as Register It With an Agent shows, and name their topics in the instruction line instead.

Install

The server needs Python 3.12 or newer. uv downloads a suitable Python when none is installed; pipx needs one installed. Releases are tags of this repository; see the changelog for what each one changes.

Install a release with uv, as the quick start does:

uv tool install git+https://github.com/jonatsu/lazy-skills-mcp@v0.2.0

Install the latest commit on main by leaving out the tag. Pin a commit with @<commit> and --reinstall when you want an install that changes only when you change it.

Install with pipx instead:

pipx install git+https://github.com/jonatsu/lazy-skills-mcp@v0.2.0

Run it without installing, with uvx, by registering this as the agent's server command:

uvx --from git+https://github.com/jonatsu/lazy-skills-mcp@v0.2.0 lazy-skills-mcp

Install from a checkout with uv tool install . in the repository root. The tool gets its own copy, so a later edit or branch switch in the checkout does not change a running server.

Check the install with lazy-skills-mcp --version, and print the folders the server will read with lazy-skills-mcp --print-skills-dir.

Register It With an Agent

Put your skills in the default folder, ~/.local/share/lazy-skills-mcp/skills, and register the bare command, or point the server at the folders that already hold your skills with --skills-dir. Add --skip-installed-in for each folder the agent loads skills from natively, so those skills are not served twice.

For Codex, which loads ~/.agents/skills natively, in ~/.codex/config.toml:

[mcp_servers.lazy-skills-mcp]
command = "lazy-skills-mcp"
args = ["--skills-dir", "~/src/agent-skills", "--skip-installed-in", "~/.agents/skills"]

For Copilot CLI, which loads ~/.copilot/skills and ~/.agents/skills natively, in ~/.copilot/mcp-config.json:

{
  "mcpServers": {
    "lazy-skills-mcp": {
      "type": "local",
      "command": "lazy-skills-mcp",
      "args": [
        "--skills-dir", "~/src/agent-skills",
        "--skip-installed-in", "~/.copilot/skills",
        "--skip-installed-in", "~/.agents/skills"
      ],
      "tools": ["*"]
    }
  }
}

The server expands the leading ~ itself, because agents start MCP servers without a shell. Each agent gets its own skip folders, which is why they are arguments rather than an environment variable. Claude Code does not need the server at all, since it already defers skill loading. If your setup installs Codex skills into ~/.codex/skills, add that folder as a skip folder too.

Register the server directly rather than behind an MCP proxy. Behind a proxy, the agent must first think of searching the proxy for skills, and agents do not reliably take that step. Direct registration costs a few hundred tokens per session and keeps the catalog in plain view.

An agent also needs a reason to search. Add a line to its instructions that names the kinds of skill behind the server and tells it to call find_skills when a request touches one of them. Replace the placeholder with the topics your own skills cover:

Skills for <the topics your skills cover> are not preloaded: the lazy-skills-mcp server holds them. Before working
on one of those topics, call its find_skills tool, then load the best match with load_skill.

Naming the topics matters: find_skills's description lists the skill names, but an agent searches more reliably when its own instructions say which requests need a skill.

Usage

usage: lazy-skills-mcp [-h] [--skills-dir DIR] [--skip-installed-in DIR]
                       [--version] [--print-skills-dir]

Serve Agent Skills on demand as MCP tools (find_skills, load_skill) over
stdio.

options:
  -h, --help            show this help message and exit
  --skills-dir DIR      A folder to read skills from, flat or grouped. Repeat
                        it to read several, in priority order. Default: the
                        LAZY_SKILLS_MCP_SKILLS_DIR list, then
                        $XDG_DATA_HOME/lazy-skills-mcp/skills, else
                        ~/.local/share/lazy-skills-mcp/skills
  --skip-installed-in DIR
                        A folder the agent loads skills from natively; skills
                        installed there are not served. Repeatable. Default:
                        none.
  --version             show program's version number and exit
  --print-skills-dir    Print the resolved skill sources, one per line, and
                        exit, without checking that they exist and without
                        starting the server.

Tools

Both tools are read-only, take no filesystem path, and resolve names only against the scanned catalog.

  • find_skills(query) returns the name and description of the skills whose name or description contains any of the whitespace-separated query terms, ignoring case and hyphens, best first and at most ten. Each term is weighted by how rare it is across the catalog (BM25's inverse document frequency), so a word in nearly every description barely counts, and a term in the skill's name counts double. An empty or missing query returns every skill. The tool's description names up to 300 skills, then counts the rest.

  • load_skill(name) returns the skill's full SKILL.md text, its absolute directory, and the relative paths of its other files. The agent then reads references/ and runs scripts/ from that directory with its own tools. An unknown name is a tool error that lists up to three close names. A large skill can exceed a client's inline tool-result limit: Copilot CLI 1.0.91 saved a 29.8 KB result to a temporary file and read it in ranges, which works but costs the agent extra calls.

A skill is left out of the catalog, with the reason logged, when its frontmatter is missing or unparsable or its name differs from its folder name. A file whose real path leaves its skill's folder, such as an outward symlink, is left out of the file list.

Skill Sources

The server reads skills from one or more source folders. It takes them from the first of these that names any:

  1. Every --skills-dir argument, in order.

  2. The LAZY_SKILLS_MCP_SKILLS_DIR environment variable, a list separated like PATH (: on Linux and macOS).

  3. $XDG_DATA_HOME/lazy-skills-mcp/skills, when XDG_DATA_HOME is set to an absolute path.

  4. ~/.local/share/lazy-skills-mcp/skills.

A level never merges with a lower one: any --skills-dir replaces the variable. Empty values are ignored, and a leading ~ is expanded. Because the default needs no argument, an agent's configuration need not name a folder at all.

Inside a source, the layout decides what is a skill, whatever tool installed it. A folder holding SKILL.md is a skill, and the server does not search inside it. Any other folder is a group, and the server searches its subfolders, up to 8 levels below the source. So a flat folder of skills and a checkout grouped as development/python/<skill>/SKILL.md both work. Hidden folders such as .git are skipped. Symlinked skills and groups are followed, as copies would be. A source that is itself a skill serves that one skill. Point a source at the folder that holds your skills rather than at a whole project: every valid SKILL.md under it is served, test fixtures and examples included.

When two skills share a name, the first one found wins: sources in the order given, then sorted paths within a source. The server logs a warning naming both folders. This makes the order of --skills-dir a priority order, so a personal folder listed first can override one skill from a shared checkout.

Each --skip-installed-in folder is read flat, one skill per subfolder. A skill whose folder name or frontmatter name appears there is not served, since the agent already loads it. Matching is by name only, so a different skill that happens to share an installed name is left out too. There is no default skip folder; a missing one logs a warning, because it is most likely a typo.

The server rescans its sources on every tool call, so a skill added or changed during a session shows up at the next call with no restart. Only the skill names listed in find_skills's tool description are fixed at startup, because Codex ignores list_changed notifications. A new skill is therefore findable at once, but named in that description only from the next session.

The server refuses to start, with a message naming the paths, when a source is missing or unreadable, when no source holds a valid skill, or when every skill found is installed in a skip folder:

lazy-skills-mcp: skills source not found: /srv/skills

The agent then reports a failed MCP server rather than an empty catalog. Problems with single skills or folders, such as an invalid SKILL.md, an unreadable group, or a group past the depth limit, are logged and the scan goes on. All diagnostics go to stderr, since stdout carries the MCP protocol.

Interface Contract

Deployments pin a commit of this repository and script against the interface below. A change to any part of it breaks them at their next pin bump, so treat it as a breaking change and say so in the commit message.

  • The console command lazy-skills-mcp, and its exit status 1 with a message on stderr when it cannot serve any skill at startup.

  • Its repeatable --skills-dir DIR and --skip-installed-in DIR flags, and --print-skills-dir, which prints the resolved sources on stdout, one path per line.

  • The LAZY_SKILLS_MCP_SKILLS_DIR environment variable, its PATH-style list form, and the resolution order above.

  • The expansion of a leading ~ in every path the flags and the variable give.

  • The default source, $XDG_DATA_HOME/lazy-skills-mcp/skills, else ~/.local/share/lazy-skills-mcp/skills.

  • The layout rule: a folder holding SKILL.md is a skill, any other folder is a group, searched at least 8 levels deep.

  • The duplicate rule: the first skill found under a name is served, by source order and then walk order.

  • The skip rule: a skill whose folder name or frontmatter name appears in a skip folder is not served.

  • The tool names find_skills and load_skill, their arguments query and name, and their result fields: skills with each skill's name and description, and content, directory and files.

Troubleshooting

Check That the Server Starts

Run the command from the agent's registration in a terminal, with the same arguments. A server that cannot serve any skill prints the reason and exits with status 1. A healthy server prints its warnings, if any, and then waits silently for MCP messages on stdin; end it with Ctrl-D.

To see a real answer, send it a handshake and a find_skills call. The last line printed is the result, listing the skills it serves:

{
  printf '%s\n' \
    '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"check","version":"0"}}}' \
    '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
    '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"find_skills","arguments":{}}}'
  sleep 2
} | lazy-skills-mcp --skills-dir ~/src/agent-skills

The sleep keeps stdin open long enough for the reply; the server stops when its input ends.

Symptoms

  • lazy-skills-mcp: command not found, or the agent cannot start the command. uv's tool folder is not on PATH. Run uv tool update-shell, or register the absolute path that uv tool dir --bin names.

  • The agent lists the server as failed. Run the startup check above. The message names the source that is missing or unreadable, says that no source holds a valid skill, or says that every skill is installed in a skip folder.

  • A skill is missing from find_skills. The server logs a warning naming each skill it leaves out and why: a missing or invalid frontmatter field, a name that differs from its folder, a duplicate name, or a group past the depth limit. Run the server by hand to see them, or read the agent's MCP log. Then check the skip folders: a skill whose name is installed there is not served, by design.

  • A new skill is findable but not named in the tool description. The description is fixed when the server starts. Start a new agent session.

  • Python reports a missing or wrong version. The server needs Python 3.12 or newer. With uv, add --python 3.12 to uv tool install.

When an Agent Never Calls find_skills

Work down this list, since each step depends on the one before it:

  1. Confirm that the server starts, as above, and that the agent does not list it as failed.

  2. Confirm that the agent's live configuration registers the server.

  3. Confirm that the agent's instructions name the kinds of skill behind the server.

  4. Check the wording. The instruction line, the server's instructions, and both tool descriptions in src/lazy_skills_mcp/server.py are all the agent sees. If the request's domain is missing from the instruction line, the agent has no reason to search.

Contributing

CONTRIBUTING.md covers setting up a checkout, the checks, and the conventions. docs/releasing.md covers cutting a release. Planned work is in ROADMAP.md, and deferred ideas with their reasoning are in BACKLOG.md.

License

MIT.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    A
    maintenance
    Enables AI agents to search and retrieve over 89K skills on-demand at runtime, eliminating the need to manually install skills upfront.
    134
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables MCP clients to discover, search, and load agent skills from many sources, including other agents' skill directories, Claude Code plugin marketplaces, and remote git repositories, with no copying or syncing required.
    1,058 npm
    6
    MIT
  • A
    license
    A
    quality
    C
    maintenance
    Enables LLM agents to discover and search a catalog of skills, then fetch skill instructions and supporting references, scripts, and assets on demand.
    10
    MIT