MCPunk
Explora y comprende bases de código mediante conversación, dividiendo archivos en fragmentos lógicos para buscar y consultar sin incrustaciones.
Documentación
MCPunk 🤖
Chatea con tu código sin embeddings, dándole al LLM herramientas para buscar en tu código de forma inteligente.
MCPunk te permite explorar y entender bases de código mediante conversación. Funciona así:
- Divide los archivos en fragmentos lógicos (funciones, clases, secciones de markdown)
- Da al LLM herramientas para buscar y consultar estos fragmentos
- Deja que el LLM encuentre el código específico que necesita para responder tus preguntas
Sin embeddings, sin configuración compleja: solo búsqueda clara y auditable que puedes ver y guiar. Funciona muy bien con Claude Desktop, o con cualquier otro cliente MCP.
Construido con lo siguiente en mente
- El contexto es el rey - Los LLM pueden ser excelentes, pero solo si se les proporciona el contexto adecuado.
- El contexto es precioso - Los LLM necesitan contexto, pero no pueden manejar demasiado. ¡Una tragedia! MCPunk es RAG que inherentemente proporciona al LLM pistas contextuales, permitiendo que el LLM se centre realmente solo en el contenido relevante.
- Humano en el bucle - Tú puedes ver exactamente qué datos ha considerado el LLM y cómo los encontró, Tú puedes entrar en el chat y dirigir las cosas donde quieras.
Configuración
Estas son instrucciones para Claude Desktop, pero MCPunk se puede usar en cualquier lugar donde se use MCP.
- Instalar uv
- Pon el fragmento a continuación en tu
claude_desktop_config.json(Detalles sobreclaude_desktop_config.jsonincluyendo ubicación) - Reinicia Claude Desktop y deberías ver las herramientas disponibles después de un pequeño retraso, como en la captura de pantalla a continuación
- Chatea: "oye amigo, ¿puedes configurar el proyecto ~/git/mcpunk y decirme cómo se dividen los archivos python en fragmentos?"
("command": "uvx", podría no funcionar, y puede que necesites usar p. ej. "command": "/Users/michael/.local/bin/uvx",)
{
"mcpServers": {
"MCPunk": {
"command": "uvx",
"args": ["mcpunk"]
}
}
}

Ejemplos de uso
Responder preguntas sobre tu código
- [Usuario] Oye amigo, ¿puedes configurar el repositorio ~/git/mcpunk y luego ayudarme a entender cómo un usuario de mcpunk obtendría el diff de git de la rama actualmente verificada en el repositorio que ha configurado con mcpunk
- [Claude] Llama a
configure_project - [Claude] Llama a
list_all_files_in_project - [Claude] Llama a
find_files_by_chunk_content - [Claude] ... hace un total de 21 llamadas a herramientas con MCPunk.
- [Claude] Ahora entiendo cómo funciona la funcionalidad de diff de git en mcpunk.
Déjame resumir cómo un usuario obtendría el diff de git de la rama actualmente verificada:
- Primero, el usuario necesita configurar mcpunk para trabajar con su proyecto usando la herramienta configure_project
- Para ver qué ramas se verificaron recientemente (para identificar contra qué hacer el diff)
- Luego, para obtener el diff entre la rama actual (HEAD) y una rama de referencia Esto mostrará las diferencias entre la rama actual (HEAD) y la rama de referencia especificada. El parámetro ref debe ser el nombre de la rama base (como "main" o "develop") contra la que quieres comparar.
- [Usuario] ¡Buen trabajo, amigo!
Revisión de PR
- [usuario] Oye amigo, ¿puedes configurar el repositorio ~/git/mcpunk y echar un
vistazo a la rama actual versus
scratch/1.5 - [Claude] Configura ~/git/mcpunk y llama a
diff_with_refpara la refscratch/1.5 - [Claude] Veo que has hecho varios cambios, principalmente agregando un nuevo archivo
de prueba
tests/test_git_analysis.py... - [usuario] ¿Cómo encaja esto en el resto de la base de código?
- [Claude] Hace 5 llamadas a herramientas para listar archivos por fragmentos, listar fragmentos, obtener detalles de fragmentos
- [Claude] Ya veo: el código analiza la salida de git reflog para rastrear ramas verificadas recientemente. La función principal get_recent_branches toma una ruta de repositorio y devuelve las últimas N ramas que se verificaron, usando _branches_from_reflog como ayuda para analizar la salida cruda de reflog.
- [Usuario] Si tuvieras prisa y tuvieras que dirigir a alguien para revisar este trabajo, ¿qué le indicarías que mirara? Por favor, describe piezas discretas de trabajo
- [Claude]
- El
split("to ")[-1]en _branches_from_reflog parece frágil - Los datos de prueba solo muestran nombres de ramas simples, ¿qué pasa con espacios/caracteres especiales?
- ¿Es example_reflog representativo de la salida real de git reflog?
- ¿Estamos probando contra el comportamiento real de git?
- El
- [Usuario] ¡Eres el mejor!
Trabajar con múltiples bases de código
Puedes simplemente pedirle a tu LLM que configure múltiples proyectos, y puede consultar libremente a través de ellos. Útil si uno depende del otro y están en repositorios diferentes. En este caso, el LLM debería reconocerlo mediante imports.
Qué es MCPunk y otros antecedentes
MCPunk es un servidor MCP que proporciona herramientas para
- Configurar un proyecto, que es un directorio de archivos. Cuando se configura, los archivos se dividen en fragmentos lógicos. MCPunk está construido para código, pero realmente podría aplicarse a cualquier documento, incluso imágenes si quieres.
- Buscar archivos en un proyecto que contengan texto específico
- Buscar fragmentos en un archivo que contengan texto específico
- Ver el contenido completo de un fragmento específico
Además, incluye algunos fragmentadores integrados. El más maduro es el fragmentador de Python.
MCPunk no tiene que usarse para conversación. Puede usarse como parte de la revisión de código en un pipeline de CI, por ejemplo. Es realmente RAG general.
sequenceDiagram
participant User
participant Claude as Claude Desktop
participant MCPunk as MCPunk Server
participant Files as File System
Note over User,Files: Setup Phase
User->>Claude: Ask question about codebase
Claude->>MCPunk: configure_project(root_path, project_name)
MCPunk->>Files: Scan files in root directory
Note over MCPunk,Files: Chunking Process
MCPunk->>MCPunk: For each file, apply appropriate chunker:
MCPunk->>MCPunk: - PythonChunker: functions, classes, imports
MCPunk->>MCPunk: - MarkdownChunker: sections by headings
MCPunk->>MCPunk: - VueChunker: template/script/style sections
MCPunk->>MCPunk: - WholeFileChunker: fallback
MCPunk->>MCPunk: Split chunks >10K chars into parts
MCPunk-->>Claude: Project configured with N files
Note over User,Files: Navigation Phase<br>(LLM freely uses all these tools repeatedly to drill in)
Claude->>MCPunk: list_all_files_in_project(project_name)
MCPunk-->>Claude: File tree structure
Claude->>MCPunk: find_files_by_chunk_content(project_name, "search term")
MCPunk-->>Claude: Files containing matching chunks
Claude->>MCPunk: find_matching_chunks_in_file(project_name, file_path, "search term")
MCPunk-->>Claude: List of matching chunk IDs in file
Claude->>MCPunk: chunk_details(chunk_id)
MCPunk-->>Claude: Full content of specific chunk
Claude->>User: Answer based on relevant code chunks
Note over User,Files: Optional Git Analysis
Claude->>MCPunk: list_most_recently_checked_out_branches(project_name)
MCPunk->>Files: Parse git reflog
MCPunk-->>Claude: List of recent branches
Claude->>MCPunk: diff_with_ref(project_name, "main")
MCPunk->>Files: Generate git diff
MCPunk-->>Claude: Diff between HEAD and reference
Curso intensivo de Roaming RAG
Ver
- https://arcturus-labs.com/blog/2024/11/21/roaming-rag--make-_the-model_-find-the-answers/
- https://simonwillison.net/2024/Dec/6/roaming-rag/
La esencia del roaming RAG es
- Descomponer el contenido (una base de código, archivos PDF, lo que sea) en "fragmentos". Cada fragmento es un elemento lógico "pequeño" como una función, una sección en un documento markdown, o todos los imports en un archivo de código.
- Proporcionar al LLM herramientas para buscar fragmentos. MCPunk hace esto proporcionando herramientas para buscar archivos que contengan fragmentos con texto específico, y para listar el contenido completo de un fragmento específico.
En comparación con el RAG más tradicional de "búsqueda vectorial":
- El LLM tiene que profundizar para encontrar fragmentos, y naturalmente es consciente de su contexto más amplio (como en qué archivo están)
- Los fragmentos siempre deben ser coherentes. Como una función completa.
- Puedes ver exactamente lo que el LLM está buscando, y generalmente es obvio si está buscando mal y puedes ayudarlo sugiriendo términos de búsqueda mejorados.
- Requiere coincidencia exacta en la búsqueda. MCPunk NO proporciona búsqueda difusa de ningún tipo.
Fragmentos
Un fragmento es una subsección de un archivo. Por ejemplo,
- Una sola función de Python
- Una sección de markdown
- Todos los imports de un archivo Python
Los fragmentos se crean a partir de un archivo mediante fragmentadores, y MCPunk viene con varios integrados.
Cuando un proyecto se configura en MCPunk, recorre todos los archivos y aplica el primer fragmentador aplicable. El LLM puede entonces usar herramientas para (1) consultar archivos que contengan fragmentos con texto específico, (2) consultar todos los fragmentos en un archivo específico, y (3) obtener el contenido completo de un fragmento.
Esta base fundamental permite a Claude navegar eficazmente por bases de código relativamente grandes comenzando con una búsqueda amplia de archivos relevantes y centrándose en áreas relevantes.
Fragmentadores integrados:
PythonChunkerdivide en clases, funciones, imports a nivel de archivo, y declaraciones a nivel de archivo (p. ej. globales). Aplicable a archivos que terminan en.pyVueChunkerdivide en fragmentos 'template', 'script', 'style' - o lo que sea que exista como elementos de nivel superior<blah>....</blah>. Aplicable a archivos que terminan en.vueMarkdownChunkerdivide en secciones de markdown (por encabezado). Aplicable a archivos que terminan en.mdWholeFileChunkerfragmentador de respaldo que crea un solo fragmento para todo el archivo. Aplicable a cualquier archivo.
Cualquier fragmento de más de 10k caracteres (configurable) se divide automáticamente en
múltiples fragmentos, con nombres sufijados con part1, part2, etc. Esto ayuda
a evitar exceder el contexto mientras se permite una navegación razonable de los fragmentos.
Fragmentadores personalizados
Cada tipo de archivo (p. ej. Python vs C) necesita un fragmentador personalizado. MCPunk viene con algunos integrados. Si ningún fragmentador específico coincide con un archivo, se usa un fragmentador predeterminado que simplemente mete todo el archivo en un solo fragmento.
La forma actual sugerida de agregar fragmentadores es hacer un fork de este proyecto y agregarlos, y ejecutar MCPunk según Desarrollo. Para agregar un fragmentador
- Agrégalo en file_chunkers.py, heredando de
BaseChunker - Agrégalo a
ALL_CHUNKERSen file_breakdown.py
Sería posible implementar algún tipo de sistema de plugins para que los módulos anuncien que tienen fragmentadores personalizados para que MCPunk los use, como el sistema de plugins de pytest, pero actualmente no hay planes para implementarlo (a menos que alguien quiera hacerlo).
Limitaciones
- A veces el LLM es malo buscando. Por ejemplo, buscar "dependency", omitiendo términos como "dependencies". Hay margen para derivar palabras.
- A veces el LLM intentará encontrar una pieza específica de código crítico pero no logra encontrarla, y luego continúa sin reconocer que tiene una conciencia contextual limitada.
- Los proyectos "grandes" no están bien probados. Un proyecto con ~1000 archivos Python que contengan en total ~250k líneas de código funciona bien. Tarda ~5s en configurar el proyecto. A medida que el tamaño de la base de código aumenta, el tiempo para realizar el fragmentado inicial aumentará, y probablemente se requerirá una búsqueda más sofisticada. El código generalmente no está escrito pensando en bases de código masivas: verás cosas como todos los datos almacenados en memoria, búsqueda iterando sobre todos los datos, varias cosas que piden a gritos una optimización básica.
- Los proyectos pequeños probablemente se beneficien más de tener todo el código concatenado y arrojado al contexto. MCPunk solo es realmente apropiado cuando esto es poco práctico.
- En algunos casos, obviamente sería mejor permitir que el LLM tome un archivo completo en lugar de tener que elegir fragmentos uno a la vez. MCPunk no tiene mecanismo para esto. En la práctica, no he encontrado que esto sea un gran problema.
Configuración
Varias cosas se pueden configurar mediante variables de entorno con prefijo MCPUNK_.
Para opciones disponibles, ver settings.py - estas se cargan
desde variables de entorno mediante Pydantic Settings.
Por ejemplo, para configurar la opción include_chars_in_response:
{
"mcpServers": {
"MCPunk": {
"command": "uvx",
"args": ["mcpunk"],
"env": {
"MCPUNK_INCLUDE_CHARS_IN_RESPONSE": "false"
}
}
}
}
Hoja de ruta y estado de desarrollo
MCPunk se considera casi completo en cuanto a funciones. No ha tenido un uso amplio, y como usuario es probable que te encuentres con errores o bordes ásperos. Los informes de errores son bienvenidos en https://github.com/jurasofish/mcpunk/issues
Ideas para la hoja de ruta
- Agregar un montón de indicaciones para ayudar con el uso de MCPunk. Sin indicaciones reales del tipo "explica cómo hacer un panqueque a un alienígena", las cosas caen un poco planas.
- Incluir comentarios a nivel de módulo al extraer declaraciones a nivel de módulo de Python.
- Posiblemente derivación de palabras para la búsqueda
- Cambiar todo el concepto de "proyecto" para que no necesite que los archivos existan realmente - esto
llevaría a permitir archivos "virtuales" dentro del proyecto.
- Considerar cambiar los archivos de tener una ruta a tener un URI, para que pudiera ser como
file://.../http[s]:///gitdiff:/// etc. URIs arbitrarios
- Considerar cambiar los archivos de tener una ruta a tener un URI, para que pudiera ser como
- Fragmentado de diffs de git. Actualmente, hay una herramienta para obtener un diff completo. Esto
podría ser muy grande. En su lugar, la herramienta podría cambiarse a
add_diff_to_projecty coloca los archivos bajo el URIgitdiff://o bajo alguna ruta falsa - Caché de un proyecto, para que no necesite reanalizar todos los archivos cada vez que reinicies el cliente MCP. Esto puede ser complicado ya que los cambios en el código de un fragmentador invalidarán la caché. Probablemente no se priorice, ya que no es tan lento para mis casos de uso.
- Capacidad para que los usuarios proporcionen código personalizado para realizar el fragmentado, quizás similar a plugins de pytest
- Algo como tree sitter podría usarse posiblemente para un fragmentador más genérico
- Seguimiento de caracteres enviados/recibidos, idealmente por chat.
- Estado, registro, etc. por chat
Desarrollo
ver run_mcp_server.py.
Si configuras Claude Desktop como se muestra a continuación, puedes reiniciarlo para ver los últimos cambios mientras trabajas en MCPunk desde tu versión local del repositorio.
{
"mcpServers": {
"MCPunk": {
"command": "/Users/michael/.local/bin/uvx",
"args": [
"--from",
"/Users/michael/git/mcpunk",
"--no-cache",
"mcpunk"
]
}
}
}
Pruebas, Linting, CI
Consulta el Makefile y los flujos de trabajo de github actions.