import { Alert, AlertDescription } from "@/components/ui/alert";
import { Button } from "@/components/ui/button";
import { CodeEditor } from "@/components/ui/codeEditor";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { getExampleBaseUrl } from "@/lib/utils/port";
import { useCopyToClipboard } from "@/hooks/useCopyToClipboard";
import { AlertTriangle, Copy } from "lucide-react";
import { useMemo, useState } from "react";
type Language = "python" | "typescript";
type Examples = {
manual: {
[L in Language]: string;
};
agentMode: {
[L in Language]: string;
};
};
// Common editor options to reduce duplication
const EditorOptions = {
scrollBeyondLastLine: false,
minimap: { enabled: false },
lineNumbers: "off",
folding: false,
lineDecorationsWidth: 0,
lineNumbersMinChars: 0,
glyphMargin: false,
} as const;
interface CodeBlockProps {
code: string;
language: string;
onLanguageChange?: (language: string) => void;
showLanguageSelect?: boolean;
readonly?: boolean;
}
function CodeBlock({ code, language, onLanguageChange, showLanguageSelect = false, readonly = true }: CodeBlockProps) {
const { copy: copyToClipboard } = useCopyToClipboard();
return (
{showLanguageSelect && onLanguageChange && (
)}
);
}
interface MCPEmptyStateProps {
error?: string | null;
statusIndicator?: React.ReactNode;
}
export function MCPEmptyState({ error, statusIndicator }: MCPEmptyStateProps) {
const [language, setLanguage] = useState("python");
// Generate examples dynamically using the port utility
const examples: Examples = useMemo(() => {
const baseUrl = getExampleBaseUrl();
return {
manual: {
python: `import openai
import requests
# Step 1: Initialize OpenAI client with Bifrost
client = openai.OpenAI(
base_url="${baseUrl}/openai",
api_key="dummy-api-key" # Handled by Bifrost
)
# Step 2: Send chat request
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "List files in current directory"}]
)
# Step 3: Check for tool calls
message = response.choices[0].message
if message.tool_calls:
for tool_call in message.tool_calls:
# Step 4: Execute tool via Bifrost
tool_result = requests.post(
"${baseUrl}/v1/mcp/tool/execute",
json={
"id": tool_call.id,
"type": "function",
"function": {
"name": tool_call.function.name,
"arguments": tool_call.function.arguments
}
}
).json()
# Step 5: Continue conversation with results
final_response = client.chat.completions.create(
model="gpt-4o",
messages=[
{"role": "user", "content": "List files in current directory"},
message,
tool_result
]
)
print(final_response.choices[0].message.content)`,
typescript: `import OpenAI from "openai";
// Step 1: Initialize OpenAI client with Bifrost
const openai = new OpenAI({
baseURL: "${baseUrl}/openai",
apiKey: "dummy-api-key", // Handled by Bifrost
});
// Step 2: Send chat request
const response = await openai.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: "List files in current directory" }],
});
const message = response.choices[0].message;
// Step 3: Check for tool calls
if (message.tool_calls) {
for (const toolCall of message.tool_calls) {
// Step 4: Execute tool via Bifrost
const toolResult = await fetch("${baseUrl}/v1/mcp/tool/execute", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
id: toolCall.id,
type: "function",
function: {
name: toolCall.function.name,
arguments: toolCall.function.arguments,
},
}),
}).then(res => res.json());
// Step 5: Continue conversation with results
const finalResponse = await openai.chat.completions.create({
model: "gpt-4o",
messages: [
{ role: "user", content: "List files in current directory" },
message,
toolResult,
],
});
console.log(finalResponse.choices[0].message.content);
}
}`,
},
agentMode: {
python: `import openai
# Agent Mode enables autonomous tool execution
# Configure auto-executable tools in MCP Gateway settings
client = openai.OpenAI(
base_url="${baseUrl}/openai",
api_key="dummy-api-key"
)
# With agent mode enabled, Bifrost automatically:
# 1. Receives tool calls from LLM
# 2. Executes auto-approved tools (e.g., read_file, list_directory)
# 3. Feeds results back to LLM
# 4. Returns final response after all iterations
response = client.chat.completions.create(
model="gpt-4o",
messages=[{
"role": "user",
"content": "List all Python files and summarize their purpose"
}]
)
# The response includes results from all auto-executed tools
# Non-auto-executable tools (e.g., write_file) are returned for manual approval
print(response.choices[0].message.content)
# If there are pending non-auto-executable tools:
if response.choices[0].message.tool_calls:
print("Pending tools requiring approval:",
[tc.function.name for tc in response.choices[0].message.tool_calls])`,
typescript: `import OpenAI from "openai";
// Agent Mode enables autonomous tool execution
// Configure auto-executable tools in MCP Gateway settings
const openai = new OpenAI({
baseURL: "${baseUrl}/openai",
apiKey: "dummy-api-key",
});
// With agent mode enabled, Bifrost automatically:
// 1. Receives tool calls from LLM
// 2. Executes auto-approved tools (e.g., read_file, list_directory)
// 3. Feeds results back to LLM
// 4. Returns final response after all iterations
const response = await openai.chat.completions.create({
model: "gpt-4o",
messages: [{
role: "user",
content: "List all Python files and summarize their purpose"
}],
});
// The response includes results from all auto-executed tools
// Non-auto-executable tools (e.g., write_file) are returned for manual approval
console.log(response.choices[0].message.content);
// If there are pending non-auto-executable tools:
if (response.choices[0].message.tool_calls) {
console.log("Pending tools requiring approval:",
response.choices[0].message.tool_calls.map(tc => tc.function.name)
);
}`,
},
};
}, []);
const isUnexpectedError = error && error.includes("An unexpected error occurred");
return (
{error && (
{isUnexpectedError ? "Looks like you haven't configured the log store in your config file." : error}
)}
Get Started with MCP Tool Execution
Execute your first MCP tool call to see logs appear
{statusIndicator}
Manual Tool Execution
Agent Mode (Auto-Execute)
Full control over tool approval. You explicitly execute each tool call via the API.
setLanguage(newLang as Language)}
showLanguageSelect
/>
Autonomous execution for pre-approved tools. Configure auto-executable tools in MCP Gateway settings.
setLanguage(newLang as Language)}
showLanguageSelect
/>
Prerequisites
-
1.
Configure MCP servers in the MCP Gateway (e.g., filesystem, web_search)
-
2.
Set
tools_to_execute to whitelist available tools
-
3.
For Agent Mode: Configure
tools_to_auto_execute for autonomous execution
);
}