shipit-skill — canal de lanzamiento en un solo paso para herramientas de desarrollador
Lleva un repositorio existente de "funciona" a publicado + listado + comercializable. Cuatro fases, cada una con un criterio de salida estricto. Se permite omitir una fase solo si su criterio ya se cumple.
Filosofía: mira antes de construir. Verifica qué existe y qué requiere el ecosistema primero — de la misma manera que le aconsejarías a cualquier usuario no reinventar la rueda.
Fase 0 — Reconocimiento (30s, siempre)
Ejecuta estas comprobaciones antes de tocar nada:
- Estado del repositorio existente —
git status,git remote -v,git logreciente. - Registro del paquete — ¿está tomado el nombre? (
pip index versions <nombre>,npm view <nombre>, CDN del registro). Los nombres suelen colisionar; los nombres con ámbito para npm (@org/pkg) evitan las reglas de typosquatting. - Proyectos similares — busca en GitHub competidores directos. Si existe uno, anota explícitamente la diferenciación; no construyas una copia exacta.
- Las brechas en los "criterios de salida" — ¿CI? ¿Dockerfile? ¿GitHub Release? ¿listado en Glama / directorios awesome? ¿material promocional actualizado? Construye una lista de verificación de lo que falta. Esa lista guía el resto.
Salida: un breve informe de brechas + plan. Obtén confirmación antes de la Fase 1 si las brechas son grandes.
Fase 1 — Línea base de ingeniería
Criterio de salida: CI verde en la rama predeterminada, metadatos del paquete correctos, Dockerfile presente (si es un servidor MCP/CLI).
- CI: agrega GitHub Actions. Python: matriz para versiones soportadas, pero ten en cuenta los extras que requieren un intérprete más reciente (p.ej.,
mcp>=2.0necesita py3.10+ — ejecuta la base en 3.9, los extras en 3.12). Siempre incluye lint + pruebas + un trabajo de handshake MCP en contenedor si se distribuye un servidor. - Dockerfile: necesario para Glama y usuarios de contenedores. Para servidores MCP stdio: imagen base + instala el paquete +
CMD [el-comando-del-servidor]. Construye desde la fuente (COPY src) a menos que el paquete publicado esté verificado — una versión desactualizada en PyPI/npm romperá silenciosamente la introspección. .dockerignore: mantén la imagen al mínimo (sin.git, pruebas, promoción, documentos).- Versión desde metadatos: MCP
serverInfo.versiony CLI--versiondeben leer la versión del paquete, no una cadena hardcodeada. - Piso de dependencias: si tu código apunta a una nueva API del SDK, establece el piso (
mcp>=2.0), no dejes>=1.0— pip/npm resuelven a la última y rompen instalaciones nuevas.
Verifica: pip install .[extras] / npm install limpio en un venv temporal, luego ejecuta el handshake MCP (initialize + tools/list) contra el contenedor.
Fase 2 — Publicar
Criterio de salida: paquete en el registro, GitHub Release con etiqueta y notas, instalación limpia verificada.
- Aumento de versión → artefactos de compilación (
python -m build/npm pack). - Etiqueta + GitHub Release: título
vX.Y.Z, notas con Cambios / Instalación / Qué-corrige. Deja quegh release createadjunte desde la etiqueta. - Publicación en el registro:
- PyPI: necesita un token (granular, con ámbito para el paquete, permiso Upload). Si el token está mal formado, PyPI devuelve
403 Invalid or non-existent authentication information— las cadenas de tipo UUID son incorrectas; los tokens reales de PyPI comienzan conpypi-.twine uploadcon--username __token__. - npm: los nombres con ámbito necesitan que la organización exista; token granular con bypass-2FA para automatización;
--//registry.npmjs.org/:_authTokenen línea evita escribir credenciales en disco.
- PyPI: necesita un token (granular, con ámbito para el paquete, permiso Upload). Si el token está mal formado, PyPI devuelve
- Verificación de instalación limpia (no negociable): crea un venv / directorio limpio, instala desde el registro, importa el módulo / ejecuta el CLI / realiza el handshake MCP. Esto detecta errores de empaquetado del tipo "funciona en mi máquina".
- Trampas:
- La CDN de npm sirve 404s en caché durante minutos después de la primera publicación — no entres en pánico, invalida la caché con un parámetro de consulta.
File already existsal reintentar generalmente significa que el primer intento tuvo éxito.- Desviación del archivo de bloqueo: renombrar paquetes → siempre ejecuta
npm installpara regenerar el bloqueo onpm cifallará en CI.
Fase 3 — Listados en directorios
Criterio de salida: listado en Glama con insignia de puntuación y PR en awesome abierto (o fusionado).
- Glama (
glama.ai/mcp/servers): el usuario envía a través del navegador (OAuth de GitHub — no se puede automatizar). Antes de enviar: Dockerfile debe existir y pasar la introspección (ver Fase 1). Después de enviar: la página tarda de minutos a horas en aparecer — consultahttps://glama.ai/mcp/servers/<propietario>/<repo>y/badges/score.svg. Agrega la insignia al README del repositorio una vez que esté activa:[](https://glama.ai/mcp/servers/propietario/repo) - awesome-mcp-servers (y listas curadas similares): los PRs son triados por bots. Formato según la convención actual de la lista (insignia + idioma + alcance + SO + comando de instalación). Los mantenedores ahora requieren la insignia de Glama en la entrada — envía a Glama primero. Agrega
🤖🤖🤖al título del PR para optar al carril rápido del agente. Haz fork → crea una rama desde el último main ascendente → agrega entrada → PR. Si un PR anterior se cerró por inactividad, fuerza el push de la rama o recréala. - Otros directorios (Smithery, PulseMCP, mcp.so…): Smithery lee un
smithery.yamlen la raíz del repositorio (comando de inicio stdio + esquema de variables de entorno opcional).
Fase 4 — Material promocional
Criterio de salida: las versiones/enlaces/números de PR en los documentos de promoción coinciden con la realidad; las publicaciones por plataforma están listas para pegar (el usuario publica manualmente — sin automatización falsa).
- Mantén
promo/con archivos por plataforma (V2EX, 知乎, Reddit, X, comunidad). - Verificación de actualización (ejecuta cada vez que cambien versiones/PRs): busca en los archivos de promoción números de versión antiguos, enlaces de PR muertos, URLs de lanzamiento desactualizadas. Actualiza o marca como desactualizado.
- Disciplina de hechos: verifica cada número/afirmación antes de publicar — vuelve a ejecutar la herramienta y compara la salida. Las afirmaciones incorrectas son desmentidas en los comentarios (p.ej., una afirmación de "sin LICENSE" que en realidad es una peculiaridad de los metadatos de GitHub).
- Mantén los comandos de instalación sin fijar (
pip install pkg) para que la promoción no se deteriore.
Referencia rápida de CLI (shipit-skill)
Ejecuta estos comandos para mover un repositorio a través de las fases. Todo es solo impresión por defecto; las variantes con efectos laterales son opt-in mediante --execute.
| Comando | Hace | Auto / impresión |
|---|---|---|
doctor [--json] | autocomprobación del entorno: gh autenticado, tokens configurados, árbol limpio en main | imprime; sale con 1 si hay brechas |
preflight [--dir .] [--version X.Y.Z] [--json] | informe de brechas de preparación para lanzamiento | imprime |
init <dir> --server <srv> --pkg <pkg> [--force] [--dry-run] | andamia CI/Dockerfile/smithery.yaml/promo | escribe archivos |
ci --lang python [--server srv] [--write ruta] [--release] | emite ci.yml; --release emite release.yml | imprime / escribe |
| `bump patch | minor | major |
release --lang python --pkg <pkg> [--repo o/r] [--execute] | puerta doctor → bump→build→publish→tag→gh release→check-promo. Tag/Release solo se crean después de que publish tenga éxito; el fallo de publish revierte el commit; las re-ejecuciones saltan tags/releases existentes; notas desde CHANGELOG | imprime / ejecuta |
publish --lang python --pkg <pkg> [--server srv] [--execute] | subida al registro (token de las variables de entorno PYPI_TOKEN/NPM_TOKEN) + verificación de instalación limpia | imprime / ejecuta |
check-promo --dir promo --version X.Y.Z [--prs id=estado,...] [--no-links] [--report] [--fix] | versiones desactualizadas / PRs desconocidos / enlaces rotos; --report emite JSON; --fix reescribe versiones desactualizadas + marca PRs desconocidos | imprime / JSON / corrige |
check-glama --repo o/r [--poll N] [--add-badge] [--json] | espera el listado de Glama; --add-badge escribe la insignia README una vez activa; --json estructurado | imprime / escribe |
awesome-pr --upstream o/r --repo o/r --fork o/r --branch b [--execute --category C --description D --install I] | receta PR, o realmente fork→edit→push→gh pr create | imprime / ejecuta |
Tokens: nunca almacenados en disco. publish/release --execute lee PYPI_TOKEN o NPM_TOKEN del entorno; pídele al usuario el token y pásalo en línea.
Límite de automatización
| Paso | Quién lo ejecuta |
|---|---|
| Archivos CI, Dockerfile, metadatos, correcciones de código | Agente |
| Artefactos de compilación, verificación de instalación limpia | Agente |
| Publicación en el registro (PyPI/npm) | Agente, con un token proporcionado por el usuario |
| Envío en navegador de Glama | Usuario (OAuth) |
| Creación de PR en awesome/otros | Agente |
| Publicación en plataformas | Usuario |
Nunca fabriques credenciales; pide el token explícitamente y úsalo en línea, nunca lo escribas en un archivo.
Cicatrices del mundo real (de publicar wheel-hub + zspace-cli)
mcp>=1.0en extras + nuevo SDK → instalaciones nuevas fallan. Establece pisos.- Python 3.9 no puede instalar
mcp>=2.0; la matriz de CI debe dividir base vs extras. - Escalar de bloque YAML + heredoc python en línea = flujo de trabajo roto. Usa un archivo de script.
- El objeto
Serverde MCP 2.x no tienelist_tools— usa decoradores@server.tool(). - La introspección de Glama necesita que stdin se mantenga abierto un momento (
sleep 1) en pruebas de humo. - Formatos de token PyPI:
pypi-...real, UUID = incorrecto. - El typosquatting de npm bloquea
wheel-hubcerca dewheelhub; los nombres con ámbito funcionan. - Falta
.dockerignore→ imágenes enormes / secretos en el contexto de compilación.