improve: add abort btn to abort the mcp add request. (#284)

This commit is contained in:
Abeautifulsnow
2025-06-26 08:51:46 +08:00
committed by GitHub
parent aa06cd6fb6
commit 9c2d4724e3
2 changed files with 25 additions and 4 deletions

View File

@@ -2,7 +2,7 @@
// SPDX-License-Identifier: MIT
import { Loader2 } from "lucide-react";
import { useCallback, useState } from "react";
import { useCallback, useRef, useState } from "react";
import { Button } from "~/components/ui/button";
import {
@@ -34,6 +34,8 @@ export function AddMCPServerDialog({
const [validationError, setValidationError] = useState<string | null>("");
const [error, setError] = useState<string | null>(null);
const [processing, setProcessing] = useState(false);
const abortControllerRef = useRef<AbortController | null>(null);
const handleChange = useCallback((value: string) => {
setInput(value);
if (!value.trim()) {
@@ -74,7 +76,9 @@ export function AddMCPServerDialog({
return;
}
}, []);
const handleAdd = useCallback(async () => {
abortControllerRef.current = new AbortController();
const config = MCPConfigSchema.parse(JSON.parse(input));
setInput(JSON.stringify(config, null, 2));
const addingServers: SimpleMCPServerMetadata[] = [];
@@ -105,7 +109,7 @@ export function AddMCPServerDialog({
setError(null);
for (const server of addingServers) {
processingServer = server.name;
const metadata = await queryMCPServerMetadata(server);
const metadata = await queryMCPServerMetadata(server, abortControllerRef.current.signal);
results.push({ ...metadata, name: server.name, enabled: true });
}
if (results.length > 0) {
@@ -115,12 +119,23 @@ export function AddMCPServerDialog({
setOpen(false);
} catch (e) {
console.error(e);
setError(`Failed to add server: ${processingServer}`);
if (e instanceof Error && e.name === 'AbortError') {
setError(`Request was cancelled`);
} else {
setError(`Failed to add server: ${processingServer}`);
}
} finally {
setProcessing(false);
abortControllerRef.current = null;
}
}, [input, onAdd]);
const handleAbort = () => {
if (abortControllerRef.current) {
abortControllerRef.current.abort();
}
};
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
@@ -165,6 +180,11 @@ export function AddMCPServerDialog({
{processing && <Loader2 className="animate-spin" />}
Add
</Button>
{
processing && (
<Button variant="destructive" onClick={handleAbort}>Abort</Button>
)
}
</div>
</div>
</DialogFooter>

View File

@@ -5,13 +5,14 @@ import type { SimpleMCPServerMetadata } from "../mcp";
import { resolveServiceURL } from "./resolve-service-url";
export async function queryMCPServerMetadata(config: SimpleMCPServerMetadata) {
export async function queryMCPServerMetadata(config: SimpleMCPServerMetadata, signal?: AbortSignal) {
const response = await fetch(resolveServiceURL("mcp/server/metadata"), {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(config),
signal,
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);