From 7e4bedecfdddd3bf9db97b132cdc835da56dd959 Mon Sep 17 00:00:00 2001 From: weijihui Date: Tue, 9 Dec 2025 11:16:06 +0800 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20mcp=E5=B7=A5=E5=85=B7=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E9=80=9A=E8=BF=87use=5Fmcp=5Ftool=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presenter/builtInToolsPresenter/index.ts | 15 +- .../builtInToolsPresenter/useMcpTool.ts | 189 ++++++++++++++++++ src/main/presenter/configPresenter/index.ts | 11 +- .../presenter/llmProviderPresenter/index.ts | 15 +- .../promptPresenter/sections/tool-use.ts | 23 ++- src/main/presenter/promptPresenter/system.ts | 23 ++- src/main/presenter/threadPresenter/index.ts | 6 - .../types/presenters/legacy.presenters.d.ts | 4 +- .../presenters/llmprovider.presenter.d.ts | 1 - 9 files changed, 248 insertions(+), 39 deletions(-) create mode 100644 src/main/presenter/builtInToolsPresenter/useMcpTool.ts diff --git a/src/main/presenter/builtInToolsPresenter/index.ts b/src/main/presenter/builtInToolsPresenter/index.ts index 298b35a..059cf08 100644 --- a/src/main/presenter/builtInToolsPresenter/index.ts +++ b/src/main/presenter/builtInToolsPresenter/index.ts @@ -13,6 +13,7 @@ import { writeFileTool, executeWriteFileTool } from './writeFileTool' import { listFilesTool, executeListFilesTool } from './listFilesTool' import { executeCommandTool, executeCommandToolHandler } from './executeCommandTool' import { useA2AServerTool, executeUseA2AServerToolHandler } from './useA2AServerTool' +import { useMcpTool, executeUseMcpTool } from './useMcpTool' export const BUILT_IN_TOOL_SERVER_NAME = 'polymind-builtin' export const BUILT_IN_TOOL_SERVER_DESCRIPTION = 'PolyMind built-in tools' @@ -21,7 +22,8 @@ export const builtInTools: Record = { [readFileTool.name]: readFileTool, [writeFileTool.name]: writeFileTool, [listFilesTool.name]: listFilesTool, - [executeCommandTool.name]: executeCommandTool + [executeCommandTool.name]: executeCommandTool, + [useMcpTool.name]: useMcpTool } type BuiltInExecutor = (args: any, toolCallId: string) => Promise @@ -29,7 +31,8 @@ const builtInToolExecutors: Record = { [readFileTool.name]: executeReadFileTool, [writeFileTool.name]: executeWriteFileTool, [listFilesTool.name]: executeListFilesTool, - [executeCommandTool.name]: executeCommandToolHandler + [executeCommandTool.name]: executeCommandToolHandler, + [useMcpTool.name]: executeUseMcpTool } const a2aBuiltInTools: Record = { @@ -209,12 +212,16 @@ export class BuiltInToolsPresenter implements IBuiltInToolsPresenter { } } + async convertBuiltInToolsToXml(enabled: boolean = true, currentAgent?: Agent): Promise { + const tools = await this.getBuiltInToolDefinitions(enabled, currentAgent) + return this.convertToolsToXml(tools) + } + /** * 将 MCPToolDefinition 转换为 XML 格式 * @returns XML 格式的工具定义字符串 */ - async convertToolsToXml(enabled: boolean = true, currentAgent?: Agent): Promise { - const tools = await this.getBuiltInToolDefinitions(enabled, currentAgent) + convertToolsToXml(tools: MCPToolDefinition[]): string { const xmlTools = tools .map((tool) => { const { name, description, parameters } = tool.function diff --git a/src/main/presenter/builtInToolsPresenter/useMcpTool.ts b/src/main/presenter/builtInToolsPresenter/useMcpTool.ts new file mode 100644 index 0000000..b39ecc8 --- /dev/null +++ b/src/main/presenter/builtInToolsPresenter/useMcpTool.ts @@ -0,0 +1,189 @@ +import { BuiltInToolDefinition, BuiltInToolResponse, buildRawData } from './base' +import { MCPToolCall, MCPToolDefinition, MCPToolResponse } from '@shared/presenter' + +export const useMcpTool: BuiltInToolDefinition = { + name: 'use_mcp_tool', + description: + 'Request to use a tool provided by a connected MCP server. Each MCP server can provide multiple tools with different capabilities. Tools have defined input schemas that specify required and optional parameters.', + parameters: { + type: 'object', + properties: { + server_name: { + type: 'string', + description: 'The name of the MCP server providing the tool.' + }, + tool_name: { + type: 'string', + description: 'The name of the tool to execute.' + }, + arguments: { + type: 'object', + description: + "A JSON object containing the tool's input parameters, following the tool's input schema." + } + }, + required: ['server_name', 'tool_name', 'arguments'] + } +} + +function validateArgs(args: any): { + serverName: string + toolName: string + toolArguments: Record +} { + const { server_name, tool_name, arguments: toolArguments } = args ?? {} + + if (typeof server_name !== 'string' || server_name.trim().length === 0) { + throw new Error('server_name is required and must be a non-empty string') + } + if (typeof tool_name !== 'string' || tool_name.trim().length === 0) { + throw new Error('tool_name is required and must be a non-empty string') + } + if ( + toolArguments === null || + toolArguments === undefined || + typeof toolArguments !== 'object' || + Array.isArray(toolArguments) + ) { + throw new Error('arguments is required and must be a JSON object') + } + + return { + serverName: server_name.trim(), + toolName: tool_name.trim(), + toolArguments + } +} + +async function resolveToolName( + mcpToolDefinitions: MCPToolDefinition[], + serverName: string, + requestedToolName: string +): Promise<{ resolvedToolName: string; definition?: MCPToolDefinition }> { + if (!Array.isArray(mcpToolDefinitions)) { + return { resolvedToolName: requestedToolName } + } + + const directMatch = mcpToolDefinitions.find( + (def) => def.server?.name === serverName && def.function.name === requestedToolName + ) + if (directMatch) { + return { resolvedToolName: directMatch.function.name, definition: directMatch } + } + + const prefixedName = `${serverName}_${requestedToolName}` + const prefixedMatch = mcpToolDefinitions.find( + (def) => def.server?.name === serverName && def.function.name === prefixedName + ) + if (prefixedMatch) { + return { resolvedToolName: prefixedMatch.function.name, definition: prefixedMatch } + } + + const suffixMatch = mcpToolDefinitions.find( + (def) => + def.server?.name === serverName && + typeof def.function.name === 'string' && + def.function.name.endsWith(`_${requestedToolName}`) + ) + if (suffixMatch) { + return { resolvedToolName: suffixMatch.function.name, definition: suffixMatch } + } + + return { resolvedToolName: requestedToolName } +} + +export async function executeUseMcpTool( + args: any, + toolCallId: string +): Promise { + try { + const { serverName, toolName, toolArguments } = validateArgs(args) + + // Import presenter lazily to avoid circular dependencies at module load time + const { presenter } = await import('@/presenter') + const mcpPresenter = presenter?.mcpPresenter + + if (!mcpPresenter || typeof mcpPresenter.callTool !== 'function') { + throw new Error('MCP presenter is not available') + } + + const toolDefinitions = await mcpPresenter.getAllToolDefinitions() + const { resolvedToolName, definition } = await resolveToolName( + toolDefinitions, + serverName, + toolName + ) + + const toolCall: MCPToolCall = { + id: toolCallId, + type: 'function', + function: { + name: resolvedToolName, + arguments: JSON.stringify(toolArguments) + }, + server: definition?.server ?? { + name: serverName, + icons: '', + description: '' + } + } + + const result = await mcpPresenter.callTool(toolCall) + const rawData: MCPToolResponse = { + ...result.rawData, + toolCallId, + _meta: { + ...(result.rawData?._meta ?? {}), + serverName, + toolName: resolvedToolName, + arguments: toolArguments + } + } + + if (rawData.requiresPermission) { + const permission = rawData.permissionRequest + const content = `Permission required to execute MCP tool.\nServer: ${serverName}\nTool: ${resolvedToolName}\nPermission: ${permission?.permissionType ?? 'unknown'}` + const metadata = { + serverName, + toolName: resolvedToolName, + permissionRequest: permission + } + return { + toolCallId, + content, + success: false, + metadata, + rawData + } + } + + const success = !rawData.isError + const contentPrefix = success ? 'MCP tool executed successfully.' : 'MCP tool execution failed.' + const content = `${contentPrefix}\nServer: ${serverName}\nTool: ${resolvedToolName}\n\n${result.content}` + + const metadata = { + serverName, + toolName: resolvedToolName, + arguments: toolArguments + } + + return { + toolCallId, + content, + success, + metadata, + rawData + } + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error) + const failureMessage = `Failed to execute MCP tool: ${errorMessage}` + const metadata = { error: errorMessage } + return { + toolCallId, + content: failureMessage, + success: false, + metadata, + rawData: buildRawData(toolCallId, failureMessage, true, metadata) + } + } +} diff --git a/src/main/presenter/configPresenter/index.ts b/src/main/presenter/configPresenter/index.ts index d6f84d2..d335484 100644 --- a/src/main/presenter/configPresenter/index.ts +++ b/src/main/presenter/configPresenter/index.ts @@ -1272,7 +1272,16 @@ export class ConfigPresenter implements IConfigPresenter { private async getBuildInSystemPrompt(agent?: Agent): Promise { // 获取内置的系统提示词 const useBuiltInToolsEnabled = this.getUseBuiltInToolsEnabled() - return await SYSTEM_PROMPT('', '', this.getLanguage(), '', useBuiltInToolsEnabled, agent) + const enabledMcpTools = await presenter.mcpPresenter.getAllToolDefinitions() + return await SYSTEM_PROMPT( + '', + '', + this.getLanguage(), + '', + useBuiltInToolsEnabled, + agent, + enabledMcpTools + ) } async getSystemPrompts(): Promise { diff --git a/src/main/presenter/llmProviderPresenter/index.ts b/src/main/presenter/llmProviderPresenter/index.ts index 8851e47..f80f887 100644 --- a/src/main/presenter/llmProviderPresenter/index.ts +++ b/src/main/presenter/llmProviderPresenter/index.ts @@ -12,7 +12,6 @@ import { ModelScopeMcpSyncOptions, ModelScopeMcpSyncResult, IConfigPresenter, - MCPToolDefinition, Agent } from '@shared/presenter' import { ProviderChange, ProviderBatchUpdate } from '@shared/provider-operations' @@ -701,7 +700,6 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { eventId: string, temperature: number = 0.6, maxTokens: number = 4096, - enabledMcpTools?: string[], thinkingBudget?: number, reasoningEffort?: 'minimal' | 'low' | 'medium' | 'high', verbosity?: 'low' | 'medium' | 'high', @@ -801,16 +799,11 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { try { console.log(`[Agent Loop] Iteration ${toolCallCount + 1} for event: ${eventId}`) - let availableTools: MCPToolDefinition[] = [] const useBuiltInToolsEnabled = this.configPresenter.getUseBuiltInToolsEnabled() - const [mcpTools, builtInTools] = await Promise.all([ - presenter.mcpPresenter.getAllToolDefinitions(enabledMcpTools), - presenter.builtInToolsPresenter.getBuiltInToolDefinitions( - useBuiltInToolsEnabled, - currentAgent - ) - ]) - availableTools = [...mcpTools, ...builtInTools] + const availableTools = await presenter.builtInToolsPresenter.getBuiltInToolDefinitions( + useBuiltInToolsEnabled, + currentAgent + ) const canExecute = this.canExecuteImmediately(providerId) if (!canExecute) { diff --git a/src/main/presenter/promptPresenter/sections/tool-use.ts b/src/main/presenter/promptPresenter/sections/tool-use.ts index 72466c6..21d3777 100644 --- a/src/main/presenter/promptPresenter/sections/tool-use.ts +++ b/src/main/presenter/promptPresenter/sections/tool-use.ts @@ -4,22 +4,31 @@ function getSystemPromptByA2ATool(toolsXML: string): string { } return '' } -export function getSharedToolUseSection(toolsXML: string): string { +export function getSharedToolUseSection(toolsXML: string, mcpToolsXML: string): string { + const connectedServers = mcpToolsXML + ? ` +Connected MCP Servers: +\`\`\`xml +${mcpToolsXML} +\`\`\` +` + : '(No MCP servers currently connected)' + return ` ==== # Tool Use You have the ability to invoke external tools to assist in resolving user problems. ${getSystemPromptByA2ATool(toolsXML)} ## Tools -The list of available tools is defined in the tag: - \`\`\`xml - - ${toolsXML} - - \`\`\` +You can prioritize using the tools listed above to solve problems. +The tools defined below are some MCP server tools, you should choose the appropriate tool based on the description of each tool to solve specific problems. +You can use the MCP server's tools via the \`use_mcp_tool\` tool. + +${connectedServers} + ## Tool Use Formatting When invoking tools, your output should **only** contain the tag and its content, without any other text, explanations or comments. Tool uses are formatted using XML-style tags. Here's the structure: diff --git a/src/main/presenter/promptPresenter/system.ts b/src/main/presenter/promptPresenter/system.ts index f390c11..3d560c6 100644 --- a/src/main/presenter/promptPresenter/system.ts +++ b/src/main/presenter/promptPresenter/system.ts @@ -7,8 +7,7 @@ import { addCustomInstructions, markdownFormattingSection } from './sections' -import { Agent } from '@shared/presenter' - +import { Agent, MCPToolDefinition } from '@shared/presenter' async function generatePrompt( cwd?: string, @@ -16,7 +15,8 @@ async function generatePrompt( language?: string, IgnoreInstructions?: string, useBuiltInToolsEnabled?: boolean, - agent?: Agent + agent?: Agent, + enabledMcpTools?: MCPToolDefinition[] ): Promise { const promptSections: string[] = [] if (agent) { @@ -34,14 +34,21 @@ async function generatePrompt( } promptSections.push(markdownFormattingSection()) + let toolsXML = '' if (useBuiltInToolsEnabled) { - const toolsXML = await presenter.builtInToolsPresenter.convertToolsToXml( + toolsXML = await presenter.builtInToolsPresenter.convertBuiltInToolsToXml( useBuiltInToolsEnabled, agent ) - promptSections.push(`${getSharedToolUseSection(toolsXML)}`) } + let mcpToolsXML = '' + if (enabledMcpTools && enabledMcpTools.length > 0) { + mcpToolsXML = presenter.builtInToolsPresenter.convertToolsToXml(enabledMcpTools) + } + + promptSections.push(`${getSharedToolUseSection(toolsXML, mcpToolsXML)}`) + promptSections.push(getSystemInfoSection(), getObjectiveSection()) const customInstructions = await addCustomInstructions( @@ -68,7 +75,8 @@ export const SYSTEM_PROMPT = async ( language?: string, IgnoreInstructions?: string, useBuiltInToolsEnabled?: boolean, - agent?: Agent + agent?: Agent, + enabledMcpTools?: MCPToolDefinition[] ): Promise => { return generatePrompt( cwd, @@ -76,6 +84,7 @@ export const SYSTEM_PROMPT = async ( language, IgnoreInstructions, useBuiltInToolsEnabled, - agent + agent, + enabledMcpTools ) } diff --git a/src/main/presenter/threadPresenter/index.ts b/src/main/presenter/threadPresenter/index.ts index 2d8746e..1f82990 100644 --- a/src/main/presenter/threadPresenter/index.ts +++ b/src/main/presenter/threadPresenter/index.ts @@ -1898,7 +1898,6 @@ export class ThreadPresenter implements IThreadPresenter { modelId: currentModelId, temperature: currentTemperature, maxTokens: currentMaxTokens, - enabledMcpTools: currentEnabledMcpTools, thinkingBudget: currentThinkingBudget, reasoningEffort: currentReasoningEffort, verbosity: currentVerbosity, @@ -1913,7 +1912,6 @@ export class ThreadPresenter implements IThreadPresenter { state.message.id, currentTemperature, // 使用最新的设置 currentMaxTokens, // 使用最新的设置 - currentEnabledMcpTools, currentThinkingBudget, currentReasoningEffort, currentVerbosity, @@ -2023,7 +2021,6 @@ export class ThreadPresenter implements IThreadPresenter { modelId, temperature, maxTokens, - enabledMcpTools, thinkingBudget, reasoningEffort, verbosity, @@ -2098,7 +2095,6 @@ export class ThreadPresenter implements IThreadPresenter { state.message.id, temperature, maxTokens, - enabledMcpTools, thinkingBudget, reasoningEffort, verbosity, @@ -4398,7 +4394,6 @@ export class ThreadPresenter implements IThreadPresenter { modelId, temperature, maxTokens, - enabledMcpTools, thinkingBudget, reasoningEffort, verbosity, @@ -4459,7 +4454,6 @@ export class ThreadPresenter implements IThreadPresenter { messageId, temperature, maxTokens, - enabledMcpTools, thinkingBudget, reasoningEffort, verbosity, diff --git a/src/shared/types/presenters/legacy.presenters.d.ts b/src/shared/types/presenters/legacy.presenters.d.ts index 96f02ad..8f62a0e 100644 --- a/src/shared/types/presenters/legacy.presenters.d.ts +++ b/src/shared/types/presenters/legacy.presenters.d.ts @@ -648,7 +648,6 @@ export interface ILlmProviderPresenter { eventId: string, temperature?: number, maxTokens?: number, - enabledMcpTools?: string[], thinkingBudget?: number, reasoningEffort?: 'minimal' | 'low' | 'medium' | 'high', verbosity?: 'low' | 'medium' | 'high', @@ -1247,7 +1246,8 @@ export interface ProgressResponse { // export interface IBuiltInToolsPresenter { - convertToolsToXml(useBuiltInToolsEnabled: boolean, currentAgent?: Agent): Promise + convertBuiltInToolsToXml(useBuiltInToolsEnabled: boolean, currentAgent?: Agent): Promise + convertToolsToXml(tools: MCPToolDefinition[]): string getBuiltInToolDefinitions(enabled?: boolean, currentAgent?: Agent | null): any /** diff --git a/src/shared/types/presenters/llmprovider.presenter.d.ts b/src/shared/types/presenters/llmprovider.presenter.d.ts index 51c8389..05c4c0e 100644 --- a/src/shared/types/presenters/llmprovider.presenter.d.ts +++ b/src/shared/types/presenters/llmprovider.presenter.d.ts @@ -151,7 +151,6 @@ export interface ILlmProviderPresenter { eventId: string, temperature?: number, maxTokens?: number, - enabledMcpTools?: string[], thinkingBudget?: number, reasoningEffort?: 'minimal' | 'low' | 'medium' | 'high', verbosity?: 'low' | 'medium' | 'high', -- Gitee From a5116d2afa5c1557b195ddef410a13a82b89fb94 Mon Sep 17 00:00:00 2001 From: weijihui Date: Tue, 9 Dec 2025 17:12:23 +0800 Subject: [PATCH 2/3] fix: add server name for use_mcp_tool args --- .../presenter/builtInToolsPresenter/index.ts | 3 ++- .../promptPresenter/sections/tool-use.ts | 23 ++++++++++++------- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/src/main/presenter/builtInToolsPresenter/index.ts b/src/main/presenter/builtInToolsPresenter/index.ts index 059cf08..577c2d7 100644 --- a/src/main/presenter/builtInToolsPresenter/index.ts +++ b/src/main/presenter/builtInToolsPresenter/index.ts @@ -226,6 +226,7 @@ export class BuiltInToolsPresenter implements IBuiltInToolsPresenter { .map((tool) => { const { name, description, parameters } = tool.function const { properties, required = [] } = parameters + const serverNameAttr = tool.server?.name ? ` server_name="${tool.server.name}"` : '' const paramsXml = Object.entries(properties) .map(([paramName, paramDef]) => { @@ -239,7 +240,7 @@ export class BuiltInToolsPresenter implements IBuiltInToolsPresenter { }) .join('\n ') - return ` + return ` ${paramsXml} ` }) diff --git a/src/main/presenter/promptPresenter/sections/tool-use.ts b/src/main/presenter/promptPresenter/sections/tool-use.ts index 21d3777..100afb6 100644 --- a/src/main/presenter/promptPresenter/sections/tool-use.ts +++ b/src/main/presenter/promptPresenter/sections/tool-use.ts @@ -19,24 +19,32 @@ ${mcpToolsXML} # Tool Use You have the ability to invoke external tools to assist in resolving user problems. ${getSystemPromptByA2ATool(toolsXML)} ## Tools +The list of available tools is defined in the tag and tag: + \`\`\`xml + + ${toolsXML} -\`\`\` + + You can prioritize using the tools listed above to solve problems. -The tools defined below are some MCP server tools, you should choose the appropriate tool based on the description of each tool to solve specific problems. +The tools defined in tag below are some MCP server tools, you should choose the appropriate tool based on the description of each tool to solve specific problems. You can use the MCP server's tools via the \`use_mcp_tool\` tool. +\`\`\`xml + + ${connectedServers} + + ## Tool Use Formatting -When invoking tools, your output should **only** contain the tag and its content, without any other text, explanations or comments. +When invoking tools, your output should **only** contain the one tag and its content, without any other text, explanations or comments. Tool uses are formatted using XML-style tags. Here's the structure: - { - "function_call": - { + "function_call": { "name": "tool_name", "arguments": { // The parameter object must be in valid JSON format. "parameter1_name": "value1", @@ -45,7 +53,6 @@ Tool uses are formatted using XML-style tags. Here's the structure: } } } - ## Tool Use Guidelines **Important Constraints:** @@ -73,7 +80,7 @@ For example, suppose you need to call a tool named "getWeather" and provide "loc } } - + ## Description of the Tool Invocation Record Structure You should not only be able to call various tools, but also be able to locate, extract, reuse, and reference the call return results from our conversations, extracting key information from them to answer questions. -- Gitee From 2db48fa70d6025c48f4bac64fdc13b359ea79a10 Mon Sep 17 00:00:00 2001 From: weijihui Date: Fri, 12 Dec 2025 10:48:40 +0800 Subject: [PATCH 3/3] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0MCP=20Servers?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E6=8F=90=E7=A4=BA=E8=AF=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presenter/builtInToolsPresenter/index.ts | 18 +++--------------- src/main/presenter/configPresenter/index.ts | 11 +---------- .../presenter/llmProviderPresenter/index.ts | 8 +++----- .../promptPresenter/sections/tool-use.ts | 7 +++++-- src/main/presenter/promptPresenter/system.ts | 17 ++++------------- src/main/presenter/threadPresenter/index.ts | 6 ++++++ .../types/presenters/legacy.presenters.d.ts | 4 ++-- .../presenters/llmprovider.presenter.d.ts | 1 + 8 files changed, 25 insertions(+), 47 deletions(-) diff --git a/src/main/presenter/builtInToolsPresenter/index.ts b/src/main/presenter/builtInToolsPresenter/index.ts index 577c2d7..c829fc0 100644 --- a/src/main/presenter/builtInToolsPresenter/index.ts +++ b/src/main/presenter/builtInToolsPresenter/index.ts @@ -195,14 +195,7 @@ export class BuiltInToolsPresenter implements IBuiltInToolsPresenter { } } - async getBuiltInToolDefinitions( - enabled: boolean = true, - currentAgent?: Agent - ): Promise { - if (!enabled) { - return [] - } - + async getBuiltInToolDefinitions(currentAgent?: Agent): Promise { try { const tools = await this.getBuiltInTools(currentAgent) return tools.map((tool) => this.mapToolToDefinition(tool)) @@ -212,11 +205,6 @@ export class BuiltInToolsPresenter implements IBuiltInToolsPresenter { } } - async convertBuiltInToolsToXml(enabled: boolean = true, currentAgent?: Agent): Promise { - const tools = await this.getBuiltInToolDefinitions(enabled, currentAgent) - return this.convertToolsToXml(tools) - } - /** * 将 MCPToolDefinition 转换为 XML 格式 * @returns XML 格式的工具定义字符串 @@ -226,7 +214,7 @@ export class BuiltInToolsPresenter implements IBuiltInToolsPresenter { .map((tool) => { const { name, description, parameters } = tool.function const { properties, required = [] } = parameters - const serverNameAttr = tool.server?.name ? ` server_name="${tool.server.name}"` : '' + const serverName = tool.server?.name ? tool.server.name : '' const paramsXml = Object.entries(properties) .map(([paramName, paramDef]) => { @@ -240,7 +228,7 @@ export class BuiltInToolsPresenter implements IBuiltInToolsPresenter { }) .join('\n ') - return ` + return ` ${paramsXml} ` }) diff --git a/src/main/presenter/configPresenter/index.ts b/src/main/presenter/configPresenter/index.ts index d335484..8f29e2a 100644 --- a/src/main/presenter/configPresenter/index.ts +++ b/src/main/presenter/configPresenter/index.ts @@ -1271,17 +1271,8 @@ export class ConfigPresenter implements IConfigPresenter { private async getBuildInSystemPrompt(agent?: Agent): Promise { // 获取内置的系统提示词 - const useBuiltInToolsEnabled = this.getUseBuiltInToolsEnabled() const enabledMcpTools = await presenter.mcpPresenter.getAllToolDefinitions() - return await SYSTEM_PROMPT( - '', - '', - this.getLanguage(), - '', - useBuiltInToolsEnabled, - agent, - enabledMcpTools - ) + return await SYSTEM_PROMPT('', '', this.getLanguage(), '', agent, enabledMcpTools) } async getSystemPrompts(): Promise { diff --git a/src/main/presenter/llmProviderPresenter/index.ts b/src/main/presenter/llmProviderPresenter/index.ts index f80f887..ab27e84 100644 --- a/src/main/presenter/llmProviderPresenter/index.ts +++ b/src/main/presenter/llmProviderPresenter/index.ts @@ -700,6 +700,7 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { eventId: string, temperature: number = 0.6, maxTokens: number = 4096, + enabledMcpTools?: string[], thinkingBudget?: number, reasoningEffort?: 'minimal' | 'low' | 'medium' | 'high', verbosity?: 'low' | 'medium' | 'high', @@ -799,12 +800,9 @@ export class LLMProviderPresenter implements ILlmProviderPresenter { try { console.log(`[Agent Loop] Iteration ${toolCallCount + 1} for event: ${eventId}`) - const useBuiltInToolsEnabled = this.configPresenter.getUseBuiltInToolsEnabled() - const availableTools = await presenter.builtInToolsPresenter.getBuiltInToolDefinitions( - useBuiltInToolsEnabled, - currentAgent - ) + const availableTools = + await presenter.builtInToolsPresenter.getBuiltInToolDefinitions(currentAgent) const canExecute = this.canExecuteImmediately(providerId) if (!canExecute) { const config = this.getProviderRateLimitConfig(providerId) diff --git a/src/main/presenter/promptPresenter/sections/tool-use.ts b/src/main/presenter/promptPresenter/sections/tool-use.ts index 100afb6..35d8fee 100644 --- a/src/main/presenter/promptPresenter/sections/tool-use.ts +++ b/src/main/presenter/promptPresenter/sections/tool-use.ts @@ -43,8 +43,10 @@ ${connectedServers} When invoking tools, your output should **only** contain the one tag and its content, without any other text, explanations or comments. Tool uses are formatted using XML-style tags. Here's the structure: + { - "function_call": { + "function_call": + { "name": "tool_name", "arguments": { // The parameter object must be in valid JSON format. "parameter1_name": "value1", @@ -53,6 +55,7 @@ Tool uses are formatted using XML-style tags. Here's the structure: } } } + ## Tool Use Guidelines **Important Constraints:** @@ -80,7 +83,7 @@ For example, suppose you need to call a tool named "getWeather" and provide "loc } } - + ## Description of the Tool Invocation Record Structure You should not only be able to call various tools, but also be able to locate, extract, reuse, and reference the call return results from our conversations, extracting key information from them to answer questions. diff --git a/src/main/presenter/promptPresenter/system.ts b/src/main/presenter/promptPresenter/system.ts index 3d560c6..e86400e 100644 --- a/src/main/presenter/promptPresenter/system.ts +++ b/src/main/presenter/promptPresenter/system.ts @@ -3,8 +3,8 @@ import { formatLanguage } from '../../../shared/language' import { getSystemInfoSection, getObjectiveSection, - getSharedToolUseSection, addCustomInstructions, + getSharedToolUseSection, markdownFormattingSection } from './sections' import { Agent, MCPToolDefinition } from '@shared/presenter' @@ -14,7 +14,6 @@ async function generatePrompt( globalCustomInstructions?: string, language?: string, IgnoreInstructions?: string, - useBuiltInToolsEnabled?: boolean, agent?: Agent, enabledMcpTools?: MCPToolDefinition[] ): Promise { @@ -34,20 +33,14 @@ async function generatePrompt( } promptSections.push(markdownFormattingSection()) - let toolsXML = '' - if (useBuiltInToolsEnabled) { - toolsXML = await presenter.builtInToolsPresenter.convertBuiltInToolsToXml( - useBuiltInToolsEnabled, - agent - ) - } + const builtInTool = await presenter.builtInToolsPresenter.getBuiltInToolDefinitions(agent) + const builtInToolXML = presenter.builtInToolsPresenter.convertToolsToXml(builtInTool) let mcpToolsXML = '' if (enabledMcpTools && enabledMcpTools.length > 0) { mcpToolsXML = presenter.builtInToolsPresenter.convertToolsToXml(enabledMcpTools) } - - promptSections.push(`${getSharedToolUseSection(toolsXML, mcpToolsXML)}`) + promptSections.push(`${getSharedToolUseSection(builtInToolXML, mcpToolsXML)}`) promptSections.push(getSystemInfoSection(), getObjectiveSection()) @@ -74,7 +67,6 @@ export const SYSTEM_PROMPT = async ( globalCustomInstructions?: string, language?: string, IgnoreInstructions?: string, - useBuiltInToolsEnabled?: boolean, agent?: Agent, enabledMcpTools?: MCPToolDefinition[] ): Promise => { @@ -83,7 +75,6 @@ export const SYSTEM_PROMPT = async ( globalCustomInstructions, language, IgnoreInstructions, - useBuiltInToolsEnabled, agent, enabledMcpTools ) diff --git a/src/main/presenter/threadPresenter/index.ts b/src/main/presenter/threadPresenter/index.ts index 3b7627b..4d141a2 100644 --- a/src/main/presenter/threadPresenter/index.ts +++ b/src/main/presenter/threadPresenter/index.ts @@ -1873,6 +1873,7 @@ export class ThreadPresenter implements IThreadPresenter { modelId: currentModelId, temperature: currentTemperature, maxTokens: currentMaxTokens, + enabledMcpTools: currentEnabledMcpTools, thinkingBudget: currentThinkingBudget, reasoningEffort: currentReasoningEffort, verbosity: currentVerbosity, @@ -1887,6 +1888,7 @@ export class ThreadPresenter implements IThreadPresenter { state.message.id, currentTemperature, // 使用最新的设置 currentMaxTokens, // 使用最新的设置 + currentEnabledMcpTools, currentThinkingBudget, currentReasoningEffort, currentVerbosity, @@ -1996,6 +1998,7 @@ export class ThreadPresenter implements IThreadPresenter { modelId, temperature, maxTokens, + enabledMcpTools, thinkingBudget, reasoningEffort, verbosity, @@ -2070,6 +2073,7 @@ export class ThreadPresenter implements IThreadPresenter { state.message.id, temperature, maxTokens, + enabledMcpTools, thinkingBudget, reasoningEffort, verbosity, @@ -4499,6 +4503,7 @@ export class ThreadPresenter implements IThreadPresenter { modelId, temperature, maxTokens, + enabledMcpTools, thinkingBudget, reasoningEffort, verbosity, @@ -4559,6 +4564,7 @@ export class ThreadPresenter implements IThreadPresenter { messageId, temperature, maxTokens, + enabledMcpTools, thinkingBudget, reasoningEffort, verbosity, diff --git a/src/shared/types/presenters/legacy.presenters.d.ts b/src/shared/types/presenters/legacy.presenters.d.ts index 8f62a0e..cf282d0 100644 --- a/src/shared/types/presenters/legacy.presenters.d.ts +++ b/src/shared/types/presenters/legacy.presenters.d.ts @@ -648,6 +648,7 @@ export interface ILlmProviderPresenter { eventId: string, temperature?: number, maxTokens?: number, + enabledMcpTools?: string[], thinkingBudget?: number, reasoningEffort?: 'minimal' | 'low' | 'medium' | 'high', verbosity?: 'low' | 'medium' | 'high', @@ -1246,9 +1247,8 @@ export interface ProgressResponse { // export interface IBuiltInToolsPresenter { - convertBuiltInToolsToXml(useBuiltInToolsEnabled: boolean, currentAgent?: Agent): Promise convertToolsToXml(tools: MCPToolDefinition[]): string - getBuiltInToolDefinitions(enabled?: boolean, currentAgent?: Agent | null): any + getBuiltInToolDefinitions(currentAgent?: Agent | null): any /** * 获取所有内置工具的定义 diff --git a/src/shared/types/presenters/llmprovider.presenter.d.ts b/src/shared/types/presenters/llmprovider.presenter.d.ts index 05c4c0e..51c8389 100644 --- a/src/shared/types/presenters/llmprovider.presenter.d.ts +++ b/src/shared/types/presenters/llmprovider.presenter.d.ts @@ -151,6 +151,7 @@ export interface ILlmProviderPresenter { eventId: string, temperature?: number, maxTokens?: number, + enabledMcpTools?: string[], thinkingBudget?: number, reasoningEffort?: 'minimal' | 'low' | 'medium' | 'high', verbosity?: 'low' | 'medium' | 'high', -- Gitee