import React, { createContext, useContext, useEffect, useState } from 'react';
import mcpService from '../../services/mcpService';
import { getUserAccessibleNodes } from '../../services/api/nodeService';
const WebMcpContext = createContext(null);
export const WebMcpProvider = ({ children }) => {
const [isMcpActive, setIsMcpActive] = useState(false);
useEffect(() => {
// Register global tools immediately.
// mcpService queues them internally if navigator.modelContext isn't ready yet,
// and flushes the queue automatically once the extension injects it.
mcpService.registerTool({
name: 'list_nodes',
description: 'List all agent nodes in the Cortex swarm mesh and their connectivity status.',
inputSchema: { type: 'object', properties: {} },
execute: async () => {
try {
const nodes = await getUserAccessibleNodes();
return {
content: [{
type: 'text',
text: JSON.stringify({
nodes: nodes.map(n => ({
id: n.node_id,
name: n.display_name,
status: n.last_status,
os: n.capabilities?.os
}))
}, null, 2)
}]
};
} catch (err) {
return { content: [{ type: 'text', text: `Error: ${err.message}` }], isError: true };
}
}
});
mcpService.registerTool({
name: 'get_app_info',
description: 'Get metadata about the Cortex Hub environment.',
inputSchema: { type: 'object', properties: {} },
execute: async () => {
return {
content: [{
type: 'text',
text: JSON.stringify({
name: 'Cortex Hub',
version: '1.0.0',
capabilities: ['swarms', 'webmcp', 'mcp-sse', 'voice-chat', 'rag'],
environment: window.location.hostname === 'localhost' ? 'development' : 'production',
mcp_server: `${window.location.origin}/api/v1/mcp/sse`,
}, null, 2)
}]
};
}
});
// Poll isMcpActive state so UI can show a badge when WebMCP is live
const statusInterval = setInterval(() => {
const active = mcpService.isActive();
setIsMcpActive(prev => {
if (prev !== active) {
if (active) console.log('[MCP] 🟢 WebMCP is now active — tools registered with browser.');
return active;
}
return prev;
});
}, 200);
return () => clearInterval(statusInterval);
}, []);
const value = {
isMcpActive,
registerTool: (tool) => {
// Normalize legacy 'handler' property
const aligned = { ...tool };
if (tool.handler && !tool.execute) aligned.execute = tool.handler;
mcpService.registerTool(aligned);
},
unregisterTool: (toolName) => mcpService.unregisterTool(toolName),
listRegistered: () => mcpService.listRegistered(),
};
return (
<WebMcpContext.Provider value={value}>
{children}
</WebMcpContext.Provider>
);
};
export const useWebMcp = () => {
const ctx = useContext(WebMcpContext);
if (!ctx) throw new Error('useWebMcp must be used within a WebMcpProvider');
return ctx;
};