npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@glidermcp/scout

v2.1.0

Published

Universal read-only code-intelligence MCP server: fuzzy and strict lexical search over any repository, any language.

Readme

@glidermcp/scout

Universal code-search MCP server for AI agents. It answers fuzzy and exhaustive lexical search over any repository and any language, from a resident, watcher-fresh index. It adds structural (syntax-aware) search where a grammar ships, and local semantic (embedding) search.

Documentation: https://glidermcp.com/scout

Install

Run directly:

npx -y @glidermcp/scout

Or add it to an MCP client configuration:

{
  "mcpServers": {
    "scout": {
      "command": "npx",
      "args": ["-y", "@glidermcp/scout"]
    }
  }
}

No Node? The same binary installs without it:

curl -fsSL https://glidermcp.com/install.sh | sh   # Linux/macOS
brew install glidermcp/tap/scout                   # Homebrew (macOS/Linux)

Tools

Scout speaks MCP over stdio and exposes three tools. find is the front door; the other two are operational.

find

Primary search over the workspace.

Strict modes (match: literal|regex|word) are exhaustive and return matches in a deterministic order. That is grep semantics over the whole workspace, and data.exhaustive: true confirms it. A strict search never truncates silently. It can hit a limit: a match-count cap, an oversized file, or the time budget. Scout then flips exhaustive to false, sets meta.partial, and marks paging.total as a floor.

fuzzy is ranked top-N with frecency and never exhaustive. target: auto routes by query shape, and every response echoes the resolved route in data.route. An explicit strict match routes auto to content, so query shape never overrules the mode you asked for. An explicit target keeps its route, and meta.degraded then names the match it did not use. A zero-hit strict search returns an honest empty result (success: true, no matches). Scout never falls back to fuzzy on its own; a hint suggests the retry instead.

Scout indexes the workspace honoring .gitignore/.ignore (like rg), and — unlike rg's default — also indexes non-gitignored hidden files (.github/, .vscode/, .env.example) so they're searchable; .git/.glider stay excluded. Set index-hidden = false in .glider/scout/config.toml for exact rg scope.

Scout also honors the repository's core.ignorecase, which rg does not read. Git folds case on Windows and on a case-insensitive macOS volume. A .gitignore line that reads packages/ therefore excludes a Packages/ directory, and scout excludes it too. Without this rule, scout indexes restored dependencies that git check-ignore reports as ignored. server_status reports the resolved value under membership. Set gitignore-case-insensitive in .glider/scout/config.toml to overrule the detection.

| Parameter | Values (default first) | Notes | | --- | --- | --- | | query | (required) | /re/ forces regex, "quoted" forces literal | | target | auto, files, content, symbols, structural, semantic | auto routes by query shape; a strict match routes auto to content | | match | auto, fuzzy, literal, regex, word | auto: fuzzy for files, literal for content; symbols use a deterministic name match (not fuzzy) | | case | auto, sensitive, insensitive | auto = smart-case (sensitive iff the query has an uppercase character) | | scope | pathPrefix, globs, languages | globs prefixed with ! exclude; languages like rust, typescript, csharp | | skip / take | 0 / 50 | take clamped to 200 | | maxPreviewChars | 200 | preview truncation | | pathStyle | relative, absolute | paths are workspace-relative, forward-slash, 1-based line/column |

Examples:

{ "query": "usrctrl" }                                      // fuzzy file/identifier hop, ranked
{ "query": "/fn handle_\\w+/", "target": "content" }        // exhaustive regex over content
{ "query": "timeout", "target": "content", "match": "word",
  "scope": { "globs": ["src/**", "!**/tests/**"] } }        // exhaustive word match, scoped
{ "query": "\"exact phrase\"" }                             // forced literal

structural matches code by shape rather than text, using ast-grep patterns ($NAME for one node, $$$ for many):

{ "query": "fn $NAME($$$) -> Option<$T>", "target": "structural" }
// -> crates/scout-retrieval/src/chunk.rs:27
//    fn chunk(&self, path: &str, bytes: &[u8]) -> Option<Vec<Chunk>>;

symbols returns a declaration outline; every match carries a symbol:

{ "query": "ProjectPath", "target": "symbols", "scope": { "languages": ["csharp"] } }
// -> "symbol": { "name": "ProjectPath", "kind": "property", "container": "TempCodeFixProject" }

semantic answers a natural-language question by fusing embedding search with a lexical ranking over the same chunks — see Semantic search.

Both syntax-aware targets need a linked grammar. These nine ship; every other language answers lexically and says so in meta.degraded:

| Grammar | Extensions | Symbol kinds | | --- | --- | --- | | rust | .rs | function, method, struct, enum, trait, type, module | | typescript | .ts .mts .cts .tsx | function, method, class, interface, enum, type, namespace | | csharp | .cs | function, method, class, struct, interface, enum, type, namespace, property, event | | javascript | .js .mjs .cjs .jsx | function, method, class | | python | .py .pyi | function, method, class | | go | .go | function, method, struct, interface | | java | .java | method, class, interface, enum | | ruby | .rb | function, method, class, module | | markdown | .md .markdown | section |

Kinds differ because the languages do — only C# has properties and events, only Rust has traits. Ask server_status for the list this build actually links.

Degradation is always visible. Asking for symbols where no grammar applies still answers, and says what happened:

{ "query": "Widget", "target": "symbols", "scope": { "globs": ["**/*.yml"] } }
// route:    { "target": "symbols", "tier": "lexical", "match": "fuzzy" }
// degraded: "symbols tier has no grammar for this scope (this build parses rust,
//            typescript, csharp, javascript, python, go, java, ruby,
//            markdown); answered
//            with lexical fuzzy identifier search"

data.route always names the tier that actually served the query.

server_status

Reports index, watcher, and tier health; detected sibling compiler servers (glider/tglider); on-disk store size; and license and telemetry state.

sync

Flushes pending watcher changes into the index now; {"full": true} forces a complete re-scan. Rarely needed — every query self-flushes via the freshness gate.

Semantic search

Semantic search is off by default, because enabling it embeds the whole workspace in the background and that cost grows with the tree. Turn it on with --semantic in your MCP client's args, or enabled = true under [semantic].

On the first start after you enable it, scout downloads one model (snowflake-arctic-embed-xs, ~86 MiB) into ~/.glidermcp/models/ and verifies every file against a checksum built into the binary. Every repository on the machine shares that download, so it happens once per user.

find keeps working while the download runs. Semantic queries answer lexically and set meta.degraded, and server_status reports the tier state, so you can tell "not ready yet" from "misconfigured".

It answers with two rankings, not one. Embeddings find text that means the same thing. A lexical index over the same chunks finds text that says the same words. Fusion is the safer choice rather than the sharper one. It keeps the embedding ranking where a question shares little vocabulary with its answer, and the lexical ranking where the words match. data.route.tier says hybrid when both legs contributed, and semantic when only the embeddings did.

The score is not a similarity. It is 1/(60 + rank), summed over the legs that ranked a chunk, so it depends only on positions. It never exceeds 0.0333. Above 0.0167, both legs found the result. A lower score tells you nothing either way. No score tells you how close the text is to your query.

| Key | Default | Notes | | --- | --- | --- | | enabled | false | Set true — or pass --semantic — to turn the tier on. The first enabled start downloads the model. | | model | snowflake-arctic-embed-xs | The model to use, and the directory it lives in. | | model-path | (unset) | Explicit model directory. Set this to use a model you provisioned yourself — scout will not download when the files are already there, which is also how to run fully offline. | | device | auto | auto, cpu, or metal — see Apple Metal. | | top-k | 20 | Default number of results a semantic query returns. | | chunk-size / chunk-overlap | 40 / 10 | Chunk window, in lines. | | exclude | (empty) | Globs of files to keep out of the vector store, on top of the built-in list. | | include | (empty) | Globs to embed even if the built-in list or your exclude would refuse them. |

Apple Metal

On Apple silicon (darwin-arm64), device = "metal" embeds on the GPU. It does not finish sooner. It costs far less CPU: measured on an M1 Pro, 0.1 effective cores against 6.7 on the CPU.

Choose metal when scout shares a machine with your real work. Keep the default when you want the index ready soonest. The two devices produce equivalent vectors rather than identical ones, and the device is not part of the store identity, so switching never re-embeds. Any other build falls back to the CPU. server_status.tiers.semantic.device names the device that ran, and deviceNote gives the reason for a fallback.

Select what the tier embeds

Scout already withholds the files that answer nothing. The list covers lockfiles, vendored trees, minified bundles, generated sources, and translation catalogues. It also covers committed package-manager payloads: a restored NuGet package, .yarn/releases/, Yarn PnP tables, bower_components/, site-packages/, and Gradle's wrapper.

That last group reaches the tier only when a repository commits it. Scout never indexed anything .gitignore covers. The NuGet rule keys on the <Id>/<Version>/lib/ shape, not on a folder named packages. Your own packages/ source therefore stays embedded, in a JS monorepo or a Unity project alike.

Every repository holds something that list has not met yet. server_status.tiers.semantic finds it for you. costliestFiles names the files with the most chunks. withdrawn counts the files with no chunks, by reason.

[semantic]
exclude = ["local-publish/**", "**/*.snapshot.json"]
include = ["vendor/our-fork/**"]

An include glob wins over an exclude glob. Both win over the built-in list. Use include to re-admit a file scout withholds by default, such as a generated client that people ask about.

SCOUT_SEMANTIC_EXCLUDE and SCOUT_SEMANTIC_INCLUDE take the same globs, separated by semicolons. Use them for a trial or a CI run. They add to the lists in the config file. The config file is the better answer for a lasting change, because the repository keeps it and a reviewer can read it.

A change to either list re-embeds the workspace one time, because a per-file content hash cannot see which files hold chunks. The tier answers lexically while it rebuilds, as it does on any first start.

A scout upgrade rebuilds the store for the same reason, when a release changes how files are cut into chunks. The release notes say so when it happens.

Query time is always offline: the one-time download is the only network access, and no MCP tool call ever triggers it.

Workspace root and git worktrees

Scout resolves its workspace root in this order: the --root argument, else the git repository or worktree containing the working directory, else the working directory itself.

So omit --root and one config serves the main checkout and every git worktree of it, from any subdirectory. This needs a client that starts the server in your project, which project-scoped configs do (Claude Code .mcp.json, Codex project entries, Cursor, VS Code). Claude Desktop has only a global config, so pin --root there.

Each root keeps its own index under its own .glider/scout/. A new worktree therefore builds its index from scratch rather than sharing the main checkout's; nothing is copied between them. The embedding model is the exception: it lives once per user under ~/.glidermcp/models/, so enabling the semantic tier in a second worktree costs the embedding pass, not the download.

One process serves one root for its lifetime. To point scout at a different repository, restart it.

Working with glider and tglider

If you run glider (C#) or tglider (TypeScript/JavaScript), prefer it for its language. Scout covers every language as the universal fallback, and names the sibling server when one owns the hit's language.

Text search is the exception. tglider ships none, and glider's search_text reads only the documents its workspace loaded. Add scout as its own MCP server to search the whole repository.

Scout ships this routing rule in its own MCP instructions, which many clients pass to the agent automatically. If yours does not, the setup guide carries a system-prompt snippet to paste.

CLI flags

--root <path>      workspace root. Optional; defaults to the git repository or
                   worktree containing the directory scout starts in, else that
                   directory. Pass it when your client starts scout outside the
                   repository.
--semantic         turn the semantic tier on: one-time model download, then embedding
--no-telemetry     disable telemetry for this run
--version          print the version and exit

Version expiration

Each scout release is valid for one month from its release date; it warns when 7 or fewer days remain and refuses to start once expired. To guarantee the latest release, use an explicit @latest: npx -y @glidermcp/scout@latest, or update a global install with npm install -g @glidermcp/scout@latest. Without @latest, npx reuses a locally installed copy when one exists in the workspace.

Platform support

This package resolves a prebuilt native binary from the matching platform package, installed automatically as an optional dependency:

| Package | Platform | | --- | --- | | @glidermcp/scout-linux-x64 | Linux x64 (static musl — works on any distro) | | @glidermcp/scout-linux-arm64 | Linux arm64 (static musl) | | @glidermcp/scout-darwin-x64 | macOS Intel | | @glidermcp/scout-darwin-arm64 | macOS Apple Silicon | | @glidermcp/scout-win32-x64 | Windows x64 |

Troubleshooting

  • Binary fails to resolve after install — your lockfile was likely generated on a different platform and omitted this platform's optional dependency. Remove node_modules and the lockfile, then reinstall.
  • SCOUT_BINARY_PATH overrides resolution with an explicit binary path (useful for dev builds).

Read-only and privacy

Scout never mutates workspace source. Its only writes are its own index state under .glider/scout/ (self-excluded from git status via a one-time git exclude entry) and shared per-user state under ~/.glidermcp. Telemetry is anonymous and can be disabled with DO_NOT_TRACK=1 or --no-telemetry.

Searching is local and offline: no query ever leaves the machine. Scout makes exactly two kinds of network request, both outside the tool surface and neither triggered by a tool call, so every tool is annotated openWorldHint: false:

  • anonymous telemetry (above), and
  • the one-time embedding-model download described under Semantic search, which happens only if you enable the semantic tier.

A default scout downloads nothing, so --no-telemetry alone leaves it with no network access at all. Searching keeps working; find target=semantic answers lexically and says so.

License

Free for personal use, open-source work, education, and a 30-day organizational evaluation under the GliderMCP EULA. Commercial use requires a paid license once plans are on sale; until then the EULA permits it free of charge. The full terms are in the LICENSE file inside this package.

Documentation: https://glidermcp.com/scout