@@ -17,7 +17,7 @@ import {
17
17
SerializedContinueConfig ,
18
18
Tool ,
19
19
} from "../../" ;
20
- import { constructMcpSlashCommand } from "../../commands/slash/mcp" ;
20
+ import { mcpPromptToSlashCommand } from "../../commands/slash/mcp" ;
21
21
import { MCPManagerSingleton } from "../../context/mcp/MCPManagerSingleton" ;
22
22
import MCPContextProvider from "../../context/providers/MCPContextProvider" ;
23
23
import { ControlPlaneProxyInfo } from "../../control-plane/analytics/IAnalyticsProvider.js" ;
@@ -26,8 +26,7 @@ import { getControlPlaneEnv } from "../../control-plane/env.js";
26
26
import { TeamAnalytics } from "../../control-plane/TeamAnalytics.js" ;
27
27
import ContinueProxy from "../../llm/llms/stubs/ContinueProxy" ;
28
28
import { getConfigDependentToolDefinitions } from "../../tools" ;
29
- import { encodeMCPToolUri } from "../../tools/callTool" ;
30
- import { getMCPToolName } from "../../tools/mcpToolName" ;
29
+ import { mcpToolToTool } from "../../tools/mcpTools" ;
31
30
import { getConfigJsonPath , getConfigYamlPath } from "../../util/paths" ;
32
31
import { localPathOrUriToPath } from "../../util/pathToUri" ;
33
32
import { Telemetry } from "../../util/posthog" ;
@@ -140,6 +139,13 @@ export default async function doLoadConfig(options: {
140
139
// Rectify model selections for each role
141
140
newConfig = rectifySelectedModelsFromGlobalContext ( newConfig , profileId ) ;
142
141
142
+ // Add tools that depend on rules etc.
143
+ newConfig . tools . push (
144
+ ...getConfigDependentToolDefinitions ( {
145
+ rules : newConfig . rules ,
146
+ } ) ,
147
+ ) ;
148
+
143
149
// Add things from MCP servers
144
150
const mcpManager = MCPManagerSingleton . getInstance ( ) ;
145
151
const mcpServerStatuses = mcpManager . getStatuses ( ) ;
@@ -151,31 +157,22 @@ export default async function doLoadConfig(options: {
151
157
} ) ;
152
158
newConfig . mcpServerStatuses = serializableStatuses ;
153
159
160
+ // Keep track of tool names to avoid duplicates
161
+ const toolNames = new Set < string > ( ) ;
162
+
163
+ newConfig . tools . forEach ( ( tool ) => {
164
+ toolNames . add ( tool . function . name ) ;
165
+ } ) ;
166
+
154
167
for ( const server of mcpServerStatuses ) {
155
168
if ( server . status === "connected" ) {
156
- const serverTools : Tool [ ] = server . tools . map ( ( tool ) => ( {
157
- displayTitle : server . name + " " + tool . name ,
158
- function : {
159
- description : tool . description ,
160
- name : getMCPToolName ( server , tool ) ,
161
- parameters : tool . inputSchema ,
162
- } ,
163
- faviconUrl : server . faviconUrl ,
164
- readonly : false ,
165
- type : "function" as const ,
166
- uri : encodeMCPToolUri ( server . id , tool . name ) ,
167
- group : server . name ,
168
- originalFunctionName : tool . name ,
169
- } ) ) ;
169
+ const serverTools : Tool [ ] = server . tools . map ( ( tool ) =>
170
+ mcpToolToTool ( server , tool ) ,
171
+ ) ;
170
172
newConfig . tools . push ( ...serverTools ) ;
171
173
172
174
const serverSlashCommands = server . prompts . map ( ( prompt ) =>
173
- constructMcpSlashCommand (
174
- server . client ,
175
- prompt . name ,
176
- prompt . description ,
177
- prompt . arguments ?. map ( ( a : any ) => a . name ) ,
178
- ) ,
175
+ mcpPromptToSlashCommand ( server . client , prompt ) ,
179
176
) ;
180
177
newConfig . slashCommands . push ( ...serverSlashCommands ) ;
181
178
@@ -205,45 +202,28 @@ export default async function doLoadConfig(options: {
205
202
}
206
203
}
207
204
208
- newConfig . tools . push (
209
- ...getConfigDependentToolDefinitions ( {
210
- rules : newConfig . rules ,
211
- } ) ,
212
- ) ;
213
-
214
- // Detect duplicate tool names
215
- const counts : Record < string , number > = { } ;
216
- newConfig . tools . forEach ( ( tool ) => {
217
- if ( counts [ tool . function . name ] ) {
218
- counts [ tool . function . name ] = counts [ tool . function . name ] + 1 ;
219
- } else {
220
- counts [ tool . function . name ] = 1 ;
221
- }
222
- } ) ;
223
-
224
- Object . entries ( counts ) . forEach ( ( [ toolName , count ] ) => {
225
- if ( count > 1 ) {
226
- errors ! . push ( {
227
- fatal : false ,
228
- message : `Duplicate (${ count } ) tools named "${ toolName } " detected. Permissions will conflict and usage may be unpredictable` ,
229
- } ) ;
230
- }
231
- } ) ;
232
-
233
- const ruleCounts : Record < string , number > = { } ;
205
+ // Warn user about duplicate tool names
206
+ // Could change this behavior in a few ways, e.g. to prepend server name to all tool names from that server if ANY are duplicate
207
+ // Object.entries(toolNameCounts).forEach(([toolName, count]) => {
208
+ // if (count > 1) {
209
+ // errors!.push({
210
+ // fatal: false,
211
+ // message: `Duplicate (${count}) tools named "${toolName}" detected. Permissions will conflict and usage may be unpredictable`,
212
+ // });
213
+ // }
214
+ // });
215
+
216
+ // Warn about duplicate rules
217
+ const ruleCounts = new Map < string , number > ( ) ;
234
218
newConfig . rules . forEach ( ( rule ) => {
235
219
if ( rule . name ) {
236
- if ( ruleCounts [ rule . name ] ) {
237
- ruleCounts [ rule . name ] = ruleCounts [ rule . name ] + 1 ;
238
- } else {
239
- ruleCounts [ rule . name ] = 1 ;
240
- }
220
+ ruleCounts . set ( rule . name , ( ruleCounts . get ( rule . name ) || 0 ) + 1 ) ;
241
221
}
242
222
} ) ;
243
223
244
- Object . entries ( ruleCounts ) . forEach ( ( [ ruleName , count ] ) => {
224
+ ruleCounts . forEach ( ( count , ruleName ) => {
245
225
if ( count > 1 ) {
246
- errors ! . push ( {
226
+ errors . push ( {
247
227
fatal : false ,
248
228
message : `Duplicate (${ count } ) rules named "${ ruleName } " detected. This may cause unexpected behavior` ,
249
229
} ) ;
0 commit comments