feat(mcp): 客户端配置新增 Oh-My-Pi 片段
在 /admin/mcp 客户端配置展示区增加 Oh-My-Pi(omp)的 MCP 配置片段, 位于 Cline 与「通用」之间。 Oh-My-Pi 的 mcpServers 条目与 Claude Code/Cursor 的关键差异:字段名 是 transport(而非 type),值仍为 streamable-http,auth 同样走 headers.Authorization。配置文件落在 ~/.pi/agent/mcp.json(全局)或 .pi/mcp.json(项目级)。 改动: - ClientConfigs / McpClientConfigs 新增 omp_json 字段 - generate_client_configs 生成 omp 片段 - ConfigCard 增加 ConfigSnippet 行 - 新增测试 omp_json_uses_transport_field_not_type,并纳入 pretty 校验循环 格式依据:2026 pi.dev / oh-my-pi 官方文档(联网核实)。
This commit is contained in:
parent
063ad6e606
commit
78fb51a310
@ -275,6 +275,8 @@ pub struct McpClientConfigs {
|
||||
pub cursor_json: String,
|
||||
/// Cline(`cline_mcp_settings.json`)。
|
||||
pub cline_json: String,
|
||||
/// Oh-My-Pi(`~/.pi/agent/mcp.json` / `.pi/mcp.json`)。字段名 `transport`,非 `type`。
|
||||
pub omp_json: String,
|
||||
/// 通用原始 JSON(单 server entry)。
|
||||
pub generic_json: String,
|
||||
/// Claude Code CLI 一行命令。
|
||||
@ -300,6 +302,7 @@ pub async fn get_mcp_client_configs(token: String) -> Result<McpClientConfigs, S
|
||||
claude_code_json: configs.claude_code_json,
|
||||
cursor_json: configs.cursor_json,
|
||||
cline_json: configs.cline_json,
|
||||
omp_json: configs.omp_json,
|
||||
generic_json: configs.generic_json,
|
||||
claude_cli: configs.claude_cli,
|
||||
})
|
||||
|
||||
@ -25,6 +25,9 @@ pub struct ClientConfigs {
|
||||
/// Cline(`cline_mcp_settings.json`)。`type: "streamableHttp"`(注意驼峰,非 `sse`),
|
||||
/// 额外带 `disabled` / `autoApprove` 字段。
|
||||
pub cline_json: String,
|
||||
/// Oh-My-Pi(`~/.pi/agent/mcp.json` 全局 / `.pi/mcp.json` 项目级)。与其它客户端的
|
||||
/// 关键差异:字段名是 `transport`(而非 `type`),值仍为 `streamable-http`。
|
||||
pub omp_json: String,
|
||||
/// 通用原始 JSON:一个 server entry 的纯净形式,供其它兼容客户端粘贴。
|
||||
pub generic_json: String,
|
||||
/// Claude Code CLI 一行命令:`claude mcp add --transport http <name> <url> --header ...`。
|
||||
@ -77,6 +80,17 @@ pub fn generate_client_configs(base_url: &str, token: &str) -> ClientConfigs {
|
||||
}
|
||||
});
|
||||
|
||||
// --- Oh-My-Pi:字段名是 transport(非 type),值仍为 streamable-http ---
|
||||
let omp_json = serde_json::json!({
|
||||
"mcpServers": {
|
||||
SERVER_NAME: {
|
||||
"transport": "streamable-http",
|
||||
"url": mcp_url,
|
||||
"headers": { "Authorization": auth_header }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// --- 通用:单个 server entry 的纯净形式 ---
|
||||
let generic_json = serde_json::json!({
|
||||
"type": "streamable-http",
|
||||
@ -94,6 +108,7 @@ pub fn generate_client_configs(base_url: &str, token: &str) -> ClientConfigs {
|
||||
claude_code_json: pretty_json(&claude_code_json),
|
||||
cursor_json: pretty_json(&cursor_json),
|
||||
cline_json: pretty_json(&cline_json),
|
||||
omp_json: pretty_json(&omp_json),
|
||||
generic_json: pretty_json(&generic_json),
|
||||
claude_cli,
|
||||
}
|
||||
@ -167,6 +182,18 @@ mod tests {
|
||||
assert_eq!(v["url"], "https://rua.plus/mcp");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn omp_json_uses_transport_field_not_type() {
|
||||
let cfg = generate_client_configs(BASE, TOKEN);
|
||||
let v: serde_json::Value = serde_json::from_str(&cfg.omp_json).unwrap();
|
||||
let entry = &v["mcpServers"]["yggdrasil"];
|
||||
// 关键差异:字段名是 transport(非 type)。
|
||||
assert_eq!(entry["transport"], "streamable-http");
|
||||
assert!(entry.get("type").is_none(), "omp 配置不应含 type 字段");
|
||||
assert_eq!(entry["url"], "https://rua.plus/mcp");
|
||||
assert_eq!(entry["headers"]["Authorization"], format!("Bearer {TOKEN}"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn claude_cli_one_liner_contains_url_and_header() {
|
||||
let cfg = generate_client_configs(BASE, TOKEN);
|
||||
@ -179,7 +206,7 @@ mod tests {
|
||||
fn all_json_is_pretty_indented() {
|
||||
let cfg = generate_client_configs(BASE, TOKEN);
|
||||
// pretty JSON 至少含一个换行 + 缩进(非单行紧凑形式)。
|
||||
for s in [&cfg.claude_code_json, &cfg.cursor_json, &cfg.cline_json, &cfg.generic_json] {
|
||||
for s in [&cfg.claude_code_json, &cfg.cursor_json, &cfg.cline_json, &cfg.omp_json, &cfg.generic_json] {
|
||||
assert!(s.contains('\n'), "JSON 应是 pretty-printed: {s}");
|
||||
assert!(s.contains(" "), "JSON 应含 2 空格缩进: {s}");
|
||||
}
|
||||
|
||||
@ -506,6 +506,7 @@ fn ConfigCard() -> Element {
|
||||
ConfigSnippet { title: "Claude Code(.mcp.json / ~/.claude.json)".to_string(), content: c.claude_code_json.clone() }
|
||||
ConfigSnippet { title: "Cursor(~/.cursor/mcp.json)".to_string(), content: c.cursor_json.clone() }
|
||||
ConfigSnippet { title: "Cline(cline_mcp_settings.json)".to_string(), content: c.cline_json.clone() }
|
||||
ConfigSnippet { title: "Oh-My-Pi(~/.pi/agent/mcp.json 或 .pi/mcp.json)".to_string(), content: c.omp_json.clone() }
|
||||
ConfigSnippet { title: "通用(单 server entry)".to_string(), content: c.generic_json.clone() }
|
||||
ConfigSnippet { title: "Claude Code CLI".to_string(), content: c.claude_cli.clone() }
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user