Inicio / Artículos

Serena MCP Server: Edición de código con reconocimiento de símbolos para asistentes de IA

Configura Serena con Docker y SSE para que Claude Code, VS Code y OpenCode cuenten con búsqueda de símbolos respaldada por LSP, renombramientos seguros y memoria persistente con menos tokens.

Editor: REACTAPP.TOP9 min de lectura2020 palabras

Fuentes: Serena MCP: Giving Your AI Coding Tools an IDE Brain

Serena es un servidor MCP de código abierto que permite a los asistentes de programación basados en IA comprender una base de código al estilo de un IDE. Probado en un monorepo de TypeScript, el efecto es notable: el asistente se vuelve más inteligente al analizar el código y utiliza menos tokens para hacerlo.

Mientras que un asistente típico ve archivos llenos de texto, Serena se conecta a un backend basado en el Language Server Protocol, el motor que está detrás de funciones como Ir a Definición, Encontrar todas las referencias y renombrar de forma segura en un editor, y publica estas funcionalidades como herramientas MCP para cualquier cliente compatible. Todo funciona en la máquina local, se admiten más de 30 lenguajes, y los clientes soportados incluyen Claude Code, VS Code, Cursor, OpenCode y Claude Desktop.

Qué falla con la búsqueda de texto plano

Si pides a un asistente que encuentre todas las funciones que manejan la autenticación, el procedimiento habitual es:

  1. Ejecutar una búsqueda de texto con grep o ripgrep para la palabra “authentication”.
  2. Leer los archivos que coincidan, a veces en su totalidad, lo que implica analizar miles de líneas en contexto.
  3. Devolver cada línea que contenga la cadena, incluyendo comentarios, literales de cadena y resultados no relacionados.

Eso funciona bien para un proyecto pequeño, pero se vuelve insostenible a medida que crece la base de código. Cuatro tareas cotidianas muestran esa limitación:

+----------------------------+-------------------------------------+--------------------------------------------+
| Task                       | Without Serena                      | With Serena                                |
+============================+=====================================+============================================+
| **Semantic search**        | Text match on "auth" - returns      | Returns `authenticateUser()`,              |
| "find auth functions"      | false positives, misses functions   | `login()`, `verifyCredentials()`           |
|                            | named `verifyCredentials`           | with file locations and line numbers       |
+----------------------------+-------------------------------------+--------------------------------------------+
| **Go to definition**       | Searches files for "User" and       | Jumps directly to the `User`               |
| "show me the User schema"  | "schema" - returns every reference  | class/interface definition with            |
|                            |                                     | full import tree                           |
+----------------------------+-------------------------------------+--------------------------------------------+
| **Find references**        | Text search for "PaymentProcessor"  | Returns all usages with context:           |
| "where is                  | - misses dynamic usages             | imports, instantiations, method calls      |
| PaymentProcessor used?"    |                                     |                                            |
+----------------------------+-------------------------------------+--------------------------------------------+
| **Cross-file refactoring** | Text search and replace - misses    | Semantic rename via LSP - updates          |
| "rename UserService        | string interpolations or aliased    | every reference correctly across           |
| to AccountService"         | imports, breaks things              | the entire codebase                        |
+----------------------------+-------------------------------------+--------------------------------------------+

El costo de los tokens agrava el problema. Sin herramientas semánticas, el asistente debe leer archivos completos para comprender su estructura y luego mantener ese texto en contexto. Con Serena, una sola llamada a find_symbol("UserService") devuelve únicamente lo que se necesita.

Trabajo a nivel de símbolos

Serena indexa un proyecto a través de un servidor de lenguaje real y crea un mapa relacional: qué funciones llaman a cuáles, dónde se definen los tipos y qué importa qué. Cuando el asistente debe comprender o modificar código, recurre a estas herramientas en lugar de leer y escribir archivos directamente:

  • find_symbol localiza un símbolo por nombre y puede devolver todo su contenido.
  • get_symbols_overview mapea los símbolos en un archivo o directorio sin leer el código fuente.
  • find_referencing_symbols enumera todos los lugares donde se hace referencia a un símbolo en todo el códigobase.
  • rename_symbol renombra a través del LSP, actualizando cada referencia.
  • replace_symbol_body sustituye el cuerpo de una función o clase sin afectar al código circundante.
  • insert_before_symbol y insert_after_symbol añaden código en una posición semántica precisa.
  • El LLM no edita línea por línea y corre el riesgo de perder alguna referencia. En su lugar, transfiere la edición a Serena, que trabaja con datos indexados y el servidor de lenguaje, por lo que las modificaciones tienen en cuenta todas las referencias. Un símbolo utilizado en 20 lugares se actualiza en los 20. La documentación del proyecto enumera todas las herramientas del servidor de lenguaje.

    Memoria y panel de control

    Cada proyecto también cuenta con un almacenamiento de memoria persistente. A medida que el asistente aprende las convenciones, los problemas comunes y las decisiones arquitectónicas, puede guardarlos como notas. Estas notas sobreviven a los reinicios de la conversación y están disponibles en la sesión siguiente, de modo que el trabajo no se reinicia desde cero.

    Un panel de control web en http://localhost:24282/dashboard/index.html está activo por defecto y muestra qué está haciendo Serena:

    • Resumen de la sesión y proyectos activos
    • Un registro de llamadas a herramientas con estadísticas sobre qué herramientas se ejecutaron, con qué frecuencia y durante cuánto tiempo
    • Registros en tiempo real del servidor
    • Un editor de configuración, para que los ajustes se modifiquen sin necesidad de reiniciar
    • Un administrador de memoria para ver y editar notas de proyectos acumuladas
    • Controles del servidor

    En macOS y Windows también existe un wrapper nativo en la bandeja del sistema, mientras que en Linux solo se utiliza el navegador.

    Los contextos determinan la lista de herramientas

    Los contextos predefinidos controlan qué herramientas se muestran. La lógica detrás es que un cliente ya puede manejar algunas tareas de forma nativa, como la lectura de archivos o la ejecución de comandos en la terminal, por lo que Serena evita duplicarlas y mantiene la lista de herramientas ordenada.

    +---------------------+------------------------------+------------------------------------------------+
    | Context             | Designed for                 | What it does                                   |
    +=====================+==============================+================================================+
    | `desktop-app`       | Claude Desktop, general use  | **Full toolset** - everything Serena offers.   |
    |                     |                              | Use this when the client has no built-in       |
    |                     |                              | coding capabilities. This is also the right    |
    |                     |                              | choice for a shared Docker instance serving    |
    |                     |                              | multiple different clients.                    |
    +---------------------+------------------------------+------------------------------------------------+
    | `claude-code`       | Claude Code                  | Disables tools that overlap with Claude        |
    |                     |                              | Code's built-in capabilities (file edits,      |
    |                     |                              | shell commands, etc.) to avoid conflicts.      |
    |                     |                              | Single-project context.                        |
    +---------------------+------------------------------+------------------------------------------------+
    | `ide`               | VS Code, Cursor, Cline, Kilo | Generic IDE augmentation - focuses on          |
    |                     |                              | semantic tools, assumes the IDE already        |
    |                     |                              | handles basic file operations.                 |
    |                     |                              | Single-project context.                        |
    +---------------------+------------------------------+------------------------------------------------+
    | `agent`             | Agno, autonomous agents      | Broader autonomy for agents that drive the     |
    |                     |                              | full workflow independently.                   |
    +---------------------+------------------------------+------------------------------------------------+
    | `codex`             | OpenAI Codex                 | Optimized for Codex's tool calling format.     |
    +---------------------+------------------------------+------------------------------------------------+
    | NOTE: The `claude-code` and `ide` contexts are **single-project**: when you pass a project          |
    | path at startup, those contexts lock down to only the tools relevant to that project and            |
    | disable the project-switching tool entirely (since you won't need it).                              |
    +---------------------+------------------------------+------------------------------------------------+
    

    Para un contenedor Docker que sirva simultáneamente a Claude Code, VS Code y OpenCode, utilice desktop-app, que es el superconjunto. Cuando Serena se ejecute localmente por cliente, elija el contexto que corresponda a esa herramienta.

    Instalación

    Utilice uv. La propia documentación de Serena advierte contra los mercados MCP, ya que suelen incluir comandos obsoletos:

    uv tool install -p 3.13 serena-agent@latest --prerelease=allow
    serena init
    

    Eso instala la CLI serena a nivel global y inicia el asistente de configuración. A continuación se configuran los clientes.

    Claude Code, global (recomendado):

    claude mcp add --scope user serena -- serena start-mcp-server \
      --context claude-code --project-from-cwdlaude mcp add serena -- serena start-mcp-server --context claude-code --project "$(pwd)"
    

    Claude Code, por proyecto:

    claude mcp add serena -- serena start-mcp-server --context claude-code --project "$(pwd)"
    

    VS Code, en .vscode/mcp.json en la raíz del proyecto:

    {
      "servers": {
        "serena": {
          "type": "stdio",
          "command": "serena",
          "args": [
            "start-mcp-server",
            "--context", "ide",
            "--project", "${workspaceFolder}"
          ]
        }
      }
    }
    

    Claude Desktop, en ~/.config/claude_desktop_config.json en Linux o ~/Library/Application Support/Claude/claude_desktop_config.json en macOS:

    {
      "mcpServers": {
        "serena": {
          "command": "serena",
          "args": ["start-mcp-server", "--context", "desktop-app"]
        }
      }
    }
    

    Ejecución en Docker

    Docker es el enfoque que prefieren los documentos de Serena para el aislamiento, especialmente cuando se permite a un agente realizar ediciones. Dentro de un contenedor solo puede ver los directorios montados en él. Un elemento de compose.yml:

    services:
      serena:
        image: ghcr.io/oraios/serena:latest
        container_name: myproject-serena
        restart: unless-stopped
        environment:
          - SERENA_DOCKER=1
        ports:
          - "10121:9121"   # SSE endpoint
          - "34282:24282"  # Web dashboard
        volumes:
          - .:/workspace/myproject
        command: >
          serena start-mcp-server
            --transport sse
            --port 9121
            --host 0.0.0.0
            --context desktop-app
            --project /workspace/myproject
    

    Notas sobre esa configuración:

    • --transport sse debe establecerse dentro de Docker, ya que stdio solo funciona cuando el cliente inicia a Serena como proceso hijo.
    • --context desktop-app ofrece el conjunto de herramientas más amplio y es adecuado para Claude Code, extensiones de VS Code y OpenCode por igual. Los contextos más específicos como claude-code desactivan herramientas de las que dependen otros clientes.
    • --project /workspace/myproject debe ser la ruta dentro del contenedor donde se monta el código. Evite usar --project-from-cwd en este caso, ya que el directorio de trabajo del contenedor es la ubicación de instalación de Serena y no el proyecto.
    • Los puertos del host inusuales (10121 y 34282) permiten que varios proyectos ejecuten su propia instancia de Serena sin colisiones.

    Al tener establecido SERENA_DOCKER=1, Serena sabe que se encuentra dentro de un contenedor. El archivo global ~/.serena/serena_config.yml, montado o integrado en la configuración, debe contener ajustes compatibles con contenedores:

    gui_log_window: false
    web_dashboard_listen_address: "0.0.0.0"
    web_dashboard_open_on_launch: false
    

    Para montar la configuración del host, agregue una asignación de volumen ~/.serena:/root/.serena. Inicie el servicio:

    docker compose up -d serena
    

    Conectar clientes al contenedor

    Cada cliente se comunica con el mismo punto final SSE, y solo difiere el formato de la configuración. Claude Code puede registrarlo a nivel global:

    claude mcp add serena --transport sse --url http://localhost:10121/sse
    

    O el proyecto puede contener un .mcp.json:

    {
      "mcpServers": {
        "serena": {
          "type": "sse",
          "url": "http://localhost:10121/sse"
        }
      }
    }
    

    VS Code utiliza un .vscode/mcp.json:

    {
      "servers": {
        "serena": {
          "type": "sse",
          "url": "http://localhost:10121/sse"
        }
      }
    }
    

    OpenCode utiliza opencode.jsonc:

    {
      "mcp": {
        "serena": {
          "type": "remote",
          "url": "http://localhost:10121/sse",
          "enabled": true
        }
      }
    }
    

    Codex, Kilo Code y otros clientes compatibles con MCP funcionan de manera similar.

    Configuración del proyecto

    Serena lee .serena/project.yml en la raíz del proyecto. Una configuración práctica de TypeScript comienza con el nombre:

    project_name: "myproject"
    

    Luego los idiomas e ignoran las reglas:

    languages:
      - typescript   # uses typescript-language-serverencoding: "utf-8"
    ignore_all_files_in_gitignore: trueignored_paths:
      - "node_modules"
      - "dist"
      - "build"
      - "coverage"
      - ".next"
      - "out"
      - ".cache"
    

    La lista ignored_paths funciona como una red de seguridad adicional a .gitignore. Solo node_modules puede contener más de 80,000 archivos, y su indexación hace que el inicio sea extremadamente lento además de saturar la búsqueda de símbolos con elementos internos de terceros.

    Qué comprometer y qué ignorar:

    .serena/project.yml      ← commit this (shared config)
    .serena/memories/        ← commit this (AI-generated project notes, useful for everyone)
    .serena/cache/           ← gitignore (rebuilt per machine)
    .serena/project.local.yml ← gitignore (per-developer overrides)
    

    Qué cambia en la práctica

    En un monorepo de Deno 2 y TypeScript con una interfaz frontal, una API y paquetes compartidos, cuatro aspectos destacan:

    • Resolución entre paquetes. Al montar todo el monorepo como un único espacio de trabajo, Serena localiza un tipo desde packages/ hasta sus usos en apps/api/ en un solo paso, mientras que antes el asistente tenía que leer archivo por archivo y unir las partes manualmente.
    • Refactorizaciones más seguras. Una tarea que involucraba unos 20 archivos, consistente en renombrar una interfaz compartida, se realizó mediante rename_symbol sin pasar por alto nada. La búsqueda y reemplazo de texto siempre deja algún uso dinámico oculto dentro de una cadena de plantilla.
    • Preguntas en lenguaje natural. Al solicitar una explicación del flujo de autenticación, se obtienen los símbolos relevantes junto con su contexto, en lugar de que el asistente busque entre archivos. La respuesta llega más rápido, con mayor precisión y utilizando menos contexto.
    • Ahorro de tokens. Es difícil medirlo con exactitud, pero es real. Para encontrar una definición basta con llamar a find_symbol y obtener el contenido directamente; además, las ediciones no se realizan fuera de contexto, ya que Serena es quien escribe.

    Los atajos de Makefile convierten este flujo de trabajo en un hábito:

    make serena-up      # Start the Serena container
    make serena-stop    # Stop it
    make serena-logs    # Tail logs
    make serena-index   # Force re-index after big changes
    make serena-health  # Health check the workspace
    

    Veredicto

    El razonamiento y la generación de código son las fortalezas de las herramientas de programación basadas en IA. Manejar una gran base de código es su punto débil. Un servidor de lenguaje diseñado específicamente para esta tarea mejora tanto la calidad de las respuestas como el costo. Los equipos que invierten mucho tiempo en leer archivos y aún así realizan refactorizaciones descuidadas en repositorios grandes encontrarán que vale la pena dedicar una tarde a su configuración. Docker mantiene todo ordenado: Serena funciona junto al resto de la infraestructura, conserva su índice y ofrece un punto de extremo SSE a cada cliente del equipo.

    Leer más