Skip to content

Commit 0d6bc70

Browse files
committed
2 parents f54bc98 + 822e661 commit 0d6bc70

File tree

1 file changed

+56
-6
lines changed

1 file changed

+56
-6
lines changed

code-mode-mcp/index.ts

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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-zA-Z0-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+
5399
function 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

Comments
 (0)