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

attrition-mcp

v0.1.0

Published

MCP server for the attrition.sh agent harness catalog — browse, resolve, install production patterns from Claude Code / Cursor / Codex.

Readme

attrition-mcp

MCP server for the attrition.sh agent harness catalog. Lets Claude Code, Cursor, and Codex browse, resolve, and pull production patterns (harness, UI, RAG, eval, design, security) the same way Context7 serves library docs.

  • Transport: stdio
  • Registry: ATTRITION_REGISTRY_URL env var, default https://agentworkspace.attrition.sh
  • Timeout: 10 s per fetch (AbortController)
  • Bounded reads: 1 MB markdown cap, 5 MB JSON cap
  • No filesystem writes, no shell out, no network calls off the registry

Catalog: https://agentworkspace.attrition.sh

Install

npx attrition-mcp

Or install locally:

npm install -g attrition-mcp
attrition-mcp

Claude Code config

Add to ~/.claude.json (global) or .claude.json in your repo:

{
  "mcpServers": {
    "attrition": {
      "command": "npx",
      "args": ["-y", "attrition-mcp"],
      "env": {
        "ATTRITION_REGISTRY_URL": "https://agentworkspace.attrition.sh"
      }
    }
  }
}

For Cursor, the equivalent lives in ~/.cursor/mcp.json with the same shape. For Codex and other MCP-capable clients, use the same command / args / env payload — consult your client's MCP config docs for the exact filename.

Tools

resolve_pack_id(query)

Fuzzy-match a free-text query against pack names, taglines, and tags. Mirrors Context7's resolve-library-id UX.

Example args: { "query": "hybrid bm25 vector rag" }

Input: { query: string } Output:

{
  "candidates": [
    { "slug": "advisor-pattern", "name": "Advisor Pattern", "tagline": "...", "packType": "harness", "score": 2 }
  ]
}

Ranked by substring-hit count over tokens. Ties break toward the Verified trust tier. Always returns at most 5 candidates.

get_pack(slug)

Fetch the full Pack JSON by slug.

Example args: { "slug": "rag-hybrid-bm25-vector" }

Input: { slug: string } (slug must match ^[a-z0-9-]+$) Output: { pack: Pack } Errors: INVALID_SLUG, NOT_FOUND, TIMEOUT, UPSTREAM_ERROR

get_pack_section(slug, section)

Fetch a single H2 section from a pack's raw markdown. Use this to pull just the piece you need (e.g. contract, layers, evaluation-checklist) instead of paying tokens for the whole pack. Payload target: under 3k tokens.

Example args: { "slug": "rag-hybrid-bm25-vector", "section": "contract" }

Input: { slug: string, section: SectionName } Valid sections: summary, install, contract, layers, use-when, avoid-when, key-outcomes, minimal-instructions, full-instructions, evaluation-checklist, failure-modes, transfer-matrix, telemetry, security-review, compares-with, related-packs, changelog, sources, examples Output: { slug, section, content: string } Errors: INVALID_SLUG, INVALID_SECTION, NOT_FOUND, PAYLOAD_TOO_LARGE, TIMEOUT

search_packs(query?, packType?, canonicalPattern?, trust?, limit?)

Typed directory query. Limit is capped at 50.

Input:

{
  "query": "advisor",
  "packType": "harness",
  "canonicalPattern": "evaluator-optimizer",
  "trust": "Verified",
  "limit": 10
}

Output: { packs: Pack[], total: number }

compare_packs(slugA, slugB, axis?)

Merge comparesWith axes from two packs. Optionally scope to a single axis.

Example args: { "slugA": "advisor-pattern", "slugB": "scout-pattern", "axis": "cost" }

Input: { slugA: string, slugB: string, axis?: "cost" | "latency" | "complexity" | "accuracy" | "a11y" | "maintainability" } Output:

{
  "a": { "...full pack A..." },
  "b": { "...full pack B..." },
  "comparison": {
    "axes": [{ "axis": "cost", "winnerSlug": "advisor-pattern", "note": "..." }],
    "verdict": "advisor-pattern wins 3/5 axes; scout-pattern wins 1."
  }
}

Change-trace tools (Pillar 2)

The three tools below query the change-trace catalog — per-session records of scenario / files touched / changes / why. They complement the five pack tools above; both sets share the same ATTRITION_REGISTRY_URL env var and run in the same MCP server process.

search_change_traces(query, project?, symbol?, sinceDate?, limit?)

Full-text search over scenarios / changes / why. Returns ranked snippets plus matching-row indexes so an agent can skip straight to the relevant row without pulling a whole trace. Payload target under 2 k tokens for top 20 matches. Limit capped at 50.

Example args: { "query": "atomicWriteFile", "project": "agent-workspace-template", "limit": 10 }

Output:

{
  "traces": [
    {
      "id": "ct_2026-04-17",
      "project": "agent-workspace-template",
      "createdAt": "2026-04-17T10:00:00Z",
      "matchingRows": [0],
      "snippet": "Wire atomicWriteFile into trace writer..."
    }
  ],
  "total": 1
}

Ranked by matching-row count, then createdAt desc. Honest-status: if the registry returns no per-row match info, matchingRows is [].

get_trace(id)

Fetch a full ChangeTrace JSON object by id.

Example args: { "id": "ct_2026-04-17" }

Input: { id: string } (must match ^ct_\d{4}-\d{2}-\d{2}(_[a-z0-9-]{1,40})?$) Output: { trace: ChangeTrace } Errors: INVALID_TRACE_ID, NOT_FOUND, TIMEOUT, PAYLOAD_TOO_LARGE, UPSTREAM_ERROR

get_row(id, rowIndex)

Fetch a single row from a trace plus resolved cross-references (referenced pack slugs and related rows in the same trace that share a touched file). Bounds-checked rowIndex. Payload target under 3 k tokens.

Example args: { "id": "ct_2026-04-17", "rowIndex": 0 }

Output:

{
  "trace": "ct_2026-04-17",
  "rowIndex": 0,
  "scenario": "...",
  "filesTouched": ["..."],
  "changes": [ /* ChangeDetail[] */ ],
  "why": { "plain": "...", "analogy": "...", "principle": "...", "hook": "..." },
  "crossReferences": {
    "packs": ["advisor-pattern"],
    "relatedRows": [ { "trace": "ct_2026-04-17", "row": 1, "reason": "shared file: ..." } ]
  }
}

Errors: INVALID_TRACE_ID, ROW_OUT_OF_RANGE, NOT_FOUND, TIMEOUT, UPSTREAM_ERROR

Error envelope

Every tool returns a structured envelope on failure — never thrown to the transport:

{ "error": { "code": "INVALID_SLUG", "message": "..." } }

| Code | Meaning | |---|---| | EMPTY_QUERY | Query string was empty or whitespace | | INVALID_SLUG | Slug failed ^[a-z0-9-]+$ | | INVALID_SECTION | Section not in the enum | | INVALID_INPUT | Input schema mismatch | | NOT_FOUND | Registry returned 404 | | TIMEOUT | Registry exceeded 10 s budget | | PAYLOAD_TOO_LARGE | Response exceeded 1 MB (md) or 5 MB (json) | | UPSTREAM_ERROR | Registry returned 5xx / invalid JSON | | NETWORK_ERROR | Transport-level failure | | INVALID_TRACE_ID | Trace id failed ^ct_\d{4}-\d{2}-\d{2}(_[a-z0-9-]{1,40})?$ | | ROW_OUT_OF_RANGE | rowIndex is past the end of the trace's rows |

Dev

npm install
npm run build                       # tsc -> dist/
npm run dev                         # tsx src/index.ts (stdio loop)
npm run verify                      # pack-tool scenarios -> "MCP OK"
npx tsx scripts/verify-trace-mcp.ts # change-trace scenarios -> "TRACE MCP OK"

Shape sync

src/types.ts mirrors the canonical Pack type from the parent repo at src/lib/pack-schema.ts. src/trace-types.ts mirrors src/lib/trace-schema.ts and the FailureMode shape from src/lib/pack-schema.ts. Both are deliberately inlined so this package stays standalone — when the parent schemas change, update both. The trace registry client accepts both { trace: ... } / { traces, total } envelopes and bare ChangeTrace / ChangeTrace[] responses so shape drift between M-milestones fails loud at the verify script instead of silently breaking production.