add mcp tools

This commit is contained in:
duanfuxiang 2025-06-03 09:33:53 +08:00
parent ec6c4cde83
commit 1dffe5292a
10 changed files with 25 additions and 33 deletions

View File

@ -783,7 +783,6 @@ const Chat = forwardRef<ChatRef, ChatProps>((props, ref) => {
model: undefined,
},
})
console.log('Updated chat messages:', newChatMessages);
}
setChatMessages(newChatMessages);

View File

@ -63,7 +63,7 @@ const CustomModeView = () => {
const [roleDefinition, setRoleDefinition] = useState<string>('')
// Selected tool groups
const [selectedTools, setSelectedTools] = useState<GroupEntry[]>([])
const [selectedTools, setSelectedTools] = useState<GroupEntry[]>([]);
// Custom instructions
const [customInstructions, setCustomInstructions] = useState<string>('')
@ -87,7 +87,7 @@ const CustomModeView = () => {
setModeName(builtinMode.slug);
setRoleDefinition(builtinMode.roleDefinition);
setCustomInstructions(builtinMode.customInstructions || '');
setSelectedTools(builtinMode.groups);
setSelectedTools(builtinMode.groups as GroupEntry[]);
setCustomModeId(''); // Built-in modes don't have custom IDs
} else {
setIsBuiltinMode(false);

View File

@ -1,9 +1,8 @@
import { Server } from 'lucide-react'
import React from 'react'
import { useSettings } from "../../../contexts/SettingsContext"
import { t } from '../../../lang/helpers'
import { ApplyStatus, SearchWebToolArgs } from "../../../types/apply"
import { ApplyStatus, UseMcpToolArgs } from "../../../types/apply"
export default function UseMcpToolBlock({
applyStatus,
@ -14,16 +13,13 @@ export default function UseMcpToolBlock({
finish
}: {
applyStatus: ApplyStatus
onApply: (args: SearchWebToolArgs) => void
onApply: (args: UseMcpToolArgs) => void
serverName: string,
toolName: string,
parameters: Record<string, unknown>,
finish: boolean
}) {
const { settings } = useSettings()
React.useEffect(() => {
if (finish && applyStatus === ApplyStatus.Idle) {
onApply({
@ -43,7 +39,7 @@ export default function UseMcpToolBlock({
<div className={'infio-chat-code-block-header'}>
<div className={'infio-chat-code-block-header-filename'}>
<Server size={14} className="infio-chat-code-block-header-icon" />
use mcp tool from
{t('mcpHub.useMcpToolFrom')}
<span className="infio-mcp-tool-server-name">{serverName}</span>
</div>
</div>
@ -56,7 +52,7 @@ export default function UseMcpToolBlock({
<span className="infio-mcp-tool-name">{toolName}</span>
</div>
</div>
: <div className="infio-mcp-tool-parameters">
{t('mcpHub.parameters')}: <div className="infio-mcp-tool-parameters">
<pre className="infio-json-pre"><code>{JSON.stringify(parameters, null, 2)}</code></pre>
</div>
</div>

View File

@ -21,10 +21,8 @@ const McpHubView = () => {
const fetchServers = async () => {
const hub = await getMcpHub()
console.log('Fetching MCP Servers from hub:', hub)
if (hub) {
const serversData = hub.getAllServers()
console.log('Fetched MCP Servers:', serversData)
setMcpServers(serversData)
}
}
@ -65,7 +63,7 @@ const McpHubView = () => {
const handleDelete = async (serverName: string) => {
const hub = await getMcpHub();
if (hub) {
if (confirm(t('mcpHub.deleteConfirm', { name: serverName }))) {
if (confirm(t('mcpHub.deleteConfirm').replace('{name}', serverName) as string)) {
await hub.deleteServer(serverName, "global")
const updatedServers = hub.getAllServers()
setMcpServers(updatedServers)
@ -103,9 +101,9 @@ const McpHubView = () => {
// 清空表单
setNewServerName('')
setNewServerConfig('')
new Notice(t('mcpHub.createSuccess', { name: newServerName }))
new Notice(t('mcpHub.createSuccess').replace('{name}', newServerName) as string)
} catch (error) {
new Notice(t('mcpHub.createFailed', { error: error.message }))
new Notice(t('mcpHub.createFailed').replace('{error}', error.message) as string)
}
}
}

View File

@ -95,7 +95,6 @@ class LLMManager implements LLMManagerInterface {
request: LLMRequestNonStreaming,
options?: LLMOptions,
): Promise<LLMResponseNonStreaming> {
console.log("model", model)
switch (model.provider) {
case ApiProvider.Infio:
return await this.infioProvider.generateResponse(

View File

@ -140,14 +140,10 @@ export class McpHub {
public async onload() {
// Ensure the MCP configuration directory exists
console.log("McpHub: Loading MCP Hub")
await this.ensureMcpFileExists()
console.log("McpHub: file exists")
await this.watchMcpSettingsFile();
console.log("McpHub: watchMcpSettingsFile")
// this.setupWorkspaceWatcher();
await this.initializeGlobalMcpServers();
console.log("McpHub: initializeGlobalMcpServers")
}
/**
@ -156,7 +152,6 @@ export class McpHub {
*/
public registerClient(): void {
this.refCount++
console.log(`McpHub: Client registered. Ref count: ${this.refCount}`)
}
/**
@ -165,9 +160,7 @@ export class McpHub {
*/
public async unregisterClient(): Promise<void> {
this.refCount--
console.log(`McpHub: Client unregistered. Ref count: ${this.refCount}`)
if (this.refCount <= 0) {
console.log("McpHub: Last client unregistered. Disposing hub.")
await this.dispose()
}
}
@ -336,7 +329,7 @@ export class McpHub {
// which should create it, then something is wrong.
// However, getMcpSettingsFilePath should handle creation.
// This check is more of a safeguard.
console.log("MCP config file does not exist, skipping initialization.");
// console.log("MCP config file does not exist, skipping initialization.");
return;
}
@ -646,6 +639,7 @@ export class McpHub {
alwaysAllow: alwaysAllowConfig.includes(tool.name),
}))
// @ts-expect-error - 服务器返回的工具对象中 name 是可选的,但 McpTool 类型要求它是必需的
return tools
} catch (error) {
console.error(`Failed to fetch tools for ${serverName}:`, error)
@ -660,6 +654,7 @@ export class McpHub {
return []
}
const response = await connection.client.request({ method: "resources/list" }, ListResourcesResultSchema)
// @ts-expect-error - 服务器返回的资源对象中 name 是可选的,但 McpResource 类型要求它是必需的
return response?.resources || []
} catch (error) {
// console.error(`Failed to fetch resources for ${serverName}:`, error)
@ -680,6 +675,7 @@ export class McpHub {
{ method: "resources/templates/list" },
ListResourceTemplatesResultSchema,
)
// @ts-expect-error - 服务器返回的资源模板对象中 name 是可选的,但 McpResourceTemplate 类型要求它是必需的
return response?.resourceTemplates || []
} catch (error) {
// console.error(`Failed to fetch resource templates for ${serverName}:`, error)
@ -1194,6 +1190,7 @@ export class McpHub {
if (connection.server.disabled) {
throw new Error(`Server "${serverName}" is disabled`)
}
// @ts-expect-error - 服务器返回的资源对象中 name 是可选的,但 McpResourceResponse 类型要求它是必需的
return await connection.client.request(
{
method: "resources/read",
@ -1231,6 +1228,7 @@ export class McpHub {
timeout = 60 * 1000
}
// @ts-expect-error - 服务器返回的工具调用对象中 name 是可选的,但 McpToolCallResponse 类型要求它是必需的
return await connection.client.request(
{
method: "tools/call",

View File

@ -381,8 +381,8 @@ export default {
disable: "Disable Server",
restart: "Restart Server",
delete: "Delete Server",
deleteConfirm: "Are you sure you want to delete server \"{name}\"?",
createSuccess: "Server \"{name}\" created successfully",
deleteConfirm: "Are you sure you want to delete server {name}?",
createSuccess: "Server {name} created successfully",
createFailed: "Failed to create server: {error}",
serverNameRequired: "Server name cannot be empty",
configRequired: "Configuration cannot be empty",
@ -396,6 +396,7 @@ export default {
noResources: "No resources available",
noErrors: "No error records",
parameters: "Parameters",
toolNoDescription: "No description"
toolNoDescription: "No description",
useMcpToolFrom: "Use MCP tool from",
}
}

View File

@ -396,7 +396,8 @@ export default {
noResources: "没有可用资源",
noErrors: "没有错误记录",
parameters: "参数",
toolNoDescription: "无描述"
toolNoDescription: "无描述",
useMcpToolFrom: "Use MCP tool from",
}
}
};

View File

@ -22,7 +22,7 @@ export type ModeConfig = {
name: string
roleDefinition: string
customInstructions?: string
groups: readonly GroupEntry[] // Now supports both simple strings and tuples with options
groups: GroupEntry[] // Now supports both simple strings and tuples with options
source?: "global" | "project" // Where this mode was loaded from
}
@ -79,7 +79,7 @@ export function getToolsForMode(groups: readonly GroupEntry[]): string[] {
}
// Main modes configuration as an ordered array
export const defaultModes: readonly ModeConfig[] = [
export const defaultModes: ModeConfig[] = [
{
slug: "ask",
name: "Ask",
@ -107,7 +107,7 @@ export const defaultModes: readonly ModeConfig[] = [
customInstructions:
"You can conduct thorough research by analyzing available information, connecting related concepts, and applying structured reasoning methods. Help users explore topics in depth by considering multiple angles, identifying relevant evidence, and evaluating the reliability of sources. Use step-by-step analysis when tackling complex problems, explaining your thought process clearly. Create visual representations like Mermaid diagrams when they help clarify relationships between ideas. Use Markdown tables to present statistical data or comparative information when appropriate. Present balanced viewpoints while highlighting the strength of evidence behind different conclusions.",
},
] as const
]
// Export the default mode slug
export const defaultModeSlug = defaultModes[0].slug

View File

@ -41,7 +41,7 @@ export async function onEnt(
}
const postData = JSON.stringify(payload)
const apiUrl = new URL(`https://hubs.infio.app/e1/api/event`)
const apiUrl = new URL(`https://hubs.infio.app/api/event`)
const options = {
hostname: apiUrl.hostname,