Files
UHD_Media_Tool/apps/web/app/api/mcp.ts
T
rootandClaude Opus 5.5 b3cc5a8313 feat(web): tools and MCP section in Agent settings, tool call IO drawer
Settings > Agent: MCP server card (endpoint, enable switch, allowed API keys,
live sessions, recent calls, copyable client config without secrets) and the
capability list (scope, risk, idempotency/replay, authorization state, 7-day
calls and failure rate, last call, schema sheet). Agent session tool cards get
a drawer with input/output schema and the redacted input/output of the call.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-09-28 20:28:41 +08:00

71 lines
2.4 KiB
TypeScript

import { keepPreviousData, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import {
CapabilityStatsResponse,
CapabilityToolsResponse,
McpServerConfig,
type McpServerConfigUpdate,
McpServerStatus,
} from "@umt/contracts";
import { TTL_MINUTE, TTL_SECOND } from "~/lib/api.ts";
import { apiParsed } from "./parse.ts";
// 能力清单 / 调用统计 / 对外 MCP 服务端(AG-1):GET /capabilities/tools、/capabilities/stats、/mcp/status,PATCH /mcp/config。
const KEY = {
tools: ["capabilities", "tools"] as const,
stats: (days: number) => ["capabilities", "stats", days] as const,
mcp: ["mcp", "status"] as const,
};
/** 能力清单(描述符 + JSON Schema + 授权状态);会话页工具卡片与设置页共用,改动少,缓存久一点 */
export function useCapabilityTools(enabled = true) {
return useQuery({
queryKey: KEY.tools,
queryFn: ({ signal }) => apiParsed(CapabilityToolsResponse, "/capabilities/tools", { signal }),
staleTime: TTL_MINUTE,
enabled,
});
}
export function useCapabilityStats(days = 7) {
return useQuery({
queryKey: KEY.stats(days),
queryFn: ({ signal }) => apiParsed(CapabilityStatsResponse, "/capabilities/stats", { params: { days }, signal }),
staleTime: 30 * TTL_SECOND,
placeholderData: keepPreviousData,
});
}
export function useMcpStatus() {
return useQuery({
queryKey: KEY.mcp,
queryFn: ({ signal }) => apiParsed(McpServerStatus, "/mcp/status", { signal }),
refetchInterval: 15 * TTL_SECOND,
});
}
export function useUpdateMcpConfig() {
const qc = useQueryClient();
return useMutation({
mutationFn: (body: McpServerConfigUpdate) => apiParsed(McpServerConfig, "/mcp/config", { method: "PATCH", body }),
onSuccess: () => qc.invalidateQueries({ queryKey: KEY.mcp }),
});
}
/**
* 给 Claude Code 等 MCP 客户端的接入配置(Streamable HTTP)。密钥用环境变量占位,不含明文:
* 客户端侧把 UMT_API_KEY 设为在「API Key」分区新建的 Key。
*/
export function mcpClientConfig(origin: string, path: string, serverName: string) {
return {
mcpServers: {
[serverName]: {
type: "http",
url: `${origin}${path}`,
// biome-ignore lint/suspicious/noTemplateCurlyInString: 客户端侧的环境变量占位,不是本地模板
headers: { Authorization: "Bearer ${UMT_API_KEY}" },
},
},
};
}