@cristiancorreau/forge 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +228 -0
- package/LICENSE +191 -0
- package/README.md +156 -0
- package/assets/adapters/claude-code/commands/deploy-check.md +12 -0
- package/assets/adapters/claude-code/commands/new-feature.md +11 -0
- package/assets/adapters/claude-code/commands/plan.md +116 -0
- package/assets/adapters/claude-code/commands/review.md +219 -0
- package/assets/adapters/claude-code/commands/session-close.md +109 -0
- package/assets/adapters/claude-code/commands/session-start.md +59 -0
- package/assets/adapters/claude-code/commands/ship.md +133 -0
- package/assets/adapters/claude-code/commands/wiki-ingest.md +7 -0
- package/assets/adapters/claude-code/commands/wiki-lint.md +5 -0
- package/assets/adapters/claude-code/commands/wiki-query.md +7 -0
- package/assets/adapters/claude-code/commands/work.md +101 -0
- package/assets/adapters/claude-code/generate-claude-md.py +304 -0
- package/assets/adapters/codex/commands/plan.md +63 -0
- package/assets/adapters/codex/commands/review.md +53 -0
- package/assets/adapters/codex/commands/session-close.md +53 -0
- package/assets/adapters/codex/commands/session-start.md +49 -0
- package/assets/adapters/codex/commands/ship.md +53 -0
- package/assets/adapters/codex/commands/work.md +53 -0
- package/assets/adapters/codex/generate-codex-config.py +269 -0
- package/assets/adapters/codex/hooks/codex.yaml.tpl +43 -0
- package/assets/adapters/codex/hooks/forge-codex-finish.sh +158 -0
- package/assets/adapters/codex/hooks/forge-codex-start.sh +186 -0
- package/assets/adapters/kiro/generate-steering.py +367 -0
- package/assets/adapters/opencode/HOOKS.md +123 -0
- package/assets/adapters/opencode/commands/plan.md +119 -0
- package/assets/adapters/opencode/commands/review.md +164 -0
- package/assets/adapters/opencode/commands/session-close.md +111 -0
- package/assets/adapters/opencode/commands/session-start.md +62 -0
- package/assets/adapters/opencode/commands/ship.md +135 -0
- package/assets/adapters/opencode/commands/work.md +82 -0
- package/assets/adapters/opencode/generate-agents-md.py +262 -0
- package/assets/core/agents/backend-engineer.md +61 -0
- package/assets/core/agents/compliance-reviewer.md +83 -0
- package/assets/core/agents/docs-writer.md +77 -0
- package/assets/core/agents/frontend-engineer.md +70 -0
- package/assets/core/agents/orchestrator.md +104 -0
- package/assets/core/agents/security-auditor.md +54 -0
- package/assets/core/agents/test-engineer.md +57 -0
- package/assets/core/hooks/hooks-registry.yaml +48 -0
- package/assets/core/hooks/post-turn-check.sh +139 -0
- package/assets/core/hooks/pre-bash-check.py +202 -0
- package/assets/core/hooks/pre-edit-check.py +317 -0
- package/assets/core/hooks/session-start.sh +184 -0
- package/assets/core/schemas/project.schema.json +503 -0
- package/assets/core/skills/README.md +88 -0
- package/assets/core/skills/aitmpl-search/SKILL.md +74 -0
- package/assets/core/skills/browser-test/SKILL.md +177 -0
- package/assets/core/skills/db-migrate/SKILL.md +163 -0
- package/assets/core/skills/local2prod/SKILL.md +147 -0
- package/assets/core/skills/new-feature/SKILL.md +155 -0
- package/assets/core/skills/obsidian-sync/SKILL.md +152 -0
- package/assets/core/skills/phase-kickoff/SKILL.md +69 -0
- package/assets/core/skills/security-audit/SKILL.md +125 -0
- package/assets/core/skills/spec/SKILL.md +72 -0
- package/assets/core/skills/wiki-ingest/SKILL.md +183 -0
- package/assets/core/skills/wiki-lint/SKILL.md +109 -0
- package/assets/core/skills/wiki-query/SKILL.md +100 -0
- package/assets/core/templates/claude-md/architecture.rules +20 -0
- package/assets/core/templates/claude-md/global.md +30 -0
- package/assets/core/templates/claude-md/project.md +36 -0
- package/assets/core/templates/daily-note.md +38 -0
- package/assets/core/templates/spec-template.md +43 -0
- package/assets/core/workflows/sdd.md +69 -0
- package/assets/core/workflows/sprint.md +59 -0
- package/assets/forge.py +1265 -0
- package/assets/hooks/pre-commit +43 -0
- package/assets/manifest.json +274 -0
- package/assets/profiles/astro/README.md +24 -0
- package/assets/profiles/astro/agents/frontend-engineer.md +74 -0
- package/assets/profiles/django/agents/api-engineer.md +83 -0
- package/assets/profiles/expo/README.md +24 -0
- package/assets/profiles/expo/agents/mobile-engineer.md +69 -0
- package/assets/profiles/express/agents/api-engineer.md +60 -0
- package/assets/profiles/fastapi/README.md +32 -0
- package/assets/profiles/fastapi/agents/api-engineer.md +87 -0
- package/assets/profiles/go-gin/agents/api-engineer.md +98 -0
- package/assets/profiles/hono-drizzle/README.md +31 -0
- package/assets/profiles/hono-drizzle/agents/api-engineer.md +82 -0
- package/assets/profiles/laravel/README.md +32 -0
- package/assets/profiles/laravel/agents/api-engineer.md +114 -0
- package/assets/profiles/laravel/agents/fullstack-engineer.md +67 -0
- package/assets/profiles/laravel/agents/migration-specialist.md +420 -0
- package/assets/profiles/nestjs/agents/api-engineer.md +79 -0
- package/assets/profiles/nextjs-admin/README.md +32 -0
- package/assets/profiles/nextjs-admin/agents/admin-engineer.md +78 -0
- package/assets/profiles/playwright-crawler/agents/scanner-engineer.md +51 -0
- package/assets/profiles/rails/agents/fullstack-engineer.md +61 -0
- package/assets/profiles/sveltekit/agents/frontend-engineer.md +96 -0
- package/assets/profiles/vuenuxt/agents/frontend-engineer.md +82 -0
- package/assets/profiles/wordpress/README.md +30 -0
- package/assets/profiles/wordpress/agents/divi-engineer.md +273 -0
- package/assets/profiles/wordpress/agents/elementor-engineer.md +310 -0
- package/assets/profiles/wordpress/agents/wp-engineer.md +216 -0
- package/assets/requirements.txt +2 -0
- package/assets/scripts/aitmpl-search.py +808 -0
- package/assets/scripts/forge-add-opportunities.py +92 -0
- package/assets/scripts/forge-audit.py +1061 -0
- package/assets/scripts/forge-generate-all.py +283 -0
- package/assets/scripts/forge-init.py +900 -0
- package/assets/scripts/forge-migrate-project-yaml.py +397 -0
- package/assets/scripts/forge-scaffold-profile.py +181 -0
- package/assets/scripts/forge-teardown.py +193 -0
- package/assets/scripts/forge-validate-project-yaml.py +457 -0
- package/assets/scripts/forge-wizard.py +1003 -0
- package/assets/scripts/setup-codex.sh +229 -0
- package/assets/scripts/team-install.sh +147 -0
- package/assets/scripts/token-stats.py +201 -0
- package/assets/templates/modes/enterprise.yaml.tpl +114 -0
- package/assets/templates/modes/multi-runtime.yaml.tpl +89 -0
- package/assets/templates/modes/new-stack.yaml.tpl +101 -0
- package/assets/templates/modes/startup.yaml.tpl +74 -0
- package/assets/templates/project.yaml.tpl +185 -0
- package/assets/templates/wiki/concepts/_template.md +22 -0
- package/assets/templates/wiki/entities/_template.md +19 -0
- package/assets/templates/wiki/index.md +32 -0
- package/assets/templates/wiki/log.md +6 -0
- package/assets/templates/wiki/sources/_template.md +25 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +64 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/audit.d.ts +2 -0
- package/dist/commands/audit.d.ts.map +1 -0
- package/dist/commands/audit.js +21 -0
- package/dist/commands/audit.js.map +1 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.d.ts.map +1 -0
- package/dist/commands/doctor.js +58 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/generate.d.ts +2 -0
- package/dist/commands/generate.d.ts.map +1 -0
- package/dist/commands/generate.js +27 -0
- package/dist/commands/generate.js.map +1 -0
- package/dist/commands/init.d.ts +2 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +22 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/validate.d.ts +2 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +20 -0
- package/dist/commands/validate.js.map +1 -0
- package/dist/lib/paths.d.ts +10 -0
- package/dist/lib/paths.d.ts.map +1 -0
- package/dist/lib/paths.js +49 -0
- package/dist/lib/paths.js.map +1 -0
- package/dist/lib/python.d.ts +4 -0
- package/dist/lib/python.d.ts.map +1 -0
- package/dist/lib/python.js +46 -0
- package/dist/lib/python.js.map +1 -0
- package/package.json +46 -0
|
@@ -0,0 +1,808 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
template-search.py — Busca templates y recursos para desarrollo con agentes IA.
|
|
4
|
+
|
|
5
|
+
Catálogo curado de frameworks, servidores MCP, skills y herramientas.
|
|
6
|
+
Funciona offline. Opcionalmente extiende con búsqueda en GitHub (--github).
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
python3 .agentic/scripts/aitmpl-search.py "fastapi"
|
|
10
|
+
python3 .agentic/scripts/aitmpl-search.py "mcp postgres"
|
|
11
|
+
python3 .agentic/scripts/aitmpl-search.py --category mcp-server
|
|
12
|
+
python3 .agentic/scripts/aitmpl-search.py --list-categories
|
|
13
|
+
python3 .agentic/scripts/aitmpl-search.py "rails" --github
|
|
14
|
+
python3 .agentic/scripts/aitmpl-search.py --json "claude"
|
|
15
|
+
"""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import argparse
|
|
19
|
+
import json
|
|
20
|
+
import os
|
|
21
|
+
import sys
|
|
22
|
+
import time
|
|
23
|
+
import textwrap
|
|
24
|
+
import urllib.error
|
|
25
|
+
import urllib.parse
|
|
26
|
+
import urllib.request
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
from typing import Optional
|
|
29
|
+
|
|
30
|
+
# ---------------------------------------------------------------------------
|
|
31
|
+
# Catálogo curado
|
|
32
|
+
# Campos: name, description, category, tags, url, language
|
|
33
|
+
#
|
|
34
|
+
# Categorías:
|
|
35
|
+
# framework — frameworks de desarrollo con agentes IA
|
|
36
|
+
# mcp-server — servidores Model Context Protocol
|
|
37
|
+
# skill — skills/comandos para Claude Code
|
|
38
|
+
# tool — herramientas de CLI o automatización
|
|
39
|
+
# profile — profiles de stack para forge
|
|
40
|
+
# resource — documentación, listas y guías
|
|
41
|
+
# ---------------------------------------------------------------------------
|
|
42
|
+
|
|
43
|
+
CATALOG: list[dict] = [
|
|
44
|
+
|
|
45
|
+
# ── Frameworks ──────────────────────────────────────────────────────────
|
|
46
|
+
|
|
47
|
+
{
|
|
48
|
+
"name": "cristiancorreau/forge",
|
|
49
|
+
"description": "Framework de desarrollo con agentes IA para equipos. Profiles para Next.js, Astro, FastAPI, Rails, NestJS, Express, Expo y más. Wizard CLI interactivo.",
|
|
50
|
+
"category": "framework",
|
|
51
|
+
"tags": ["claude-code", "agents", "typescript", "python", "ruby", "nextjs", "astro", "fastapi", "rails", "nestjs", "express", "expo"],
|
|
52
|
+
"url": "https://github.com/cristiancorreau/forge",
|
|
53
|
+
"language": "Python",
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
"name": "paul-gauthier/aider",
|
|
57
|
+
"description": "Pair programming con LLMs en la terminal. Soporta Claude, GPT-4, Gemini. Edita archivos directamente y hace commits automáticos.",
|
|
58
|
+
"category": "framework",
|
|
59
|
+
"tags": ["claude", "gpt4", "pair-programming", "git", "terminal"],
|
|
60
|
+
"url": "https://github.com/paul-gauthier/aider",
|
|
61
|
+
"language": "Python",
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "BuilderIO/micro-agent",
|
|
65
|
+
"description": "Agente IA que escribe código hasta que los tests pasan. TDD automático: genera código iterativamente hasta lograr green tests.",
|
|
66
|
+
"category": "framework",
|
|
67
|
+
"tags": ["tdd", "testing", "code-generation", "claude", "openai"],
|
|
68
|
+
"url": "https://github.com/BuilderIO/micro-agent",
|
|
69
|
+
"language": "TypeScript",
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
"name": "anthropics/anthropic-quickstarts",
|
|
73
|
+
"description": "Quickstarts oficiales de Anthropic: customer support agent, computer use, multi-agent portfolio. Ejemplos de referencia.",
|
|
74
|
+
"category": "framework",
|
|
75
|
+
"tags": ["claude", "anthropic", "multi-agent", "computer-use", "quickstart"],
|
|
76
|
+
"url": "https://github.com/anthropics/anthropic-quickstarts",
|
|
77
|
+
"language": "Python",
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "anthropics/claude-code-action",
|
|
81
|
+
"description": "GitHub Action oficial para usar Claude Code en CI/CD. Permite que Claude revise PRs, corrija bugs y responda issues automáticamente.",
|
|
82
|
+
"category": "framework",
|
|
83
|
+
"tags": ["claude-code", "github-actions", "ci-cd", "pr-review"],
|
|
84
|
+
"url": "https://github.com/anthropics/claude-code-action",
|
|
85
|
+
"language": "TypeScript",
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
# ── MCP Servers — oficiales ──────────────────────────────────────────────
|
|
89
|
+
|
|
90
|
+
{
|
|
91
|
+
"name": "MCP — filesystem",
|
|
92
|
+
"description": "Acceso seguro al sistema de archivos local con control de directorios permitidos. Leer, escribir, listar y buscar archivos.",
|
|
93
|
+
"category": "mcp-server",
|
|
94
|
+
"tags": ["filesystem", "files", "read", "write", "mcp", "oficial"],
|
|
95
|
+
"url": "https://github.com/modelcontextprotocol/servers/tree/main/src/filesystem",
|
|
96
|
+
"language": "TypeScript",
|
|
97
|
+
"install": {
|
|
98
|
+
"slug": "filesystem",
|
|
99
|
+
"command": "npx",
|
|
100
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "{ALLOWED_DIR}"],
|
|
101
|
+
"params": [{"key": "ALLOWED_DIR", "label": "Directorio permitido", "default": "."}],
|
|
102
|
+
"env": [],
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"name": "MCP — git",
|
|
107
|
+
"description": "Operaciones git: leer historial, diffs, commits, branches y status. Integración completa con repositorios git locales.",
|
|
108
|
+
"category": "mcp-server",
|
|
109
|
+
"tags": ["git", "version-control", "commits", "diff", "mcp", "oficial"],
|
|
110
|
+
"url": "https://github.com/modelcontextprotocol/servers/tree/main/src/git",
|
|
111
|
+
"language": "Python",
|
|
112
|
+
"install": {
|
|
113
|
+
"slug": "git",
|
|
114
|
+
"command": "uvx",
|
|
115
|
+
"args": ["mcp-server-git", "--repository", "{REPO_PATH}"],
|
|
116
|
+
"params": [{"key": "REPO_PATH", "label": "Ruta del repositorio git", "default": "."}],
|
|
117
|
+
"env": [],
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"name": "MCP — github",
|
|
122
|
+
"description": "Integración con la API de GitHub: repos, issues, PRs, branches, commits, búsqueda de código. Requiere GITHUB_TOKEN.",
|
|
123
|
+
"category": "mcp-server",
|
|
124
|
+
"tags": ["github", "issues", "pull-requests", "api", "mcp", "oficial"],
|
|
125
|
+
"url": "https://github.com/modelcontextprotocol/servers/tree/main/src/github",
|
|
126
|
+
"language": "TypeScript",
|
|
127
|
+
"install": {
|
|
128
|
+
"slug": "github",
|
|
129
|
+
"command": "npx",
|
|
130
|
+
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
131
|
+
"params": [],
|
|
132
|
+
"env": [{"key": "GITHUB_TOKEN", "label": "GitHub personal access token (ghp_...)"}],
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"name": "MCP — postgres",
|
|
137
|
+
"description": "Acceso read-only a bases de datos PostgreSQL. Ejecutar queries, explorar schemas y tablas. Ideal para análisis de datos.",
|
|
138
|
+
"category": "mcp-server",
|
|
139
|
+
"tags": ["postgres", "postgresql", "database", "sql", "mcp", "oficial"],
|
|
140
|
+
"url": "https://github.com/modelcontextprotocol/servers/tree/main/src/postgres",
|
|
141
|
+
"language": "TypeScript",
|
|
142
|
+
"install": {
|
|
143
|
+
"slug": "postgres",
|
|
144
|
+
"command": "npx",
|
|
145
|
+
"args": ["-y", "@modelcontextprotocol/server-postgres", "{CONNECTION_STRING}"],
|
|
146
|
+
"params": [{"key": "CONNECTION_STRING", "label": "PostgreSQL connection string", "default": "postgresql://localhost/mydb"}],
|
|
147
|
+
"env": [],
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"name": "MCP — sqlite",
|
|
152
|
+
"description": "Interacción con bases de datos SQLite: queries, introspección de schema, gestión de datos. Memo de conocimiento incorporado.",
|
|
153
|
+
"category": "mcp-server",
|
|
154
|
+
"tags": ["sqlite", "database", "sql", "local", "mcp", "oficial"],
|
|
155
|
+
"url": "https://github.com/modelcontextprotocol/servers/tree/main/src/sqlite",
|
|
156
|
+
"language": "Python",
|
|
157
|
+
"install": {
|
|
158
|
+
"slug": "sqlite",
|
|
159
|
+
"command": "uvx",
|
|
160
|
+
"args": ["mcp-server-sqlite", "--db-path", "{DB_PATH}"],
|
|
161
|
+
"params": [{"key": "DB_PATH", "label": "Ruta del archivo SQLite", "default": "./data.db"}],
|
|
162
|
+
"env": [],
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"name": "MCP — fetch",
|
|
167
|
+
"description": "Fetch de URLs y conversión a Markdown. Permite a Claude leer páginas web, documentación y APIs HTTP.",
|
|
168
|
+
"category": "mcp-server",
|
|
169
|
+
"tags": ["http", "fetch", "web", "scraping", "markdown", "mcp", "oficial"],
|
|
170
|
+
"url": "https://github.com/modelcontextprotocol/servers/tree/main/src/fetch",
|
|
171
|
+
"language": "Python",
|
|
172
|
+
"install": {
|
|
173
|
+
"slug": "fetch",
|
|
174
|
+
"command": "uvx",
|
|
175
|
+
"args": ["mcp-server-fetch"],
|
|
176
|
+
"params": [],
|
|
177
|
+
"env": [],
|
|
178
|
+
},
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"name": "MCP — brave-search",
|
|
182
|
+
"description": "Búsqueda web con Brave Search API. Web search y local search con privacidad. Requiere BRAVE_API_KEY.",
|
|
183
|
+
"category": "mcp-server",
|
|
184
|
+
"tags": ["search", "web-search", "brave", "internet", "mcp", "oficial"],
|
|
185
|
+
"url": "https://github.com/modelcontextprotocol/servers/tree/main/src/brave-search",
|
|
186
|
+
"language": "TypeScript",
|
|
187
|
+
"install": {
|
|
188
|
+
"slug": "brave-search",
|
|
189
|
+
"command": "npx",
|
|
190
|
+
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
|
|
191
|
+
"params": [],
|
|
192
|
+
"env": [{"key": "BRAVE_API_KEY", "label": "Brave Search API key"}],
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
"name": "MCP — slack",
|
|
197
|
+
"description": "Integración con Slack: enviar mensajes, leer canales, gestionar usuarios. Requiere Slack Bot Token.",
|
|
198
|
+
"category": "mcp-server",
|
|
199
|
+
"tags": ["slack", "messaging", "communication", "mcp", "oficial"],
|
|
200
|
+
"url": "https://github.com/modelcontextprotocol/servers/tree/main/src/slack",
|
|
201
|
+
"language": "TypeScript",
|
|
202
|
+
"install": {
|
|
203
|
+
"slug": "slack",
|
|
204
|
+
"command": "npx",
|
|
205
|
+
"args": ["-y", "@modelcontextprotocol/server-slack"],
|
|
206
|
+
"params": [],
|
|
207
|
+
"env": [
|
|
208
|
+
{"key": "SLACK_BOT_TOKEN", "label": "Slack Bot Token (xoxb-...)"},
|
|
209
|
+
{"key": "SLACK_TEAM_ID", "label": "Slack Team ID"},
|
|
210
|
+
],
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
"name": "MCP — puppeteer",
|
|
215
|
+
"description": "Automatización de browser con Puppeteer: navegar, hacer screenshots, rellenar formularios y ejecutar JavaScript.",
|
|
216
|
+
"category": "mcp-server",
|
|
217
|
+
"tags": ["puppeteer", "browser", "automation", "screenshot", "scraping", "mcp", "oficial"],
|
|
218
|
+
"url": "https://github.com/modelcontextprotocol/servers/tree/main/src/puppeteer",
|
|
219
|
+
"language": "TypeScript",
|
|
220
|
+
"install": {
|
|
221
|
+
"slug": "puppeteer",
|
|
222
|
+
"command": "npx",
|
|
223
|
+
"args": ["-y", "@modelcontextprotocol/server-puppeteer"],
|
|
224
|
+
"params": [],
|
|
225
|
+
"env": [],
|
|
226
|
+
},
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"name": "MCP — sequential-thinking",
|
|
230
|
+
"description": "Herramienta de razonamiento paso a paso con revisión y backtracking. Para problemas complejos que requieren análisis estructurado.",
|
|
231
|
+
"category": "mcp-server",
|
|
232
|
+
"tags": ["reasoning", "thinking", "analysis", "chain-of-thought", "mcp", "oficial"],
|
|
233
|
+
"url": "https://github.com/modelcontextprotocol/servers/tree/main/src/sequentialthinking",
|
|
234
|
+
"language": "TypeScript",
|
|
235
|
+
"install": {
|
|
236
|
+
"slug": "sequential-thinking",
|
|
237
|
+
"command": "npx",
|
|
238
|
+
"args": ["-y", "@modelcontextprotocol/server-sequential-thinking"],
|
|
239
|
+
"params": [],
|
|
240
|
+
"env": [],
|
|
241
|
+
},
|
|
242
|
+
},
|
|
243
|
+
{
|
|
244
|
+
"name": "MCP — memory",
|
|
245
|
+
"description": "Grafo de conocimiento persistente. Claude puede guardar y recuperar información entre conversaciones con entidades y relaciones.",
|
|
246
|
+
"category": "mcp-server",
|
|
247
|
+
"tags": ["memory", "knowledge-graph", "persistence", "mcp", "oficial"],
|
|
248
|
+
"url": "https://github.com/modelcontextprotocol/servers/tree/main/src/memory",
|
|
249
|
+
"language": "TypeScript",
|
|
250
|
+
"install": {
|
|
251
|
+
"slug": "memory",
|
|
252
|
+
"command": "npx",
|
|
253
|
+
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
|
254
|
+
"params": [],
|
|
255
|
+
"env": [],
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
{
|
|
259
|
+
"name": "MCP — everything",
|
|
260
|
+
"description": "Servidor MCP de referencia con prompts, tools y resources de ejemplo. Útil para probar clientes MCP y aprender el protocolo.",
|
|
261
|
+
"category": "mcp-server",
|
|
262
|
+
"tags": ["reference", "testing", "demo", "mcp", "oficial"],
|
|
263
|
+
"url": "https://github.com/modelcontextprotocol/servers/tree/main/src/everything",
|
|
264
|
+
"language": "TypeScript",
|
|
265
|
+
"install": {
|
|
266
|
+
"slug": "everything",
|
|
267
|
+
"command": "npx",
|
|
268
|
+
"args": ["-y", "@modelcontextprotocol/server-everything"],
|
|
269
|
+
"params": [],
|
|
270
|
+
"env": [],
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
|
|
274
|
+
# ── MCP Servers — comunidad ───────────────────────────────────────────────
|
|
275
|
+
|
|
276
|
+
{
|
|
277
|
+
"name": "MCP — supabase (comunidad)",
|
|
278
|
+
"description": "Integración con Supabase: ejecutar queries SQL, gestionar tablas, auth y storage via MCP.",
|
|
279
|
+
"category": "mcp-server",
|
|
280
|
+
"tags": ["supabase", "postgres", "database", "auth", "storage", "mcp"],
|
|
281
|
+
"url": "https://github.com/supabase-community/supabase-mcp",
|
|
282
|
+
"language": "TypeScript",
|
|
283
|
+
"install": {
|
|
284
|
+
"slug": "supabase",
|
|
285
|
+
"command": "npx",
|
|
286
|
+
"args": ["-y", "@supabase/mcp-server-supabase", "--access-token", "{ACCESS_TOKEN}"],
|
|
287
|
+
"params": [{"key": "ACCESS_TOKEN", "label": "Supabase personal access token"}],
|
|
288
|
+
"env": [],
|
|
289
|
+
},
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
"name": "MCP — Cloudflare",
|
|
293
|
+
"description": "Gestión de Workers, KV, R2, D1, AI Gateway y Vectorize de Cloudflare via MCP. Oficial de Cloudflare.",
|
|
294
|
+
"category": "mcp-server",
|
|
295
|
+
"tags": ["cloudflare", "workers", "kv", "r2", "d1", "edge", "mcp"],
|
|
296
|
+
"url": "https://github.com/cloudflare/mcp-server-cloudflare",
|
|
297
|
+
"language": "TypeScript",
|
|
298
|
+
"install": {
|
|
299
|
+
"slug": "cloudflare",
|
|
300
|
+
"command": "npx",
|
|
301
|
+
"args": ["-y", "@cloudflare/mcp-server-cloudflare"],
|
|
302
|
+
"params": [],
|
|
303
|
+
"env": [{"key": "CLOUDFLARE_API_TOKEN", "label": "Cloudflare API token"}],
|
|
304
|
+
},
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
"name": "MCP — Vercel",
|
|
308
|
+
"description": "Gestión de proyectos, deploys, dominios y logs de Vercel via MCP. Integración oficial.",
|
|
309
|
+
"category": "mcp-server",
|
|
310
|
+
"tags": ["vercel", "deploy", "serverless", "hosting", "mcp"],
|
|
311
|
+
"url": "https://github.com/vercel/mcp-server",
|
|
312
|
+
"language": "TypeScript",
|
|
313
|
+
"install": {
|
|
314
|
+
"slug": "vercel",
|
|
315
|
+
"command": "npx",
|
|
316
|
+
"args": ["-y", "@vercel/mcp-adapter"],
|
|
317
|
+
"params": [],
|
|
318
|
+
"env": [{"key": "VERCEL_TOKEN", "label": "Vercel API token"}],
|
|
319
|
+
},
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
"name": "MCP — Linear",
|
|
323
|
+
"description": "Integración con Linear: crear y consultar issues, proyectos y cycles. Para equipos que usan Linear como tracker.",
|
|
324
|
+
"category": "mcp-server",
|
|
325
|
+
"tags": ["linear", "project-management", "issues", "mcp"],
|
|
326
|
+
"url": "https://github.com/linear/linear-mcp",
|
|
327
|
+
"language": "TypeScript",
|
|
328
|
+
"install": {
|
|
329
|
+
"slug": "linear",
|
|
330
|
+
"command": "npx",
|
|
331
|
+
"args": ["-y", "@linear/mcp-server"],
|
|
332
|
+
"params": [],
|
|
333
|
+
"env": [{"key": "LINEAR_API_KEY", "label": "Linear API key"}],
|
|
334
|
+
},
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
"name": "MCP — Playwright",
|
|
338
|
+
"description": "Automatización de browser con Playwright via MCP. Navegación, screenshots, testing E2E e interacción con páginas web.",
|
|
339
|
+
"category": "mcp-server",
|
|
340
|
+
"tags": ["playwright", "browser", "e2e", "testing", "automation", "mcp"],
|
|
341
|
+
"url": "https://github.com/microsoft/playwright-mcp",
|
|
342
|
+
"language": "TypeScript",
|
|
343
|
+
"install": {
|
|
344
|
+
"slug": "playwright",
|
|
345
|
+
"command": "npx",
|
|
346
|
+
"args": ["-y", "@playwright/mcp@latest"],
|
|
347
|
+
"params": [],
|
|
348
|
+
"env": [],
|
|
349
|
+
},
|
|
350
|
+
},
|
|
351
|
+
{
|
|
352
|
+
"name": "MCP — Sentry",
|
|
353
|
+
"description": "Consulta issues, eventos y trazas de Sentry. Permite a Claude diagnosticar errores de producción directamente.",
|
|
354
|
+
"category": "mcp-server",
|
|
355
|
+
"tags": ["sentry", "errors", "monitoring", "debugging", "mcp"],
|
|
356
|
+
"url": "https://github.com/getsentry/sentry-mcp",
|
|
357
|
+
"language": "Python",
|
|
358
|
+
"install": {
|
|
359
|
+
"slug": "sentry",
|
|
360
|
+
"command": "uvx",
|
|
361
|
+
"args": ["mcp-server-sentry"],
|
|
362
|
+
"params": [],
|
|
363
|
+
"env": [{"key": "SENTRY_AUTH_TOKEN", "label": "Sentry auth token"}],
|
|
364
|
+
},
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
"name": "MCP — Docker",
|
|
368
|
+
"description": "Gestión de contenedores, imágenes y volúmenes Docker via MCP. Ejecutar y gestionar el ciclo de vida de containers.",
|
|
369
|
+
"category": "mcp-server",
|
|
370
|
+
"tags": ["docker", "containers", "devops", "infrastructure", "mcp"],
|
|
371
|
+
"url": "https://github.com/ckreiling/mcp-server-docker",
|
|
372
|
+
"language": "Python",
|
|
373
|
+
"install": {
|
|
374
|
+
"slug": "docker",
|
|
375
|
+
"command": "uvx",
|
|
376
|
+
"args": ["mcp-server-docker"],
|
|
377
|
+
"params": [],
|
|
378
|
+
"env": [],
|
|
379
|
+
},
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
"name": "MCP — AWS (aws-kb-retrieval)",
|
|
383
|
+
"description": "Retrieval desde AWS Knowledge Base. Para proyectos en AWS que usan Bedrock Knowledge Bases.",
|
|
384
|
+
"category": "mcp-server",
|
|
385
|
+
"tags": ["aws", "bedrock", "knowledge-base", "rag", "mcp", "oficial"],
|
|
386
|
+
"url": "https://github.com/modelcontextprotocol/servers/tree/main/src/aws-kb-retrieval-server",
|
|
387
|
+
"language": "TypeScript",
|
|
388
|
+
"install": {
|
|
389
|
+
"slug": "aws-kb",
|
|
390
|
+
"command": "npx",
|
|
391
|
+
"args": ["-y", "@modelcontextprotocol/server-aws-kb-retrieval"],
|
|
392
|
+
"params": [],
|
|
393
|
+
"env": [
|
|
394
|
+
{"key": "AWS_ACCESS_KEY_ID", "label": "AWS Access Key ID"},
|
|
395
|
+
{"key": "AWS_SECRET_ACCESS_KEY", "label": "AWS Secret Access Key"},
|
|
396
|
+
{"key": "AWS_REGION", "label": "AWS Region", "default": "us-east-1"},
|
|
397
|
+
],
|
|
398
|
+
},
|
|
399
|
+
},
|
|
400
|
+
|
|
401
|
+
# ── Profiles de forge ─────────────────────────────────────────────────────
|
|
402
|
+
|
|
403
|
+
{
|
|
404
|
+
"name": "forge profile — hono-drizzle",
|
|
405
|
+
"description": "Agente api-engineer especializado en Hono + Drizzle ORM + TypeScript. Incluye rutas, schemas, migraciones y tests.",
|
|
406
|
+
"category": "profile",
|
|
407
|
+
"tags": ["hono", "drizzle", "typescript", "api", "orm", "edge"],
|
|
408
|
+
"url": "https://github.com/cristiancorreau/forge/tree/main/profiles/hono-drizzle",
|
|
409
|
+
"language": "TypeScript",
|
|
410
|
+
},
|
|
411
|
+
{
|
|
412
|
+
"name": "forge profile — nextjs-admin",
|
|
413
|
+
"description": "Agente admin-engineer para dashboards con Next.js 15 + shadcn/ui. Componentes, tablas de datos y gestión interna.",
|
|
414
|
+
"category": "profile",
|
|
415
|
+
"tags": ["nextjs", "shadcn", "react", "dashboard", "admin", "typescript"],
|
|
416
|
+
"url": "https://github.com/cristiancorreau/forge/tree/main/profiles/nextjs-admin",
|
|
417
|
+
"language": "TypeScript",
|
|
418
|
+
},
|
|
419
|
+
{
|
|
420
|
+
"name": "forge profile — astro",
|
|
421
|
+
"description": "Agente frontend-engineer para sitios con Astro. SSG/SSR, islands architecture, Content Collections y Tailwind.",
|
|
422
|
+
"category": "profile",
|
|
423
|
+
"tags": ["astro", "ssg", "ssr", "islands", "typescript", "tailwind", "static"],
|
|
424
|
+
"url": "https://github.com/cristiancorreau/forge/tree/main/profiles/astro",
|
|
425
|
+
"language": "TypeScript",
|
|
426
|
+
},
|
|
427
|
+
{
|
|
428
|
+
"name": "forge profile — fastapi",
|
|
429
|
+
"description": "Agente api-engineer para FastAPI + Python. Endpoints async, Pydantic schemas, SQLAlchemy y pytest.",
|
|
430
|
+
"category": "profile",
|
|
431
|
+
"tags": ["fastapi", "python", "async", "pydantic", "sqlalchemy", "pytest"],
|
|
432
|
+
"url": "https://github.com/cristiancorreau/forge/tree/main/profiles/fastapi",
|
|
433
|
+
"language": "Python",
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
"name": "forge profile — rails",
|
|
437
|
+
"description": "Agente fullstack-engineer para Ruby on Rails. Modelos, migraciones, controllers, views y RSpec.",
|
|
438
|
+
"category": "profile",
|
|
439
|
+
"tags": ["rails", "ruby", "activerecord", "rspec", "fullstack"],
|
|
440
|
+
"url": "https://github.com/cristiancorreau/forge/tree/main/profiles/rails",
|
|
441
|
+
"language": "Ruby",
|
|
442
|
+
},
|
|
443
|
+
{
|
|
444
|
+
"name": "forge profile — nestjs",
|
|
445
|
+
"description": "Agente api-engineer para NestJS + TypeScript. Módulos, guards, decorators y arquitectura escalable.",
|
|
446
|
+
"category": "profile",
|
|
447
|
+
"tags": ["nestjs", "typescript", "node", "api", "modules", "guards"],
|
|
448
|
+
"url": "https://github.com/cristiancorreau/forge/tree/main/profiles/nestjs",
|
|
449
|
+
"language": "TypeScript",
|
|
450
|
+
},
|
|
451
|
+
{
|
|
452
|
+
"name": "forge profile — express",
|
|
453
|
+
"description": "Agente api-engineer para Express + Node.js + TypeScript. Middleware, rutas, validación y Jest.",
|
|
454
|
+
"category": "profile",
|
|
455
|
+
"tags": ["express", "nodejs", "typescript", "middleware", "api"],
|
|
456
|
+
"url": "https://github.com/cristiancorreau/forge/tree/main/profiles/express",
|
|
457
|
+
"language": "TypeScript",
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
"name": "forge profile — expo",
|
|
461
|
+
"description": "Agente mobile-engineer para React Native con Expo. Navegación, componentes nativos y EAS.",
|
|
462
|
+
"category": "profile",
|
|
463
|
+
"tags": ["expo", "react-native", "mobile", "ios", "android", "typescript"],
|
|
464
|
+
"url": "https://github.com/cristiancorreau/forge/tree/main/profiles/expo",
|
|
465
|
+
"language": "TypeScript",
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
"name": "forge profile — playwright-crawler",
|
|
469
|
+
"description": "Agente scanner-engineer para scraping y crawling con Playwright. Extracción de datos, screenshots y automatización.",
|
|
470
|
+
"category": "profile",
|
|
471
|
+
"tags": ["playwright", "scraping", "crawler", "browser", "automation", "typescript"],
|
|
472
|
+
"url": "https://github.com/cristiancorreau/forge/tree/main/profiles/playwright-crawler",
|
|
473
|
+
"language": "TypeScript",
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
"name": "forge profile — django",
|
|
477
|
+
"description": "Agente api-engineer para Django 4.x + DRF + PostgreSQL + pytest-django. Modelos, migraciones, serializers, viewsets y tests.",
|
|
478
|
+
"category": "profile",
|
|
479
|
+
"tags": ["django", "python", "drf", "postgresql", "rest-api", "pytest"],
|
|
480
|
+
"url": "https://github.com/cristiancorreau/forge/tree/main/profiles/django",
|
|
481
|
+
"language": "Python",
|
|
482
|
+
},
|
|
483
|
+
{
|
|
484
|
+
"name": "forge profile — vuenuxt",
|
|
485
|
+
"description": "Agente frontend-engineer para Nuxt 3 + Vue 3 + Pinia + TypeScript. Pages, componentes, composables y SSR.",
|
|
486
|
+
"category": "profile",
|
|
487
|
+
"tags": ["nuxt", "vue", "typescript", "pinia", "ssr", "tailwind"],
|
|
488
|
+
"url": "https://github.com/cristiancorreau/forge/tree/main/profiles/vuenuxt",
|
|
489
|
+
"language": "TypeScript",
|
|
490
|
+
},
|
|
491
|
+
{
|
|
492
|
+
"name": "forge profile — go-gin",
|
|
493
|
+
"description": "Agente api-engineer para Go + Gin/Echo + sqlc + PostgreSQL + testify. Handlers, services, repositories e migrations.",
|
|
494
|
+
"category": "profile",
|
|
495
|
+
"tags": ["go", "golang", "gin", "echo", "sqlc", "postgresql", "rest-api"],
|
|
496
|
+
"url": "https://github.com/cristiancorreau/forge/tree/main/profiles/go-gin",
|
|
497
|
+
"language": "Go",
|
|
498
|
+
},
|
|
499
|
+
{
|
|
500
|
+
"name": "forge profile — sveltekit",
|
|
501
|
+
"description": "Agente frontend-engineer para SvelteKit 2 + Svelte 5 + TypeScript + Tailwind. Routes, components, load functions y form actions.",
|
|
502
|
+
"category": "profile",
|
|
503
|
+
"tags": ["sveltekit", "svelte", "typescript", "tailwind", "ssr", "vite"],
|
|
504
|
+
"url": "https://github.com/cristiancorreau/forge/tree/main/profiles/sveltekit",
|
|
505
|
+
"language": "TypeScript",
|
|
506
|
+
},
|
|
507
|
+
{
|
|
508
|
+
"name": "forge profile — laravel",
|
|
509
|
+
"description": "Tres agentes para proyectos Laravel: api-engineer (Sanctum + Eloquent + Form Requests), fullstack-engineer (Blade + Livewire 3 o Inertia) y migration-specialist (upgrade L6→L13 paso a paso con breaking changes por versión).",
|
|
510
|
+
"category": "profile",
|
|
511
|
+
"tags": ["laravel", "php", "eloquent", "sanctum", "livewire", "blade", "inertia", "migration", "upgrade"],
|
|
512
|
+
"url": "https://github.com/cristiancorreau/forge/tree/main/profiles/laravel",
|
|
513
|
+
"language": "PHP",
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
"name": "forge profile — wordpress",
|
|
517
|
+
"description": "Tres agentes para proyectos WordPress: wp-engineer (FSE + bloques Gutenberg + Interactivity API + WP REST API), divi-engineer (Divi Theme Builder + módulos ET_Builder_Module + Dynamic Content) y elementor-engineer (Elementor Pro + widgets personalizados + Dynamic Tags + Loop Grid).",
|
|
518
|
+
"category": "profile",
|
|
519
|
+
"tags": ["wordpress", "php", "gutenberg", "fse", "divi", "elementor", "page-builder", "blocks", "theme-builder"],
|
|
520
|
+
"url": "https://github.com/cristiancorreau/forge/tree/main/profiles/wordpress",
|
|
521
|
+
"language": "PHP",
|
|
522
|
+
},
|
|
523
|
+
|
|
524
|
+
# ── Tools ────────────────────────────────────────────────────────────────
|
|
525
|
+
|
|
526
|
+
{
|
|
527
|
+
"name": "anthropics/claude-code (CLI)",
|
|
528
|
+
"description": "Claude Code oficial — CLI para desarrollo con agentes IA directamente en la terminal. Instalación: npm i -g @anthropic-ai/claude-code",
|
|
529
|
+
"category": "tool",
|
|
530
|
+
"tags": ["claude-code", "cli", "terminal", "official"],
|
|
531
|
+
"url": "https://docs.anthropic.com/claude-code",
|
|
532
|
+
"language": "TypeScript",
|
|
533
|
+
},
|
|
534
|
+
{
|
|
535
|
+
"name": "modelcontextprotocol/inspector",
|
|
536
|
+
"description": "Inspector visual para servidores MCP. Permite probar y depurar servers MCP en una interfaz web interactiva.",
|
|
537
|
+
"category": "tool",
|
|
538
|
+
"tags": ["mcp", "debugging", "inspector", "testing", "development"],
|
|
539
|
+
"url": "https://github.com/modelcontextprotocol/inspector",
|
|
540
|
+
"language": "TypeScript",
|
|
541
|
+
},
|
|
542
|
+
|
|
543
|
+
# ── Resources ─────────────────────────────────────────────────────────────
|
|
544
|
+
|
|
545
|
+
{
|
|
546
|
+
"name": "modelcontextprotocol/servers (todos)",
|
|
547
|
+
"description": "Repositorio oficial con todos los servers MCP de referencia: filesystem, git, github, postgres, sqlite, fetch, slack, puppeteer, memory y más.",
|
|
548
|
+
"category": "resource",
|
|
549
|
+
"tags": ["mcp", "servers", "reference", "official"],
|
|
550
|
+
"url": "https://github.com/modelcontextprotocol/servers",
|
|
551
|
+
"language": "TypeScript",
|
|
552
|
+
},
|
|
553
|
+
{
|
|
554
|
+
"name": "punkpeye/awesome-mcp-servers",
|
|
555
|
+
"description": "Lista curada de servidores MCP de la comunidad. Cubre bases de datos, APIs, herramientas de desarrollo, comunicación y más.",
|
|
556
|
+
"category": "resource",
|
|
557
|
+
"tags": ["mcp", "awesome", "curated", "list", "community"],
|
|
558
|
+
"url": "https://github.com/punkpeye/awesome-mcp-servers",
|
|
559
|
+
"language": "",
|
|
560
|
+
},
|
|
561
|
+
{
|
|
562
|
+
"name": "Documentación oficial MCP",
|
|
563
|
+
"description": "Documentación del Model Context Protocol: guías para construir servers y clients, especificación del protocolo y ejemplos.",
|
|
564
|
+
"category": "resource",
|
|
565
|
+
"tags": ["mcp", "docs", "specification", "protocol", "official"],
|
|
566
|
+
"url": "https://modelcontextprotocol.io",
|
|
567
|
+
"language": "",
|
|
568
|
+
},
|
|
569
|
+
{
|
|
570
|
+
"name": "Documentación Claude Code",
|
|
571
|
+
"description": "Docs oficiales de Claude Code: hooks, slash commands, configuración de agentes, CLAUDE.md, MCP y más.",
|
|
572
|
+
"category": "resource",
|
|
573
|
+
"tags": ["claude-code", "docs", "hooks", "agents", "official"],
|
|
574
|
+
"url": "https://docs.anthropic.com/claude-code",
|
|
575
|
+
"language": "",
|
|
576
|
+
},
|
|
577
|
+
]
|
|
578
|
+
|
|
579
|
+
CATEGORIES = sorted(set(t["category"] for t in CATALOG))
|
|
580
|
+
|
|
581
|
+
# ---------------------------------------------------------------------------
|
|
582
|
+
# Búsqueda local
|
|
583
|
+
# ---------------------------------------------------------------------------
|
|
584
|
+
|
|
585
|
+
def _search_local(query: str, category: Optional[str] = None) -> list[dict]:
|
|
586
|
+
terms = query.lower().split() if query else []
|
|
587
|
+
results = []
|
|
588
|
+
for item in CATALOG:
|
|
589
|
+
if category and item["category"] != category:
|
|
590
|
+
continue
|
|
591
|
+
if not terms:
|
|
592
|
+
results.append((0, item))
|
|
593
|
+
continue
|
|
594
|
+
haystack = " ".join([
|
|
595
|
+
item["name"],
|
|
596
|
+
item["description"],
|
|
597
|
+
item["category"],
|
|
598
|
+
" ".join(item["tags"]),
|
|
599
|
+
item.get("language", ""),
|
|
600
|
+
]).lower()
|
|
601
|
+
score = sum(1 for t in terms if t in haystack)
|
|
602
|
+
if score > 0:
|
|
603
|
+
results.append((score, item))
|
|
604
|
+
|
|
605
|
+
results.sort(key=lambda x: x[0], reverse=True)
|
|
606
|
+
return [x[1] for x in results]
|
|
607
|
+
|
|
608
|
+
|
|
609
|
+
# ---------------------------------------------------------------------------
|
|
610
|
+
# GitHub API (opcional, --github)
|
|
611
|
+
# ---------------------------------------------------------------------------
|
|
612
|
+
|
|
613
|
+
CACHE_FILE = Path.home() / ".forge" / "template-search-cache.json"
|
|
614
|
+
CACHE_TTL = 1800
|
|
615
|
+
|
|
616
|
+
|
|
617
|
+
def _cache_load() -> dict:
|
|
618
|
+
if not CACHE_FILE.exists():
|
|
619
|
+
return {}
|
|
620
|
+
try:
|
|
621
|
+
with open(CACHE_FILE) as f:
|
|
622
|
+
data = json.load(f)
|
|
623
|
+
if time.time() - data.get("_ts", 0) > CACHE_TTL:
|
|
624
|
+
return {}
|
|
625
|
+
return data
|
|
626
|
+
except (json.JSONDecodeError, OSError):
|
|
627
|
+
return {}
|
|
628
|
+
|
|
629
|
+
|
|
630
|
+
def _cache_save(data: dict) -> None:
|
|
631
|
+
CACHE_FILE.parent.mkdir(parents=True, exist_ok=True)
|
|
632
|
+
data["_ts"] = time.time()
|
|
633
|
+
try:
|
|
634
|
+
with open(CACHE_FILE, "w") as f:
|
|
635
|
+
json.dump(data, f)
|
|
636
|
+
except OSError:
|
|
637
|
+
pass
|
|
638
|
+
|
|
639
|
+
|
|
640
|
+
def _fetch_github(query: str, limit: int) -> list[dict]:
|
|
641
|
+
cache = _cache_load()
|
|
642
|
+
cache_key = f"gh_{query}_{limit}"
|
|
643
|
+
if cache_key in cache:
|
|
644
|
+
return cache[cache_key]
|
|
645
|
+
|
|
646
|
+
topic_q = "topic:claude-code OR topic:mcp-server OR topic:ai-agent"
|
|
647
|
+
full_q = urllib.parse.urlencode({
|
|
648
|
+
"q": f"{query} ({topic_q})",
|
|
649
|
+
"sort": "stars",
|
|
650
|
+
"order": "desc",
|
|
651
|
+
"per_page": min(limit, 20),
|
|
652
|
+
})
|
|
653
|
+
url = f"https://api.github.com/search/repositories?{full_q}"
|
|
654
|
+
headers = {
|
|
655
|
+
"Accept": "application/vnd.github+json",
|
|
656
|
+
"User-Agent": "forge-template-search/2.0",
|
|
657
|
+
}
|
|
658
|
+
token = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN")
|
|
659
|
+
if token:
|
|
660
|
+
headers["Authorization"] = f"Bearer {token}"
|
|
661
|
+
|
|
662
|
+
req = urllib.request.Request(url, headers=headers)
|
|
663
|
+
try:
|
|
664
|
+
with urllib.request.urlopen(req, timeout=10) as resp:
|
|
665
|
+
data = json.loads(resp.read().decode("utf-8"))
|
|
666
|
+
except urllib.error.HTTPError as e:
|
|
667
|
+
if e.code == 403:
|
|
668
|
+
print(" Límite de GitHub alcanzado. Exporta GITHUB_TOKEN para más requests.", file=sys.stderr)
|
|
669
|
+
return []
|
|
670
|
+
except (urllib.error.URLError, json.JSONDecodeError, OSError):
|
|
671
|
+
return []
|
|
672
|
+
|
|
673
|
+
results = []
|
|
674
|
+
for item in data.get("items", []):
|
|
675
|
+
results.append({
|
|
676
|
+
"name": item.get("full_name", ""),
|
|
677
|
+
"description": item.get("description") or "",
|
|
678
|
+
"category": "github",
|
|
679
|
+
"tags": item.get("topics", []),
|
|
680
|
+
"url": item.get("html_url", ""),
|
|
681
|
+
"language": item.get("language") or "",
|
|
682
|
+
"stars": item.get("stargazers_count", 0),
|
|
683
|
+
})
|
|
684
|
+
|
|
685
|
+
cache[cache_key] = results
|
|
686
|
+
_cache_save(cache)
|
|
687
|
+
return results
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
# ---------------------------------------------------------------------------
|
|
691
|
+
# Output
|
|
692
|
+
# ---------------------------------------------------------------------------
|
|
693
|
+
|
|
694
|
+
CATEGORY_LABELS = {
|
|
695
|
+
"framework": "Framework",
|
|
696
|
+
"mcp-server": "MCP Server",
|
|
697
|
+
"skill": "Skill",
|
|
698
|
+
"tool": "Herramienta",
|
|
699
|
+
"profile": "Profile forge",
|
|
700
|
+
"resource": "Recurso",
|
|
701
|
+
"github": "GitHub",
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
|
|
705
|
+
def _print_results(results: list[dict], as_json: bool) -> None:
|
|
706
|
+
if as_json:
|
|
707
|
+
print(json.dumps(results, ensure_ascii=False, indent=2))
|
|
708
|
+
return
|
|
709
|
+
if not results:
|
|
710
|
+
print("Sin resultados. Prueba con otro término o usa --list-categories.")
|
|
711
|
+
return
|
|
712
|
+
for i, t in enumerate(results, 1):
|
|
713
|
+
cat = CATEGORY_LABELS.get(t.get("category", ""), t.get("category", ""))
|
|
714
|
+
name = t.get("name", "")
|
|
715
|
+
desc = t.get("description", "")
|
|
716
|
+
tags = t.get("tags", [])
|
|
717
|
+
url = t.get("url", "")
|
|
718
|
+
lang = t.get("language", "")
|
|
719
|
+
stars = t.get("stars")
|
|
720
|
+
|
|
721
|
+
meta_parts = [f"[{cat}]"]
|
|
722
|
+
if lang:
|
|
723
|
+
meta_parts.append(lang)
|
|
724
|
+
if stars:
|
|
725
|
+
meta_parts.append(f"★ {stars:,}")
|
|
726
|
+
meta = " ".join(meta_parts)
|
|
727
|
+
|
|
728
|
+
print(f"{i:>2}. {name}")
|
|
729
|
+
if desc:
|
|
730
|
+
for line in textwrap.wrap(desc, width=68, initial_indent=" ",
|
|
731
|
+
subsequent_indent=" "):
|
|
732
|
+
print(line)
|
|
733
|
+
if tags:
|
|
734
|
+
tag_str = " ".join(f"#{t}" for t in tags[:8])
|
|
735
|
+
print(f" {tag_str}")
|
|
736
|
+
print(f" {meta}")
|
|
737
|
+
print(f" {url}")
|
|
738
|
+
print()
|
|
739
|
+
|
|
740
|
+
|
|
741
|
+
# ---------------------------------------------------------------------------
|
|
742
|
+
# CLI
|
|
743
|
+
# ---------------------------------------------------------------------------
|
|
744
|
+
|
|
745
|
+
def main() -> None:
|
|
746
|
+
parser = argparse.ArgumentParser(
|
|
747
|
+
description="Busca templates y recursos para desarrollo con agentes IA.",
|
|
748
|
+
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
749
|
+
epilog=textwrap.dedent("""\
|
|
750
|
+
Ejemplos:
|
|
751
|
+
%(prog)s "fastapi"
|
|
752
|
+
%(prog)s "mcp postgres"
|
|
753
|
+
%(prog)s --category mcp-server
|
|
754
|
+
%(prog)s --category profile
|
|
755
|
+
%(prog)s "rails" --github
|
|
756
|
+
%(prog)s --list-categories
|
|
757
|
+
"""),
|
|
758
|
+
)
|
|
759
|
+
parser.add_argument("query", nargs="?", default="",
|
|
760
|
+
help="Término de búsqueda")
|
|
761
|
+
parser.add_argument("--limit", type=int, default=20, metavar="N",
|
|
762
|
+
help="Máximo de resultados (default: 20)")
|
|
763
|
+
parser.add_argument("--json", dest="as_json", action="store_true",
|
|
764
|
+
help="Salida en JSON")
|
|
765
|
+
parser.add_argument("--category", "-c", metavar="CAT",
|
|
766
|
+
help=f"Filtrar por categoría: {', '.join(CATEGORIES)}")
|
|
767
|
+
parser.add_argument("--github", action="store_true",
|
|
768
|
+
help="Extender con búsqueda en GitHub API (requiere red)")
|
|
769
|
+
parser.add_argument("--list-categories", action="store_true",
|
|
770
|
+
help="Listar categorías disponibles y cantidad de items")
|
|
771
|
+
|
|
772
|
+
args = parser.parse_args()
|
|
773
|
+
|
|
774
|
+
if args.list_categories:
|
|
775
|
+
print("Categorías disponibles:\n")
|
|
776
|
+
for cat in CATEGORIES:
|
|
777
|
+
count = sum(1 for t in CATALOG if t["category"] == cat)
|
|
778
|
+
label = CATEGORY_LABELS.get(cat, cat)
|
|
779
|
+
print(f" {cat:<16} {label} ({count} items)")
|
|
780
|
+
print(f"\nTotal catálogo: {len(CATALOG)} items\n")
|
|
781
|
+
return
|
|
782
|
+
|
|
783
|
+
if not args.query and not args.category:
|
|
784
|
+
parser.print_help()
|
|
785
|
+
sys.exit(1)
|
|
786
|
+
|
|
787
|
+
results = _search_local(args.query, args.category)
|
|
788
|
+
|
|
789
|
+
if args.github and args.query:
|
|
790
|
+
print("Buscando en GitHub...", file=sys.stderr)
|
|
791
|
+
gh = _fetch_github(args.query, args.limit)
|
|
792
|
+
seen = {r["url"] for r in results}
|
|
793
|
+
for item in gh:
|
|
794
|
+
if item["url"] not in seen:
|
|
795
|
+
results.append(item)
|
|
796
|
+
seen.add(item["url"])
|
|
797
|
+
|
|
798
|
+
results = results[: args.limit]
|
|
799
|
+
|
|
800
|
+
if not args.as_json:
|
|
801
|
+
source = "catálogo local" + (" + GitHub" if args.github else "")
|
|
802
|
+
print(f"Resultados: {len(results)} ({source})\n", file=sys.stderr)
|
|
803
|
+
|
|
804
|
+
_print_results(results, args.as_json)
|
|
805
|
+
|
|
806
|
+
|
|
807
|
+
if __name__ == "__main__":
|
|
808
|
+
main()
|