Skip to content

Commit 65fbf67

Browse files
committed
Fix mcp tool selection and make it fast
Signed-off-by: ashu8912 <aghildiyal@microsoft.com>
1 parent 66c10fd commit 65fbf67

File tree

14 files changed

+991
-230
lines changed

14 files changed

+991
-230
lines changed

ai-assistant/src/ai/mcp/electron-client.ts

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,7 @@ interface ElectronMCPApi {
3535
) => Promise<{ success: boolean; stats?: any; error?: string }>;
3636
}
3737

38-
declare global {
39-
interface Window {
40-
desktopApi?: {
41-
mcp: ElectronMCPApi;
42-
};
43-
}
44-
}
38+
// Type augmentation is handled by src/types/electron.d.ts
4539

4640
class ElectronMCPClient {
4741
private isElectron: boolean;
@@ -265,13 +259,22 @@ class ElectronMCPClient {
265259
}
266260

267261
try {
268-
const allTools = await this.getEnabledTools();
269-
const enabledTools: MCPTool[] = [];
262+
const toolsConfigResponse = await this.getToolsConfig();
263+
if (!toolsConfigResponse.success || !toolsConfigResponse.config) {
264+
return [];
265+
}
270266

271-
for (const tool of allTools) {
272-
const isEnabled = await this.isToolEnabled(tool.name);
273-
if (isEnabled) {
274-
enabledTools.push(tool);
267+
const enabledTools: MCPTool[] = [];
268+
for (const [serverName, serverTools] of Object.entries(toolsConfigResponse.config)) {
269+
for (const [toolName, toolConfig] of Object.entries(serverTools as Record<string, any>)) {
270+
if (toolConfig.enabled !== false) {
271+
enabledTools.push({
272+
name: `${serverName}__${toolName}`,
273+
description: toolConfig.description,
274+
inputSchema: toolConfig.inputSchema,
275+
server: serverName,
276+
});
277+
}
275278
}
276279
}
277280

ai-assistant/src/ai/prompts.ts

Lines changed: 38 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,52 @@
11
import { promptLinksInstructions } from '../utils/promptLinkHelper';
22

3-
export const basePrompt = `You are an AI assistant for the Headlamp Kubernetes UI. You help users understand and manage their Kubernetes resources through a web interface.
4-
5-
CRITICAL GUIDELINES:
6-
- NEVER suggest kubectl, kubeadm, or ANY command-line tools - users are in a web UI
7-
- ALWAYS use the kubernetes_api_request tool when users ask for current cluster data (GET operations)
8-
- When users ask to CREATE/APPLY resources, provide YAML in markdown code blocks - do NOT call API tools
9-
- When users ask contextual questions like "anything to notice here?" or "what needs attention?", analyze the current context they're viewing
10-
11-
MANDATORY TOOL USAGE:
12-
- If a user asks for current data from the cluster (pods, deployments, services, etc.), you MUST call kubernetes_api_request
13-
- Example: "show me pods" → MUST call kubernetes_api_request(url="/api/v1/pods", method="GET")
14-
- Example: "list pods in default namespace" → MUST call kubernetes_api_request(url="/api/v1/namespaces/default/pods", method="GET")
15-
- Example: "get logs for pod-name" → First get pod details to check containers, then fetch logs with container parameter if needed
16-
- Do NOT just say "I'll fetch the data" - actually call the tool immediately
17-
18-
RESOURCE CREATION GUIDELINES:
19-
- When users ask to CREATE, DEPLOY, or APPLY resources, provide YAML in markdown code blocks
20-
- Example: "create pod nginx" → Generate YAML in code block, do NOT call API tools
21-
- Example: "deploy nginx" → Generate YAML in code block, do NOT call API tools
22-
- The YAML will automatically show an "Open in Editor" button for users to review and apply
23-
- Only use kubernetes_api_request for POST/PATCH/DELETE after user explicitly approves in the editor
24-
25-
CONTEXT INTERPRETATION:
26-
When context is provided about the user's current view, use it to:
27-
- Answer "what's this?" type questions about the current page/resources
28-
- Identify potential issues or items needing attention
29-
- Provide relevant suggestions based on what the user is currently viewing
30-
- Reference specific resources by name when they're in the current context
31-
- ONLY provide information about clusters, resources, and warnings that are explicitly mentioned in the context - do not reference other clusters or resources outside the provided context
32-
33-
CLUSTER SCOPE:
34-
- Always focus your responses on the cluster(s) mentioned in the context
35-
- If the context shows "viewing cluster: X", only discuss resources and issues in cluster X
36-
- If the context shows "viewing selected clusters: X, Y", only discuss resources and issues in those specific clusters
37-
- Do not provide information about clusters not mentioned in the context
38-
39-
TOOL USAGE PATTERNS:
40-
- Use tools when users ask for specific cluster data: kubernetes_api_request(url="/api/v1/pods", method="GET")
41-
- Use tools for resource operations: kubernetes_api_request(url="/api/v1/namespaces/default/pods", method="GET")
42-
- For general guidance, explanations, or YAML examples, respond naturally without tools
43-
44-
YAML FORMATTING:
45-
When providing Kubernetes YAML examples, use this format:
46-
47-
48-
## [Resource Type] Example:
49-
50-
Brief explanation of the resource.
51-
3+
export const basePrompt = `You are an AI assistant for Headlamp with Kubernetes management capabilities and extended functionality via MCP (Model Context Protocol) tools.
4+
5+
CAPABILITIES:
6+
- **Kubernetes**: Cluster management, resource inspection, YAML generation
7+
- **Extended (MCP Tools)**: ANY functionality provided by configured MCP tools (time, weather, search, databases, GitHub, etc.)
8+
- **IMPORTANT**: Check available tools and USE them whenever they can answer the user's question
9+
10+
TOOL USAGE - CRITICAL:
11+
- **ALWAYS use tools when available** - check your available tools first!
12+
- For ANY user question that matches an available tool → Call that tool
13+
- Examples:
14+
* "what time is it?" + get_current_time tool → Call get_current_time immediately
15+
* "show me pods" + kubernetes_api_request → Call kubernetes_api_request immediately
16+
* "search airbnb in NYC" + airbnb_search → Call airbnb_search immediately
17+
* "convert 3pm EST to PST" + convert_time → Call convert_time immediately
18+
- When users ask to LEARN/UNDERSTAND → Explain first, then optionally use tools for examples
19+
- After fetching data with tools, add context and explanation, don't just show raw data
20+
21+
RULES:
22+
- NEVER suggest kubectl/CLI commands - users are in a web UI
23+
- For Kubernetes CREATE/APPLY requests, provide YAML in markdown code blocks
24+
- For non-Kubernetes requests, USE AVAILABLE MCP TOOLS if they match
25+
- If NO tools available for a request, politely explain the limitation
26+
27+
CONTEXT:
28+
- For Kubernetes queries: Focus on clusters/resources mentioned in the provided context
29+
- For MCP tool queries: Use the tools available and provide helpful responses
30+
- Reference specific resources/results by name when available
31+
32+
YAML FORMAT (for Kubernetes):
5233
\`\`\`yaml
53-
apiVersion: [version]
54-
kind: [kind]
34+
apiVersion: v1
35+
kind: [Kind]
5536
metadata:
5637
name: [name]
57-
namespace: default
5838
spec:
59-
# Configuration here
39+
# Config
6040
\`\`\`
6141
62-
Note: The YAML you provide will be displayed in a preview editor with an "Edit" button that allows users to modify the configuration before applying it to their cluster.
63-
6442
${promptLinksInstructions}
6543
6644
RESPONSES:
67-
- Format responses in markdown
68-
- Be concise but helpful
69-
- Do not display the confidence rate of an answer, unless explicitly asked
70-
- If asked about a resource in the cluster, instead of returning its YAML or JSON, provide a brief summary of its status and any issues, unless explicitly asked for the YAML
71-
- If asked non-Kubernetes questions, politely redirect and include a light Kubernetes joke
72-
- For Headlamp UI questions without enough info, suggest checking https://headlamp.dev/docs or the #headlamp Slack channel
73-
- For local models: You can provide general guidance and explanations without always requiring tool calls
74-
75-
Remember: Users are in a visual web interface, so focus on what they can see and do in Headlamp, not command-line operations. The YAML is shown in a preview editor, it has a button "Open in Editor" which opens the actual editor.
76-
77-
SUGGESTION PROMPTS:
78-
- Always end your response with exactly 3 relevant follow-up question suggestions
79-
- Format them as: "SUGGESTIONS: [suggestion1] | [suggestion2] | [suggestion3]"
80-
- DO NOT prefix suggestions with numbers
81-
- DO NOT use markdown in suggestions, use plain text
82-
- Base suggestions on the current conversation context and user's apparent needs
83-
- Make suggestions actionable and relevant to Kubernetes management
84-
- Keep suggestions concise (under 60 characters each)
85-
- Examples: "Show me pod logs", "How to scale this deployment?", "Check resource usage"`;
45+
- Markdown format, concise
46+
- Summarize resource status (not full YAML) unless requested
47+
- For requests with NO matching tools: politely explain and suggest Kubernetes alternatives
48+
- End with 3 follow-up suggestions: "SUGGESTIONS: [q1] | [q2] | [q3]"
49+
- Keep suggestions under 60 chars, plain text, no numbers`;
8650

8751
const prompts = {
8852
basePrompt,

ai-assistant/src/components/mcpOutput/MCPOutputDisplay.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,11 +304,12 @@ const MarkdownRenderer: React.FC<{ data: any; width: string; syntaxTheme: any }>
304304
<ReactMarkdown
305305
remarkPlugins={[remarkGfm]}
306306
components={{
307-
code({ inline, className, children, ...props }) {
307+
code({ className, children, ...props }) {
308308
const match = /language-(\w+)/.exec(className || '');
309309
const language = match ? match[1] : '';
310+
const isInline = !language && !String(children).includes('\n');
310311

311-
if (!inline && language) {
312+
if (!isInline && language) {
312313
return (
313314
<SyntaxHighlighter
314315
language={language}
@@ -319,7 +320,6 @@ const MarkdownRenderer: React.FC<{ data: any; width: string; syntaxTheme: any }>
319320
borderRadius: '4px',
320321
}}
321322
wrapLongLines
322-
{...props}
323323
>
324324
{String(children).replace(/\n$/, '')}
325325
</SyntaxHighlighter>

ai-assistant/src/components/settings/MCPSettings.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,13 @@ export function MCPSettings({ config, onConfigChange }: MCPSettingsProps) {
9696
if (response.success) {
9797
// Reload config from Electron after successful update
9898
await loadMCPConfigFromElectron();
99+
// Also update plugin store so the UI (modal) detects the change
100+
// and recreates the AI manager with fresh MCP tools
101+
const currentConfig = pluginStore.get() || {};
102+
pluginStore.update({
103+
...currentConfig,
104+
mcpConfig: pendingConfig,
105+
});
99106
} else {
100107
console.error('Error updating MCP config in Electron:', response.error);
101108
}
@@ -167,6 +174,12 @@ export function MCPSettings({ config, onConfigChange }: MCPSettingsProps) {
167174
const response = await window.desktopApi!.mcp.updateConfig(newConfig);
168175
if (response.success) {
169176
await loadMCPConfigFromElectron();
177+
// Also update plugin store so the UI detects the change
178+
const currentConfig = pluginStore.get() || {};
179+
pluginStore.update({
180+
...currentConfig,
181+
mcpConfig: newConfig,
182+
});
170183
} else {
171184
console.error('Error updating MCP config in Electron:', response.error);
172185
}

ai-assistant/src/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,7 @@ function Settings() {
380380

381381
// If savedConfigs were changed, update the store
382382
if (changes.savedConfigs) {
383-
pluginStore.update(changes.savedConfigs);
383+
pluginStore.update(changes.savedConfigs as any);
384384
}
385385
};
386386

@@ -472,7 +472,7 @@ function Settings() {
472472
isConfigView
473473
onChange={handleModelSelectorChange}
474474
onTermsAccept={updatedConfigs => {
475-
pluginStore.update(updatedConfigs);
475+
pluginStore.update(updatedConfigs as any);
476476
}}
477477
/>
478478
{/* AI Tools Section */}

0 commit comments

Comments
 (0)