Scalable CTags

Servidor MCP de CTags con autodiscovery, diseñado para proyectos grandes

Documentación

Servidor MCP para permitir la navegación de código mediante un archivo de tags. Tiene como objetivo manejar archivos de tags grandes con una sobrecarga mínima.

Lars Hollenbach db4e896232 fix(server): register watcher with absolute path on manual load...

load_tags_file called o.watcher.Add(path) with the user-supplied path,
which can be relative. fsnotify reports events for that file under a
different key (the path the kernel gives back), so a relative-path load
could silently drop watcher events.

Use the absolute path returned by ParseTagsFile (pf.Path), which the index and discovery layer already canonicalise to. Add tests covering both plain and non-canonical (./tags) relative inputs.

AI-Assisted: written with opencode and MiniMax-M3

2026-08-05 04:00:18 +02:00
archived-planschore(plans): move auto-discovery to archive2026-07-14 22:34:30 +02:00
cmd/ctags-mcpfeat(server) Load discovered tags files in background worker pool2026-08-05 03:46:06 +02:00
internalfix(server): register watcher with absolute path on manual load2026-08-05 04:00:18 +02:00
testdata/tagsfeat: implement scalable CTags MCP server with memory-mapped file parsing2026-07-10 02:15:43 +02:00
.envrcfeat: implement scalable CTags MCP server with memory-mapped file parsing2026-07-10 02:15:43 +02:00
.gitignorechore: fix gitignore, add missing main.go2026-07-14 23:17:16 +02:00
AGENTS.mdfeat(server) Load discovered tags files in background worker pool2026-08-05 03:46:06 +02:00
flake.lockfeat: implement scalable CTags MCP server with memory-mapped file parsing2026-07-10 02:15:43 +02:00
flake.nixfeat: implement scalable CTags MCP server with memory-mapped file parsing2026-07-10 02:15:43 +02:00
go.modrefactor(parser,indexer,server) consolidate shared fields into CTagsEntry and strip filePaths + fileID from TagIndex2026-07-15 03:04:31 +02:00
go.sumrefactor(parser,indexer,server) consolidate shared fields into CTagsEntry and strip filePaths + fileID from TagIndex2026-07-15 03:04:31 +02:00
README.mdfeat(server) Load discovered tags files in background worker pool2026-08-05 03:46:06 +02:00

Servidor MCP de CTags Escalable

Un servidor de búsqueda de símbolos ctags con mapeo de memoria que expone una interfaz MCP (Model Context Protocol) para agentes de IDE y herramientas LLM. Diseñado para manejar múltiples archivos de tags grandes en varios subproyectos.

Características

  • Soporte multi-archivo: Carga y busca en múltiples archivos de tags simultáneamente
  • Actualización automática: Observa los archivos cargados y se actualiza automáticamente
  • Campos extendidos: Extrae kind, language y filePath del formato extendido v2 de ctags

Compilación

Requiere Go 1.26+ y un entorno Nix (o la cadena de herramientas estándar de Go).

# With Nix (recommended)
nix develop --command go build -o ctags-mcp ./cmd/ctags-mcp

# Without Nix
go build -o ctags-mcp ./cmd/ctags-mcp

Archivo de tags

Genera un archivo de tags para tu proyecto antes de ejecutar el servidor:

ctags -n -R .

La bandera -n (--excmd=number) es obligatoria: indica a ctags que almacene números de línea en lugar de patrones regex como comandos de búsqueda. Sin ella, el servidor devuelve line: 0 para todas las búsquedas de símbolos.

Ejecución

El servidor se comunica a través de stdio (JSON-RPC).

./ctags-mcp

Al iniciar, el servidor descubre automáticamente los archivos tags y tags.in desde el directorio de trabajo actual (hasta 8 niveles de profundidad) y los analiza en un grupo de goroutines en segundo plano: el handshake de MCP responde inmediatamente, sin importar cuán grandes sean los archivos de tags. Las herramientas de búsqueda (lookup_symbol, get_symbol_info) se bloquean hasta que se complete la carga inicial; list_tags_files responde de inmediato e informa el status por archivo (loading / ready) más una bandera loadingComplete de nivel superior. Los directorios ocultos (con prefijo de punto) siempre se omiten. Usa --auto-discover=false para deshabilitar el auto-descubrimiento por completo.

Por defecto, los directorios adicionales que coinciden con la bandera --skip-dirs (nombres de directorio separados por comas) se excluyen (por ejemplo, vendor, node_modules).

Configura el descubrimiento:

BanderaPredeterminadoDescripción
--auto-discovertrueHabilitar (true) o deshabilitar (false) el auto-descubrimiento
--depth8Niveles máximos de recursión por debajo del directorio de trabajo
--skip-dirs(ninguno)Nombres de directorio separados por comas a excluir

Uso en opencode

Agrega el servidor a tu opencode.json bajo la clave mcp:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "ctags": {
      "type": "local",
      "command": ["./ctags-mcp"],
      "enabled": true
    }
  }
}

Después de editar opencode.json, cierra y reinicia opencode para que los cambios surtan efecto.

Herramientas disponibles

La respuesta de load_tags_file incluye un campo preloaded establecido en true cuando el archivo fue auto-descubierto al iniciar.

HerramientaDescripciónParámetros
load_tags_fileCargar un archivo de tags de ctags y construir el índicepath (obligatorio)
lookup_symbolBuscar en el índice un símbolo por nombre (se bloquea hasta que se complete la carga inicial)name (obligatorio), fileID (opcional)
get_symbol_infoObtener información detallada sobre un solo símbolo (se bloquea hasta que se complete la carga inicial)name (obligatorio), fileID (opcional)
list_tags_filesListar todos los archivos de tags descubiertos con metadatos, status (loading / ready) y bandera loadingCompleteninguno

Recursos disponibles

URIDescripción
tagsfile://metadataMetadatos JSON para un archivo de tags cargado
file://{abspath}:{line}Contenido de la línea fuente de una entrada de tag

Ejemplo de uso

Una vez que el servidor esté configurado en opencode, puedes hacer preguntas en lenguaje natural y el agente usará las herramientas:

"Find all references to AddTagsFile in the codebase"
"Show me detailed info about the EntryRef struct"
"What tags files are currently loaded?"
"Look up the Lookup function, filtering by fileID 0"

El agente llamará a list_tags_files para verificar qué ya está cargado, luego usará lookup_symbol o get_symbol_info para responder. Para proyectos sin un archivo de tags en disco, llamará a load_tags_file primero.

Arquitectura

internal/
  parser/       Streaming line-by-line ctags parser
  indexer/      In-memory index (map[string][]Entry); lock-free single-pass
                parsing (ParseTagsFile) with deferred merge (InstallParsed)
  server/       MCP protocol layer (Server) + index lifecycle
                (IndexOrchestrator: discovery, background load, watch/rebuild)
  cmd/ctags-mcp/  Entry point (stdio transport)