refactor(frontend): Migrate MCP API calls to generated queries/types

Replace manual BackendAPI.mcpDiscoverTools, mcpOAuthLogin, and
mcpOAuthCallback methods with Orval-generated functions from
__generated__/endpoints/mcp/mcp.ts. Remove manual MCPTool and
MCPDiscoverToolsResponse types from types.ts in favor of generated
MCPToolResponse and DiscoverToolsResponse models.
This commit is contained in:
Zamil Majdy
2026-02-12 18:24:49 +04:00
parent a4d194cb07
commit 5ca2e4cd47
5 changed files with 56 additions and 71 deletions

View File

@@ -21,8 +21,13 @@ import { Label } from "@/components/__legacy__/ui/label";
import { LoadingSpinner } from "@/components/__legacy__/ui/loading";
import { Badge } from "@/components/__legacy__/ui/badge";
import { ScrollArea } from "@/components/__legacy__/ui/scroll-area";
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
import type { CredentialsMetaInput, MCPTool } from "@/lib/autogpt-server-api";
import type { CredentialsMetaInput } from "@/lib/autogpt-server-api";
import type { MCPToolResponse } from "@/app/api/__generated__/models/mCPToolResponse";
import {
postV2DiscoverAvailableToolsOnAnMcpServer,
postV2InitiateOauthLoginForAnMcpServer,
postV2ExchangeOauthCodeForMcpTokens,
} from "@/app/api/__generated__/endpoints/mcp/mcp";
import { CaretDown } from "@phosphor-icons/react";
import { openOAuthPopup } from "@/lib/oauth-popup";
import { CredentialsProvidersContext } from "@/providers/agent-credentials/credentials-provider";
@@ -50,12 +55,11 @@ export function MCPToolDialog({
onClose,
onConfirm,
}: MCPToolDialogProps) {
const api = useBackendAPI();
const allProviders = useContext(CredentialsProvidersContext);
const [step, setStep] = useState<DialogStep>("url");
const [serverUrl, setServerUrl] = useState("");
const [tools, setTools] = useState<MCPTool[]>([]);
const [tools, setTools] = useState<MCPToolResponse[]>([]);
const [serverName, setServerName] = useState<string | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
@@ -63,7 +67,7 @@ export function MCPToolDialog({
const [oauthLoading, setOauthLoading] = useState(false);
const [showManualToken, setShowManualToken] = useState(false);
const [manualToken, setManualToken] = useState("");
const [selectedTool, setSelectedTool] = useState<MCPTool | null>(null);
const [selectedTool, setSelectedTool] = useState<MCPToolResponse | null>(null);
const [credentials, setCredentials] = useState<CredentialsMetaInput | null>(
null,
);
@@ -105,9 +109,13 @@ export function MCPToolDialog({
setLoading(true);
setError(null);
try {
const result = await api.mcpDiscoverTools(url, authToken);
setTools(result.tools);
setServerName(result.server_name);
const response =
await postV2DiscoverAvailableToolsOnAnMcpServer({
server_url: url,
auth_token: authToken || null,
});
setTools(response.data.tools);
setServerName(response.data.server_name ?? null);
setAuthRequired(false);
setShowManualToken(false);
setStep("tool");
@@ -130,7 +138,7 @@ export function MCPToolDialog({
setLoading(false);
}
},
[api],
[],
);
const handleDiscoverTools = useCallback(() => {
@@ -148,9 +156,10 @@ export function MCPToolDialog({
setOauthLoading(true);
try {
const { login_url, state_token } = await api.mcpOAuthLogin(
serverUrl.trim(),
);
const loginResponse = await postV2InitiateOauthLoginForAnMcpServer({
server_url: serverUrl.trim(),
});
const { login_url, state_token } = loginResponse.data;
const { promise, cleanup } = openOAuthPopup(login_url, {
stateToken: state_token,
@@ -165,9 +174,19 @@ export function MCPToolDialog({
setOauthLoading(false);
const mcpProvider = allProviders?.["mcp"];
const callbackResult = mcpProvider
? await mcpProvider.mcpOAuthCallback(result.code, state_token)
: await api.mcpOAuthCallback(result.code, state_token);
let callbackResult;
if (mcpProvider) {
callbackResult = await mcpProvider.mcpOAuthCallback(
result.code,
state_token,
);
} else {
const cbResponse = await postV2ExchangeOauthCodeForMcpTokens({
code: result.code,
state_token,
});
callbackResult = cbResponse.data;
}
setCredentials({
id: callbackResult.id,
@@ -178,9 +197,12 @@ export function MCPToolDialog({
setAuthRequired(false);
// Discover tools now that we're authenticated
const toolsResult = await api.mcpDiscoverTools(serverUrl.trim());
setTools(toolsResult.tools);
setServerName(toolsResult.server_name);
const toolsResponse =
await postV2DiscoverAvailableToolsOnAnMcpServer({
server_url: serverUrl.trim(),
});
setTools(toolsResponse.data.tools);
setServerName(toolsResponse.data.server_name ?? null);
setStep("tool");
} catch (e: any) {
// If server doesn't support OAuth → show manual token entry
@@ -210,7 +232,7 @@ export function MCPToolDialog({
setLoading(false);
oauthAbortRef.current = null;
}
}, [api, serverUrl, allProviders]);
}, [serverUrl, allProviders]);
// Auto-start OAuth sign-in when server returns 401/403
useEffect(() => {
@@ -398,7 +420,7 @@ function MCPToolCard({
selected,
onSelect,
}: {
tool: MCPTool;
tool: MCPToolResponse;
selected: boolean;
onSelect: () => void;
}) {

View File

@@ -5,6 +5,7 @@ import {
BlockIOCredentialsSubSchema,
CredentialsMetaInput,
} from "@/lib/autogpt-server-api/types";
import { postV2InitiateOauthLoginForAnMcpServer } from "@/app/api/__generated__/endpoints/mcp/mcp";
import { openOAuthPopup } from "@/lib/oauth-popup";
import { useQueryClient } from "@tanstack/react-query";
import { useEffect, useRef, useState } from "react";
@@ -183,9 +184,11 @@ export function useCredentialsInput({
let state_token: string;
if (isMCP) {
({ login_url, state_token } = await api.mcpOAuthLogin(
discriminatorValue!,
));
const mcpLoginResponse =
await postV2InitiateOauthLoginForAnMcpServer({
server_url: discriminatorValue!,
});
({ login_url, state_token } = mcpLoginResponse.data);
} else {
({ login_url, state_token } = await api.oAuthLogin(
provider,

View File

@@ -33,7 +33,6 @@ import type {
GraphMeta,
GraphUpdateable,
HostScopedCredentials,
MCPDiscoverToolsResponse,
LibraryAgent,
LibraryAgentID,
LibraryAgentPreset,
@@ -793,38 +792,6 @@ export default class BackendAPI {
return this._request("POST", "/otto/ask", query);
}
////////////////////////////////////////
///////////// MCP FUNCTIONS ////////////
////////////////////////////////////////
async mcpDiscoverTools(
serverUrl: string,
authToken?: string,
): Promise<MCPDiscoverToolsResponse> {
return this._request("POST", "/mcp/discover-tools", {
server_url: serverUrl,
auth_token: authToken || null,
});
}
async mcpOAuthLogin(
serverUrl: string,
): Promise<{ login_url: string; state_token: string }> {
return this._request("POST", "/mcp/oauth/login", {
server_url: serverUrl,
});
}
async mcpOAuthCallback(
code: string,
stateToken: string,
): Promise<CredentialsMetaResponse> {
return this._request("POST", "/mcp/oauth/callback", {
code,
state_token: stateToken,
});
}
////////////////////////////////////////
////////// INTERNAL FUNCTIONS //////////
////////////////////////////////////////

View File

@@ -759,18 +759,6 @@ export enum SpecialBlockID {
OUTPUT = "363ae599-353e-4804-937e-b2ee3cef3da4",
}
export type MCPTool = {
name: string;
description: string;
input_schema: Record<string, any>;
};
export type MCPDiscoverToolsResponse = {
tools: MCPTool[];
server_name: string | null;
protocol_version: string | null;
};
export type AnalyticsMetrics = {
metric_name: string;
metric_value: number;

View File

@@ -8,6 +8,7 @@ import {
HostScopedCredentials,
UserPasswordCredentials,
} from "@/lib/autogpt-server-api";
import { postV2ExchangeOauthCodeForMcpTokens } from "@/app/api/__generated__/endpoints/mcp/mcp";
import { useBackendAPI } from "@/lib/autogpt-server-api/context";
import { useSupabase } from "@/lib/supabase/hooks/useSupabase";
import { toDisplayName } from "@/providers/agent-credentials/helper";
@@ -125,14 +126,18 @@ export default function CredentialsProvider({
[api, addCredentials, onFailToast],
);
/** Wraps `BackendAPI.mcpOAuthCallback`, and adds the result to the internal credentials store. */
/** Exchanges an MCP OAuth code for tokens and adds the result to the internal credentials store. */
const mcpOAuthCallback = useCallback(
async (
code: string,
state_token: string,
): Promise<CredentialsMetaResponse> => {
try {
const credsMeta = await api.mcpOAuthCallback(code, state_token);
const response = await postV2ExchangeOauthCodeForMcpTokens({
code,
state_token,
});
const credsMeta = response.data;
addCredentials("mcp", credsMeta);
return credsMeta;
} catch (error) {
@@ -140,7 +145,7 @@ export default function CredentialsProvider({
throw error;
}
},
[api, addCredentials, onFailToast],
[addCredentials, onFailToast],
);
/** Wraps `BackendAPI.createAPIKeyCredentials`, and adds the result to the internal credentials store. */