kli-axi
Agent eXecution Interface — AI Agent 与外部系统之间的统一工具层。
通过 CLI 作为万能适配器,将 MCP server 和 Python 函数统一为可搜索、可描述、可调用的命令。Agent 无需猜测命令格式或解析人类可读输出,所有交互都是结构化 JSON。
核心理念
几乎所有主流 Agent 框架都把 bash 作为基础能力。axi 在这个"万能通道"之上建一层 Agent-native 的工具层:
- 渐进式披露 —
search → describe → run,按需获取信息,不吃 context window - Agent-first 输出 — 统一紧凑 JSON,无表格、无颜色、无进度条
- 双来源统一 — MCP server 和原生 Python 工具,对 Agent 来说是同一套接口
本项目是独立维护版本,源码复制自 deku0818/axi
的 290b20e9d584d5d61cdf7bae47a83e142db569da,保留上游 MIT 声明。
PyPI 分发名为 kli-axi,Python 模块仍为 axi,命令仍为 axi。
kli-axi 与上游 axi-cli 使用相同模块和命令,请在独立环境中安装其中一个。
安装
# 需要 Python 3.12+, uv
uv tool install kli-axi==0.0.12
# 源码开发
uv sync
快速开始
# 搜索工具
axi search "web"
# 查看工具详情
axi describe jina/jina_search
# 执行工具
axi run jina/jina_search --query "hello world" --count 3
配置
配置文件默认为 ~/.axi/axi.json;项目级配置通过 AXI_CONFIG 环境变量指定(如 export AXI_CONFIG=/path/to/project/axi.json,或写进 direnv 的 .envrc)。每份配置对应一个独立的 daemon,多项目互不干扰。格式参考 axi.json.example:
{
"mcpServers": {
"jina": {
"command": "npx",
"args": ["jina-mcp-tools"],
"env": { "JINA_API_KEY": "your-key" }
},
"retrieval": {
"url": "http://localhost:8000/mcp"
}
},
"nativeTools": [
{"module": "my_project.tools"},
{"module": "./scripts/tools.py", "name": "scripts"}
],
"search": {
"embedding": {
"provider": "jina"
}
},
"daemon": {
"idleTimeoutMinutes": 30
}
}
- mcpServers — MCP server 配置,key 名作为工具命名空间。支持
command(本地进程)和url(HTTP streaming)两种模式 - nativeTools — 原生 Python 工具,
module支持文件路径和模块路径,name可选(省略则自动推导) - search — 搜索配置,
embedding段启用语义搜索(支持 Jina/OpenAI) - daemon — daemon 进程配置,如 idle 超时时间
完整配置参考见 docs/configuration.md。
CLI 命令
| 命令 | 说明 |
|---|---|
axi list [server] |
列出所有 server 及工具 |
axi search <query> |
混合搜索工具(BM25 + Embedding,支持 --top-k/-k) |
axi grep <pattern> |
正则表达式搜索工具(支持 --limit/-l) |
axi describe <tool> |
查看工具完整 schema |
axi run <tool> --key value |
执行工具(也支持 -j '{...}' 传 JSON) |
axi mcp |
将 axi 工具导出为 MCP server(stdio / HTTP) |
axi doctor |
自检:配置、daemon、MCP 连接、embedding、native 工具来源;有问题非零退出 |
axi daemon start |
手动启动 daemon(通常无需手动,CLI 会自动拉起) |
axi daemon status |
查看 daemon 状态(PID、运行时长、空闲时长、工具数量等) |
axi daemon stop |
手动停止 daemon |
所有输出统一为紧凑 JSON。axi run 返回统一信封:
{"status": "success", "data": "..."}
{"status": "error", "error": "错误信息"}
注册原生工具
from axi import tool
@tool(name="query_orders", description="按区域查询订单")
def query_orders(region: str, limit: int = 10) -> dict:
return {"orders": [...], "total": 42}
装饰器自动从函数签名提取参数 schema。注册后同时获得 CLI 调用和 PTC 调用能力。
PTC(Programmatic Tool Calling)
Agent 可以写 Python 代码批量调用工具,在本地做数据过滤和聚合,避免反复 LLM round-trip:
from axi import tool
search = tool("jina/jina_search")
results = search(query="python async", count=5)
导出为 MCP server
用 axi 封装的工具写一次,既能 CLI 调用,也能一条命令变成 MCP server 给任何 MCP 客户端(Claude Desktop、Claude Code 等)使用:
axi mcp # 全部工具,元工具模式(search/grep/describe/run)
axi mcp --server mytools # 只暴露一组工具,平铺模式
axi mcp --server a,b --transport http --port 8321 # HTTP 长驻服务
两种暴露形态(互斥):
- 平铺(指定
--server时默认)— 每个工具注册为独立 MCP tool,对端直接看到并调用。单 server 用裸工具名,多 server 加server__前缀 - 元工具(全量导出时默认)— 只暴露
search/grep/describe/run四个工具,对端以渐进式披露的方式发现和调用,上下文占用恒定,工具再多也不吃 context
--flat / --meta 可强制覆盖默认判定。
MCP 客户端配置示例(stdio 由客户端拉起,用 AXI_CONFIG 锚定项目):
{
"mcpServers": {
"my-tools": {
"command": "axi",
"args": ["mcp", "--server", "mytools"],
"env": { "AXI_CONFIG": "/path/to/project/axi.json" }
}
}
}
搜索
axi 提供两种搜索方式:
axi search— 混合搜索,默认 BM25 关键词搜索(bm25s + jieba 分词,支持中英文)。配置search.embedding后启用 BM25 + Embedding 混合搜索(RRF 融合排序,分数归一化 0-1)axi grep— 正则表达式搜索,按工具名和描述匹配
结果按相关性排序返回,顺序本身即信号(不含分数:native 与 MCP 来自两套索引、分数不可比)。
Daemon 模式
MCP 工具通过后台 daemon 长连接执行,支持有状态 MCP server(如 browser MCP)。
axi CLI ──(Unix socket)──> daemon ──(stdio)──> MCP server A
──(stdio)──> MCP server B
自动管理
执行 axi search、describe、run 等命令时,CLI 会自动检测 daemon 是否运行,未运行则自动拉起。大多数情况下无需手动管理。
生命周期
| 阶段 | 行为 |
|---|---|
| 启动 | 加载 axi.json → 连接所有 MCP server → 创建 Unix socket → 写入 PID 文件 → 启动 idle watchdog |
| 运行 | 通过 ~/.axi/daemons/<hash>.sock 监听请求,路由到对应 MCP server 执行 |
| 空闲关闭 | 默认 30 分钟无活动自动关闭(每 60 秒检查一次;status 和 shutdown 请求不重置计时器) |
| 手动关闭 | axi daemon stop 发送关闭指令,daemon 优雅退出 |
| 信号关闭 | 收到 SIGTERM / SIGINT 时优雅关闭(清理 socket 和 PID 文件) |
空闲超时可通过 axi.json 的 daemon.idleTimeoutMinutes 配置:
{ "daemon": { "idleTimeoutMinutes": 60 } }
手动管理
axi daemon start # 手动启动(通常不需要)
axi daemon status # 查看状态
axi daemon stop # 手动停止
axi daemon status 输出示例:
{
"status": "running",
"pid": 12345,
"config_path": "/path/to/project/axi.json",
"uptime_seconds": 1800,
"idle_seconds": 120,
"idle_timeout_seconds": 1800,
"idle_remaining_seconds": 1680,
"server_tools": { "jina": 5, "browser": 3 },
"native_tools": 2
}
文件位置
daemon 按配置文件隔离:每份 AXI_CONFIG 对应一个独立 daemon,运行时文件位于 ~/.axi/daemons/,文件名为配置文件绝对路径的哈希:
| 文件 | 说明 |
|---|---|
<hash>.sock |
Unix socket,CLI 与 daemon 的通信通道 |
<hash>.pid |
daemon 进程 PID,用于检测是否存活 |
<hash>.log |
daemon 启动和错误日志 |
axi daemon status 的 config_path 字段显示当前 daemon 服务的配置文件。
HTTP 入口认证与结构化输出
HTTP 服务可通过 --auth-key-env AXI_MCP_ACCESS_KEY 启用独立的 Bearer Key。
Key 只从指定的服务端环境变量读取;变量未配置时启动失败,每次请求均校验,
缺失或错误返回 401。不要把真实 Key 写进命令行、URL 或日志。
AXI_MCP_ALLOWED_HOSTS 为逗号分隔的 HTTP Host 白名单,例如 mcp.example.com。
非 localhost 监听必须显式配置;AXI_MCP_ALLOWED_ORIGINS 为浏览器 Origin 白名单。
没有 Origin 的原生客户端允许访问,有 Origin 的请求必须命中白名单。
反向代理应保留或正确设置 Host,对外使用 HTTPS。
这是预共享 Key 接入,不提供 OAuth 授权发现;客户端需支持自定义请求 header。 原有 stdio 和未启用认证的 localhost 调试保持兼容。
原生工具可在 @tool 上声明 output_model(Pydantic 模型或对象类型)和
annotations。axi 会导出 outputSchema 和工具注解,校验声明的输出,
同时返回 structuredContent 与兼容旧客户端的 JSON 文本。
未声明输出模型的工具保留原有执行行为。
技术栈
Python 3.12+ / Typer / Pydantic / MCP SDK / bm25s + jieba / LangChain(Embedding)
发布到 PyPI
在 PyPI 账号的 Publishing 页面添加 pending publisher:
- Project:
kli-axi - Owner:
klaus-zzz - Repository:
kli-axi - Workflow:
publish.yml - Environment:
pypi
修改 pyproject.toml 版本并更新锁文件、通过测试后,推送对应版本的 v* 标签。
.github/workflows/publish.yml 会重新测试、构建,并通过 OIDC 发布到 pypi.org,
无需在仓库保存 PyPI Token。私有 GitHub 仓库不影响 PyPI 包被公开下载。
License
MIT
Metadata
Release files for kli-axi 0.0.12
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| kli_axi-0.0.12.tar.gz | 48.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| kli_axi-0.0.12-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 97.0 kB
Release files / kli_axi-0.0.12.tar.gz
| Download URL | kli_axi-0.0.12.tar.gz |
|---|---|
| Size | 48.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
ac6b4d3e76f1d3663cb533007541f4005f3c8c0e617da626bf6d88c4c3cb424d
|
|
BLAKE2b-256 checksum How to use checksums |
d1effd93c2ee8fbdee06dc313cf7ae3bb33912432900dff71779ba9eab5886a8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / kli_axi-0.0.12-py3-none-any.whl
| Download URL | kli_axi-0.0.12-py3-none-any.whl |
|---|---|
| Size | 48.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bc8ce2f511799e75389de3ebafb4a6679df9997b7293832ba4b78b6554daf98b
|
|
BLAKE2b-256 checksum How to use checksums |
f6afe7774b23494a3a4bf5cab50d2586fff76b4a55702742d28eccecc0e50f21
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|