Skip to content

Commit f1674e6

Browse files
authored
Merge pull request #192 from rajbos/copilot/rebase-changes-from-pr-187
Fix MCP tool detection from toolNames.json
2 parents 89e8dca + 12c0f38 commit f1674e6

File tree

1 file changed

+84
-15
lines changed

1 file changed

+84
-15
lines changed

src/extension.ts

Lines changed: 84 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1653,12 +1653,23 @@ class CopilotTokenTracker implements vscode.Disposable {
16531653

16541654
// Detect tool calls from Copilot CLI
16551655
if (event.type === 'tool.call' || event.type === 'tool.result') {
1656-
analysis.toolCalls.total++;
16571656
const toolName = event.data?.toolName || event.toolName || 'unknown';
1658-
analysis.toolCalls.byTool[toolName] = (analysis.toolCalls.byTool[toolName] || 0) + 1;
1657+
1658+
// Check if this is an MCP tool by name pattern
1659+
if (this.isMcpTool(toolName)) {
1660+
// Count as MCP tool
1661+
analysis.mcpTools.total++;
1662+
const serverName = this.extractMcpServerName(toolName);
1663+
analysis.mcpTools.byServer[serverName] = (analysis.mcpTools.byServer[serverName] || 0) + 1;
1664+
analysis.mcpTools.byTool[toolName] = (analysis.mcpTools.byTool[toolName] || 0) + 1;
1665+
} else {
1666+
// Count as regular tool call
1667+
analysis.toolCalls.total++;
1668+
analysis.toolCalls.byTool[toolName] = (analysis.toolCalls.byTool[toolName] || 0) + 1;
1669+
}
16591670
}
16601671

1661-
// Detect MCP tools
1672+
// Detect MCP tools from explicit MCP events
16621673
if (event.type === 'mcp.tool.call' || (event.data?.mcpServer)) {
16631674
analysis.mcpTools.total++;
16641675
const serverName = event.data?.mcpServer || 'unknown';
@@ -1726,12 +1737,23 @@ class CopilotTokenTracker implements vscode.Disposable {
17261737
// Detect tool invocations
17271738
if (responseItem.kind === 'toolInvocationSerialized' ||
17281739
responseItem.kind === 'prepareToolInvocation') {
1729-
analysis.toolCalls.total++;
17301740
const toolName = responseItem.toolId ||
17311741
responseItem.toolName ||
17321742
responseItem.invocationMessage?.toolName ||
17331743
'unknown';
1734-
analysis.toolCalls.byTool[toolName] = (analysis.toolCalls.byTool[toolName] || 0) + 1;
1744+
1745+
// Check if this is an MCP tool by name pattern
1746+
if (this.isMcpTool(toolName)) {
1747+
// Count as MCP tool
1748+
analysis.mcpTools.total++;
1749+
const serverName = this.extractMcpServerName(toolName);
1750+
analysis.mcpTools.byServer[serverName] = (analysis.mcpTools.byServer[serverName] || 0) + 1;
1751+
analysis.mcpTools.byTool[toolName] = (analysis.mcpTools.byTool[toolName] || 0) + 1;
1752+
} else {
1753+
// Count as regular tool call
1754+
analysis.toolCalls.total++;
1755+
analysis.toolCalls.byTool[toolName] = (analysis.toolCalls.byTool[toolName] || 0) + 1;
1756+
}
17351757
}
17361758

17371759
// Detect MCP servers starting
@@ -1826,6 +1848,29 @@ class CopilotTokenTracker implements vscode.Disposable {
18261848
}
18271849
}
18281850

1851+
/**
1852+
* Check if a tool name indicates it's an MCP (Model Context Protocol) tool.
1853+
* MCP tools are identified by names starting with "mcp." or "mcp_"
1854+
*/
1855+
private isMcpTool(toolName: string): boolean {
1856+
return toolName.startsWith('mcp.') || toolName.startsWith('mcp_');
1857+
}
1858+
1859+
/**
1860+
* Extract server name from an MCP tool name.
1861+
* MCP tool names follow the format: mcp.server.tool or mcp_server_tool
1862+
* For example: "mcp.io.github.git" → "io", "mcp_io_github_git" → "io"
1863+
* Note: Splits on both '.' and '_' to handle various naming conventions
1864+
*/
1865+
private extractMcpServerName(toolName: string): string {
1866+
// Remove the mcp. or mcp_ prefix
1867+
const withoutPrefix = toolName.replace(/^mcp[._]/, '');
1868+
// Split on . or _ and take the first part (server identifier)
1869+
const parts = withoutPrefix.split(/[._]/);
1870+
// Return the first non-empty part, or 'unknown' if none exist
1871+
return parts[0] || 'unknown';
1872+
}
1873+
18291874
/**
18301875
* Analyze a request object for all context references.
18311876
* This is the unified method that processes text, contentReferences, and variableData.
@@ -2862,11 +2907,27 @@ class CopilotTokenTracker implements vscode.Disposable {
28622907
if ((event.type === 'tool.call' || event.type === 'tool.result') && turns.length > 0) {
28632908
const lastTurn = turns[turns.length - 1];
28642909
const toolName = event.data?.toolName || event.toolName || 'unknown';
2865-
lastTurn.toolCalls.push({
2866-
toolName,
2867-
arguments: event.type === 'tool.call' ? JSON.stringify(event.data?.arguments || {}) : undefined,
2868-
result: event.type === 'tool.result' ? event.data?.output : undefined
2869-
});
2910+
2911+
// Check if this is an MCP tool by name pattern
2912+
if (this.isMcpTool(toolName)) {
2913+
const serverName = this.extractMcpServerName(toolName);
2914+
lastTurn.mcpTools.push({ server: serverName, tool: toolName });
2915+
} else {
2916+
// Add to regular tool calls
2917+
lastTurn.toolCalls.push({
2918+
toolName,
2919+
arguments: event.type === 'tool.call' ? JSON.stringify(event.data?.arguments || {}) : undefined,
2920+
result: event.type === 'tool.result' ? event.data?.output : undefined
2921+
});
2922+
}
2923+
}
2924+
2925+
// Handle explicit MCP tool calls from CLI
2926+
if ((event.type === 'mcp.tool.call' || event.data?.mcpServer) && turns.length > 0) {
2927+
const lastTurn = turns[turns.length - 1];
2928+
const serverName = event.data?.mcpServer || 'unknown';
2929+
const toolName = event.data?.toolName || event.toolName || 'unknown';
2930+
lastTurn.mcpTools.push({ server: serverName, tool: toolName });
28702931
}
28712932
} catch {
28722933
// Skip malformed lines
@@ -3015,11 +3076,19 @@ class CopilotTokenTracker implements vscode.Disposable {
30153076
// Extract tool invocations
30163077
if (item.kind === 'toolInvocationSerialized' || item.kind === 'prepareToolInvocation') {
30173078
const toolName = item.toolId || item.toolName || item.invocationMessage?.toolName || item.toolSpecificData?.kind || 'unknown';
3018-
toolCalls.push({
3019-
toolName,
3020-
arguments: item.input ? JSON.stringify(item.input) : undefined,
3021-
result: item.result ? (typeof item.result === 'string' ? item.result : JSON.stringify(item.result)) : undefined
3022-
});
3079+
3080+
// Check if this is an MCP tool by name pattern
3081+
if (this.isMcpTool(toolName)) {
3082+
const serverName = this.extractMcpServerName(toolName);
3083+
mcpTools.push({ server: serverName, tool: toolName });
3084+
} else {
3085+
// Add to regular tool calls
3086+
toolCalls.push({
3087+
toolName,
3088+
arguments: item.input ? JSON.stringify(item.input) : undefined,
3089+
result: item.result ? (typeof item.result === 'string' ? item.result : JSON.stringify(item.result)) : undefined
3090+
});
3091+
}
30233092
}
30243093

30253094
// Extract MCP tools

0 commit comments

Comments
 (0)