react front end show available tools from mcp

This commit is contained in:
2026-03-05 19:32:46 +08:00
parent eb7e85e4e6
commit 3fc3d7288c
4 changed files with 76 additions and 0 deletions

View File

@@ -6,6 +6,7 @@ import {
getGraphDefaultConfig,
getPipelineDefaultConfig,
getMcpToolConfig,
listMcpAvailableTools,
listAvailableGraphs,
listGraphConfigs,
listPipelines,
@@ -403,6 +404,8 @@ export default function App() {
const [mcpConfigPath, setMcpConfigPath] = useState<string>("");
const [mcpEntries, setMcpEntries] = useState<McpEntry[]>([]);
const [mcpToolKeys, setMcpToolKeys] = useState<string[]>([]);
const [mcpToolsByServer, setMcpToolsByServer] = useState<Record<string, string[]>>({});
const [mcpErrorsByServer, setMcpErrorsByServer] = useState<Record<string, string>>({});
const [busy, setBusy] = useState(false);
const configKeySet = useMemo(
@@ -654,6 +657,7 @@ export default function App() {
setStatusMessage((error as Error).message);
return;
}
await refreshMcpAvailableTools();
setStatusMessage("MCP config loaded.");
} catch (error) {
setStatusMessage((error as Error).message);
@@ -693,6 +697,7 @@ export default function App() {
const resp = await updateMcpToolConfig({ raw_content: rawContent });
setMcpConfigPath(resp.path || "");
setMcpToolKeys(resp.tool_keys || []);
await refreshMcpAvailableTools();
setStatusMessage("MCP config saved.");
} catch (error) {
setStatusMessage((error as Error).message);
@@ -701,6 +706,27 @@ export default function App() {
}
}
async function refreshMcpAvailableTools(): Promise<void> {
try {
const resp = await listMcpAvailableTools();
const nextTools: Record<string, string[]> = {};
const nextErrors: Record<string, string> = {};
const servers = resp.servers || {};
for (const [serverName, info] of Object.entries(servers)) {
nextTools[serverName] = Array.isArray(info?.tools) ? info.tools : [];
if (typeof info?.error === "string" && info.error.trim()) {
nextErrors[serverName] = info.error;
}
}
setMcpToolsByServer(nextTools);
setMcpErrorsByServer(nextErrors);
} catch (error) {
const message = (error as Error).message || "Unknown error";
setMcpToolsByServer({});
setMcpErrorsByServer({ _global: message });
}
}
function addMcpEntry(): void {
setMcpEntries((prev) => [...prev, createEmptyMcpEntry()]);
}
@@ -1149,6 +1175,23 @@ export default function App() {
Remove
</button>
</div>
{entry.name.trim() ? (
<div className="mcp-tools-inline">
<p className="empty">
Available tools:{" "}
{(mcpToolsByServer[entry.name.trim()] || []).length > 0
? mcpToolsByServer[entry.name.trim()].join(", ")
: "(none)"}
</p>
{mcpErrorsByServer[entry.name.trim()] ? (
<p className="mcp-tools-error">
Error: {mcpErrorsByServer[entry.name.trim()]}
</p>
) : null}
</div>
) : (
<p className="empty">Set MCP Name, then Save/Reload to fetch tools.</p>
)}
<div className="mcp-entry-grid">
<label>
MCP Name
@@ -1229,6 +1272,9 @@ export default function App() {
))
)}
</div>
{mcpErrorsByServer._global ? (
<p className="mcp-tools-error">Error: {mcpErrorsByServer._global}</p>
) : null}
</section>
)}
</main>

View File

@@ -4,6 +4,7 @@ import type {
GraphConfigReadResponse,
GraphConfigUpsertRequest,
GraphConfigUpsertResponse,
McpAvailableToolsResponse,
McpToolConfigResponse,
McpToolConfigUpdateRequest,
McpToolConfigUpdateResponse,
@@ -114,6 +115,10 @@ export function updateMcpToolConfig(
});
}
export function listMcpAvailableTools(): Promise<McpAvailableToolsResponse> {
return fetchJson("/v1/tool-configs/mcp/tools");
}
export function createPipeline(
payload: PipelineCreateRequest
): Promise<PipelineCreateResponse> {

View File

@@ -317,6 +317,19 @@ button:disabled {
margin-top: 10px;
}
.mcp-tools-error {
color: #a33434;
margin: 6px 0 0 0;
}
.mcp-tools-inline {
background: #f8fbff;
border: 1px solid #d7e6f6;
border-radius: 8px;
margin: 0 0 10px 0;
padding: 8px;
}
.mcp-entry-card {
background: #fff;
border: 1px solid #d7e6f6;

View File

@@ -105,3 +105,15 @@ export type McpToolConfigUpdateResponse = {
tool_keys: string[];
};
export type McpAvailableToolsResponse = {
available_tools: string[];
errors: string[];
servers: Record<
string,
{
tools: string[];
error?: string | null;
}
>;
};