feat: disable all web mcp by default (new users) (#6677)

This commit is contained in:
Dinh Long Nguyen 2025-10-01 09:35:09 +07:00 committed by GitHub
parent 46d55030f0
commit 4cb3c46f89
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 59 additions and 5 deletions

View File

@ -25,4 +25,10 @@ export abstract class MCPExtension extends BaseExtension implements MCPInterface
* @returns A React component or null if no custom component is provided * @returns A React component or null if no custom component is provided
*/ */
getToolComponent?(): ComponentType<MCPToolComponentProps> | null getToolComponent?(): ComponentType<MCPToolComponentProps> | null
/**
* Optional method to get the list of tool names that should be disabled by default
* @returns Array of tool names that should be disabled by default for new users
*/
getDefaultDisabledTools?(): Promise<string[]>
} }

View File

@ -242,4 +242,19 @@ export default class MCPExtensionWeb extends MCPExtension {
getToolComponent(): ComponentType<MCPToolComponentProps> | null { getToolComponent(): ComponentType<MCPToolComponentProps> | null {
return WebSearchButton return WebSearchButton
} }
/**
* Returns the list of tool names that should be disabled by default for new users
* All MCP web tools are disabled by default to prevent accidental API usage
* @returns Array of tool names to disable by default
*/
async getDefaultDisabledTools(): Promise<string[]> {
try {
const tools = await this.getTools()
return tools.map(tool => tool.name)
} catch (error) {
console.error('Failed to get default disabled tools:', error)
return []
}
}
} }

View File

@ -8,6 +8,8 @@ type ToolDisabledState = {
disabledTools: Record<string, string[]> // threadId -> toolNames[] disabledTools: Record<string, string[]> // threadId -> toolNames[]
// Global default disabled tools (for new threads/index page) // Global default disabled tools (for new threads/index page)
defaultDisabledTools: string[] defaultDisabledTools: string[]
// Flag to track if defaults have been initialized from extension
defaultsInitialized: boolean
// Actions // Actions
setToolDisabledForThread: ( setToolDisabledForThread: (
@ -19,6 +21,8 @@ type ToolDisabledState = {
getDisabledToolsForThread: (threadId: string) => string[] getDisabledToolsForThread: (threadId: string) => string[]
setDefaultDisabledTools: (toolNames: string[]) => void setDefaultDisabledTools: (toolNames: string[]) => void
getDefaultDisabledTools: () => string[] getDefaultDisabledTools: () => string[]
isDefaultsInitialized: () => boolean
markDefaultsAsInitialized: () => void
// Initialize thread tools from default or existing thread settings // Initialize thread tools from default or existing thread settings
initializeThreadTools: (threadId: string, allTools: MCPTool[]) => void initializeThreadTools: (threadId: string, allTools: MCPTool[]) => void
} }
@ -28,6 +32,7 @@ export const useToolAvailable = create<ToolDisabledState>()(
(set, get) => ({ (set, get) => ({
disabledTools: {}, disabledTools: {},
defaultDisabledTools: [], defaultDisabledTools: [],
defaultsInitialized: false,
setToolDisabledForThread: ( setToolDisabledForThread: (
threadId: string, threadId: string,
@ -81,6 +86,14 @@ export const useToolAvailable = create<ToolDisabledState>()(
return get().defaultDisabledTools return get().defaultDisabledTools
}, },
isDefaultsInitialized: () => {
return get().defaultsInitialized
},
markDefaultsAsInitialized: () => {
set({ defaultsInitialized: true })
},
initializeThreadTools: (threadId: string, allTools: MCPTool[]) => { initializeThreadTools: (threadId: string, allTools: MCPTool[]) => {
const state = get() const state = get()
// If thread already has settings, don't override // If thread already has settings, don't override
@ -109,6 +122,7 @@ export const useToolAvailable = create<ToolDisabledState>()(
partialize: (state) => ({ partialize: (state) => ({
disabledTools: state.disabledTools, disabledTools: state.disabledTools,
defaultDisabledTools: state.defaultDisabledTools, defaultDisabledTools: state.defaultDisabledTools,
defaultsInitialized: state.defaultsInitialized,
}), }),
} }
) )

View File

@ -1,19 +1,38 @@
import { useEffect } from 'react' import { useEffect } from 'react'
import { getServiceHub } from '@/hooks/useServiceHub' import { getServiceHub } from '@/hooks/useServiceHub'
import { MCPTool } from '@/types/completion'
import { SystemEvent } from '@/types/events' import { SystemEvent } from '@/types/events'
import { useAppState } from './useAppState' import { useAppState } from './useAppState'
import { useToolAvailable } from './useToolAvailable'
import { ExtensionManager } from '@/lib/extension'
import { ExtensionTypeEnum, MCPExtension } from '@janhq/core'
export const useTools = () => { export const useTools = () => {
const updateTools = useAppState((state) => state.updateTools) const updateTools = useAppState((state) => state.updateTools)
const { isDefaultsInitialized, setDefaultDisabledTools, markDefaultsAsInitialized } = useToolAvailable()
useEffect(() => { useEffect(() => {
function setTools() { async function setTools() {
getServiceHub().mcp().getTools().then((data: MCPTool[]) => { try {
// Get MCP extension first
const mcpExtension = ExtensionManager.getInstance().get<MCPExtension>(
ExtensionTypeEnum.MCP
)
// Fetch tools
const data = await getServiceHub().mcp().getTools()
updateTools(data) updateTools(data)
}).catch((error) => {
// Initialize default disabled tools for new users (only once)
if (!isDefaultsInitialized() && data.length > 0 && mcpExtension?.getDefaultDisabledTools) {
const defaultDisabled = await mcpExtension.getDefaultDisabledTools()
if (defaultDisabled.length > 0) {
setDefaultDisabledTools(defaultDisabled)
markDefaultsAsInitialized()
}
}
} catch (error) {
console.error('Failed to fetch MCP tools:', error) console.error('Failed to fetch MCP tools:', error)
}) }
} }
setTools() setTools()