Startseite / Artikel

Serena MCP Server: Symbolorientiertes Code-Editing für KI-Assistenten

Konfigurieren Sie Serena mit Docker und SSE, damit Claude Code, VS Code und OpenCode eine durch LSP unterstützte Symbolsuche, sicheres Umbenennen sowie persistente Speicherung mit weniger Tokens erhalten.

Verlag: REACTAPP.TOP9 Min. Lesezeit2020 Wörter

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

Serena ist ein Open-Source-MCP-Server, der KI-Code-Assistenten ein IDE-ähnliches Verständnis einer Codebasis bietet. In einem TypeScript-Monorepo getestet, ist die Wirkung deutlich spürbar: Der Assistent wird im Umgang mit dem Code intelligenter und verbraucht dabei weniger Tokens.

Während ein herkömmlicher Assistent nur Dateien voller Text sieht, stellt Serena eine Verbindung zu einem Language Server Protocol-Backend her – dem Motor hinter Funktionen wie „Zur Definition gehen“, „Alle Referenzen finden“ und sicheren Umbenennungen in einem Editor – und stellt diese Funktionen als MCP-Tools für alle kompatiblen Clients zur Verfügung. Alles läuft auf dem lokalen Rechner, es werden mehr als 30 Sprachen unterstützt, und zu den unterstützten Clients gehören Claude Code, VS Code, Cursor, OpenCode und Claude Desktop.

Was stimmt nicht mit der Suche in reinem Text?

Fragt man einen Assistenten, alle Funktionen zu finden, die die Authentifizierung handhaben, verläuft der übliche Ablauf wie folgt:

  1. Führen Sie eine Textsuche mit grep oder ripgrep nach dem Wort „authentication“ durch.
  2. Lesen Sie die passenden Dateien, manchmal die gesamten, wodurch Tausende von Zeilen in den Kontext einbezogen werden.
  3. Legen Sie jede Zeile frei, die den String enthält, einschließlich Kommentare, String-Literale sowie unverwandter Treffer.

Das ist für ein kleines Projekt in Ordnung, wird aber mit zunehmender Größe des Codebases problematisch. Vier alltägliche Aufgaben zeigen diesen Unterschied auf:

+----------------------------+-------------------------------------+--------------------------------------------+
| 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                        |
+----------------------------+-------------------------------------+--------------------------------------------+

Die Kosten für Tokens verschärfen das Problem. Ohne semantische Tools muss der Assistent ganze Dateien lesen, um die Struktur zu verstehen, und trägt diesen Text anschließend im Kontext mit sich. Mit Serena liefert ein einziger Aufruf von find_symbol("UserService") genau das, was benötigt wird.

Arbeiten auf Symbolebene

Serena indiziert ein Projekt über einen echten Sprachserver und erstellt eine relationale Karte: Welche Funktionen rufen welche auf, wo Typen definiert sind und was was importiert. Wenn der Assistent Code verstehen oder ändern muss, greift er statt auf reine Datei-Lese- und Schreibvorgänge auf diese Tools zurück:

  • find_symbol findet ein Symbol anhand seines Namens und kann seinen vollständigen Inhalt zurückgeben.
  • get_symbols_overview erstellt eine Übersicht der Symbole in einer Datei oder einem Verzeichnis, ohne den Quellcode lesen zu müssen.
  • find_referencing_symbols listet alle Aufrufstellen sowie Verwendungen im gesamten Codebasis auf.
  • rename_symbol ändert den Namen über den LSP und aktualisiert dabei jede Referenz.
  • replace_symbol_body ersetzt den Inhalt einer Funktion oder Klasse und lässt den umgebenden Code unverändert.
  • insert_before_symbol und insert_after_symbol fügen Code an einer präzisen semantischen Stelle ein.
  • Das LLM bearbeitet nicht Zeile für Zeile und riskiert so, irgendwo eine Referenz zu verlieren. Es überträgt die Bearbeitung an Serena, die mit indizierten Daten sowie dem Sprachserver arbeitet, wodurch die Änderungen referenzorientiert erfolgen. Ein Symbol, das an 20 Stellen verwendet wird, wird an allen 20 Stellen aktualisiert. In den Projektunterlagen sind alle Tools des Sprachservers aufgelistet.

    Speicher und Dashboard

    Jedes Projekt verfügt außerdem über einen persistenten Speicher. Da der Assistent Konventionen, Fallstricke sowie Architekturentscheidungen lernt, kann er diese als Notizen speichern. Sie bleiben auch nach einem Neustart des Gesprächs erhalten und stehen in der nächsten Sitzung zur Verfügung, sodass die Arbeit nicht von vorne beginnen muss.

    Ein Web-Dashboard unter http://localhost:24282/dashboard/index.html ist standardmäßig aktiv und zeigt an, was Serena gerade tut:

    • Überblick über die Sitzung sowie aktive Projekte
    • Ein Protokoll der Tool-Aufrufe mit Statistiken dazu, welche Tools verwendet wurden, wie oft und für wie lange
    • Echtzeit-Server-Protokolle
    • Ein Konfigurationseditor, damit Einstellungen ohne Neustart geändert werden können
    • Ein Speichermanager zum Anzeigen und Bearbeiten von angesammelten Projektnotizen
    • Server-Kontrollen

    Auf macOS und Windows gibt es außerdem eine native Systemtray-Oberfläche, während Linux nur über den Browser nutzbar ist.

    Die Kontexte bestimmen die Tool-Liste

    Vordefinierte Kontexte steuern, welche Tools zur Verfügung gestellt werden. Der Grund dafür ist, dass ein Client bereits einige Aufgaben nativ bewältigen kann, wie beispielsweise das Lesen von Dateien oder die Ausführung von Shell-Befehlen; daher verzichtet Serena darauf, diese Funktionen doppelt anzubieten, und hält die Tool-Liste übersichtlich.

    +---------------------+------------------------------+------------------------------------------------+
    | 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).                              |
    +---------------------+------------------------------+------------------------------------------------+
    

    Für einen Docker-Container, der Claude Code, VS Code und OpenCode gemeinsam bereitstellt, verwenden Sie desktop-app, den Über-Set. Wenn Serena lokal pro Client ausgeführt wird, wählen Sie den Kontext, der zu diesem Tool passt.

    Installation

    Verwenden Sie uv. Serenas eigene Dokumentation warnt vor MCP-Marktplätzen, da diese oft veraltete Befehle liefern:

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

    Dadurch wird die serena CLI global installiert und der Einrichtungswizard gestartet. Anschließend werden die Clients konfiguriert.

    Claude Code, global (empfohlen):

    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 pro Projekt:

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

    VS Code, in .vscode/mcp.json am Projektverzeichnisanfang:

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

    Claude Desktop, in ~/.config/claude_desktop_config.json unter Linux oder ~/Library/Application Support/Claude/claude_desktop_config.json unter macOS:

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

    Ausführen in Docker

    Docker ist der von Serenas Dokumentation bevorzugte Ansatz für die Isolation, insbesondere dann, wenn einem Agenten Änderungen gestattet sind. In einem Container kann dieser nur die in ihn eingebundenen Verzeichnisse sehen. Ein Eintrag in 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
    

    Hinweise zu dieser Konfiguration:

    • --transport sse muss innerhalb von Docker gesetzt werden, da stdio nur dann funktioniert, wenn der Client Serena selbst als Kindprozess startet.
    • --context desktop-app stellt das umfangreichste Werkzeugset zur Verfügung und eignet sich sowohl für Claude Code, VS Code-Erweiterungen als auch für OpenCode. Engere Kontexte wie claude-code deaktivieren Werkzeuge, auf die andere Clients angewiesen sind.
    • --project /workspace/myproject muss der im Container interne Pfad sein, an dem der Code montiert wird. Verwenden Sie hier nicht --project-from-cwd, da der Arbeitsverzeichnis des Containers der Installationsort von Serena ist und nicht das Projekt.
    • Unübliche Host-Ports (10121 und 34282) ermöglichen es mehreren Projekten, jeweils ihre eigene Serena ohne Kollisionen zu betreiben.

    Wenn SERENA_DOCKER=1 gesetzt ist, weiß Serena, dass sie sich innerhalb eines Containers befindet. Die globale Datei ~/.serena/serena_config.yml, die entweder eingemontet oder direkt in die Einrichtung integriert ist, sollte konfigurationseinstellungen enthalten, die für Container geeignet sind:

    gui_log_window: false
    web_dashboard_listen_address: "0.0.0.0"
    web_dashboard_open_on_launch: false
    

    Um die Host-Konfiguration zu mounten, fügen Sie eine Volumenkopplung ~/.serena:/root/.serena hinzu. Starten Sie den Dienst:

    docker compose up -d serena
    

    Verbindung der Clients mit dem Container

    Jeder Client kommuniziert mit demselben SSE-Endpunkt, lediglich das Konfigurationsformat unterscheidet sich. Claude Code kann es global registrieren:

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

    Oder das Projekt kann eine .mcp.json enthalten:

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

    VS Code verwendet eine .vscode/mcp.json:

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

    OpenCode verwendet opencode.jsonc:

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

    Codex, Kilo Code und andere MCP-kompatible Clients funktionieren auf ähnliche Weise.

    Projektkonfiguration

    Serena liest .serena/project.yml im Projektverzeichnis. Eine praktische TypeScript-Einrichtung beginnt mit dem Namen:

    project_name: "myproject"
    

    Dann Sprachen und ignorieren Sie die Regeln:

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

    Die Liste ignored_paths dient als zusätzliche Sicherheitsmaßnahme zu .gitignore. Allein node_modules kann mehr als 80.000 Dateien enthalten, wodurch das Indexieren extrem langsam wird und die Suche nach Symbolen durch interne Strukturen von Drittanbietern überladen wird.

    Was kommittiert und was ignoriert werden soll:

    .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)
    

    Was ändert sich in der Praxis

    In einem Deno 2- und TypeScript-Monorepo mit Frontend, API und gemeinsamen Paketen heben sich vier Aspekte hervor:

    • Über-Paket-Lösung. Durch das Mounten des gesamten Monorepos als ein einziger Arbeitsbereich ermittelt Serena in einem Schritt den Typ aus packages/ sowie seine Verwendungen unter apps/api/, während der Assistent früher Datei für Datei durchgehen und die Informationen zusammenfügen musste.
    • Sichere Refaktorisierungen. Eine Aufgabe, die etwa 20 Dateien betraf und eine gemeinsame Schnittstelle umbenannte, wurde über rename_symbol abgewickelt, ohne etwas zu übersehen. Eine Textsuche und -ersatzfunktion lässt immer noch eine dynamische Verwendung, die sich in einer Template-String befindet, unberücksichtigt.
  • Fragen in natürlicher Sprache. Wenn man um eine Erklärung des Authentifizierungsablaufs bittet, werden die relevanten Symbole zusammen mit dem Kontext bereitgestellt, anstatt dass der Assistent durch Dateien blättert. Die Antwort kommt schneller, genauer und mit weniger verwendetem Kontext.
  • Token-Einsparung. Es ist schwierig, das genau zu messen, aber es ist real. Um eine Definition zu finden, wird find_symbol aufgerufen und der Inhalt direkt abgerufen; Änderungen bleiben außerhalb des Kontexts, da Serena den Text schreibt.
  • Makefile-Skripte machen den Arbeitsablauf zu einer Gewohnheit:

    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
    

    Urteil

    Logisches Denken und Codegenerierung sind die Stärken von KI-basierten Programmierwerkzeugen. Das Arbeiten mit großen Codebasen ist hingegen eine Schwachstelle. Ein für genau diese Aufgabe konzipiertes Sprachserver verbessert sowohl die Qualität der Ergebnisse als auch die Kosten. Teams, die viel Zeit mit dem Lesen von Dateien verbringen und dennoch ungenaue Refaktorisierungen in großen Repositorien durchführen, werden in einem Nachmittag Aufwand eine lohnende Investition sehen. Docker hält alles ordentlich: Serena läuft neben dem Rest des Stacks, behält seinen Index bei und stellt jedem Teammitglied einen SSE-Endpunkt zur Verfügung.