chore: add stack trace to mcp error message (#17269)

This commit is contained in:
YutaSaito 2025-12-05 12:19:00 +09:00 • committed by GitHub
parent 4f3b843efe
commit 7106509ef0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 50 additions and 5 deletions

View file

@ -1,4 +1,5 @@
import importlib
import traceback
from typing import Dict, List, Optional, Union
from fastapi import APIRouter, Depends, Query, Request
@ -326,7 +327,12 @@ if MCP_AVAILABLE:
except Exception as e:
verbose_logger.error(f"Error in MCP operation: {e}", exc_info=True)
return {"status": "error", "message": "An internal error has occurred."}
stack_trace = traceback.format_exc()
return {
"status": "error",
"message": f"An internal error has occurred: {str(e)}",
"stack_trace": stack_trace,
}
@router.post("/test/connection")
async def test_connection(

View file

@ -1,5 +1,5 @@
import React, { useEffect } from "react";
import { Button, Spin, Alert } from "antd";
import { Button, Spin, Alert, Collapse } from "antd";
import { CheckCircleOutlined, ExclamationCircleOutlined, ReloadOutlined, ToolOutlined } from "@ant-design/icons";
import { Card, Title, Text } from "@tremor/react";
import { useTestMCPConnection } from "../../hooks/useTestMCPConnection";
@ -12,7 +12,7 @@ interface MCPConnectionStatusProps {
}
const MCPConnectionStatus: React.FC<MCPConnectionStatusProps> = ({ accessToken, oauthAccessToken, formValues, onToolsLoaded }) => {
const { tools, isLoadingTools, toolsError, canFetchTools, fetchTools } = useTestMCPConnection({
const { tools, isLoadingTools, toolsError, toolsErrorStackTrace, canFetchTools, fetchTools } = useTestMCPConnection({
accessToken,
oauthAccessToken,
formValues,
@ -95,7 +95,38 @@ const MCPConnectionStatus: React.FC<MCPConnectionStatusProps> = ({ accessToken,
{toolsError && (
<Alert
message="Connection Failed"
description={toolsError}
description={
<div>
<div>{toolsError}</div>
{toolsErrorStackTrace && (
<Collapse
items={[
{
key: "stack-trace",
label: "Stack Trace",
children: (
<pre style={{
whiteSpace: "pre-wrap",
wordBreak: "break-word",
fontSize: "12px",
fontFamily: "monospace",
margin: 0,
padding: "8px",
backgroundColor: "#f5f5f5",
borderRadius: "4px",
maxHeight: "400px",
overflow: "auto"
}}>
{toolsErrorStackTrace}
</pre>
),
},
]}
style={{ marginTop: "12px" }}
/>
)}
</div>
}
type="error"
showIcon
action={

View file

@ -5964,7 +5964,7 @@ export const listMCPTools = async (accessToken: string, serverId: string) => {
throw new Error("Failed to fetch MCP tools");
}
// Return the full response object which includes tools, error, and message
// Return the full response object which includes tools, error, message, and stack_trace
return data;
} catch (error) {
console.error("Failed to fetch MCP tools:", error);
@ -5973,6 +5973,7 @@ export const listMCPTools = async (accessToken: string, serverId: string) => {
tools: [],
error: "network_error",
message: error instanceof Error ? error.message : "Failed to fetch MCP tools",
stack_trace: null,
};
}
};

View file

@ -29,6 +29,7 @@ interface UseTestMCPConnectionReturn {
tools: any[];
isLoadingTools: boolean;
toolsError: string | null;
toolsErrorStackTrace: string | null;
hasShownSuccessMessage: boolean;
canFetchTools: boolean;
fetchTools: () => Promise<void>;
@ -44,6 +45,7 @@ export const useTestMCPConnection = ({
const [tools, setTools] = useState<any[]>([]);
const [isLoadingTools, setIsLoadingTools] = useState(false);
const [toolsError, setToolsError] = useState<string | null>(null);
const [toolsErrorStackTrace, setToolsErrorStackTrace] = useState<string | null>(null);
const [hasShownSuccessMessage, setHasShownSuccessMessage] = useState(false);
// Check if we have the minimum required fields to fetch tools
@ -137,18 +139,21 @@ export const useTestMCPConnection = ({
if (toolsResponse.tools && !toolsResponse.error) {
setTools(toolsResponse.tools);
setToolsError(null);
setToolsErrorStackTrace(null);
if (toolsResponse.tools.length > 0 && !hasShownSuccessMessage) {
setHasShownSuccessMessage(true);
}
} else {
const errorMessage = toolsResponse.message || "Failed to retrieve tools list";
setToolsError(errorMessage);
setToolsErrorStackTrace(toolsResponse.stack_trace || null);
setTools([]);
setHasShownSuccessMessage(false);
}
} catch (error) {
console.error("Tools fetch error:", error);
setToolsError(error instanceof Error ? error.message : String(error));
setToolsErrorStackTrace(null);
setTools([]);
setHasShownSuccessMessage(false);
} finally {
@ -159,6 +164,7 @@ export const useTestMCPConnection = ({
const clearTools = () => {
setTools([]);
setToolsError(null);
setToolsErrorStackTrace(null);
setHasShownSuccessMessage(false);
};
@ -190,6 +196,7 @@ export const useTestMCPConnection = ({
tools,
isLoadingTools,
toolsError,
toolsErrorStackTrace,
hasShownSuccessMessage,
canFetchTools,
fetchTools,