Serena 项目源码地图:基于 MCP 的编码 Agent 工具集核心架构解析
【免费下载链接】serenaA powerful MCP toolkit for coding, providing semantic retrieval and editing capabilities - the IDE for your agent项目地址: https://gitcode.com/GitHub_Trending/ser/serena
本文基于仓库记忆文档 .serena/memories/project_structure.md 展开,系统梳理 Serena(PyPI 包名
serena-agent)的源码布局、核心模块职责与项目级不变量。读者将掌握:Serena 各入口点(CLI / MCP 服务器 / 项目服务器 / 钩子)如何接线、工具层与配置层的实现位置、LSP 客户端框架与测试体系的组织方式,以及贡献代码或二次开发时应遵守的约束。
一、Serena 是什么
Serena 是一个基于MCP(Model Context Protocol)的“编码 Agent IDE”:它以语言服务器(Language Server)为驱动,为编程 Agent 提供语义级代码检索、编辑与重构能力。与普通基于文本搜索/字符串替换的工具不同,Serena 借助各语言官方语言服务器获得符号级(symbol-level)的代码理解,从而支持“按符号名定位定义、按符号引用批量改名、按函数体位置插入/替换代码”等结构化操作。
从其核心描述(见 pyproject.toml)可以看到项目定位:
A powerful MCP toolkit for coding, providing semantic retrieval and editing capabilities - the IDE for your agent
整个仓库是一个monorepo式布局,wheel 打包时同时包含三个顶层 Python 包:serena(Agent 与工具核心)、interprompt(提示词模板库)、solidlsp(LSP 客户端框架),见 pyproject.toml 的 hatch 构建配置:
[tool.hatch.build.targets.wheel] packages = ["src/serena", "src/interprompt", "src/solidlsp"]二、源码地图:逐模块导航
记忆文档给出了一张“Source map”,下面结合源码逐一展开说明每个目录的真实职责。
2.1src/serena/—— Agent、MCP 服务器、工具与项目/配置层
这是 Serena 的主包,所有面向用户的编排逻辑都在这里。
入口与接线(entrypoints/wiring)
| 文件 | 职责 |
|---|---|
| agent.py | 核心SerenaAgent:持有工具集(ToolSet)、活动项目、活动模式(modes),负责系统提示词生成、项目激活、任务调度与工具调用记录 |
| mcp.py | MCP 服务器封装:将内部Tool实例转换为 MCP 工具并注册到 FastMCP,支持 stdio / sse / streamable-http 三种传输 |
| project_server.py | 本地 HTTP 项目服务器:供其他进程按“项目名 + 工具名 + JSON 参数”远程调用工具(query_project接口) |
| cli.py | Click 命令行入口:serena init/setup/start-mcp-server/...等子命令 |
| hooks.py | Claude Code 等客户端的钩子命令(serena-hooks入口,见hook_commands) |
这些文件正是记忆文档中所说的“entrypoints/wiring”——它们本身不含具体功能实现,而是把底层能力组装成对外可用的服务。
工具层src/serena/tools/
工具是 Agent 与底层能力之间的薄封装,每个工具类都继承自 tools_base.py 中的Tool基类(第 142 行class Tool(Component))。基类提供了统一的名字推导(get_name)、工具描述与 docstring 提取(get_tool_description/get_apply_docstring)、max_answer_chars截断、参数别名(get_param_aliases)以及 MCP 兼容的apply_ex执行入口。
按功能划分,工具模块包括:
- memory_tools.py —— 记忆读写(
write_memory/read_memory/ 列表 / 重命名 / 编辑) - symbol_tools.py —— 符号级检索与编辑(按
name_path查找符号、查引用、查实现、替换函数体、重命名符号) - file_tools.py —— 文件读写、多文件正则/字面量替换(含
occurrence_ids精确指定替换点) - workflow_tools.py —— 工作流编排(完成任务、会话查询等)
- query_project_tools.py —— 跨进程项目查询(经由 project_server)
- config_tools.py —— 配置读取与项目注册
- cmd_tools.py —— 执行 shell 命令
- jetbrains_tools.py —— 当语言后端为 JetBrains 插件时替代部分 LSP 工具
配置层src/serena/config/
| 文件 | 职责 |
|---|---|
| serena_config.py | 全局SerenaConfig与项目级ProjectConfig/RegisteredProject:配置加载、默认值、项目注册表持久化、语言后端(LSP vs JetBrains)判定 |
| context_mode.py | SerenaAgentContext(上下文)与SerenaAgentMode(模式)的 YAML 加载与注册表管理 |
| client_setup.py | 各客户端(Claude Code、Codex、Copilot 等)的 MCP 服务器一键配置(serena setup的后端实现) |
记忆文档提到的resources/config/contexts/*.yml与resources/config/modes/*.yml在本仓库中对应 src/serena/resources/config/contexts/ 与 src/serena/resources/config/modes/。实测该目录下包含 16 个内置上下文定义(agent.yml、claude-code.yml、codex.yml、chatgpt.yml、vscode.yml、ide.yml等,以及context.template.yml模板)和 10 个内置模式定义(editing.yml、planning.yml、interactive.yml、one-shot.yml、no-memories.yml等,以及mode.template.yml模板)。目录路径常量定义在 constants.py,默认上下文为desktop-app(同文件第 24 行)。
符号编辑与 LS 生命周期
- code_editor.py —— 符号编辑执行器,包含三种实现:基于文件系统的
CodeEditor、基于 LSP 文本编辑的LanguageServerCodeEditor、基于 JetBrains 插件的JetBrainsCodeEditor。支持按符号替换函数体(replace_body)、符号前后插入(insert_after_symbol/insert_before_symbol)、按行插入/删除、符号删除与重命名。 - symbol.py —— 符号数据模型与检索器。核心是
LanguageServerSymbolRetriever,提供find/find_unique/find_referencing_symbols/find_implementing_symbols/get_symbol_overview/get_symbol_diagnostics等语义查询,以及符号的分组(GroupedSymbolDict)与name_path匹配(NamePathPattern,支持子串匹配)。 - ls_manager.py —— 语言服务器生命周期管理:
LanguageServerManager负责创建、启动、重启、停止各语言的SolidLanguageServer,按文件后缀路由到合适的 LS,并支持缓存保存与文件系统变更同步(sync_file_system_changes)。
辅助设施
- dashboard.py —— 基于 Flask 的 Web 仪表盘:日志查看、工具调用统计、配置概览、记忆管理、语言服务器增删、新闻公告等 REST 接口,另含 pywebview 桌面查看器与系统托盘(tray)管理。
- gui_log_viewer.py —— GUI 日志查看器与
MemoryLogHandler(内存环形日志缓冲,供仪表盘拉取)。 - prompt_factory.py 与 generated/generated_prompt_factory.py —— 提示词工厂:前者是手写入口,后者是从模板自动生成的代码(由 scripts/gen_prompt_factory.py 重新生成)。从
generated_prompt_factory.py的类定义可看到其产物形态:create_system_prompt、create_connection_prompt、create_onboarding_prompt、create_cc_system_prompt_override等。 - analytics.py —— token 估算(tiktoken / Claude API / 平均字符数三种估算器)与工具调用用量统计。
- task_executor.py —— 任务队列执行器,支持超时、取消与完成回调。
- agno.py —— 可选的 agno Agent 集成(
agnoextra 依赖),把 Serena 工具包装成 agno 的Function。 - jetbrains/ —— JetBrains 语言后端:
jetbrains_plugin_client.py(与 IDEA 插件通信的 HTTP 客户端,含符号查找/引用/类型层级/重命名/内联/安全检查等)、jetbrains_types.py(DTO 类型)、launch_coordinator.py(启动并等待插件服务器就绪)。 - memories/ —— 记忆子系统:
memory_manager.py(记忆文件的读写、列表、重命名、引用传播)、memory_reference_analysis.py(记忆间引用完整性校验与自动加前缀修复)。
2.2src/solidlsp/—— LSP 客户端框架
solidlsp是 Serena 的语言服务器基础设施,与具体的 Agent 逻辑解耦:
- ls.py / ls_process.py / ls_request.py —— 语言服务器的进程启动、请求/响应模型;
- ls_config.py ——
LanguageServerId枚举与服务器配置注册; - lsp_protocol_handler/ —— 基于 pygls 的 LSP 协议处理器(
server.py、lsp_requests.py、lsp_types.py、lsp_constants.py); - language_servers/ ——78 个按语言拆分的服务器适配模块,每个文件对应一门语言/工具链:
clangd_language_server.py、gopls.py、rust_analyzer.py、pyright_server.py、basedpyright_server.py、ruby_lsp.py、typescript_language_server.py、omnisharp.py、scala_language_server.py等; - dependency_provider.py / settings.py —— 语言服务器依赖下载/路径解析与运行时设置;
- util/ ——
subprocess_util.py(跨平台子进程参数)、cache.py、zip.py等通用工具。
2.3src/interprompt/—— 提示词模板库
interprompt是一个独立的提示词模板库(jinja 模板 + 多语言提示词 + prompt 工厂),代码注释及.syncCommitId.*文件(仓库中存在 src/interprompt/.syncCommitId.remote 与 src/interprompt/.syncCommitId.this)表明它从外部仓库同步而来,并用提交 ID 记录同步点。generated_prompt_factory.py实际上就是把interprompt的模板渲染成 Python 函数。
2.4 测试与脚本
- test/serena/ —— Agent 核心的 pytest 套件:
test_symbol_editing.py(符号编辑,配套 syrupy 快照 test/serena/snapshots/test_symbol_editing.ambr)、test_file_tools.py、test_memories_manager.py、test_mcp.py、test_dashboard.py等。 - test/solidlsp/ —— 按语言划分的 LSP 集成测试,每个语言一个目录(
ada/、go/、rust/、typescript/…)。这些测试由 pytest 标记(marker)按语言门控:[tool.pytest.ini_options].markers在 pyproject.toml 中定义了 clojure / crystal / python / go / java / rust / typescript / cpp / scala / solidity 等 50+ 个语言标记,每个标记说明对应语言服务器的运行前提。 - test/resources/repos/ /—— 语言服务器测试所用的固定夹具项目(fixture repos),例如
typescript/test_repo。注意该目录被 ty 类型检查与 codespell 明确排除(见 pyproject.toml 与 L390),因为其中包含第三方锁定文件与压缩代码。 - scripts/ —— 开发工具脚本:
gen_prompt_factory.py(重新生成提示词工厂)、print_tool_overview.py(打印工具总览)、profile_tool_call.py(工具调用性能剖析)、agno_agent.py、build_news_json.py、mcp_server.py、memory_graph.py等。 - docs/ —— Jupyter Book 文档源,构建命令为
poe doc-build(定义于 pyproject.toml,内部串联 autogen_docs → create_toc → jupyter-book config → sphinx-build)。
三、项目级不变量(Project-wide invariants)
记忆文档最后一部分给出了三条必须遵守的“不变量”,它们与源码/配置一一对应,是理解打包与运行方式的关键。
3.1 PyPI 包名与 wheel 内容
- PyPI 包名为
serena-agent,版本当前为1.7.1.dev0,见 pyproject.toml; - wheel 包含
serena、interprompt、solidlsp三个包(hatchpackages配置)。
3.2 Python 版本范围与精确锁依赖
- 要求
>=3.11, <3.15(pyproject.toml),classifier 声明了 3.11–3.14; - 所有依赖在
pyproject.toml中精确固定版本(==)。其原因是:uvx从 git 安装时会忽略 lockfile,因此必须把版本精确 pin 在 pyproject 中才能保证可复现。这一注释直接出现在依赖块里(第 43-44 行:"Exact pins because uvx installs from git, ignoring the lock file.")。例如mcp==1.28.1、pydantic==2.12.5、anthropic==0.117.0、pygls==2.1.1、flask==3.1.3等。 - 可选 extra:
dev(pytest、ruff、ty、sphinx/jupyter-book 文档链等)、agno、google。
3.3 命令行入口点
[project.scripts](pyproject.toml)注册了三个可执行命令:
[project.scripts] serena = "serena.cli:top_level" serena-agent = "serena.cli:top_level" serena-hooks = "serena.hooks:hook_commands"serena/serena-agent→ cli.py 的top_level。实测该 Click 应用包含以下子命令族:init:初始化(可选--language-backend lsp|jetbrains);setup:为指定客户端配置 MCP 服务器;start-mcp-server:启动 MCP 服务器,支持--transport stdio|sse|streamable-http、--context、--default-modes/--added-modes、--host/--port、--enable-web-dashboard、--open-web-dashboard、--log-level、--trace-lsp-communication、--tool-timeout等;print-system-prompt:打印系统提示词(--only-instructions、--modes);start-project-server:启动项目服务器(--host/--port/--log-level);dashboard-viewer:以独立窗口打开仪表盘;modes list/create/edit/delete与contexts list/create/edit/delete:管理自定义模式与上下文 YAML;projects create/index/is-ignored-path/index-file/health-check:注册项目、索引、健康检查;tools list/description:列出工具与查看工具描述;memories initialize/list/read/write/delete/rename/edit/check/auto-prefix-references:完整记忆管理;prompts list/create-override/edit-override/list-overrides/delete-override/print-prompt-template/print-cc-system-prompt-override:提示词模板覆盖管理。
serena-hooks→ hooks.py 的hook_commands,为支持钩子的客户端提供activate/cleanup/remind/auto-approve/reset等操作(钩子内部会基于工具调用频率在“符号化工具优先”与普通工具之间做提醒/放行决策,见 hooks.py 中PreToolUseHook相关实现)。
四、从源码结构看 Serena 的分层架构
综合上述源码地图,可以推断出 Serena 的整体分层:
┌─ 对外接口层 ─────────────────────────────┐ │ CLI (cli.py) │ MCP Server (mcp.py) │ │ Project Server (project_server.py) │ │ Hooks (hooks.py) │ Web Dashboard │ └───────────────┬────────────────────────┘ ┌───────────────▼────────────────────────┐ │ Agent 编排层 (agent.py) │ │ ToolSet / Modes / 系统提示词 / 项目激活 │ └───────────────┬────────────────────────┘ ┌───────────────▼────────────────────────┐ │ 工具层 tools/ (继承 tools_base.Tool) │ │ 记忆 / 符号 / 文件 / 配置 / 命令 / 查询 │ └───────────────┬────────────────────────┘ ┌───────────────▼────────────────────────┐ │ 能力实现层 │ │ symbol.py 检索 │ code_editor.py 编辑 │ │ ls_manager.py │ memories/ │ jetbrains/ │ └───────────────┬────────────────────────┘ ┌───────────────▼────────────────────────┐ │ solidlsp 语言服务器框架(78 个适配器) │ └────────────────────────────────────────┘其中值得注意的几个“职责单一”设计点:
- 工具类只做参数校验与结果格式化:真正的语义能力(符号查找、文本替换、诊断获取)都在
symbol.py、code_editor.py、text_utils.py等实现层,工具层是薄封装。例如file_tools.py中的多文件替换最终调用text_utils.MultiFileContentReplacer(见 text_utils.py)完成 occurrence 匹配与 diff 渲染。 - 编辑后诊断回读:
tools_base.py中存在DiagnosticsContext之类的上下文管理器(从EditingToolWithDiagnostics推断),配合 ls_diagnostics.py 在符号编辑前后对比诊断快照,让 Agent 知道一次编辑是否引入了新的编译错误——这体现了“语义编辑 + 校验闭环”的设计。 - 双语言后端抽象:
LanguageBackend枚举(LSP / JetBrains,定义于serena_config.py)决定同一套工具名映射到哪种实现——LSP 后端走solidlsp+LanguageServerSymbolRetriever,JetBrains 后端走jetbrains_plugin_client.py的 HTTP 接口,工具层通过get_lsp_tool_class_replacements做替换。这让“IDE 中的 Agent”既能独立工作(LSP),也能深度融入 JetBrains IDE(插件)。
五、给贡献者与二次开发者的实践指引
结合记忆文档与仓库实况,参与本项目的正确姿势如下:
- 定位代码:先对照本篇文章的源码地图找到所属层。改工具行为 → src/serena/tools/;改符号检索 → symbol.py;改语言服务器适配 → src/solidlsp/language_servers/;改提示词模板 →
src/interprompt/或重新生成generated_prompt_factory.py(运行 scripts/gen_prompt_factory.py)。 - 写测试:核心逻辑测试放 test/serena/,语言服务器集成测试放test/solidlsp/ /,并给测试打上对应语言的 pytest 标记(marker 注册见 pyproject.toml)。符号编辑类快照测试使用 syrupy(
--snapshot-update更新快照)。 - 跑检查:
poe test(pytest)、poe lint/poe format(ruff)、poe type-check(ty)。注意 poe 的 executor 被显式配置为simple而非uv——注释说明这是因为 Serena MCP 服务器运行时会占用 Python 环境,用uv执行器会尝试重建环境导致失败(pyproject.toml)。 - 遵守设计不变量:不要在配置中放宽 Python 版本范围、不要引入未 pin 的依赖版本、新增工具类时继承
tools_base.Tool并在对应工具模块注册,新增语言时在solidlsp/language_servers/添加适配器并在ls_config.py注册LanguageServerId。
六、总结
.serena/memories/project_structure.md本质上是 Serena 的“项目核心速查表”:它用一张源码地图 + 三条不变量,把 78 个语言服务器适配器、数十个工具、三层 MCP/CLI/钩子入口组织进一个清晰的认知框架。本文在此基础上逐文件验证并补充了模块职责、关键类与配置路径,可作为阅读源码、提交贡献或基于 Serena 构建二次开发方案时的第一份索引。若要继续深入,推荐从 agent.py(编排核心)与 symbol.py(语义检索核心)读起,并结合 test/solidlsp/ 下的语言级测试理解端到端行为。
【免费下载链接】serenaA powerful MCP toolkit for coding, providing semantic retrieval and editing capabilities - the IDE for your agent项目地址: https://gitcode.com/GitHub_Trending/ser/serena
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考