返回市场
附录服务器

附录服务器

作者:E-xyza36 星标更新:2025-11-23

项目介绍

Codicil

通过MCP(模型上下文协议)对Elixir项目进行语义代码搜索和分析

Codicil是一个Elixir库,它为AI编码助手提供了对代码库的深度语义理解。你可以用自然语言提问,根据行为查找函数,追踪依赖关系,并理解代码之间的关系——这一切都通过模型上下文协议实现。

它能做什么?

想象一下向你的AI编码助手提问:

  • “找到验证用户输入的函数”
  • “显示调用这个函数的内容”
  • “这个模块有哪些依赖?”

Codicil通过以下方式使这些成为可能:

  1. 理解你的代码 - 在编译期间分析Elixir项目,提取函数、模块及其关系。
  2. 创建语义搜索 - 使用AI理解代码“做什么”,而不仅仅是它的命名。
  3. 连接到AI助手 - 提供通过MCP与Claude、ChatGPT和其他AI编码工具交互的工具。

主要特性

  • 语义函数搜索 - 通过描述其功能来查找代码。
  • 依赖分析 - 查看函数调用图和模块关系。
  • 自动索引 - 集成到编译过程中,无需手动扫描。
  • 多LLM支持 - 支持Anthropic Claude、OpenAI、Cohere、Google Gemini和Grok。

安装与设置

常规步骤(适用于所有项目)

这些步骤适用于Phoenix和非Phoenix项目。

第一步:添加依赖项

在你的mix.exs中添加Codicil:

def deps do
  [
    # ... 你现有的依赖项
    {:codicil, "~> 0.4", only: [:dev, :test]}
  ]
end

然后安装:

mix deps.get

第二步:初始化数据库

Codicil使用SQLite存储索引代码。初始化它:

mix codicil.setup

第三步:配置环境变量

创建或编辑你的.env文件(或在shell中设置):

# 必需:选择你的LLM提供商
export CODICIL_LLM_PROVIDER=openai  # 或:anthropic, cohere, google, grok

# 必需:为选定的提供商添加你的API密钥
export OPENAI_API_KEY=your_key_here
# 或
export ANTHROPIC_API_KEY=your_key_here
# 或
export COHERE_API_KEY=your_key_here
# 或
export GOOGLE_API_KEY=your_key_here

# 可选:嵌入式提供者(默认为openai)
# 如果你想使用Voyage AI作为嵌入式:
# export CODICIL_EMBEDDING_PROVIDER=voyage
# export VOYAGE_API_KEY=your_voyage_key_here

加载环境变量:

source .env

第四步:启用编译器跟踪器

编辑你的mix.exs以在开发环境中启用Codicil的跟踪器:

def project do
  [
    app: :my_app,
    version: "0.1.0",
    elixir: "~> 1.14",
    # 在开发和测试中启用Codicil跟踪器
    elixirc_options: elixirc_options(Mix.env()),
    deps: deps()
  ]
end

defp elixirc_options(:prod), do: []
defp elixirc_options(_env), do: [tracers: [Codicil.Tracer]]

这确保了跟踪器仅在开发和测试中运行,而不是在生产中。


Phoenix项目设置

如果你使用的是Phoenix,请继续执行以下步骤。

第五步(Phoenix):在路由器中添加MCP路由

在你的Phoenix路由器中添加Codicil MCP端点。编辑lib/my_app_web/router.ex

defmodule MyAppWeb.Endpoint do

  # ... 你的端点内容

  # Codicil MCP端点(只有当Codicil被加载时可用)
  if Code.ensure_loaded?(Codicil) do
    plug Codicil.Plug
  end
end

第六步(Phoenix):启动Phoenix并编译

启动你的Phoenix服务器:

mix phx.server

MCP服务器将在http://localhost:4000/codicil/mcp(或你配置的Phoenix端口)上可用。

编译你的项目以触发索引:

# 在另一个终端
mix compile --force

查看Phoenix日志以查看正在被索引的函数!


非Phoenix项目设置

如果你不使用Phoenix,请继续执行以下步骤。

第五步(非Phoenix):添加Bandit依赖项

添加Bandit以提供MCP端点。编辑mix.exs

def deps do
  [
    # ... 你现有的依赖项
    {:codicil, "~> 0.4", only: [:dev, :test]},
    {:bandit, "~> 1.6", only: :dev}  # 用于MCP的HTTP服务器
  ]
end

安装:

mix deps.get

第六步(非Phoenix):添加Mix别名以启动MCP服务器

添加一个Mix别名以启动MCP服务器。编辑你的mix.exs

def project do
  [
    # ... 其他配置
    aliases: aliases()
  ]
end

defp aliases do
  [
    # ... 你现有的别名(如果有)
    codicil: "run --no-halt -e 'Bandit.start_link(plug: Codicil.Plug, port: 4700)'"
  ]
end

第六步a(非Phoenix,可选):同时运行多个MCP服务器

如果你想同时运行多个MCP服务器(例如Codicil + Tidewave),可以在单个Mix别名中组合它们:

defp aliases do
  [
    # ... 你现有的别名(如果有)
    mcp: "run --no-halt -e 'Agent.start(fn -> Bandit.start_link(plug: Codicil.Plug, port:  4700); Bandit.start_link(plug: Tidewave, port: 4000) end)'"
  ]
end

这将在同一个代理中启动两个MCP服务器:

  • Codicil MCP服务器在http://localhost:4700/codicil/mcp
  • Tidewave MCP服务器在http://localhost:4700/tidewave/mcp

注意:每个MCP服务器需要自己的端口。根据需要调整端口号。

第七步(非Phoenix):启动MCP服务器并编译

启动MCP服务器:

mix codicil

MCP服务器将在http://localhost:4700/codicil/mcp上启动。

在第二个终端中编译你的项目以触发索引:

mix compile --force

在终端1中查看日志以查看正在被索引的函数!


配置你的AI助手

一旦Codicil运行起来,配置你的AI助手(如Claude Desktop、Cline等)以连接到MCP服务器:

Phoenix项目:

  • URLhttp://localhost:4000/codicil/mcp(使用你的Phoenix端口)
  • 传输:HTTP带SSE

非Phoenix项目:

  • URLhttp://localhost:4700/codicil/mcp
  • 传输:HTTP带SSE

现在可以使用以下MCP工具:

  • find_similar_functions - 通过描述进行语义搜索
  • list_function_callers - 查找调用特定函数的内容(调试和重构时有用)
  • list_function_callees - 查找函数调用的内容(调试执行路径和重构时有用)
  • list_module_dependencies - 分析模块依赖关系
  • get_function_source_code - 获取带有上下文的完整函数源代码(代替grep

验证是否正常工作

Phoenix项目:

# 检查MCP端点是否响应
curl http://localhost:4000/codicil/mcp

# 检查已索引的函数
sqlite3 deps/codicil/priv/codicil.db "SELECT module, name, arity FROM functions LIMIT 10;"

非Phoenix项目:

# 检查MCP服务器是否响应
curl http://localhost:4700/codicil/mcp

# 检查已索引的函数
sqlite3 deps/codicil/priv/codicil.db "SELECT module, name, arity FROM functions LIMIT 10;"

工作原理

在编译期间,Codicil:

  1. 通过Codicil.Tracer捕获模块/函数定义。
  2. 从字节码中提取文档和关系。
  3. 使用LLM生成语义摘要(限速,异步)。
  4. 创建用于语义搜索的向量嵌入。
  5. 将所有内容存储在本地SQLite数据库中。
  6. 监视文件更改并自动重新编译。

然后,你的AI助手通过MCP工具查询这些数据。

架构

编译 → 跟踪器 → ModuleTracer GenServer → 速率限制器 → LLM/嵌入
                                          ↓
                                SQLite数据库
                              (函数、模块,
                               调用图、向量)
                                          ↓
                                     MCP工具
                                          ↓
                                   AI助手

技术栈:

  • SQLite,带有sqlite-vec扩展用于向量搜索
  • Ecto用于数据库访问
  • 编译器跟踪器用于自动代码分析
  • 多个LLM提供商(Anthropic、OpenAI、Cohere、Google、Grok)
  • 通过Bandit + Plug的MCP服务器
  • 文件系统监视器用于自动重新编译

MCP工具参考

find_similar_functions

通过向量相似性搜索查找具有语义描述的函数:

{
  "description": "验证电子邮件地址的函数",
  "limit": 10
}

list_function_callers

查找调用特定函数的内容(调试和重构影响分析时有用):

{
  "moduleName": "MyApp.User",
  "functionName": "create",
  "arity": 1
}

list_function_callees

查找函数调用的内容(调试执行路径和重构时有用):

{
  "moduleName": "MyApp.Orders",
  "functionName": "process",
  "arity": 1
}

list_module_dependencies

分析模块依赖关系(导入、别名、使用、需要以及运行时调用):

{
  "moduleName": "MyApp.Accounts"
}

get_function_source_code

获取带有模块指令和位置的完整函数源代码。使用此方法代替grep或文件读取以获得完整上下文。

{
  "moduleName": "MyApp.User",
  "functionName": "create",
  "arity": 1
}

高级配置

自定义工具描述

你可以在编译时覆盖默认的MCP工具描述,以优化你的AI助手如何使用这些工具。不同的模型(Claude、GPT-4、Codex等)可能有不同的偏好,因此自定义描述可以提高工具选择的准确性并减少不必要的工具调用。

要查看当前默认描述,请使用IEx:

iex -S mix
iex> Codicil.MCP.Tool.get_description(Codicil.MCP.Tools.FindSimilarFunctions)

要自定义描述,请在你的config/config.exs(或config/dev.exs)中添加:

config :codicil, Codicil.MCP.Tools.FindSimilarFunctions, """
通过语义描述查找函数。当你按行为而非名称搜索功能时使用此工具。返回排名结果及代码片段。
"""

# 其他可配置的工具模块:
# - Codicil.MCP.Tools.ListFunctionCallers
# - Codicil.MCP.Tools.ListFunctionCallees
# - Codicil.MCP.Tools.ListModuleDependencies
# - Codicil.MCP.Tools.GetFunctionSourceCode

更改工具描述后,重新编译:

mix clean
mix compile

自定义模型

覆盖默认模型:

export CODICIL_LLM_MODEL=claude-3-5-sonnet-20241022
export CODICIL_EMBEDDING_MODEL=voyage-3

分离嵌入式提供者

使用不同的提供者进行嵌入:

export CODICIL_LLM_PROVIDER=anthropic
export CODICIL_EMBEDDING_PROVIDER=openai
export ANTHROPIC_API_KEY=your_claude_key
export OPENAI_API_KEY=your_openai_key

本地LLM支持(兼容OpenAI)

export CODICIL_LLM_PROVIDER=openai
export OPENAI_API_KEY=dummy
export OPENAI_BASE_URL=http://localhost:11434/v1  # 例如Ollama
export CODICIL_LLM_MODEL=llama3

故障排除

“函数未被索引”

解决方案

  • 验证环境变量是否设置:echo $CODICIL_LLM_PROVIDER
  • 检查MCP服务器是否运行:curl http://localhost:4000/codicil/mcp(Phoenix)或curl http://localhost:4700/codicil/mcp(非Phoenix)
  • 强制重新编译:mix compile --force
  • 检查日志中的跟踪器错误

“数据库未找到”

解决方案

  • 初始化数据库:mix codicil.setup

“端口4700已被占用”(非Phoenix)

解决方案

  • 检查什么进程占用了该端口:lsof -i :4700
  • 终止进程或更改Mix别名中的端口

“路由未找到”(Phoenix)

解决方案:确保你在Phoenix路由器中添加了forward "/codicil/mcp", Codicil.Plug路由并重启了服务器。

跟踪器未运行

解决方案:验证跟踪器是否在你的mix.exs中启用:

defp elixirc_options(_env), do: [tracers: [Codicil.Tracer]]

强制干净地重新编译:

mix clean
mix compile

开发

贡献给Codicil?这是如何设置开发环境的:

# 克隆仓库
git clone https://github.com/yourusername/codicil.git
cd codicil

# 安装依赖项
mix deps.get

# 设置数据库
mix codicil.setup

# 运行测试
mix test

# 格式化代码
mix format

数据库模式

Codicil使用SQLite,具有以下表:

  • functions - 函数定义,带有摘要和嵌入
  • modules - 模块定义
  • function_calls - 调用图边
  • module_dependencies - 导入/别名/使用/需要关系

向量搜索由sqlite-vec扩展提供动力。

生产警告

切勿将Codicil部署到生产环境。 Codicil是一个开发工具,它:

  • 发起LLM API调用(会产生费用)
  • 在运行时索引代码(性能开销)
  • 运行HTTP服务器(安全风险)

始终将Codicil作为仅限dev的依赖项包括:

{:codicil, "~> 0.6", only: [:dev, :test]}

上述跟踪器配置(elixirc_options(:prod), do: [])确保在生产构建中禁用Codicil。

文档

完整的文档可在以下位置找到:

致谢

Codicil受到GraphSense的设计模式启发,GraphSense是一个TypeScript/Node.js语义代码搜索工具。GraphSense率先采用了结合向量相似性搜索和LLM验证的方法,以实现准确的代码发现。

许可证

MIT许可证 - 详情见LICENSE文件。