Skip to content

Repository files navigation

leoai-mcp-adapter

这是一个面向 LeoAI 的独立 Streamable HTTP MCP 适配器。它为 PoJun 等客户端提供范围受限、显式映射的 Tool,不嵌入 LeoAI、 不复制其 Agent 循环,也不提供任意 HTTP 转发。默认的 observe Profile 只提供 只读能力;显式启用的 operate Profile 额外提供带审计的 Session、终端、文件、 系统、Docker、受限扫描、结构化数据库和文件传输操作。

2x Profile 面向 LeoAI main 分支 commit 6fb4de979db23de4fa8b23e5ed6a98c710a82fda 的 API;1x Profile 面向官方 1.0.1 Release。当前已经完成本地协议与契约测试,以及 LeoAI 1.0.1 Java/PHP Puppet 的真实 Observe、Session、终端、文件、进程、服务、网络和扫描矩阵验证。 1x Profile 的 SQLite 元数据、查询、插入、更新和删除映射也已在真实 1.0.1 环境通过;终端的 Base64 输出解码后与 canary 一致。 真实 Java Puppet 已通过主机、端口和指纹扫描;Recon 请求已到达 LeoAI,但新生成的 Java Puppet 返回了上游 requestId 不匹配。这属于 LeoAI Runtime 兼容性缺口, Adapter 不会为此降级。PoJun Docker Runtime 验证仍是环境级发布门禁。

发布版 LeoAi-2.0.0.jar 已通过 Adapter 登录、Tool discovery、Project/Session、 基础信息、进程、服务、网络和终端真实回放。使用该 JAR 自带生成器生成的 protocol-v2 PHP Puppet 后,文件 Profile/CRUD、PTY 终端、SQLite runtime-capabilities 以及 2x objectRef 元数据、查询、插入、更新和删除完整矩阵均通过。测试机原有的旧 Java Puppet 存在 action 编码不兼容且缺少 SQLite JDBC Driver,属于 Server/Puppet 混合 版本与目标运行时依赖问题;升级到 2.0.0 后应重新生成或确保 Puppet 协议版本匹配。

Adapter 支持两个显式的上游协议 Profile。连接官方 LeoAI 1.0.1 时设置 LEOAI_PROTOCOL_PROFILE=1x;连接当前 2.x API 时设置 LEOAI_PROTOCOL_PROFILE=2x。默认值为 2x,以保持现有部署行为不变。一个进程在 整个生命周期内只绑定一个 Profile;需要同时连接两个 LeoAI 版本时,应运行两个相互 独立的 Adapter 实例。Adapter 不猜测版本,也不会在操作失败后换用另一套协议重试。

LeoAI 1.0.1 不包含新版 Project API。在该版本上,leo_list_projects 和 leo_list_project_puppets 会返回 leoai_capability_unsupported,Session 和文件 Tool 仍可使用。缺少显式文件系统 Profile 接口时,Adapter 会通过旧版只读根目录列表 接口推导路径语义。Adapter 默认使用 LeoAI 初始密码 54ikun,在首次认证时自动 完成密码迁移;不同 LeoAI 构建可通过 LEOAI_INITIAL_PASSWORD_FILE 覆盖该值。

Tool

默认注册以下 Tool:

  • leo_list_projects
  • leo_list_project_puppets
  • leo_list_sessions
  • leo_get_session_capabilities
  • leo_get_current_host
  • leo_get_basic_info
  • leo_get_recon_summary
  • leo_get_file_profile
  • leo_list_files

只有设置 MCP_ENABLE_FILE_READ=true 时才会注册 leo_read_file。默认的 observe Profile 不暴露命令执行、文件写入或其他操作能力。

设置 MCP_TOOL_PROFILE=operate 后,还会注册以下能力:

  • leo_open_session / leo_close_session
  • leo_open_terminal / leo_write_terminal / leo_read_terminal / leo_stop_terminal;init/write 会带上 includeOutput
  • leo_create_file / leo_edit_file / leo_create_directory
  • leo_move_file / leo_copy_file / leo_delete_file
  • leo_list_processes / leo_find_processes / leo_kill_process
  • leo_list_services / leo_query_service / leo_control_service
  • leo_list_network_connections / leo_get_network_connection_summary
  • leo_preview_network_probe / leo_start_network_probe / leo_query_network_probe / leo_control_network_probe
  • 使用 LeoAI 已保存连接的数据库方言、能力、元数据和表查询 Tool
  • 结构化数据库连接测试、行插入、更新和删除 Tool,不提供原始 SQL Tool
  • 有边界的上传/下载启动、查询、控制和任务列表 Tool
  • 使用固定 Endpoint 的 Docker 信息、列表、检查、日志、执行、控制和删除 Tool

当 MCP_ALLOWED_PLUGIN_IDS 非空时,operate 还会注册 leo_invoke_allowed_plugin。调用的 ID 必须位于部署侧允许列表中,并且对应 LeoAI 中已经安装的插件。Adapter 不会创建、上传或动态加载插件。

设置 MCP_ENABLE_ONBOARDING=true 且当前为 operate,或直接使用 privileged Profile 时,还会注册上线登记 Tool:

  • leo_list_disguises / leo_list_shell_generator_types
  • leo_create_project
  • leo_generate_runtime_artifact / leo_generate_webshell / leo_generate_memory_shell
  • leo_add_puppet

这些 Tool 只封装 LeoAI 已有生成器和 Puppet 登记接口。生成结果返回制品内容,不返回 连接机密。http/httpchunk 内存壳必须传 headerName/headerValue; JDK 9+ 传 targetJavaVersion,Spring Boot 3 / Tomcat 10 传 servletNamespace=jakarta。 LeoAI 2.2.0 生成器和 leo_add_puppet 都需要同一把 payloadKey。生成时可不传,Adapter 会生成并在 artifact.payloadKey 返回;登记时必须原样带回。 leo_add_puppet 只登记已经可达的 connLink,不会替 Agent 投递制品。 默认 observe 和未开开关的 operate 都不暴露这组能力。

扫描走 LeoAI 统一 network-probe 工作流:先 preview 再 start,再用 query 拉 summary、分页 results,或 view=fingerprints 拉组件识别。可达性已不再是同步 接口。start/control 属于 Action,登录过期后不会重放;preview/query 可以 重新认证并重试一次。目标接受 IP/CIDR/URL/host:port,不要再调用已删除的 host/port/fingerprint/recon scan Tools。

数据库 Tool 只接受已保存的 connectionId,凭据和任意连接字符串不能作为 MCP 输入。文件上传来源必须是不能包含父级穿越的 LeoAI VFS 相对路径;下载只返回任务 元数据,不返回下载文件内容。数据库修改、传输启动/控制和插件调用都属于 Action, 认证过期后不会重放;元数据和任务查询可以重新认证并重试一次。

未来的 privileged Profile 预留给需要独立设计的高风险能力。Adapter 永远不会暴露 通用请求转发。

配置

日常运行推荐使用仓库内的 TOML 示例。服务地址、账号、LeoAI 密码、可选的初始密码 和 MCP 客户端 Token 都可以写在同一个配置文件中,不作为 MCP Tool 参数传入:

cp adapter.example.toml adapter.toml
chmod 600 adapter.toml

然后只需编辑 adapter.toml。包含内联密码和 Token 时,Adapter 强制要求配置文件 权限为 0600;未知字段或同一凭据同时使用内联值与文件路径时会拒绝启动。生成的 adapter.toml 已加入 Git 忽略规则。

列表项 mcp_allowed_hosts 和 mcp_allowed_plugin_ids 在 TOML 中使用字符串数组。 原有 Secret 文件与环境变量方式仍然支持,适合容器或编排系统;启动时二选一,使用 --config 后配置完全来自 TOML,不与环境变量隐式合并。若部署时不希望在 TOML 内联凭据,仍可使用 leoai_password_file、leoai_initial_password_file 和 mcp_client_token_file,相对路径按 TOML 所在目录解析。

本地可信网络若不想维护 Host 白名单,可以设置:

mcp_dns_rebinding_protection = false

这会接受任意 Host,但 Bearer Token 认证仍然生效。公网或不可信网络建议保持默认值 true,并通过 mcp_allowed_hosts 明确允许访问 Adapter 的域名或 IP。

环境变量 默认值 用途
LEOAI_BASE_URL 必填 固定的 LeoAI Origin
LEOAI_USERNAME 必填 专用的低权限 LeoAI 账号
LEOAI_PASSWORD_FILE 必填 保存 LeoAI 密码的 Secret 文件
LEOAI_INITIAL_PASSWORD_FILE 54ikun 覆盖 LeoAI 初始密码;需改密时自动迁移到 LEOAI_PASSWORD_FILE
MCP_CLIENT_TOKEN_FILE 必填 保存 Bearer Token 的 Secret 文件
ADAPTER_ENV production 可选 production、development 或 test
LEOAI_TLS_VERIFY true 验证 LeoAI TLS;生产环境必须为 true
LEOAI_CONNECT_TIMEOUT_SECONDS 5 上游连接超时
LEOAI_READ_TIMEOUT_SECONDS 30 上游读取超时
LEOAI_PROTOCOL_PROFILE 2x 固定的上游契约,可选 1x 或 2x
MCP_MAX_CONCURRENCY 8 超限时快速失败的上游并发上限
MCP_MAX_RESPONSE_BYTES 1048576 LeoAI 响应体最大字节数
MCP_TOOL_PROFILE observe 部署侧 Profile,可选 observe、operate 或 privileged
MCP_ENABLE_FILE_READ false 是否注册可选的文件读取 Tool
MCP_ENABLE_ONBOARDING false 是否在 operate 中注册生成器与 Puppet 登记 Tool
MCP_MAX_FILE_BYTES 262144 单次可选文件读取的最大字节数
MCP_MAX_FILE_WRITE_BYTES 262144 单次创建/编辑文件允许的最大 UTF-8 字节数
MCP_ALLOWED_PLUGIN_IDS 空 允许调用的已安装插件 ID,使用英文逗号分隔
MCP_BIND_HOST 127.0.0.1 HTTP 监听地址
MCP_BIND_PORT 8000 HTTP 监听端口
MCP_DNS_REBINDING_PROTECTION true 是否校验 HTTP Host;设为 false 可显式全部放开
MCP_ALLOWED_HOSTS 仅本机 允许的 HTTP Host,使用英文逗号分隔

生产模式拒绝明文 HTTP LeoAI URL,也不允许关闭 TLS 验证。只有在受控的本地 LeoAI 部署中才能使用 ADAPTER_ENV=development。

运行

uv sync --locked
uv run leoai-mcp-adapter --config adapter.toml

不传 --config 时仍按原方式读取环境变量:

uv run leoai-mcp-adapter

服务 Endpoint:

  • GET /healthz:无需认证,只表示 Adapter 进程存活
  • GET /readyz:需要 Bearer 认证,验证 LeoAI Session 是否就绪
  • /mcp:需要 Bearer 认证的 Streamable HTTP MCP

使用反向代理或容器部署时,设置 MCP_BIND_HOST=0.0.0.0,并将 MCP_ALLOWED_HOSTS 显式配置为外部实际使用的 Host。TLS 终止层和 Adapter 都应位于 受控网络中。

PoJun MCP 注册示例:

{
  "type": "http",
  "url": "https://leoai-mcp.internal.example/mcp",
  "headers": {
    "Authorization": "Bearer <adapter-client-token>"
  }
}

仓库同时提供两份轻量项目技能:

  • use-leoai-mcp:调查已有 Puppet / Session。Context1337 私仓 ID:absec://team/skill/use-leoai-mcp
  • leoai-onboard-memory-shell:把授权 Java 执行点上线为可打开 Session 的 Puppet。Context1337 私仓 ID:absec://team/skill/leoai-onboard-memory-shell

PoJun 新建「LeoAI 上线专用」Project 时上传 onboarding skill,阶段范围建议 bootstrap + explore。Skill 不包含凭据、服务地址或 Tool 实现,仍需为 Project 单独启用上述 LeoAI HTTP MCP。

构建可选容器镜像:

docker build -t leoai-mcp-adapter:0.1.0 .

运行镜像时,应将两个 Secret 文件以只读方式挂载。容器使用非特权用户运行,不包含 LeoAI 或 Java Runtime。

验证

uv run pytest
uv run ruff check .

信任模型、API 映射、发布门禁和明确排除的能力,参见 设计规格。

About

No description, website, or topics provided.

Resources

Stars

5 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages