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

codebridge-mcp

v5.0.0

Published

AI-friendly MCP server for navigating any TypeScript or JavaScript codebase

Readme

Codebridge

An MCP (Model Context Protocol) server that gives AI assistants a structured, queryable view of any TypeScript or JavaScript project — single-package repos or large monorepos — without needing to read thousands of files.

Installation

npm install -g codebridge-mcp

Then build the index for your repo and connect it to Claude Code — see Setup below.


The Problem

Large codebases have tens of thousands of source files and hundreds of thousands of symbols. Asking an AI to "understand the codebase" by reading files is slow, expensive, and context-limited. The Codebase Interface Layer solves this by pre-indexing the repo into four JSON files and exposing them as tools Claude can call directly.

Works with any JS/TS project: single-package repos, monorepos (Yarn/npm/pnpm workspaces, Lerna, Turborepo, Nx), or any custom layout. Both ESM and CommonJS are supported.

Why MCP tools beat grep

The fundamental difference: grep treats code as text. MCP treats code as a graph.

Code is a graph of relationships — functions call functions, types reference types, modules import modules, packages depend on packages. grep is blind to this graph.

1. Understands re-exports and aliases

A symbol has one identity but potentially many names across the codebase:

// pkg-types/index.ts
export { FindRecipientPersonaType } from './types/FindRecipientPersonaType';

// pkg-ui/index.ts
export { FindRecipientPersonaType } from 'pkg-types';

// consumer file
import { FindRecipientPersonaType } from 'pkg-ui'; // same type, different import path

grep finds the string FindRecipientPersonaType. MCP finds the symbol — regardless of which barrel it came through.

2. Returns structured results, not raw text

find_call_sites gives you file + line number + code snippet for every real invocation — already filtered to actual call sites (fn(, <Component, new Foo(). grep returns every line matching a pattern, including comments, imports, type annotations, and strings — you sift through noise.

3. Semantic symbol resolution

get_type_definition resolves a type name across the entire monorepo index in one call. With grep you'd search for the definition, find 10 matches (re-exports, type aliases, interface merges), and manually determine which is canonical.

4. Transitive impact analysis

grep can find direct usages. It cannot answer: "if I change this type's shape, which packages break downstream?"

Type T (pkg-types)
  └─ used by PackageA
       └─ re-exported by PackageB
            └─ consumed by PackageC  ← grep never finds this

find_impact walks the dependency graph. grep only sees one hop.

5. Package-boundary awareness

find_file_package, search_packages, get_package_info understand the monorepo's workspace graph. grep has no concept of package ownership — you'd have to infer it from directory paths and traverse package.json files manually.

6. Natural language queries

search_description lets you ask "where is the zero-query search logic?" without knowing any symbol names. grep requires you to already know what you're looking for.

7. Eliminates the cold-start problem

When entering an unfamiliar area, get_file_context gives you a curated map of a file's symbols, imports, and importers in one call. With grep you'd spend multiple rounds building a mental model manually.

8. Indexed, not scanned

The MCP tools query a pre-built semantic index (like a language server). grep does a full file scan every time — slower on a large monorepo, and blind to semantics.

When grep/Glob is still the right tool

| Situation | Use | |---|---| | Content-level searches (specific string literal, regex pattern) | grep | | Searching comments or log messages | grep | | You know the exact file and just need a line number | grep | | MCP returns no results (private/protected members, instance method calls) | grep | | Searching across file types MCP doesn't index | grep |


Architecture

┌──────────────────────────────────────────────────────────────────────────┐
│                             monorepo root                                │
│                                                                          │
│  packages/*/package.json   ──┐                                           │
│  packages/*/src/index.ts   ──┤                                           │
│  packages/*/**/*.ts(x)     ──┤──► indexBuilder.ts                        │
│  apps/*/**/*.ts(x)         ──┤         │                                 │
│  libs/*/**/*.js(x)         ──┘         ▼                                 │
│                                 ┌────────────────┐                       │
│                                 │    data/       │                       │
│                                 │  graph.json    │  package dependency   │
│                                 │  symbols.json  │  package-level exports│
│                                 │  files.json    │  file-level index     │
│                                 │  types.json    │  type definition bodies│
│                                 └───────┬────────┘                       │
│                                         │                                │
│                                    store.ts (load/cache)                 │
│                                         │                                │
│         ┌──────────┬──────────┬─────────┼─────────┬──────────┬────────┐  │
│         ▼          ▼          ▼         ▼         ▼          ▼        ▼  │
│    buildIndex searchPkgs getPkgInfo searchSym findImpact searchFile  ... │
│                                         │                                │
│                                    index.ts (MCP server)                 │
│                                    stdio transport                       │
└─────────────────────────────────────────┼────────────────────────────────┘
                                          │
                                    Claude Code
                               (calls tools by name)

Four-phase index build (run once)

npm run build-index walks your workspace package directories and writes four files:

| File | Contents | | ------------------- | ---------------------------------------------------------------- | | data/graph.json | All packages, dependency edges, reverse dependents map | | data/symbols.json | Symbols exported from each package's barrel file (index.ts) | | data/files.json | Every source file, symbols, import graph, reverse importedBy | | data/types.json | Full declaration bodies for every interface/type/enum/schema |

All query tools load these files once into memory (cached). Subsequent calls are in-process lookups — no file scanning.


Setup

1. Install

# Recommended — global install from npm
npm install -g codebridge-mcp

# Or build from source
git clone https://github.com/your-org/codebridge-mcp
cd codebridge-mcp && npm install && npm run build

2. Configure for your monorepo

The indexer auto-detects your workspace structure with no configuration required for most setups. Configuration is resolved in this priority order:

Auto-detection (zero config)

Single-package repos are detected automatically — if no workspace packages are found, the repo root package.json is treated as the single package and all source files under the root are indexed.

Monorepos are detected by reading your existing package manager config:

| Config file | Field read | |---|---| | package.json | workspaces (Yarn / npm workspaces) | | pnpm-workspace.yaml | packages list | | lerna.json | packages field | | (fallback) | ['packages', 'shared'] |

For barrel export detection (which file in each package is the public API), the indexer reads each package's package.json main, module, exports, and types fields to derive the source path, then falls back to src/index.ts, index.ts, src/index.js, index.js.

Examples that work with zero config:

# Yarn / npm workspaces in package.json:
{ "workspaces": ["packages/*", "apps/*"] }

# pnpm-workspace.yaml:
packages:
  - 'packages/*'
  - 'apps/*'
  - 'libs/*'

# lerna.json:
{ "packages": ["packages/*", "apps/*"] }

Explicit override — .codebase-index.json

Place this file in your monorepo root to override any auto-detected setting:

{
  "packageDirs": ["packages", "apps", "libs", "services"],
  "indexFiles": ["src/index.ts", "src/main.ts", "index.ts"],
  "skipDirs": ["coverage", "fixtures", "e2e"]
}

| Field | Default | Description | |---|---|---| | packageDirs | auto-detected | Directories under repo root that contain workspace packages | | indexFiles | auto-detected per package | Barrel export filenames to scan for public API symbols | | skipDirs | [] | Additional directory names to skip when walking the file tree (added to the built-in skip list) |

The built-in skip list already excludes: node_modules, .git, dist, build, lib, obj, .yarn, .cache, coverage, .turbo, .nx, .next, .nuxt, out, storybook-static.

3. Build the index

Full index (entire monorepo)

# Run from the monorepo root
npm run build-index

# Run from anywhere — point at the repo with --root
npm run build-index -- --root /path/to/my-monorepo

# Or via environment variable
CODEBASE_ROOT=/path/to/my-monorepo npm run build-index

Scoped index (one root package + its transitive deps)

Use --scope to limit indexing to a single package and everything it depends on. Useful for large monorepos where a full build takes too long.

# by exact package name
npm run build-index -- --scope my-ui-package

# by file path — resolves to the owning package automatically
npm run build-index -- --scope packages/ui/src/components/Button.tsx

# by directory path inside the package
npm run build-index -- --scope packages/ui/src/components

# include devDependencies in the transitive closure (default: runtime deps only)
npm run build-index -- --scope my-ui-package --dev-deps

# scoped build against a specific repo root
npm run build-index -- --root /path/to/my-monorepo --scope my-package-name

Run npm run build-index at any time to restore the full index.

Flag reference

| Flag | Description | | ----------------- | --------------------------------------------------------------------------------------------------- | | --root <path> | Target repo directory. Defaults to CODEBASE_ROOT env var, then process.cwd() | | --scope <value> | Limit to one root package + its transitive deps. Accepts package name, file path, or directory path | | --dev-deps | Also follow devDependencies when collecting the transitive closure (only with --scope) |

4. Connect to Claude Code

If installed globally via npm, use codebridge-mcp as the command directly:

{
  "mcpServers": {
    "codebridge-mcp": {
      "command": "codebridge-mcp",
      "env": {
        "CODEBASE_ROOT": "/path/to/my-repo"
      }
    }
  }
}

If running from a local build, point at the compiled file:

{
  "mcpServers": {
    "codebridge-mcp": {
      "command": "node",
      "args": ["/path/to/codebridge-mcp/build/index.js"],
      "env": {
        "CODEBASE_ROOT": "/path/to/my-repo"
      }
    }
  }
}

Restart Claude Code to pick it up. Approve the server when prompted.


Language support

The indexer extracts symbols and imports from:

| Language | Extensions | Module formats | |---|---|---| | TypeScript | .ts, .tsx | ESM (import/export) | | JavaScript | .js, .jsx, .mjs, .cjs | ESM + CommonJS (require/module.exports) |

The following file types are tracked in the index (path only, no symbol extraction):

.scss, .css, .less, .json, .md, .mdx, .svg, .graphql, .gql


Data Model

graph.json — package dependency graph

{
  "packages": {
    "my-utils": {
      "name": "my-utils",
      "path": "packages/utils/my-utils",
      "dependencies": ["my-types", "my-config"],
      "devDependencies": []
    }
  },
  "dependents": {
    "my-utils": ["my-ui", "my-services"]
  },
  "builtAt": "2026-01-01T10:00:00.000Z"
}

symbols.json — package-level exported symbols

Only covers symbols re-exported from barrel files (index.ts, index.js, or whatever is detected per package).

{
  "bySymbol": {
    "Button": ["my-ui"],
    "formatDate": ["my-utils"]
  },
  "byPackage": {
    "my-utils": [
      { "name": "formatDate", "isType": false },
      { "name": "DateRange", "isType": true }
    ]
  },
  "builtAt": "..."
}

files.json — file-level index

{
  "files": {
    "packages/utils/my-utils/src/formatDate.ts": {
      "path": "packages/utils/my-utils/src/formatDate.ts",
      "package": "my-utils",
      "description": "Date formatting utilities.",
      "symbols": ["formatDate", "DateRange"],
      "symbolKinds": {
        "formatDate": "function",
        "DateRange": "type"
      },
      "symbolDocs": {
        "formatDate": "Formats a Date into a locale string."
      },
      "pkgImports": ["date-fns"],
      "fileImports": ["../utils/locale"]
    }
  },
  "bySymbol": { "formatDate": ["packages/utils/my-utils/src/formatDate.ts"] },
  "byPackage": { "my-utils": ["packages/utils/my-utils/src/formatDate.ts", ...] },
  "importedBy": { "packages/utils/my-utils/src/formatDate.ts": ["packages/ui/my-ui/src/DatePicker.tsx"] },
  "builtAt": "..."
}

Symbol kind classification

| Kind | Covers | | ----------------------- | ---------------------------------------------------------------------------------------- | | schema | const whose name ends in Schema/Contract/Validator/Payload/Request/Response, or whose value uses Zod/Yup calls | | interface | TypeScript interface declarations | | type | TypeScript type aliases | | enum | enum / const enum | | class | class / abstract class | | function | function / async function | | const / let / var | Everything else | | method | Class member method (all visibilities: public, protected, private) | | property | Class member property | | getter / setter | Class accessor methods |

Class members are indexed with qualified names ClassName.memberName.


MCP Tools (14 total)

Package-level tools

build_index

Scans the entire repo and writes all four data files. Automatically skipped when a full index already exists — only re-run after package changes.

build_index()
→ Index built successfully
    Packages indexed       : 312
    Package-level symbols  : 4821
    Source files indexed   : 8103
    File-level symbols     : 11294
    Type definitions       : 3840

build_scoped_index

Build a focused index for one package and all its transitive dependencies. Accepts a package name, a file path, or a directory path — all resolve to the owning package automatically.

build_scoped_index({ packageName: "my-ui-package" })
→ Scoped index built for "my-ui-package"
    Root package   : my-ui-package
    Total packages : 87  (transitive closure)
    Source files   : 2341
    Symbols        : 5102

All query tools now operate on this scoped dataset.
Run build_index to restore the full repo index.

search_packages

Fuzzy-search packages by name or path fragment.

search_packages({ query: "button" })
→ my-button          path: packages/ui/my-button
→ my-icon-button     path: packages/ui/my-icon-button

get_package_info

Full details for one package: path, deps, dependents, exported symbols.

get_package_info({ packageName: "my-utils" })
→ Package: my-utils
  Path:    packages/utils/my-utils
  Used by: 24 packages
  Exports: formatDate, parseDate, DateRange, ...

search_symbol

Find which package publicly exports a symbol (via its barrel file).

search_symbol({ symbol: "Button", exact: true })
→ Button  [class]  from: my-ui

find_impact

Blast-radius analysis — all packages that transitively depend on a given package.

find_impact({ packageName: "my-utils" })
→ Total impacted: 24  |  Direct: 8  |  Indirect: 16

find_file_package

Given any file path, identify its owning package. Walks up the directory tree — no index required.

find_file_package({ filePath: "packages/utils/my-utils/src/formatDate.ts" })
→ Package: my-utils  |  Used by 24 packages

File-level tools

search_file

Find any source file by filename or path fragment.

search_file({ query: "formatDate" })
→ packages/utils/my-utils/src/formatDate.ts
    package: my-utils
    symbols: formatDate, DateRange

search_deep_symbol

Find the exact file that defines any symbol — including internal helpers never re-exported from index.ts.

search_deep_symbol({ symbol: "useButtonState" })
→ useButtonState
    packages/ui/my-button/src/hooks/useButtonState.ts  [my-button]

get_type_definition

Look up the full declaration body of any TypeScript interface, type alias, enum, or Zod/Yup schema.

get_type_definition({ query: "ButtonProps" })
→ ── ButtonProps  (interface)  [my-button]
     packages/ui/my-button/src/types/ButtonProps.ts

     export interface ButtonProps {
       label: string;
       onClick?: () => void;
       disabled?: boolean;
       variant?: 'primary' | 'secondary';
     }

search_description

Find components and files by describing what they do in plain English.

search_description({ query: "formats date for display" })
→ packages/utils/my-utils/src/formatDate.ts  (score: 34)
    summary : Utilities for formatting dates for UI rendering.
    symbols : formatDate, parseDate, DateRange

get_file_context

Full context for a single file: symbols it defines, what it imports, and what imports it.

get_file_context({ filePath: "formatDate" })
→ File:    packages/utils/my-utils/src/formatDate.ts
  Package: my-utils

  Symbols defined (2):
    formatDate, DateRange

  Imports from packages (1):
    date-fns

  Imported by (3 files):
    packages/ui/my-ui/src/DatePicker.tsx  [my-ui]
    ...

find_usages

Find every file that imports a specific symbol. Traverses barrel re-export chains.

find_usages({ symbol: "Button" })
→ Found 18 file(s) importing "Button"

  my-app (3 files):
    packages/app/my-app/src/pages/Home.tsx
    packages/app/my-app/src/components/Toolbar.tsx
    ...

find_call_sites

Find files that actually use a specific function, component, or class — not just files that import it. Returns real usage lines with line numbers.

find_call_sites({ symbol: "formatDate" })
→ Found 7 file(s) calling "formatDate":

  my-ui (2 files):
    packages/ui/my-ui/src/DatePicker.tsx
      L42: const display = formatDate(value, 'MMM d, yyyy');
    packages/ui/my-ui/src/Calendar.tsx
      L88: label={formatDate(date)}

Typical agent workflow

Tracing a change's blast radius

User: "I need to change the DateRange type"

Claude:
  1. search_symbol("DateRange")
     → my-utils

  2. find_impact("my-utils")
     → 24 packages affected

  3. get_type_definition("DateRange")
     → full type body

  4. find_usages("DateRange")
     → every file that imports it

  5. Edit the type, fix downstream type errors

Exploring an unfamiliar area

User: "Find the button hover animation logic"

Claude:
  1. search_description({ query: "button hover animation" })
     → packages/ui/my-button/src/hooks/useButtonAnimation.ts

  2. get_file_context("useButtonAnimation.ts")
     → imports, importers, symbols

  3. Read file and edit

Scoped work on one package

User: "I'm working on my-checkout-flow"

Claude:
  1. build_scoped_index({ packageName: "my-checkout-flow" })
     → 87 packages, 2341 files (vs full repo)

  2. All subsequent tools operate on this smaller dataset

Re-indexing

The data/ files are gitignored — each developer builds their own local index. Re-run npm run build-index after:

  • Adding or removing packages
  • Renaming a package in package.json
  • Significant changes to barrel exports

Compatibility

| Repo type | Auto-detected? | Notes | |---|---|---| | Single-package TS/JS repo | ✓ | Root package.json treated as the one package | | Yarn workspaces (classic & berry) | ✓ | Reads package.json workspaces | | npm workspaces | ✓ | Reads package.json workspaces | | pnpm | ✓ | Reads pnpm-workspace.yaml | | Lerna | ✓ | Reads lerna.json packages | | Turborepo | ✓ | Reads package.json workspaces (Turbo uses standard workspaces) | | Nx | Manual | Use .codebase-index.json packageDirs | | Custom layout | Manual | Use .codebase-index.json packageDirs | | CommonJS projects | ✓ | require(), module.exports, exports.Foo all indexed | | ESM projects | ✓ | import/export fully indexed |