@@ -50,6 +50,52 @@ const mcp = new McpServer({
5050 version : "1.0.0" ,
5151} ) ;
5252
53+ /**
54+ * Sanitizes an identifier to be a valid TypeScript identifier.
55+ */
56+ function sanitizeIdentifier ( name : string ) : string {
57+ return name
58+ . replace ( / [ ^ a - z A - Z 0 - 9 _ ] / g, '_' )
59+ . replace ( / ^ [ 0 - 9 ] / , '_$&' ) ;
60+ }
61+
62+ /**
63+ * Converts a UTCP tool name to its TypeScript interface name.
64+ */
65+ function utcpNameToTsInterfaceName ( utcpName : string ) : string {
66+ if ( utcpName . includes ( '.' ) ) {
67+ const parts = utcpName . split ( '.' ) ;
68+ const manualName = parts [ 0 ] ! ;
69+ const toolParts = parts . slice ( 1 ) ;
70+ const sanitizedManualName = sanitizeIdentifier ( manualName ) ;
71+ const toolName = toolParts . map ( part => sanitizeIdentifier ( part ) ) . join ( '_' ) ;
72+ return `${ sanitizedManualName } .${ toolName } ` ;
73+ } else {
74+ return sanitizeIdentifier ( utcpName ) ;
75+ }
76+ }
77+
78+ /**
79+ * Finds a tool by either UTCP name or TypeScript interface name.
80+ */
81+ async function findToolByName ( client : CodeModeUtcpClient , name : string ) : Promise < { tool : any , utcpName : string } | null > {
82+ // First, try direct lookup by UTCP name
83+ const directTool = await client . config . tool_repository . getTool ( name ) ;
84+ if ( directTool ) {
85+ return { tool : directTool , utcpName : name } ;
86+ }
87+
88+ // If not found, search through all tools to find one whose TS interface name matches
89+ const allTools = await client . config . tool_repository . getTools ( ) ;
90+ for ( const tool of allTools ) {
91+ if ( utcpNameToTsInterfaceName ( tool . name ) === name ) {
92+ return { tool, utcpName : tool . name } ;
93+ }
94+ }
95+
96+ return null ;
97+ }
98+
5399function setupMcpTools ( ) {
54100 // Register MCP prompt for using the code mode server
55101 mcp . registerPrompt ( "utcp_codemode_usage" , {
@@ -126,7 +172,7 @@ Remember: The power of this system comes from combining multiple tools in sophis
126172 try {
127173 const tools = await client . searchTools ( input . task_description , input . limit ) ;
128174 const toolsWithInterfaces = tools . map ( t => ( {
129- name : t . name ,
175+ name : utcpNameToTsInterfaceName ( t . name ) ,
130176 description : t . description ,
131177 typescript_interface : client . toolToTypeScriptInterface ( t )
132178 } ) ) ;
@@ -144,7 +190,7 @@ Remember: The power of this system comes from combining multiple tools in sophis
144190 const client = await initializeUtcpClient ( ) ;
145191 try {
146192 const tools = await client . config . tool_repository . getTools ( ) ;
147- const toolNames = tools . map ( t => t . name ) ;
193+ const toolNames = tools . map ( t => utcpNameToTsInterfaceName ( t . name ) ) ;
148194 return { content : [ { type : "text" , text : JSON . stringify ( { tools : toolNames } ) } ] } ;
149195 } catch ( e : any ) {
150196 return { content : [ { type : "text" , text : JSON . stringify ( { success : false , error : e . message } ) } ] } ;
@@ -160,7 +206,11 @@ Remember: The power of this system comes from combining multiple tools in sophis
160206 } , async ( input ) => {
161207 const client = await initializeUtcpClient ( ) ;
162208 try {
163- const variables = await client . getRequiredVariablesForRegisteredTool ( input . tool_name ) ;
209+ const found = await findToolByName ( client , input . tool_name ) ;
210+ if ( ! found ) {
211+ return { content : [ { type : "text" , text : JSON . stringify ( { success : false , tool_name : input . tool_name , error : `Tool '${ input . tool_name } ' not found` } ) } ] } ;
212+ }
213+ const variables = await client . getRequiredVariablesForRegisteredTool ( found . utcpName ) ;
164214 return { content : [ { type : "text" , text : JSON . stringify ( { success : true , tool_name : input . tool_name , required_variables : variables } ) } ] } ;
165215 } catch ( e : any ) {
166216 return { content : [ { type : "text" , text : JSON . stringify ( { success : false , tool_name : input . tool_name , error : e . message } ) } ] } ;
@@ -176,11 +226,11 @@ Remember: The power of this system comes from combining multiple tools in sophis
176226 } , async ( input ) => {
177227 const client = await initializeUtcpClient ( ) ;
178228 try {
179- const tool = await client . config . tool_repository . getTool ( input . tool_name ) ;
180- if ( ! tool ) {
229+ const found = await findToolByName ( client , input . tool_name ) ;
230+ if ( ! found ) {
181231 return { content : [ { type : "text" , text : JSON . stringify ( { success : false , error : `Tool '${ input . tool_name } ' not found` } ) } ] } ;
182232 }
183- const typescript_interface = client . toolToTypeScriptInterface ( tool ) ;
233+ const typescript_interface = client . toolToTypeScriptInterface ( found . tool ) ;
184234 return { content : [ { type : "text" , text : typescript_interface } ] } ;
185235 } catch ( e : any ) {
186236 return { content : [ { type : "text" , text : JSON . stringify ( { success : false , error : e . message } ) } ] } ;
0 commit comments