langfuse-trace-mcp 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- langfuse_trace_mcp-0.1.0/.gitignore +15 -0
- langfuse_trace_mcp-0.1.0/.python-version +1 -0
- langfuse_trace_mcp-0.1.0/LICENSE +21 -0
- langfuse_trace_mcp-0.1.0/PKG-INFO +323 -0
- langfuse_trace_mcp-0.1.0/README.md +303 -0
- langfuse_trace_mcp-0.1.0/pyproject.toml +66 -0
- langfuse_trace_mcp-0.1.0/src/langfuse_mcp/__init__.py +3 -0
- langfuse_trace_mcp-0.1.0/src/langfuse_mcp/__main__.py +42 -0
- langfuse_trace_mcp-0.1.0/src/langfuse_mcp/client.py +172 -0
- langfuse_trace_mcp-0.1.0/src/langfuse_mcp/config.py +62 -0
- langfuse_trace_mcp-0.1.0/src/langfuse_mcp/content.py +275 -0
- langfuse_trace_mcp-0.1.0/src/langfuse_mcp/contracts.json +2394 -0
- langfuse_trace_mcp-0.1.0/src/langfuse_mcp/models.py +64 -0
- langfuse_trace_mcp-0.1.0/src/langfuse_mcp/server.py +84 -0
- langfuse_trace_mcp-0.1.0/src/langfuse_mcp/service.py +603 -0
- langfuse_trace_mcp-0.1.0/src/langfuse_mcp/state.py +202 -0
- langfuse_trace_mcp-0.1.0/tests/conftest.py +67 -0
- langfuse_trace_mcp-0.1.0/tests/fixtures/langfuse.json +22 -0
- langfuse_trace_mcp-0.1.0/tests/smoke_stdio.py +110 -0
- langfuse_trace_mcp-0.1.0/tests/test_client.py +192 -0
- langfuse_trace_mcp-0.1.0/tests/test_content.py +271 -0
- langfuse_trace_mcp-0.1.0/tests/test_contracts.py +83 -0
- langfuse_trace_mcp-0.1.0/tests/test_service.py +240 -0
- langfuse_trace_mcp-0.1.0/tests/test_state.py +192 -0
- langfuse_trace_mcp-0.1.0/tests/test_stdio.py +249 -0
- langfuse_trace_mcp-0.1.0/uv.lock +927 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 langfuse-trace-mcp contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: langfuse-trace-mcp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Read-only stdio MCP server for Langfuse traces
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
License-File: LICENSE
|
|
7
|
+
Keywords: langfuse,mcp,observability,traces
|
|
8
|
+
Classifier: Environment :: Console
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Topic :: Utilities
|
|
13
|
+
Requires-Python: >=3.12
|
|
14
|
+
Requires-Dist: anyio<5,>=4.9
|
|
15
|
+
Requires-Dist: httpx<0.29,>=0.28.1
|
|
16
|
+
Requires-Dist: jsonschema[format]<5,>=4.25
|
|
17
|
+
Requires-Dist: mcp==1.27.0
|
|
18
|
+
Requires-Dist: pydantic<3,>=2.11
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# langfuse-trace-mcp
|
|
22
|
+
|
|
23
|
+
用于分析 Langfuse Trace、Session 和 badcase 的只读 Python MCP 服务,通过 stdio 提供六个工具。服务负责查询、分页和正文切片,分析由 Codex、Claude 等调用方完成;工具内部不调用大模型。
|
|
24
|
+
|
|
25
|
+
支持按 Trace ID、Session ID 或时间范围查询,先返回摘要,再按需分页读取节点和正文,减少一次查询带来的 token 消耗。
|
|
26
|
+
|
|
27
|
+
Python 分发包名为 `langfuse-trace-mcp`,命令行入口为 `langfuse-mcp`,Python 模块名为 `langfuse_mcp`。
|
|
28
|
+
|
|
29
|
+
## 1. 安装
|
|
30
|
+
|
|
31
|
+
准备好以下内容:
|
|
32
|
+
|
|
33
|
+
- Python 3.12+ 和 [uv](https://docs.astral.sh/uv/getting-started/installation/)。已有 uv 时无需重新安装。
|
|
34
|
+
- 项目源码,以及运行客户端的机器能够访问的 Langfuse 地址。
|
|
35
|
+
- 同一个 Langfuse 项目的 Public Key 和 Secret Key,可从该项目的 API Keys 设置中获取。
|
|
36
|
+
|
|
37
|
+
进入项目根目录安装依赖:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
cd /absolute/path/to/langfuse-mcp
|
|
41
|
+
uv sync --locked
|
|
42
|
+
uv run --no-sync langfuse-mcp --help
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
将 `/absolute/path/to/langfuse-mcp` 替换为实际源码目录;macOS / Linux 可在该目录执行 `pwd` 获取绝对路径。
|
|
46
|
+
|
|
47
|
+
`uv sync --locked` 会创建项目虚拟环境 `.venv`,按 `uv.lock` 安装依赖和本项目。依赖包含官方 MCP Python SDK 和 httpx;服务直接调用 Langfuse Public API,不需要安装 Langfuse SDK。
|
|
48
|
+
|
|
49
|
+
安装后,可执行文件位于:
|
|
50
|
+
|
|
51
|
+
| 系统 | 可执行文件 |
|
|
52
|
+
| --- | --- |
|
|
53
|
+
| macOS / Linux | `/absolute/path/to/langfuse-mcp/.venv/bin/langfuse-mcp` |
|
|
54
|
+
| Windows | `C:/absolute/path/to/langfuse-mcp/.venv/Scripts/langfuse-mcp.exe` |
|
|
55
|
+
|
|
56
|
+
下文以 macOS / Linux 为例。Windows 用户将 `command` 换成对应的 `.exe` 绝对路径;JSON / TOML 中可用 `/` 表示路径分隔符。
|
|
57
|
+
|
|
58
|
+
## 2. 在客户端中配置
|
|
59
|
+
|
|
60
|
+
服务通过 **stdio** 通信,由客户端自动启动和管理进程,无需先手动启动或使用 `nohup` 常驻后台。它不提供可填写到远程 MCP 连接框的 HTTP 地址。
|
|
61
|
+
|
|
62
|
+
所有客户端使用相同的三个启动参数:
|
|
63
|
+
|
|
64
|
+
| 参数 | 填写内容 |
|
|
65
|
+
| --- | --- |
|
|
66
|
+
| `--base-url` | Langfuse 服务地址,如 `https://langfuse.example.com`;不要追加 `/api/public` |
|
|
67
|
+
| `--public-key` | Langfuse 项目的 Public Key |
|
|
68
|
+
| `--secret-key` | 同一项目的 Secret Key |
|
|
69
|
+
|
|
70
|
+
下面的路径、地址和密钥都是占位符,使用前请替换。配置直接指向 `.venv` 中的可执行文件,无需激活虚拟环境,也不依赖桌面应用能否找到 `uv`。连接凭据在启动时传入,工具调用中无需传入凭据或 `environment`。
|
|
71
|
+
|
|
72
|
+
### Codex 桌面客户端 / CLI
|
|
73
|
+
|
|
74
|
+
打开 `~/.codex/config.toml`,添加以下配置;若已有 `[mcp_servers.langfuse]`,修改原条目即可:
|
|
75
|
+
|
|
76
|
+
```toml
|
|
77
|
+
[mcp_servers.langfuse]
|
|
78
|
+
command = "/absolute/path/to/langfuse-mcp/.venv/bin/langfuse-mcp"
|
|
79
|
+
args = [
|
|
80
|
+
"--base-url", "https://langfuse.example.com",
|
|
81
|
+
"--public-key", "<public_key>",
|
|
82
|
+
"--secret-key", "<secret_key>",
|
|
83
|
+
]
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
保存后重启 Codex 桌面客户端,或重新启动 Codex CLI 会话。桌面客户端可在 **Settings → MCP servers** 中检查服务。
|
|
87
|
+
|
|
88
|
+
如果安装了 Codex CLI,也可在终端检查登记的配置:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
codex mcp get langfuse
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
应显示 `enabled: true`、`transport: stdio` 及配置的启动命令。该命令只确认配置已登记,实际连接和查询可用下文的对话示例验证。
|
|
95
|
+
|
|
96
|
+
### Claude Desktop
|
|
97
|
+
|
|
98
|
+
打开 Claude 桌面应用的 **Settings → Developer → Edit Config**。配置文件通常位于:
|
|
99
|
+
|
|
100
|
+
| 系统 | 配置文件 |
|
|
101
|
+
| --- | --- |
|
|
102
|
+
| macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
|
|
103
|
+
| Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
|
|
104
|
+
|
|
105
|
+
将 `langfuse` 加入 `mcpServers`。已有其他服务时,保留原条目并合并此配置:
|
|
106
|
+
|
|
107
|
+
```json
|
|
108
|
+
{
|
|
109
|
+
"mcpServers": {
|
|
110
|
+
"langfuse": {
|
|
111
|
+
"command": "/absolute/path/to/langfuse-mcp/.venv/bin/langfuse-mcp",
|
|
112
|
+
"args": [
|
|
113
|
+
"--base-url", "https://langfuse.example.com",
|
|
114
|
+
"--public-key", "<public_key>",
|
|
115
|
+
"--secret-key", "<secret_key>"
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
保存后完全退出并重新打开 Claude Desktop。在 Developer 设置中检查连接状态,或从对话输入框的 **Connectors** 中查看 `langfuse` 和可用工具。
|
|
123
|
+
|
|
124
|
+
此配置用于本地桌面应用,Claude 网页版不能直接启动本机的 stdio 进程。
|
|
125
|
+
|
|
126
|
+
### Claude Code
|
|
127
|
+
|
|
128
|
+
已安装 Claude Code 时,在 macOS / Linux 终端执行:
|
|
129
|
+
|
|
130
|
+
```bash
|
|
131
|
+
claude mcp add --transport stdio --scope user langfuse -- \
|
|
132
|
+
/absolute/path/to/langfuse-mcp/.venv/bin/langfuse-mcp \
|
|
133
|
+
--base-url 'https://langfuse.example.com' \
|
|
134
|
+
--public-key '<public_key>' \
|
|
135
|
+
--secret-key '<secret_key>'
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
`--scope user` 表示该用户的所有项目均可使用;`--` 后面是服务的启动命令与参数。安装目录含空格时,用引号包住整个可执行文件路径。
|
|
139
|
+
|
|
140
|
+
检查配置及连接:
|
|
141
|
+
|
|
142
|
+
```bash
|
|
143
|
+
claude mcp get langfuse
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
重新启动 Claude Code 会话,输入 `/mcp` 查看 `langfuse` 的连接状态和工具。Claude Code 与 Claude Desktop 分别管理 MCP 配置,使用哪个客户端就配置哪一个。
|
|
147
|
+
|
|
148
|
+
以上接入方式依据 [OpenAI 官方 Codex MCP 文档](https://developers.openai.com/codex/mcp)、[Claude Desktop 本地 MCP 指南](https://modelcontextprotocol.io/docs/develop/connect-local-servers)和 [Claude Code MCP 文档](https://code.claude.com/docs/en/mcp)。
|
|
149
|
+
|
|
150
|
+
## 3. 开始查询
|
|
151
|
+
|
|
152
|
+
连接成功后,直接在 Codex 或 Claude 中描述需求,例如:
|
|
153
|
+
|
|
154
|
+
> 使用 langfuse MCP 分析 trace_id 为 `<trace_id>` 的请求。先获取摘要和第一页 observations,定位可疑节点后再按需读取 input/output,不要一次读取全部正文。
|
|
155
|
+
|
|
156
|
+
> 查询 session_id 为 `<session_id>` 的 Trace,先返回 10 条,说明哪些请求可能需要进一步排查。
|
|
157
|
+
|
|
158
|
+
> 查询北京时间 2026-10-10 09:00 到 10:00 之间开始的 Trace,先返回 20 条摘要;需要查看更多时再续页。
|
|
159
|
+
|
|
160
|
+
> 查找北京时间 2026-10-10 09:00 到 10:00 之间有 Trace 开始的 Session,先返回第一页。
|
|
161
|
+
|
|
162
|
+
服务只返回事实数据,badcase 分析由调用方完成。下面列出工具和调用示例,方便明确控制查询范围。
|
|
163
|
+
|
|
164
|
+
### 六个工具
|
|
165
|
+
|
|
166
|
+
| 工具 | 首次调用的主要参数 | 用途 |
|
|
167
|
+
| --- | --- | --- |
|
|
168
|
+
| `list_traces` | session_id,或 from_time + to_time;可选 name、user_id、tags、order、view、limit | 查找 Trace,或分页读取一个 Session 的 Trace |
|
|
169
|
+
| `get_trace` | trace_id | 获取单条 Trace 的基本信息和指标 |
|
|
170
|
+
| `list_observations` | trace_id,或 from_time + to_time;可选 parent_observation_id、name、type、level、view、limit | 分页查看节点与错误状态 |
|
|
171
|
+
| `get_observation` | trace_id + observation_id | 查看单节点的耗时、模型、用量与错误信息 |
|
|
172
|
+
| `read_content` | trace_id、可选 observation_id、field;可选 path、format、offset、limit | 读取 input/output/metadata 等字段的结构或片段 |
|
|
173
|
+
| `list_sessions` | from_time + to_time;可选 time_basis、limit | 按 Trace 开始时间或 Session 创建时间发现 Session |
|
|
174
|
+
|
|
175
|
+
完整参数与返回值见包内的 `langfuse_mcp/contracts.json`,源码中对应 `src/langfuse_mcp/contracts.json`;详细设计位于源码仓库的 `docs/stdio-mcp-design.md`。工具发现只返回输入 Schema 和简短说明,工具结果为一个包含紧凑 JSON 的 TextContent。
|
|
176
|
+
|
|
177
|
+
### 按 Trace 查看节点和正文
|
|
178
|
+
|
|
179
|
+
常用调用顺序如下。这里表示 MCP 工具名和参数,不是 shell 命令:
|
|
180
|
+
|
|
181
|
+
1. `get_trace({"trace_id":"..."})` 获取概况。
|
|
182
|
+
2. `list_observations({"trace_id":"...","limit":20})` 查看一页节点。
|
|
183
|
+
3. `get_observation({"trace_id":"...","observation_id":"..."})` 定位可疑节点。
|
|
184
|
+
4. `read_content({"trace_id":"...","observation_id":"...","field":"input","path":"/messages","limit":10})` 查看一页消息预览。
|
|
185
|
+
5. 对需要分析的消息读取 `/messages/3/content`,按需续读正文。
|
|
186
|
+
|
|
187
|
+
### 按 Session 或时间查询
|
|
188
|
+
|
|
189
|
+
调用 `list_traces`,单独提供 `session_id` 即可查询 Session 内的 Trace:
|
|
190
|
+
|
|
191
|
+
```json
|
|
192
|
+
{"session_id": "<session_id>", "limit": 10}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
调用 `list_traces` 查询指定时间范围,时间必须包含时区:
|
|
196
|
+
|
|
197
|
+
```json
|
|
198
|
+
{
|
|
199
|
+
"from_time": "2026-10-10T09:00:00+08:00",
|
|
200
|
+
"to_time": "2026-10-10T10:00:00+08:00",
|
|
201
|
+
"limit": 20
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
调用 `list_sessions` 发现这个时间范围内有 Trace 开始的 Session:
|
|
206
|
+
|
|
207
|
+
```json
|
|
208
|
+
{
|
|
209
|
+
"from_time": "2026-10-10T09:00:00+08:00",
|
|
210
|
+
"to_time": "2026-10-10T10:00:00+08:00",
|
|
211
|
+
"time_basis": "trace_started",
|
|
212
|
+
"limit": 20
|
|
213
|
+
}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
如果要按 Session 自身的创建时间查询,将 `time_basis` 改为 `created`。
|
|
217
|
+
|
|
218
|
+
### 获取下一页
|
|
219
|
+
|
|
220
|
+
当返回的 `next_cursor` 非空时,调用**同一个工具**,只传该 cursor:
|
|
221
|
+
|
|
222
|
+
```json
|
|
223
|
+
{"cursor": "<上一次返回的 next_cursor>"}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
不要同时传 `limit`、ID 或时间条件;查询条件已保存在 cursor 中。`next_cursor: null` 表示结束。列表和 `read_content` 都使用这一续页方式。
|
|
227
|
+
|
|
228
|
+
## 4. 分页与内容读取
|
|
229
|
+
|
|
230
|
+
- 列表默认 20 条,最大 50 条。每次至多获取一个新的上游源页,不会自动遍历整个 Trace 或时间窗口。
|
|
231
|
+
- 后续调用同一个工具时只传 `{"cursor":"上次的 next_cursor"}`。cursor 与其他参数混用会报错;`next_cursor=null` 表示结束。
|
|
232
|
+
- 一页因输出长度限制分多次返回时,优先消费已读取的剩余记录。同一 cursor 重试会重放相同结果。
|
|
233
|
+
- Observation 的 level 筛选和 Session 去重可能产生空 items,但 next_cursor 仍有值;这时可以继续读取。
|
|
234
|
+
- 时间必须带时区,范围为 `[from_time,to_time)`。Trace、Observation、Session created 模式分别过滤 timestamp、startTime、createdAt。
|
|
235
|
+
- `read_content` 用 JSON Pointer 定位字段,再处理选中的内容。文本按 Unicode 字符分页;数组和对象按项/键分页。字符串化 JSON 可以按路径访问,`format=text` 可以连续读取其文本。
|
|
236
|
+
- 正文默认 4000 字符、最多 8000;数组/对象默认 20 项、最多 50。整个返回同时受 12,000 个 JSON 字符和 64 KiB 限制。
|
|
237
|
+
- 正文 cursor 固定已读取的内容;新建不同路径的请求不保证与旧快照同时刻。实体缓存有效 5 秒;cursor 空闲 15 分钟、最长 1 小时,进程重启或状态淘汰后需重新查询。
|
|
238
|
+
- 选中内容中的已知秘密字段、启动密钥及明确标记的 base64 会被处理,并附带 warnings;敏感字段不能通过子路径绕过脱敏。偏移量对应处理后的内容。不会执行正文指令或下载其中的 URL。
|
|
239
|
+
|
|
240
|
+
节点集合使用 Langfuse 原生分页。当前旧版 API 对单节点 I/O 不提供字符范围下载,因此首次读取仍可能下载整条节点;后续由 MCP 切片返回。单响应解压后最多 32 MiB,一次工具调用累计最多 64 MiB、最多 3 次请求(含重试),工具总时限 30 秒。
|
|
241
|
+
|
|
242
|
+
本版使用参考部署支持的 Trace 列表、Observation v1 和 Session 列表端点。官方已将它们标为 legacy,Langfuse v4 的兼容性需另行验证。页码分页受持续写入和晚到数据影响,不提供跨页强一致快照。
|
|
243
|
+
|
|
244
|
+
## 5. 验证与排查
|
|
245
|
+
|
|
246
|
+
以下命令都在项目根目录执行。
|
|
247
|
+
|
|
248
|
+
只检查安装、stdio 握手和六个工具的发现,不访问 Langfuse:
|
|
249
|
+
|
|
250
|
+
```bash
|
|
251
|
+
uv run --no-sync python tests/smoke_stdio.py \
|
|
252
|
+
--base-url http://127.0.0.1:1 \
|
|
253
|
+
--public-key placeholder --secret-key placeholder \
|
|
254
|
+
--discovery-only
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
预期输出 `PASS initialize tools/list`。客户端显示已连接也只代表 MCP 连接正常,Langfuse 地址和密钥会在第一次实际查询时验证。
|
|
258
|
+
|
|
259
|
+
要验证真实 Langfuse 查询,传入实际连接参数和一个存在的 Trace ID:
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
uv run --no-sync python tests/smoke_stdio.py \
|
|
263
|
+
--base-url https://langfuse.example.com \
|
|
264
|
+
--public-key '<public_key>' --secret-key '<secret_key>' \
|
|
265
|
+
--trace-id '<existing_trace_id>'
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
验收脚本只读取小页和一个正文片段,输出通过项与错误码。它不会自动加载其他项目的配置。没有节点的 Trace 会明确跳过单节点检查。
|
|
269
|
+
|
|
270
|
+
| 现象 | 检查方法 |
|
|
271
|
+
| --- | --- |
|
|
272
|
+
| 客户端找不到命令、出现 `ENOENT` | 确认已执行 `uv sync --locked`,且 `command` 是实际存在的绝对路径;目录含空格时,JSON / TOML 中仍填写完整路径字符串 |
|
|
273
|
+
| 修改配置后未出现工具 | 检查 JSON / TOML 格式,保留其他配置条目,保存后重启相应客户端或 CLI 会话 |
|
|
274
|
+
| 显示已连接,但查询报 `AUTH_FAILED` | 检查地址和两个 Key 是否属于同一 Langfuse 项目 |
|
|
275
|
+
| 查询报连接错误或超时 | 确认运行客户端的机器能访问 Langfuse;内网部署需要相应网络连接 |
|
|
276
|
+
| 手动启动后终端没有输出 | stdio 服务在等待客户端消息,属于正常行为;可用上面的 discovery 检查,按 Ctrl+C 结束手动启动的进程 |
|
|
277
|
+
| 返回 `CURSOR_EXPIRED` | cursor 已过期、被淘汰或服务已重启,重新提交首次查询条件 |
|
|
278
|
+
|
|
279
|
+
服务 stdout 仅用于 MCP 消息,日志写入 stderr;客户端报告启动失败时,可在其 MCP 日志中查看原因。
|
|
280
|
+
|
|
281
|
+
## 6. 开发与相关文档
|
|
282
|
+
|
|
283
|
+
```bash
|
|
284
|
+
uv run ruff format --check .
|
|
285
|
+
uv run ruff check .
|
|
286
|
+
uv run pytest -m "not live"
|
|
287
|
+
uv build
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
测试使用人工数据和 httpx MockTransport;stdio 集成测试需要允许监听临时的 `127.0.0.1` 端口。覆盖源页拆分、游标重放与取消、Session 去重、正文切片、响应限额、协议错误、两个 MCP 协议版本和 EOF 退出。
|
|
291
|
+
|
|
292
|
+
构建出的 wheel 可以安装到独立 Python 环境,并直接运行该环境的 `langfuse-mcp` 可执行文件。源码仓库的 `docs/implementation-plan.md` 和 `docs/validation.md` 分别记录实施方案与验证结果;`docs` 不随发行包分发。
|
|
293
|
+
|
|
294
|
+
## 7. 构建与发布
|
|
295
|
+
|
|
296
|
+
发行包使用标准的 `pyproject.toml` 元数据和 Hatchling 构建后端。文件范围由构建配置明确限定:
|
|
297
|
+
|
|
298
|
+
- 源码发行包(`.tar.gz`):源码、测试及人工数据、README、MIT 许可证、`pyproject.toml`、`uv.lock`、`.python-version`、`.gitignore`,以及构建工具生成的包元数据。
|
|
299
|
+
- wheel(`.whl`):`langfuse_mcp` 运行模块、`contracts.json`、MIT 许可证和安装元数据。
|
|
300
|
+
- 两种发行包均排除整个 `docs`、`.git`、字节码和 `.DS_Store`;虚拟环境、缓存、旧构建产物及 ZIP 不在文件清单中。
|
|
301
|
+
|
|
302
|
+
构建并校验待发布文件:
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
uv build --no-sources
|
|
306
|
+
uvx --from 'twine>=7,<8' twine check --strict \
|
|
307
|
+
dist/langfuse_trace_mcp-0.1.0-py3-none-any.whl \
|
|
308
|
+
dist/langfuse_trace_mcp-0.1.0.tar.gz
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
准备好 PyPI 发布令牌并在本机设置 `UV_PUBLISH_TOKEN` 后,明确指定本次上传的两个文件,避免旧包或 ZIP 混入:
|
|
312
|
+
|
|
313
|
+
```bash
|
|
314
|
+
uv publish \
|
|
315
|
+
dist/langfuse_trace_mcp-0.1.0-py3-none-any.whl \
|
|
316
|
+
dist/langfuse_trace_mcp-0.1.0.tar.gz
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
构建和 `twine check` 不会上传文件;只有 `uv publish` 执行发布。每次新发布需递增版本号,同步 `pyproject.toml` 与 `src/langfuse_mcp/__init__.py`,运行 `uv lock` 并在命令中使用对应版本的文件名。
|
|
320
|
+
|
|
321
|
+
## 8. 许可证
|
|
322
|
+
|
|
323
|
+
本项目采用 MIT 许可证,完整条款见 `LICENSE`。许可证随源码发行包及 wheel 一同分发。
|
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
# langfuse-trace-mcp
|
|
2
|
+
|
|
3
|
+
用于分析 Langfuse Trace、Session 和 badcase 的只读 Python MCP 服务,通过 stdio 提供六个工具。服务负责查询、分页和正文切片,分析由 Codex、Claude 等调用方完成;工具内部不调用大模型。
|
|
4
|
+
|
|
5
|
+
支持按 Trace ID、Session ID 或时间范围查询,先返回摘要,再按需分页读取节点和正文,减少一次查询带来的 token 消耗。
|
|
6
|
+
|
|
7
|
+
Python 分发包名为 `langfuse-trace-mcp`,命令行入口为 `langfuse-mcp`,Python 模块名为 `langfuse_mcp`。
|
|
8
|
+
|
|
9
|
+
## 1. 安装
|
|
10
|
+
|
|
11
|
+
准备好以下内容:
|
|
12
|
+
|
|
13
|
+
- Python 3.12+ 和 [uv](https://docs.astral.sh/uv/getting-started/installation/)。已有 uv 时无需重新安装。
|
|
14
|
+
- 项目源码,以及运行客户端的机器能够访问的 Langfuse 地址。
|
|
15
|
+
- 同一个 Langfuse 项目的 Public Key 和 Secret Key,可从该项目的 API Keys 设置中获取。
|
|
16
|
+
|
|
17
|
+
进入项目根目录安装依赖:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
cd /absolute/path/to/langfuse-mcp
|
|
21
|
+
uv sync --locked
|
|
22
|
+
uv run --no-sync langfuse-mcp --help
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
将 `/absolute/path/to/langfuse-mcp` 替换为实际源码目录;macOS / Linux 可在该目录执行 `pwd` 获取绝对路径。
|
|
26
|
+
|
|
27
|
+
`uv sync --locked` 会创建项目虚拟环境 `.venv`,按 `uv.lock` 安装依赖和本项目。依赖包含官方 MCP Python SDK 和 httpx;服务直接调用 Langfuse Public API,不需要安装 Langfuse SDK。
|
|
28
|
+
|
|
29
|
+
安装后,可执行文件位于:
|
|
30
|
+
|
|
31
|
+
| 系统 | 可执行文件 |
|
|
32
|
+
| --- | --- |
|
|
33
|
+
| macOS / Linux | `/absolute/path/to/langfuse-mcp/.venv/bin/langfuse-mcp` |
|
|
34
|
+
| Windows | `C:/absolute/path/to/langfuse-mcp/.venv/Scripts/langfuse-mcp.exe` |
|
|
35
|
+
|
|
36
|
+
下文以 macOS / Linux 为例。Windows 用户将 `command` 换成对应的 `.exe` 绝对路径;JSON / TOML 中可用 `/` 表示路径分隔符。
|
|
37
|
+
|
|
38
|
+
## 2. 在客户端中配置
|
|
39
|
+
|
|
40
|
+
服务通过 **stdio** 通信,由客户端自动启动和管理进程,无需先手动启动或使用 `nohup` 常驻后台。它不提供可填写到远程 MCP 连接框的 HTTP 地址。
|
|
41
|
+
|
|
42
|
+
所有客户端使用相同的三个启动参数:
|
|
43
|
+
|
|
44
|
+
| 参数 | 填写内容 |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| `--base-url` | Langfuse 服务地址,如 `https://langfuse.example.com`;不要追加 `/api/public` |
|
|
47
|
+
| `--public-key` | Langfuse 项目的 Public Key |
|
|
48
|
+
| `--secret-key` | 同一项目的 Secret Key |
|
|
49
|
+
|
|
50
|
+
下面的路径、地址和密钥都是占位符,使用前请替换。配置直接指向 `.venv` 中的可执行文件,无需激活虚拟环境,也不依赖桌面应用能否找到 `uv`。连接凭据在启动时传入,工具调用中无需传入凭据或 `environment`。
|
|
51
|
+
|
|
52
|
+
### Codex 桌面客户端 / CLI
|
|
53
|
+
|
|
54
|
+
打开 `~/.codex/config.toml`,添加以下配置;若已有 `[mcp_servers.langfuse]`,修改原条目即可:
|
|
55
|
+
|
|
56
|
+
```toml
|
|
57
|
+
[mcp_servers.langfuse]
|
|
58
|
+
command = "/absolute/path/to/langfuse-mcp/.venv/bin/langfuse-mcp"
|
|
59
|
+
args = [
|
|
60
|
+
"--base-url", "https://langfuse.example.com",
|
|
61
|
+
"--public-key", "<public_key>",
|
|
62
|
+
"--secret-key", "<secret_key>",
|
|
63
|
+
]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
保存后重启 Codex 桌面客户端,或重新启动 Codex CLI 会话。桌面客户端可在 **Settings → MCP servers** 中检查服务。
|
|
67
|
+
|
|
68
|
+
如果安装了 Codex CLI,也可在终端检查登记的配置:
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
codex mcp get langfuse
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
应显示 `enabled: true`、`transport: stdio` 及配置的启动命令。该命令只确认配置已登记,实际连接和查询可用下文的对话示例验证。
|
|
75
|
+
|
|
76
|
+
### Claude Desktop
|
|
77
|
+
|
|
78
|
+
打开 Claude 桌面应用的 **Settings → Developer → Edit Config**。配置文件通常位于:
|
|
79
|
+
|
|
80
|
+
| 系统 | 配置文件 |
|
|
81
|
+
| --- | --- |
|
|
82
|
+
| macOS | `~/Library/Application Support/Claude/claude_desktop_config.json` |
|
|
83
|
+
| Windows | `%APPDATA%\Claude\claude_desktop_config.json` |
|
|
84
|
+
|
|
85
|
+
将 `langfuse` 加入 `mcpServers`。已有其他服务时,保留原条目并合并此配置:
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"mcpServers": {
|
|
90
|
+
"langfuse": {
|
|
91
|
+
"command": "/absolute/path/to/langfuse-mcp/.venv/bin/langfuse-mcp",
|
|
92
|
+
"args": [
|
|
93
|
+
"--base-url", "https://langfuse.example.com",
|
|
94
|
+
"--public-key", "<public_key>",
|
|
95
|
+
"--secret-key", "<secret_key>"
|
|
96
|
+
]
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
保存后完全退出并重新打开 Claude Desktop。在 Developer 设置中检查连接状态,或从对话输入框的 **Connectors** 中查看 `langfuse` 和可用工具。
|
|
103
|
+
|
|
104
|
+
此配置用于本地桌面应用,Claude 网页版不能直接启动本机的 stdio 进程。
|
|
105
|
+
|
|
106
|
+
### Claude Code
|
|
107
|
+
|
|
108
|
+
已安装 Claude Code 时,在 macOS / Linux 终端执行:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
claude mcp add --transport stdio --scope user langfuse -- \
|
|
112
|
+
/absolute/path/to/langfuse-mcp/.venv/bin/langfuse-mcp \
|
|
113
|
+
--base-url 'https://langfuse.example.com' \
|
|
114
|
+
--public-key '<public_key>' \
|
|
115
|
+
--secret-key '<secret_key>'
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`--scope user` 表示该用户的所有项目均可使用;`--` 后面是服务的启动命令与参数。安装目录含空格时,用引号包住整个可执行文件路径。
|
|
119
|
+
|
|
120
|
+
检查配置及连接:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
claude mcp get langfuse
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
重新启动 Claude Code 会话,输入 `/mcp` 查看 `langfuse` 的连接状态和工具。Claude Code 与 Claude Desktop 分别管理 MCP 配置,使用哪个客户端就配置哪一个。
|
|
127
|
+
|
|
128
|
+
以上接入方式依据 [OpenAI 官方 Codex MCP 文档](https://developers.openai.com/codex/mcp)、[Claude Desktop 本地 MCP 指南](https://modelcontextprotocol.io/docs/develop/connect-local-servers)和 [Claude Code MCP 文档](https://code.claude.com/docs/en/mcp)。
|
|
129
|
+
|
|
130
|
+
## 3. 开始查询
|
|
131
|
+
|
|
132
|
+
连接成功后,直接在 Codex 或 Claude 中描述需求,例如:
|
|
133
|
+
|
|
134
|
+
> 使用 langfuse MCP 分析 trace_id 为 `<trace_id>` 的请求。先获取摘要和第一页 observations,定位可疑节点后再按需读取 input/output,不要一次读取全部正文。
|
|
135
|
+
|
|
136
|
+
> 查询 session_id 为 `<session_id>` 的 Trace,先返回 10 条,说明哪些请求可能需要进一步排查。
|
|
137
|
+
|
|
138
|
+
> 查询北京时间 2026-10-10 09:00 到 10:00 之间开始的 Trace,先返回 20 条摘要;需要查看更多时再续页。
|
|
139
|
+
|
|
140
|
+
> 查找北京时间 2026-10-10 09:00 到 10:00 之间有 Trace 开始的 Session,先返回第一页。
|
|
141
|
+
|
|
142
|
+
服务只返回事实数据,badcase 分析由调用方完成。下面列出工具和调用示例,方便明确控制查询范围。
|
|
143
|
+
|
|
144
|
+
### 六个工具
|
|
145
|
+
|
|
146
|
+
| 工具 | 首次调用的主要参数 | 用途 |
|
|
147
|
+
| --- | --- | --- |
|
|
148
|
+
| `list_traces` | session_id,或 from_time + to_time;可选 name、user_id、tags、order、view、limit | 查找 Trace,或分页读取一个 Session 的 Trace |
|
|
149
|
+
| `get_trace` | trace_id | 获取单条 Trace 的基本信息和指标 |
|
|
150
|
+
| `list_observations` | trace_id,或 from_time + to_time;可选 parent_observation_id、name、type、level、view、limit | 分页查看节点与错误状态 |
|
|
151
|
+
| `get_observation` | trace_id + observation_id | 查看单节点的耗时、模型、用量与错误信息 |
|
|
152
|
+
| `read_content` | trace_id、可选 observation_id、field;可选 path、format、offset、limit | 读取 input/output/metadata 等字段的结构或片段 |
|
|
153
|
+
| `list_sessions` | from_time + to_time;可选 time_basis、limit | 按 Trace 开始时间或 Session 创建时间发现 Session |
|
|
154
|
+
|
|
155
|
+
完整参数与返回值见包内的 `langfuse_mcp/contracts.json`,源码中对应 `src/langfuse_mcp/contracts.json`;详细设计位于源码仓库的 `docs/stdio-mcp-design.md`。工具发现只返回输入 Schema 和简短说明,工具结果为一个包含紧凑 JSON 的 TextContent。
|
|
156
|
+
|
|
157
|
+
### 按 Trace 查看节点和正文
|
|
158
|
+
|
|
159
|
+
常用调用顺序如下。这里表示 MCP 工具名和参数,不是 shell 命令:
|
|
160
|
+
|
|
161
|
+
1. `get_trace({"trace_id":"..."})` 获取概况。
|
|
162
|
+
2. `list_observations({"trace_id":"...","limit":20})` 查看一页节点。
|
|
163
|
+
3. `get_observation({"trace_id":"...","observation_id":"..."})` 定位可疑节点。
|
|
164
|
+
4. `read_content({"trace_id":"...","observation_id":"...","field":"input","path":"/messages","limit":10})` 查看一页消息预览。
|
|
165
|
+
5. 对需要分析的消息读取 `/messages/3/content`,按需续读正文。
|
|
166
|
+
|
|
167
|
+
### 按 Session 或时间查询
|
|
168
|
+
|
|
169
|
+
调用 `list_traces`,单独提供 `session_id` 即可查询 Session 内的 Trace:
|
|
170
|
+
|
|
171
|
+
```json
|
|
172
|
+
{"session_id": "<session_id>", "limit": 10}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
调用 `list_traces` 查询指定时间范围,时间必须包含时区:
|
|
176
|
+
|
|
177
|
+
```json
|
|
178
|
+
{
|
|
179
|
+
"from_time": "2026-10-10T09:00:00+08:00",
|
|
180
|
+
"to_time": "2026-10-10T10:00:00+08:00",
|
|
181
|
+
"limit": 20
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
调用 `list_sessions` 发现这个时间范围内有 Trace 开始的 Session:
|
|
186
|
+
|
|
187
|
+
```json
|
|
188
|
+
{
|
|
189
|
+
"from_time": "2026-10-10T09:00:00+08:00",
|
|
190
|
+
"to_time": "2026-10-10T10:00:00+08:00",
|
|
191
|
+
"time_basis": "trace_started",
|
|
192
|
+
"limit": 20
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
如果要按 Session 自身的创建时间查询,将 `time_basis` 改为 `created`。
|
|
197
|
+
|
|
198
|
+
### 获取下一页
|
|
199
|
+
|
|
200
|
+
当返回的 `next_cursor` 非空时,调用**同一个工具**,只传该 cursor:
|
|
201
|
+
|
|
202
|
+
```json
|
|
203
|
+
{"cursor": "<上一次返回的 next_cursor>"}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
不要同时传 `limit`、ID 或时间条件;查询条件已保存在 cursor 中。`next_cursor: null` 表示结束。列表和 `read_content` 都使用这一续页方式。
|
|
207
|
+
|
|
208
|
+
## 4. 分页与内容读取
|
|
209
|
+
|
|
210
|
+
- 列表默认 20 条,最大 50 条。每次至多获取一个新的上游源页,不会自动遍历整个 Trace 或时间窗口。
|
|
211
|
+
- 后续调用同一个工具时只传 `{"cursor":"上次的 next_cursor"}`。cursor 与其他参数混用会报错;`next_cursor=null` 表示结束。
|
|
212
|
+
- 一页因输出长度限制分多次返回时,优先消费已读取的剩余记录。同一 cursor 重试会重放相同结果。
|
|
213
|
+
- Observation 的 level 筛选和 Session 去重可能产生空 items,但 next_cursor 仍有值;这时可以继续读取。
|
|
214
|
+
- 时间必须带时区,范围为 `[from_time,to_time)`。Trace、Observation、Session created 模式分别过滤 timestamp、startTime、createdAt。
|
|
215
|
+
- `read_content` 用 JSON Pointer 定位字段,再处理选中的内容。文本按 Unicode 字符分页;数组和对象按项/键分页。字符串化 JSON 可以按路径访问,`format=text` 可以连续读取其文本。
|
|
216
|
+
- 正文默认 4000 字符、最多 8000;数组/对象默认 20 项、最多 50。整个返回同时受 12,000 个 JSON 字符和 64 KiB 限制。
|
|
217
|
+
- 正文 cursor 固定已读取的内容;新建不同路径的请求不保证与旧快照同时刻。实体缓存有效 5 秒;cursor 空闲 15 分钟、最长 1 小时,进程重启或状态淘汰后需重新查询。
|
|
218
|
+
- 选中内容中的已知秘密字段、启动密钥及明确标记的 base64 会被处理,并附带 warnings;敏感字段不能通过子路径绕过脱敏。偏移量对应处理后的内容。不会执行正文指令或下载其中的 URL。
|
|
219
|
+
|
|
220
|
+
节点集合使用 Langfuse 原生分页。当前旧版 API 对单节点 I/O 不提供字符范围下载,因此首次读取仍可能下载整条节点;后续由 MCP 切片返回。单响应解压后最多 32 MiB,一次工具调用累计最多 64 MiB、最多 3 次请求(含重试),工具总时限 30 秒。
|
|
221
|
+
|
|
222
|
+
本版使用参考部署支持的 Trace 列表、Observation v1 和 Session 列表端点。官方已将它们标为 legacy,Langfuse v4 的兼容性需另行验证。页码分页受持续写入和晚到数据影响,不提供跨页强一致快照。
|
|
223
|
+
|
|
224
|
+
## 5. 验证与排查
|
|
225
|
+
|
|
226
|
+
以下命令都在项目根目录执行。
|
|
227
|
+
|
|
228
|
+
只检查安装、stdio 握手和六个工具的发现,不访问 Langfuse:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
uv run --no-sync python tests/smoke_stdio.py \
|
|
232
|
+
--base-url http://127.0.0.1:1 \
|
|
233
|
+
--public-key placeholder --secret-key placeholder \
|
|
234
|
+
--discovery-only
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
预期输出 `PASS initialize tools/list`。客户端显示已连接也只代表 MCP 连接正常,Langfuse 地址和密钥会在第一次实际查询时验证。
|
|
238
|
+
|
|
239
|
+
要验证真实 Langfuse 查询,传入实际连接参数和一个存在的 Trace ID:
|
|
240
|
+
|
|
241
|
+
```bash
|
|
242
|
+
uv run --no-sync python tests/smoke_stdio.py \
|
|
243
|
+
--base-url https://langfuse.example.com \
|
|
244
|
+
--public-key '<public_key>' --secret-key '<secret_key>' \
|
|
245
|
+
--trace-id '<existing_trace_id>'
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
验收脚本只读取小页和一个正文片段,输出通过项与错误码。它不会自动加载其他项目的配置。没有节点的 Trace 会明确跳过单节点检查。
|
|
249
|
+
|
|
250
|
+
| 现象 | 检查方法 |
|
|
251
|
+
| --- | --- |
|
|
252
|
+
| 客户端找不到命令、出现 `ENOENT` | 确认已执行 `uv sync --locked`,且 `command` 是实际存在的绝对路径;目录含空格时,JSON / TOML 中仍填写完整路径字符串 |
|
|
253
|
+
| 修改配置后未出现工具 | 检查 JSON / TOML 格式,保留其他配置条目,保存后重启相应客户端或 CLI 会话 |
|
|
254
|
+
| 显示已连接,但查询报 `AUTH_FAILED` | 检查地址和两个 Key 是否属于同一 Langfuse 项目 |
|
|
255
|
+
| 查询报连接错误或超时 | 确认运行客户端的机器能访问 Langfuse;内网部署需要相应网络连接 |
|
|
256
|
+
| 手动启动后终端没有输出 | stdio 服务在等待客户端消息,属于正常行为;可用上面的 discovery 检查,按 Ctrl+C 结束手动启动的进程 |
|
|
257
|
+
| 返回 `CURSOR_EXPIRED` | cursor 已过期、被淘汰或服务已重启,重新提交首次查询条件 |
|
|
258
|
+
|
|
259
|
+
服务 stdout 仅用于 MCP 消息,日志写入 stderr;客户端报告启动失败时,可在其 MCP 日志中查看原因。
|
|
260
|
+
|
|
261
|
+
## 6. 开发与相关文档
|
|
262
|
+
|
|
263
|
+
```bash
|
|
264
|
+
uv run ruff format --check .
|
|
265
|
+
uv run ruff check .
|
|
266
|
+
uv run pytest -m "not live"
|
|
267
|
+
uv build
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
测试使用人工数据和 httpx MockTransport;stdio 集成测试需要允许监听临时的 `127.0.0.1` 端口。覆盖源页拆分、游标重放与取消、Session 去重、正文切片、响应限额、协议错误、两个 MCP 协议版本和 EOF 退出。
|
|
271
|
+
|
|
272
|
+
构建出的 wheel 可以安装到独立 Python 环境,并直接运行该环境的 `langfuse-mcp` 可执行文件。源码仓库的 `docs/implementation-plan.md` 和 `docs/validation.md` 分别记录实施方案与验证结果;`docs` 不随发行包分发。
|
|
273
|
+
|
|
274
|
+
## 7. 构建与发布
|
|
275
|
+
|
|
276
|
+
发行包使用标准的 `pyproject.toml` 元数据和 Hatchling 构建后端。文件范围由构建配置明确限定:
|
|
277
|
+
|
|
278
|
+
- 源码发行包(`.tar.gz`):源码、测试及人工数据、README、MIT 许可证、`pyproject.toml`、`uv.lock`、`.python-version`、`.gitignore`,以及构建工具生成的包元数据。
|
|
279
|
+
- wheel(`.whl`):`langfuse_mcp` 运行模块、`contracts.json`、MIT 许可证和安装元数据。
|
|
280
|
+
- 两种发行包均排除整个 `docs`、`.git`、字节码和 `.DS_Store`;虚拟环境、缓存、旧构建产物及 ZIP 不在文件清单中。
|
|
281
|
+
|
|
282
|
+
构建并校验待发布文件:
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
uv build --no-sources
|
|
286
|
+
uvx --from 'twine>=7,<8' twine check --strict \
|
|
287
|
+
dist/langfuse_trace_mcp-0.1.0-py3-none-any.whl \
|
|
288
|
+
dist/langfuse_trace_mcp-0.1.0.tar.gz
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
准备好 PyPI 发布令牌并在本机设置 `UV_PUBLISH_TOKEN` 后,明确指定本次上传的两个文件,避免旧包或 ZIP 混入:
|
|
292
|
+
|
|
293
|
+
```bash
|
|
294
|
+
uv publish \
|
|
295
|
+
dist/langfuse_trace_mcp-0.1.0-py3-none-any.whl \
|
|
296
|
+
dist/langfuse_trace_mcp-0.1.0.tar.gz
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
构建和 `twine check` 不会上传文件;只有 `uv publish` 执行发布。每次新发布需递增版本号,同步 `pyproject.toml` 与 `src/langfuse_mcp/__init__.py`,运行 `uv lock` 并在命令中使用对应版本的文件名。
|
|
300
|
+
|
|
301
|
+
## 8. 许可证
|
|
302
|
+
|
|
303
|
+
本项目采用 MIT 许可证,完整条款见 `LICENSE`。许可证随源码发行包及 wheel 一同分发。
|