Serena MCP Server: редагування коду з урахуванням символів для допоміжних систем ШІ
Налаштуйте Serena за допомогою Docker та SSE, щоб Claude Code, VS Code та OpenCode отримали пошук символів із підтримкою LSP, безпечну заміну назв та постійну пам’ять із меншою кількістю токенів.
Джерела: Serena MCP: Giving Your AI Coding Tools an IDE Brain
Serena — це сервер MCP з відкритим кодом, який надає AI-асистентам з кодування розуміння кодової бази у стилі IDE. Після випробування на монорепозиторії на TypeScript ефект є помітним: асистент краще розуміє код та витрачає на це менше токенів.
Де звичайний асистент бачить файли, повні тексту, Serena підключається до бекенду Language Server Protocol — двигуна, який стоїть за функціями «Йти до визначення», «Знайти всі посилання» та безпечне перейменування в редакторі, — та розповсюджує ці функції як інструменти MCP для будь-якого сумісного клієнта. Усе працює на локальній машині, підтримується понад 30 мов, а серед сумісних клієнтів — Claude Code, VS Code, Cursor, OpenCode та Claude Desktop.
Що не так із пошуком у звичайному тексті
Якщо попросити асистента знайти всі функції, які обробляють автентифікацію, звичайна процедура виглядає так:
- Виконайте пошук тексту за допомогою
grepабоripgrepза словом „authentication“. - Прочитайте відповідні файли, іноді всі цілком, щоб побачити тисячі рядків у контексті.
- Поверніть кожен рядок, який містить цей рядок, включаючи коментарі, літерали рядків та несумісні результати пошуку.
Це підходить для невеликого проекту, але стає неконтрольованим у міру зростання кодової бази. Чотири повсякденні завдання демонструють цю проблему:
+----------------------------+-------------------------------------+--------------------------------------------+
| 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 |
+----------------------------+-------------------------------------+--------------------------------------------+
Вартість токенів посилює проблему. Без семантичних інструментів асистент читає цілі файли, щоб зрозуміти їхню структуру, а потім використовує цей текст у контексті. З Serena один виклик find_symbol("UserService") повертає саме те, що потрібно.
Робота на рівні символів
Serena індексує проект через справжній мовний сервер та створює відносну карту: які функції викликають одна одну, де визначені типи та що імпортується. Коли асистенту потрібно зрозуміти чи змінити код, він використовує ці інструменти замість прямого читання та запису файлів:
find_symbolзнаходить символ за назвою та може повернути його повний вміст.get_symbols_overviewстворює карту символів у файлі чи каталозі без читання вихідного коду.find_referencing_symbolsперелічує всі місця виклику та використання символів у всьому кодовому базі.
rename_symbol змінює назву через LSP, оновлюючи кожен посилання.replace_symbol_body замінює тіло функції чи класу, залишаючи навколишній код недоторканим.insert_before_symbol та insert_after_symbol додають код у точне семантичне місце.LLM не редагує текст рядок за рядком, щоб уникнути втрати посилань. Він передає завдання на редагування Serena, яка працює з індексованими даними та мовним сервером, тому зміни враховують усі посилання. Символ, використаний у 20 місцях, оновлюється у всіх 20. У документації проекту перелічені всі інструменти мовного сервера.
Пам’ять та панель керування
Кожен проект також має постійний сховище пам’яті. У міру того, як асистент вивчає стандарти, особливості та архітектурні рішення, він може зберігати їх у вигляді нотаток. Вони зберігаються після скидання розмови та доступні під час наступної сесії, тож робота не починається з нуля.
Веб-панель керування за адресою http://localhost:24282/dashboard/index.html увімкнена за замовчуванням та відображає те, що робить Serena:
- Огляд сеансу та активні проекти
- Журнал викликів інструментів із статистикою щодо того, які інструменти використовувалися, як часто та протягом якого часу
- Журнали сервера в реальному часі
- Редактор налаштувань, щоб зміни відбувалися без перезавантаження
- Менеджер пам’яті для перегляду та редагування накопичених приміток до проектів
- Керування сервером
У macOS та Windows також є нативний інтерфейс у системній панелі, тоді як у Linux використовується лише браузер.
Контексти визначають список інструментів
Заздалегідь визначені контексти контролюють, які інструменти будуть доступні. Причина полягає у тому, що клієнт може вже самостійно обробляти деякі завдання, такі як читання файлів чи виконання команд у шеллі, тому Serena уникає їх дублювання та підтримує охайний список інструментів.
+---------------------+------------------------------+------------------------------------------------+
| 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). |
+---------------------+------------------------------+------------------------------------------------+
Для одного контейнера Docker, який обслуговує Claude Code, VS Code та OpenCode одночасно, використовуйте desktop-app — його надмножину. Коли Serena запускається локально для кожного клієнта, оберіть контекст, що відповідає цьому інструменту.
Встановлення
Використовуйте uv. Власна документація Serena попереджає про ринки MCP, які часто постачають застарілі команди:
uv tool install -p 3.13 serena-agent@latest --prerelease=allow
serena init
Це встановлює serena CLI у глобальному режимі та запускає майстра налаштувань. Далі налаштовуються клієнти.
Claude Code, глобальний (рекомендовано):
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, за проектом:
claude mcp add serena -- serena start-mcp-server --context claude-code --project "$(pwd)"
VS Code, у файлі .vscode/mcp.json у корені проекту:
{
"servers": {
"serena": {
"type": "stdio",
"command": "serena",
"args": [
"start-mcp-server",
"--context", "ide",
"--project", "${workspaceFolder}"
]
}
}
}
Claude Desktop знаходиться у файлі ~/.config/claude_desktop_config.json у Linux або у файлі ~/Library/Application Support/Claude/claude_desktop_config.json у macOS:
{
"mcpServers": {
"serena": {
"command": "serena",
"args": ["start-mcp-server", "--context", "desktop-app"]
}
}
}
Робота в Docker
Docker — це підхід, який рекомендують документація Serena для ізоляції, особливо коли агенту дозволено вносити зміни. У контейнері він може бачити лише ті каталоги, які до нього підключені. Приклад запису у 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
Примітки щодо цієї конфігурації:
--transport sseмає бути встановлений всередині Docker, оскількиstdioможе працювати лише тоді, коли клієнт запускає Serena як дочірній процес.--context desktop-appнадає найбільший набір інструментів та підходить як для Claude Code, так і для розширень VS Code та OpenCode. Більш вузькі контексти, такі якclaude-code, вимикають інструменти, від яких залежать інші клієнти.--project /workspace/myprojectмає бути внутрішнім шляхом у контейнері, де монтується код. Уникайте тут--project-from-cwd, оскільки робоча директорія контейнера — це місце встановлення Serena, а не проект.- Незвичайні порти хоста (
10121та34282) дозволяють кільком проектам кожен з них запускати власну версію Serena без конфліктів.
Якщо встановлено SERENA_DOCKER=1, Serena розуміє, що знаходиться всередині контейнера. Глобальний файл ~/.serena/serena_config.yml, який монтується або вбудовується в налаштування, має містити параметри, придатні для роботи з контейнерами:
gui_log_window: false
web_dashboard_listen_address: "0.0.0.0"
web_dashboard_open_on_launch: false
Щоб завантажити конфігурацію хоста, додайте мапування об’єму ~/.serena:/root/.serena. Запустіть сервіс:
docker compose up -d serena
Підключення клієнтів до контейнера
Кожен клієнт взаємодіє з тим самим кінцевим пунктом SSE, і відрізняється лише формат конфігурації. Claude Code може зареєструвати його глобально:
claude mcp add serena --transport sse --url http://localhost:10121/sse
Або проєкт може містити файл .mcp.json:
{
"mcpServers": {
"serena": {
"type": "sse",
"url": "http://localhost:10121/sse"
}
}
}
VS Code використовує файл .vscode/mcp.json:
{
"servers": {
"serena": {
"type": "sse",
"url": "http://localhost:10121/sse"
}
}
}
OpenCode використовує opencode.jsonc:
{
"mcp": {
"serena": {
"type": "remote",
"url": "http://localhost:10121/sse",
"enabled": true
}
}
}
Codex, Kilo Code та інші клієнти, сумісні з MCP, працюють аналогічно.
Конфігурація проекту
Serena читає файл .serena/project.yml у корені проекту. Практична налаштування TypeScript починаються з імені:
project_name: "myproject"
Потім мови та ігнорування правил:
languages:
- typescript # uses typescript-language-serverencoding: "utf-8"
ignore_all_files_in_gitignore: trueignored_paths:
- "node_modules"
- "dist"
- "build"
- "coverage"
- ".next"
- "out"
- ".cache"
Список ignored_paths є додатковим захистом поруч із файлом .gitignore. Лише папка node_modules може містити понад 80 000 файлів, а їх індексування значно уповільнює запуск та заповнює результати пошуку символів внутрішніми елементами сторонніх бібліотек.
Що комітувати, а що ігнорувати:
.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)
Які зміни на практиці
У монорепозиторії Deno 2 та TypeScript із фронтендом, API та спільними пакетами виділяються чотири аспекти:
- Розв’язання проблем між пакетами. Оскільки весь монорепозиторій підключається як одне робоче простір, Serena в одному кроці відстежує тип з
packages/до його використань уapps/api/, тоді як раніше асистент мусив читати файли по одному та складати інформацію самостійно. - Безпечніші рефакторинги. Завдання з редагуванням близько 20 файлів та зміною назви спільного інтерфейсу пройшло через функцію
rename_symbolта не пропустило нічого. Пошук та заміна тексту завжди залишає одне динамічне використання, приховане всередині рядка-шаблону.
find_symbol та отримати текст безпосередньо, а зміни не виходять за межі контексту, оскільки текст пише Serena.Шортикати у Makefile допомагають зробити робочий процес звичкою:
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
Висновок
Логічні міркування та генерація коду є сильними сторонами інструментів програмування на основі ШІ. Однак робота з великими кодовими базами є їхньою слабкою стороною. Сервер мови, створений саме для цієї мети, підвищує якість результатів та скорочує витрати. Команди, які витрачають багато часу на читання файлів, але все одно роблять недбалі зміни у великих репозиторіях, вважатимуть, що півдня на налаштування було вартим зусиль. Docker допомагає підтримувати порядок: Serena працює поруч із рештою компонентів стеку, зберігає свій індекс та надає один кінець SSE кожному клієнту в команді.