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í:

  1. Divide los archivos en fragmentos lógicos (funciones, clases, secciones de markdown)
  2. Da al LLM herramientas para buscar y consultar estos fragmentos
  3. 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.

MCPunk MCP server

GitHub Repository

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.

  1. Instalar uv
  2. Pon el fragmento a continuación en tu claude_desktop_config.json (Detalles sobre claude_desktop_config.json incluyendo ubicación)
  3. 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
  4. 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:
    1. Primero, el usuario necesita configurar mcpunk para trabajar con su proyecto usando la herramienta configure_project
    2. Para ver qué ramas se verificaron recientemente (para identificar contra qué hacer el diff)
    3. 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_ref para la ref scratch/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?
  • [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

La esencia del roaming RAG es

  1. 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.
  2. 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:

  • PythonChunker divide en clases, funciones, imports a nivel de archivo, y declaraciones a nivel de archivo (p. ej. globales). Aplicable a archivos que terminan en .py
  • VueChunker divide en fragmentos 'template', 'script', 'style' - o lo que sea que exista como elementos de nivel superior <blah>....</blah>. Aplicable a archivos que terminan en .vue
  • MarkdownChunker divide en secciones de markdown (por encabezado). Aplicable a archivos que terminan en .md
  • WholeFileChunker fragmentador 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

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
  • 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_project y coloca los archivos bajo el URI gitdiff:// 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.