@@ -3,13 +3,26 @@ import type { PluginInfo, PluginTool } from '@opentiny/tiny-robot'
33import { getMetaApi , META_SERVICE } from '@opentiny/tiny-engine-meta-register'
44import type { McpTool } from '../../types/mcp.types'
55import type { RequestTool } from '../../types/chat.types'
6+ import { getRobotServiceOptions } from '../../utils'
7+ import { MCPHost } from '../../services/MCPHost'
8+
9+ const mcpHost = new MCPHost ( )
10+
11+ const defaultMcpIcon =
12+ 'https://res.hc-cdn.com/lowcode-portal/1.1.80.20250515160330/assets/opentiny-tinyengine-logo-4f8a3801.svg'
13+
14+ enum PluginAddState {
15+ Added = 'added' ,
16+ Idle = 'idle' ,
17+ Loading = 'loading'
18+ }
619
720const ENGINE_MCP_SERVER : PluginInfo = {
821 id : 'tiny-engine-mcp-server' ,
922 name : 'Tiny Engine MCP 工具' ,
10- icon : 'https://res.hc-cdn.com/lowcode-portal/1.1.80.20250515160330/assets/opentiny-tinyengine-logo-4f8a3801.svg' ,
23+ icon : defaultMcpIcon ,
1124 description : '使用TinyEngine设计器能力,如操作画布、编辑页面等' ,
12- added : true
25+ addState : PluginAddState . Added
1326}
1427
1528const inUseMcpServers = ref < PluginInfo [ ] > ( [ { ...ENGINE_MCP_SERVER , enabled : true , expanded : true , tools : [ ] } ] )
@@ -18,6 +31,9 @@ const updateServerTools = (serverId: string, tools: PluginTool[]) => {
1831 const mcpServer = inUseMcpServers . value . find ( ( item ) => item . id === serverId )
1932 if ( mcpServer ) {
2033 mcpServer . tools = tools
34+ if ( ! mcpHost . getClient ( serverId ) && serverId === ENGINE_MCP_SERVER . id ) {
35+ mcpHost . setClient ( serverId , getMetaApi ( META_SERVICE . McpService ) ?. getMcpClient ( ) )
36+ }
2137 }
2238}
2339
@@ -31,13 +47,14 @@ const updateEngineTools = async () => {
3147 enabled : tool . status === 'enabled'
3248 } ) )
3349 updateServerTools ( ENGINE_MCP_SERVER . id , engineTools )
50+ return engineTools
3451}
3552
3653const convertMCPToOpenAITools = ( mcpTools : McpTool [ ] ) : RequestTool [ ] => {
3754 return mcpTools . map ( ( tool : McpTool ) => ( {
3855 type : 'function' ,
3956 function : {
40- name : tool . name ,
57+ name : tool . id || tool . name ,
4158 description : tool . description || '' ,
4259 parameters : {
4360 type : 'object' ,
@@ -50,12 +67,6 @@ const convertMCPToOpenAITools = (mcpTools: McpTool[]): RequestTool[] => {
5067 } ) ) as RequestTool [ ]
5168}
5269
53- const getEngineServer = ( ) => {
54- return inUseMcpServers . value . find ( ( item ) => item . id === ENGINE_MCP_SERVER . id )
55- }
56-
57- const isToolsEnabled = computed ( ( ) => getEngineServer ( ) ?. tools ?. some ( ( tool ) => tool . enabled ) )
58-
5970const updateEngineServerToolStatus = ( toolId : string , enabled : boolean ) => {
6071 getMetaApi ( META_SERVICE . McpService ) ?. updateTool ?.( toolId , { enabled } )
6172}
@@ -67,15 +78,38 @@ const updateEngineServer = (engineServer: PluginInfo, enabled: boolean) => {
6778 } )
6879}
6980
81+ const updateMcpServerToggle = async ( server : PluginInfo , enabled : boolean ) => {
82+ if ( server . id === ENGINE_MCP_SERVER . id ) {
83+ server . enabled = enabled
84+ return
85+ }
86+ const inuseServer = inUseMcpServers . value . find ( ( s ) => s . id === server . id )
87+ if ( ! inuseServer ) {
88+ return
89+ }
90+ try {
91+ if ( enabled ) {
92+ const { tools } = await connectMcpServer ( inuseServer ) // eslint-disable-line
93+ inuseServer . tools = tools . map ( ( tool ) => ( { ...tool , enabled : true } ) )
94+ } else {
95+ await disconnectMcpServer ( inuseServer . id ) // eslint-disable-line
96+ inuseServer . tools = [ ]
97+ }
98+ inuseServer . enabled = enabled
99+ } catch ( error ) {
100+ inuseServer . enabled = false
101+ }
102+ }
103+
70104const updateMcpServerStatus = async ( server : PluginInfo , added : boolean ) => {
71105 // 市场添加状态修改
72- server . added = added
106+ server . addState = added ? PluginAddState . Added : PluginAddState . Idle
73107 if ( added ) {
74108 const newServer : PluginInfo = {
75109 ...server ,
76110 id : server . id || `mcp-server-${ Date . now ( ) } ` ,
77111 enabled : true ,
78- added : true ,
112+ addState : PluginAddState . Added ,
79113 expanded : false ,
80114 tools : server . tools || [ ]
81115 }
@@ -103,33 +137,109 @@ const updateMcpServerToolStatus = (currentServer: PluginInfo, toolId: string, en
103137 }
104138}
105139
140+ const updateCustomMcpServers = async ( ) => {
141+ const mcpServersConfig = getRobotServiceOptions ( ) . mcpConfig ?. mcpServers || { }
142+ if ( ! Object . keys ( mcpServersConfig ) . length ) return
143+ const customMcpServers = Object . entries ( mcpServersConfig ) . map ( ( [ id , config ] ) => ( { id, ...config } ) )
144+ const logger = console
145+
146+ customMcpServers . forEach ( ( server ) => {
147+ if ( ! [ 'streamablehttp' , 'sse' ] . includes ( server . type ?. toLowerCase ( ) ) || ! server . url ) {
148+ logger . error ( `解析mcpServer: ${ server . id } 配置失败,type/url字段缺失或有误.` )
149+ return
150+ }
151+
152+ if ( inUseMcpServers . value . find ( ( s ) => s . id === server . id ) ) {
153+ return
154+ }
155+ const newServer : PluginInfo = {
156+ id : server . id ,
157+ name : server . name || server . id ,
158+ icon : server . icon || defaultMcpIcon ,
159+ description : server . description || '' ,
160+ enabled : false ,
161+ addState : PluginAddState . Added ,
162+ expanded : false ,
163+ type : server . type ,
164+ url : server . url ,
165+ tools : [ ]
166+ }
167+ inUseMcpServers . value . push ( newServer )
168+ } )
169+ }
170+
171+ const connectMcpServer = ( server : PluginInfo ) => {
172+ return mcpHost . connectToServer ( {
173+ id : server . id ,
174+ url : server . url ,
175+ type : server . type
176+ } )
177+ }
178+
179+ const disconnectMcpServer = ( serverId : string ) => {
180+ return mcpHost . disconnect ( serverId )
181+ }
182+
106183const refreshMcpServerTools = ( ) => {
107184 updateEngineTools ( )
185+ updateCustomMcpServers ( )
108186}
109187
110- let llmTools : RequestTool [ ] | null = null
111-
112- const listTools = async ( ) : Promise < McpTool [ ] > => {
113- const mcpTools = await getMetaApi ( META_SERVICE . McpService ) ?. getMcpClient ( ) ?. listTools ( )
114- return mcpTools ?. tools || [ ]
188+ const toolsMap = computed ( ( ) => {
189+ return inUseMcpServers . value
190+ . filter ( ( server ) => server . enabled )
191+ . reduce ( ( acc , server ) => {
192+ server . tools
193+ . filter ( ( tool ) => tool . enabled )
194+ . forEach ( ( tool ) => {
195+ acc [ tool . id || tool . name ] = {
196+ server : server . id ,
197+ ...tool
198+ }
199+ } )
200+ return acc
201+ } , { } )
202+ } )
203+
204+ const callTool = async ( toolId : string , args : Record < string , unknown > ) => {
205+ return mcpHost . getClient ( toolsMap . value [ toolId ] ?. server ) ?. callTool ( { name : toolId , arguments : args || { } } ) || { }
115206}
116207
117- const callTool = async ( toolId : string , args : Record < string , unknown > ) =>
118- getMetaApi ( META_SERVICE . McpService ) ?. getMcpClient ( ) ?. callTool ( { name : toolId , arguments : args } ) || { }
208+ const tools = computed ( ( ) => {
209+ return convertMCPToOpenAITools (
210+ inUseMcpServers . value
211+ . filter ( ( server ) => server . enabled )
212+ . map ( ( server ) => server . tools . filter ( ( tool ) => tool . enabled ) )
213+ . flat ( )
214+ )
215+ } )
119216
120217const getLLMTools = async ( ) => {
121- const mcpTools = await getMetaApi ( META_SERVICE . McpService ) ?. getMcpClient ( ) ?. listTools ( )
122- llmTools = convertMCPToOpenAITools ( mcpTools ?. tools || [ ] )
123- return llmTools
218+ const servers = inUseMcpServers . value . filter ( ( server ) => server . enabled && server . tools . length > 0 )
219+ const tools = await Promise . all (
220+ servers . map ( async ( server ) => {
221+ const enabledTools = server . tools ?. filter ( ( tool ) => tool . enabled ) . map ( ( tool ) => tool . id || tool . name ) || [ ]
222+ const client = mcpHost . getClient ( server . id )
223+ if ( client ) {
224+ const listToolResult : { tools : McpTool [ ] } = await client . listTools ( )
225+ return listToolResult . tools . filter ( ( tool ) => enabledTools . includes ( tool . name ) )
226+ }
227+ return [ ]
228+ } )
229+ )
230+
231+ return convertMCPToOpenAITools ( tools . flat ( ) )
124232}
125233
234+ const isToolsEnabled = computed ( ( ) => tools . value . length > 0 )
235+
126236export default function useMcpServer ( ) {
127237 return {
128238 inUseMcpServers,
129239 refreshMcpServerTools,
130240 updateMcpServerStatus,
131241 updateMcpServerToolStatus,
132- listTools ,
242+ updateMcpServerToggle ,
133243 callTool,
134244 getLLMTools,
135245 isToolsEnabled
0 commit comments