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

@mks2508/axon-mcp

v0.2.2

Published

MCP server axon: expone read+write del roadmap v2 a clientes MCP (Claude Code, opencode). TERCER consumer del core (mismo modelo que CLI), sin BFF. Spec MCP 2026-07-28 + SDK v2 dual-era + stdio (local) + HTTP streamable (deploy).

Readme

@mks2508/axon-mcp

MCP server para el modelo de roadmap axon v2. Tercer consumer del core (mismo modelo que la CLI), sin BFF ni SDK de cliente. Expone read + write del roadmap a clientes MCP (Claude Code, opencode) sobre JSON-RPC stdio y HTTP streamable (Stateless).

  • Spec: MCP 2026-07-28 (dual-era: 2025 + 2026 negotiation).
  • Runtime: Bun-first (engines.bun >=1.1). El tarball shippea TS directo (mismo patrón que @mks2508/axon). Sin build step.
  • Stack: @modelcontextprotocol/server@^2 + zod@^4 (v4 z.object({...}) schema, no raw shape). SDK v1 solo en devDeps para tests.

Install & wire-up

Claude Code

# Stdio (local, sin auth — el cliente y el server viven en el mismo trust zone).
claude mcp add axon-mcp -- bunx @mks2508/axon-mcp
# O si lo instalaste como dev dep en tu repo:
claude mcp add axon-mcp -- bun ./node_modules/@mks2508/axon-mcp/src/index.ts

opencode

opencode no tiene formato de plugin nativo — el bin trae su propio adapter:

# ./opencode.json (cwd)
bunx @mks2508/axon-mcp init --opencode

# ~/.config/opencode/opencode.json (global)
bunx @mks2508/axon-mcp init --opencode --global

# con modelo autoridad explícito (se resuelve a absoluto)
bunx @mks2508/axon-mcp init --opencode --model /abs/path/to/your/roadmap.model.yml

Primera conexión puede tardar: bunx -y resuelve+descarga el tarball la primera vez y eso puede exceder el timeout de conexión MCP del cliente (opencode mcp list reportó Connection closed en cold y connected con el paquete cacheado). Un retry lo arregla.

Merge NO destructivo e idempotente: si opencode.json ya existe, solo se toca la key mcp.axon — el resto del fichero (otras keys, otros mcp.*) se preserva. Re-run sin --model reescribe mcp.axon con la shape canónica (si antes tenía environment por un --model previo, se pierde — es determinista, no accidental). JSON inválido en disco → error, fichero intacto.

Shape que escribe (schema mcp de opencode, verificado contra source):

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "axon": {
      "type": "local",
      "command": ["bunx", "-y", "@mks2508/axon-mcp@latest"],
      "enabled": true
      // "environment": { "AXON_MODEL": "<abs path>" } — solo si se pasó --model
    }
  }
}

Skills/CLAUDE.md: opencode lee nativamente ~/.claude/skills/<name>/SKILL.md y ~/.claude/CLAUDE.md (compat directa, no hace falta nada adicional aquí) — depende de que esas copias existan en disco; si algún tombstone de dotfiles las borra, esta compat se rompe (data point, no resuelto por esta unidad).

HTTP mode (deploy interno)

AXON_MCP_TOKEN=$(openssl rand -hex 32) \
AXON_MODEL=/abs/path/to/your/roadmap.model.yml \
bunx @mks2508/axon-mcp serve --port 7361

Auth: Authorization: Bearer $AXON_MCP_TOKEN (401 si falta o no coincide). ADR-0029 bearer+tailnet v1; OAuth RS cuando haya deploy público.

Health sin auth: GET /healthz{"ok": true, "server": "axon-mcp"}.

Tools (6)

| Tool | Tipo | Mutates | Descripción | |---------------|--------|---------|-------------| | query | read | no | status (dashboard) · show <id> · now (actionable) · graph (DAG SVG) · roadmap. | | set_status | write | sí | Cambia status de un nodo (done estampa completedDate). | | set_gate | write | sí | Mutar verdict (pass/provisional/partial/open) + evidencia de un item existente; con create: true (+ class opcional) crea uno nuevo en vez de una 7ª tool — sin create, un itemId con typo sigue fallando (nunca upsert). | | add_node | write | sí | Añade nodo top-level o milestone (parent). | | rm_node | write | sí | Borra nodo. Bloquea si tiene dependents (force=true los rompe). | | set_node | write | sí | Patch de title/zone/dependsOn/refs/docs. |

format: 'human' | 'json'human devuelve content[].text (1-3 líneas); json devuelve structuredContent con campo summary (workaround bug #55677 — Claude Code descarta text cuando ambos canales están presentes, así que duplicamos la prosa en structuredContent.summary).

Prompts (2)

Aparecen en Claude Code como /mcp__axon__<nombre>:

  • estado — Llama query status + query now y devuelve resumen ejecutivo.
  • cerrar-milestone <nodeId> — Guía paso a paso: set_gate → confirmar → set_status done → verificar.

Apps (MCP Apps / SEP-1865, widgets ui:// interactivos)

Baseline (format: human, sección "Tools" arriba) queda 100% intacto en TODOS los clients — MCP Apps es una capa adicional, opt-in por el host, no un reemplazo.

query declara _meta.ui.resourceUri: "ui://axon/app" — un único resource router (vanilla JS + SVG, sin react, sin frameworks) que monta la vista dedicada según structuredContent.command:

| command | vista | |---|---| | status | status-card (counts, gates, violations) | | graph | dag-viewer (pan/zoom, click nodo → detalle + dropdown status → write) | | roadmap | roadmap-table (tabla de nodos top-level) | | show / now | fallback de texto (sin widget dedicado, lock A1) |

Por qué un solo resource y no uno por vista: SEP-1865 declara _meta.ui.resourceUri de forma ESTÁTICA en la definición de la tool (tools/list) — un CallToolResult no puede seleccionar un resource distinto por llamada (spec, sección "Predeclared Resources vs. Inline Embedding": "Require UI resources to be registered and referenced in tool metadata"; alternativa de "embedded resources" — resource per-call — evaluada y descartada). Como query es una sola tool MCP (lock L1, consolidada), solo puede declarar UN resourceUri — de ahí el router.

Escribir desde el DAG (lock A2): click nodo → dropdown status → Apply dispara tools/call set_status desde el iframe, y tras el ok re-lanza query graph para refrescar la vista. Cada call incluye model: structuredContent.modelPath — en Desktop el cwd del server MCP no es el repo, así que la resolución por .claude/axon.config.json NO dispara; sin este threading los writes fallarían justo en el client al que apunta la feature. Errores del tools/call se muestran en un banner en la UI (no se silencian); el permission prompt del host antes de ejecutar el write es flujo normal, no un error.

Clients que la renderizan

Matriz oficial (modelcontextprotocol.io/extensions/client-matrix): Claude Desktop y claude.ai (web) SÍ la soportan; también VS Code Copilot, ChatGPT, Cursor, Goose, Postman, MCPJam. Claude Code NO la soporta (ausente de la matriz + sin mención en su changelog) — en Claude Code, query sigue funcionando exactamente igual que antes (content[].text compacto), el host simplemente ignora _meta.ui porque no negoció la extension io.modelcontextprotocol/ui en el initialize.

Probarla en Claude Desktop (config manual)

Claude Desktop no lee .claude/axon.config.json — pasa AXON_MODEL explícito:

// ~/Library/Application Support/Claude/claude_desktop_config.json
{
  "mcpServers": {
    "axon-mcp": {
      "command": "bunx",
      "args": ["-y", "@mks2508/axon-mcp"],
      "env": { "AXON_MODEL": "/abs/path/to/your/roadmap.model.yml" }
    }
  }
}

Reinicia Claude Desktop, invoca query status (o graph/roadmap) desde el chat — el widget se renderiza inline. format: 'json' NO es necesario para que el widget aparezca (el widget lee structuredContent, que el server ya adjunta siempre).

Build del widget (bun run build:apps)

El HTML del widget es un artefacto build-time checked-in (src/apps/app.generated.html, convención *.generated.* del repo) — el runtime del server NO ejecuta ningún build step, solo lee el fichero. Regenerar tras tocar src/apps/router.ts o src/apps/views/*.ts:

bun run build:apps       # bundlea con `bun build` (target browser, minify) e inyecta
                          # el bundle inline en src/apps/template.html
bun run typecheck:apps   # tsc --noEmit con lib DOM (separado del tsconfig del server:
                          # el server corre en Bun/Node, sin document/window)

@modelcontextprotocol/ext-apps (App Bridge, npm ^1.7.5) es devDependency SOLO — se bundlea, no se shipea como dependency runtime. Guard automático en el build: si el bundle contiene la cadena "react" en cualquier forma, el script aborta (lock: nunca shipear react en el HTML final).

Resolución del modelo (en cada tool call)

  1. model parameter (si el cliente lo pasa).
  2. AXON_MODEL env var.
  3. Campo roadmapModel de .claude/axon.config.json en cwd.
  4. Error con hint accionable (AXON_MCP_NO_MODEL_RESOLVED).

Sin BFF, sin estado en memoria

Stateless per-request (HTTP) y sin sesiones persistentes (stdio). Cada tool call resuelve modelo, carga DAG, ejecuta handler de core, devuelve resultado. Sin caches, sin locks compartidos — el modelo es el state, los write handlers de core son atómicos.

Development

# Tests (bun:test, 53 tests, 5 files)
bun test

# Typecheck
bunx tsc --noEmit -p tsconfig.json

# Smoke local (stdio)
bun ./src/index.ts
# En otro terminal:
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"smoke","version":"0"}}}' | bun ./src/index.ts

ADR-0029

axon-mcp-distribution: bearer+tailnet v1 con HTTP server local. Stateless streamable, auth via env token. Mismo modelo de distribución que el resto del monorepo.

License

MIT