react front end show available tools from mcp
This commit is contained in:
@@ -6,6 +6,7 @@ import {
|
|||||||
getGraphDefaultConfig,
|
getGraphDefaultConfig,
|
||||||
getPipelineDefaultConfig,
|
getPipelineDefaultConfig,
|
||||||
getMcpToolConfig,
|
getMcpToolConfig,
|
||||||
|
listMcpAvailableTools,
|
||||||
listAvailableGraphs,
|
listAvailableGraphs,
|
||||||
listGraphConfigs,
|
listGraphConfigs,
|
||||||
listPipelines,
|
listPipelines,
|
||||||
@@ -403,6 +404,8 @@ export default function App() {
|
|||||||
const [mcpConfigPath, setMcpConfigPath] = useState<string>("");
|
const [mcpConfigPath, setMcpConfigPath] = useState<string>("");
|
||||||
const [mcpEntries, setMcpEntries] = useState<McpEntry[]>([]);
|
const [mcpEntries, setMcpEntries] = useState<McpEntry[]>([]);
|
||||||
const [mcpToolKeys, setMcpToolKeys] = useState<string[]>([]);
|
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 [busy, setBusy] = useState(false);
|
||||||
|
|
||||||
const configKeySet = useMemo(
|
const configKeySet = useMemo(
|
||||||
@@ -654,6 +657,7 @@ export default function App() {
|
|||||||
setStatusMessage((error as Error).message);
|
setStatusMessage((error as Error).message);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
await refreshMcpAvailableTools();
|
||||||
setStatusMessage("MCP config loaded.");
|
setStatusMessage("MCP config loaded.");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setStatusMessage((error as Error).message);
|
setStatusMessage((error as Error).message);
|
||||||
@@ -693,6 +697,7 @@ export default function App() {
|
|||||||
const resp = await updateMcpToolConfig({ raw_content: rawContent });
|
const resp = await updateMcpToolConfig({ raw_content: rawContent });
|
||||||
setMcpConfigPath(resp.path || "");
|
setMcpConfigPath(resp.path || "");
|
||||||
setMcpToolKeys(resp.tool_keys || []);
|
setMcpToolKeys(resp.tool_keys || []);
|
||||||
|
await refreshMcpAvailableTools();
|
||||||
setStatusMessage("MCP config saved.");
|
setStatusMessage("MCP config saved.");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setStatusMessage((error as Error).message);
|
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 {
|
function addMcpEntry(): void {
|
||||||
setMcpEntries((prev) => [...prev, createEmptyMcpEntry()]);
|
setMcpEntries((prev) => [...prev, createEmptyMcpEntry()]);
|
||||||
}
|
}
|
||||||
@@ -1149,6 +1175,23 @@ export default function App() {
|
|||||||
Remove
|
Remove
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</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">
|
<div className="mcp-entry-grid">
|
||||||
<label>
|
<label>
|
||||||
MCP Name
|
MCP Name
|
||||||
@@ -1229,6 +1272,9 @@ export default function App() {
|
|||||||
))
|
))
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
{mcpErrorsByServer._global ? (
|
||||||
|
<p className="mcp-tools-error">Error: {mcpErrorsByServer._global}</p>
|
||||||
|
) : null}
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import type {
|
|||||||
GraphConfigReadResponse,
|
GraphConfigReadResponse,
|
||||||
GraphConfigUpsertRequest,
|
GraphConfigUpsertRequest,
|
||||||
GraphConfigUpsertResponse,
|
GraphConfigUpsertResponse,
|
||||||
|
McpAvailableToolsResponse,
|
||||||
McpToolConfigResponse,
|
McpToolConfigResponse,
|
||||||
McpToolConfigUpdateRequest,
|
McpToolConfigUpdateRequest,
|
||||||
McpToolConfigUpdateResponse,
|
McpToolConfigUpdateResponse,
|
||||||
@@ -114,6 +115,10 @@ export function updateMcpToolConfig(
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function listMcpAvailableTools(): Promise<McpAvailableToolsResponse> {
|
||||||
|
return fetchJson("/v1/tool-configs/mcp/tools");
|
||||||
|
}
|
||||||
|
|
||||||
export function createPipeline(
|
export function createPipeline(
|
||||||
payload: PipelineCreateRequest
|
payload: PipelineCreateRequest
|
||||||
): Promise<PipelineCreateResponse> {
|
): Promise<PipelineCreateResponse> {
|
||||||
|
|||||||
@@ -317,6 +317,19 @@ button:disabled {
|
|||||||
margin-top: 10px;
|
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 {
|
.mcp-entry-card {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
border: 1px solid #d7e6f6;
|
border: 1px solid #d7e6f6;
|
||||||
|
|||||||
@@ -105,3 +105,15 @@ export type McpToolConfigUpdateResponse = {
|
|||||||
tool_keys: string[];
|
tool_keys: string[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type McpAvailableToolsResponse = {
|
||||||
|
available_tools: string[];
|
||||||
|
errors: string[];
|
||||||
|
servers: Record<
|
||||||
|
string,
|
||||||
|
{
|
||||||
|
tools: string[];
|
||||||
|
error?: string | null;
|
||||||
|
}
|
||||||
|
>;
|
||||||
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user