Skip to main content
Any Framework

An MCP server that catalogs the command-line tools available on the current machine (availability, shadowing, version, capabilities) and suggests how to install missing ones.

Published
Jul 16, 2026
3mo ago
Total Downloads
278
278

Install

dotnet add package CliCatalog.Mcp --version 0.1.3

No framework information available.

README

CLI Catalog MCP Server

An MCP server that catalogs the command-line tools available on the current machine β€” what exists, where it lives, which copy actually runs, its version/identity, and (on demand) what it can do β€” and, when a tool is missing, how to install it.

It exposes a single, self-describing tool, get_clis, designed to be cheap enough to keep in an agent's context on every turn.

Source code is maintained in a separate repository β€” github.com/dotutils/list-cli-mcp-impl β€” which is currently private.

See it in action

An agent is asked to fetch data from Azure DevOps. Without a catalog of what's installed, it can't tell that the machine already has the az CLI (with the azure-devops extension) that would answer the question β€” so it gives up or guesses. With this server in context, the agent discovers az via get_clis, and just runs it.

Without the MCP β€” doesn't realize az is available With the MCP β€” finds and uses the az CLI
Copilot without the CLI Catalog MCP: it fails to realize the az CLI can reach Azure DevOps Copilot with the CLI Catalog MCP: it discovers the az CLI via get_clis and uses it to query Azure DevOps

What it's good for

  • Stop guessing whether a CLI exists. Before an agent runs rg, docker, gh, jq, kubectl, … it can check availability instantly instead of failing on a missing command.
  • Explain shadowing. When the same command lives in several PATH directories, it reports the winner and the shadowed copies β€” the answer to "why am I getting the wrong python?".
  • Capability discovery. Ask by intent ("json diff", "container runtime") and get a ranked shortlist. When the client supports MCP Sampling, results are ranked semantically by the client's model.
  • Install suggestions. A miss returns typo corrections ("did you mean rg?") and per-manager install commands (winget / scoop / brew / apt) β€” as advisory text only. Beyond the bundled catalog, a miss also consults live package managers (winget on Windows; npm on any platform) so tools outside the curated list still get an install suggestion (source: "online"). On by default; opt out with CLICATALOG_ONLINE_INSTALL_SEARCH=0, and suppressed entirely under execution-policy=never.
  • Onboarding / environment diagnostics. A fast, structured inventory of a dev box, CI runner, or container.

How it works

Discovery is tiered so callers pay only for the depth they need:

Depth Answers Cost
existence (L1, default) name, absolute path, kind, PATH shadowing instant, no execution
identity (L2) version, file hash, architecture moderate; non-executing sources first
capability (L3) description, subcommands, flags opt-in; --help probing only with allowExec

Safe by default: L1 never executes anything; L2 prefers non-executing sources (Windows PE version resource, file metadata); L3 execution is opt-in, time-boxed, and sandboxed-in-intent (closed stdin, disabled pager, hard timeout, output cap). The server never installs or modifies anything.

Requirements

Build & run

dotnet build list-cli-mcp.slnx -c Release
dotnet run --project src/CliCatalog.Mcp        # starts the stdio server (waits for an MCP client)

Run as a .NET tool (dnx / global install)

The host is published to NuGet.org as a .NET tool (command name cli-catalog-mcp, package id CliCatalog.Mcp), so it can be run without a persistent install via dnx (the .NET 10 one-off tool runner, similar to npx). It is downloaded and cached on first use:

dnx CliCatalog.Mcp --yes           # latest published version
dnx [email protected] --yes     # or pin a specific version

Or install it once and get a cli-catalog-mcp command on your PATH:

dotnet tool install -g CliCatalog.Mcp             # from NuGet.org
cli-catalog-mcp                                    # starts the stdio server

Use it from an MCP client (e.g. VS Code / Copilot)

Point your client at the server over stdio. The smallest config uses dnx, which downloads and runs the published package on demand β€” no install step. --yes skips the download confirmation prompt (required because the client runs the server non-interactively):

// .vscode/mcp.json
{
  "servers": {
    "cli-catalog": {
      "type": "stdio",
      "command": "dnx",
      "args": ["CliCatalog.Mcp", "--yes"]
    }
  }
}

If you installed it globally (dotnet tool install -g CliCatalog.Mcp), point at the command directly:

{
  "servers": {
    "cli-catalog": {
      "type": "stdio",
      "command": "cli-catalog-mcp"
    }
  }
}

For local development against a source checkout, run it via dotnet run:

{
  "servers": {
    "cli-catalog": {
      "type": "stdio",
      "command": "dotnet",
      "args": ["run", "--project", "src/CliCatalog.Mcp", "-c", "Release"]
    }
  }
}

The get_clis tool

All parameters are optional; the mode is chosen by which you pass:

Param Type Default Purpose
name string | string[] β€” Check/inspect specific command(s); a miss adds corrections + install options.
query string β€” Discover tools by capability; returns a ranked shortlist.
depth existence | identity | capability existence How much detail to return.
scope installed | installable | both installed Search installed tools and/or known catalogs.
cursor string β€” Opaque pagination token from a previous nextCursor.
allowExec bool false Permit --help/--version probing when no non-executing source exists.

Behavior by input:

  • no arguments β†’ list installed commands (paginated).
  • name β†’ resolve the winner + full shadowing chain + details at depth; a miss returns did-you-mean + install options.
  • query β†’ ranked shortlist (semantic when Sampling is available, otherwise lexical full-text).

Example β€” a miss with correction + install options:

{
  "results": [{
    "name": "ripgrepp", "status": "not-found",
    "didYouMean": [{ "name": "rg", "package": "ripgrep", "distance": 1 }],
    "install": [{ "manager": "winget", "id": "BurntSushi.ripgrep.MSVC", "command": "winget install BurntSushi.ripgrep.MSVC" }]
  }],
  "hints": ["Pass scope=installable to search tools you could install."]
}

Example β€” a miss for a tool outside the bundled catalog, answered by the live winget search (source: "online"):

{
  "results": [{
    "name": "eza", "status": "not-found",
    "install": [{ "manager": "winget", "id": "eza-community.eza", "command": "winget install eza-community.eza" }],
    "source": "online", "confidence": 0.55
  }]
}

Results are structured JSON only, and every capability/identity field is tagged with its source (and confidence where applicable) so agents know how a value was derived.

Configuration (environment variables)

Operator-facing, read at startup:

Variable Meaning
CLICATALOG_INCLUDE_PATHS Explicit PATH-separated dirs to scan (skips the process PATH unless combined with the next).
CLICATALOG_ALSO_SCAN_PROCESS_PATH 1/true to also scan the process PATH alongside includes.
CLICATALOG_EXCLUDE_PATHS PATH-separated dirs to skip.
CLICATALOG_EXECUTION_POLICY never | on-demand (default) | allowlist.
CLICATALOG_EXEC_ALLOWLIST / CLICATALOG_EXEC_DENYLIST Comma-separated command names for allowlist policy.
CLICATALOG_ONLINE_INSTALL_SEARCH 0/false to disable the live package-manager install search (winget / npm) on a miss. On by default.
CLICATALOG_ONLINE_INSTALL_TIMEOUT_MS Timeout for a single online install-search probe (default 10000).
CLICATALOG_PAGE_SIZE Page size for the no-arg list.
CLICATALOG_CACHE_PATH SQLite cache path, or memory for an in-memory cache. Defaults to a per-user cache dir.

Project layout

src/CliCatalog.Core   # scanning, cache (SQLite + FTS5), change detection, enrichment, sampling β€” no MCP dep
src/CliCatalog.Mcp    # stdio host: the get_clis tool, resources, list_changed notifier
tests/                # unit, exec-hazard/security, and stdio end-to-end tests
docs/                 # design & implementation plan

Planned / not yet implemented

The server is useful today (L1–L3 discovery, lexical + Sampling-based query, install suggestions), but several higher-fidelity features from the design plan are still ahead:

  • Bridge to completion-spec databases for high-fidelity capabilities. Instead of scraping --help, pull structured subcommands/flags/descriptions from the existing completion corpora β€” carapace (carapace <cmd> export, ~1000+ commands, millisecond exports) and bundled Fig / Amazon Q specs (400+ popular CLIs). These are the well-known "tool description" databases that power shell autocompletion, giving accurate L3 data mostly without executing the target.
  • Semantic search over the catalog (local embeddings). Layer an optional, offline ONNX embedding retriever (e.g. bge-small / MiniLM) onto the existing FTS5 query mode for a hybrid lexical+semantic match β€” so intent queries like "container runtime" rank well even without a client model. Off by default.
  • Richer provenance resolvers. Map each binary back to its owning package manager (winget / scoop / choco, apt / dnf, brew, command-not-found) β€” non-executing where possible β€” to answer "who installed this node?" and to strengthen install suggestions.
  • Trust & tamper signals. Per-entry signature/hash verdicts (WinVerifyTrust / codesign / dpkg -V / rpm -V) by default, with opt-in network attestation (Sigstore / SLSA) and an OSV/NVD vulnerability overlay; Elicitation-gated warnings for tampered / untrusted binaries. Includes a learned-spec store that persists inferred capability specs keyed by (path, sha256, version).
  • Push-based change detection. Optional FileSystemWatcher invalidation with richer list_changed diffs, beyond the current TTL + on-miss refresh.
  • Runtime guard companion (out of scope for v1). A separate shell-hook / PATH-shim component that queries this server's trust oracle before commands run β€” documented, not built here.

See docs/design-and-implementation-plan.md for the full design, rationale, and roadmap.

Changes from Previous Version

No structural changes between v0.1.0 and v0.1.3.

Adoption Assessment

Assess this package against its supported frameworks, license, maintenance signals and dependency graph before making it a project standard.

No SPDX license expression is published. Review the license text and your organisation's policy before redistribution.No target framework metadata is available. Confirm compatibility in a representative project before standardising on this package.

Related Guides & Workflows

Learn how to evaluate, integrate, or audit this package in your .NET project.