Skip to content

Commit 7aac617

Browse files
JooHyung Parkcursoragent
andcommitted
[ai-assisted] feat(analytics): track MCP tool execution duration instead of result type
Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent d96d011 commit 7aac617

3 files changed

Lines changed: 16 additions & 39 deletions

File tree

ANALYTICS_EVENTS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ Triggered when an MCP tool is invoked.
6262
|----------|------|-------------|
6363
| tool_name | string | Name of the tool (e.g., `create_rectangle`) |
6464
| success | boolean | Whether the tool call succeeded |
65-
| result_type | string | (optional) Type of result returned |
65+
| duration_ms | number | (optional) Time in ms from request received to response returned |
6666
| error_message | string | (optional) Error description if failed |
6767

6868
---

src/main/analytics/analytics-service.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ export function trackMCPToolCall(
100100
toolName: string,
101101
success: boolean,
102102
errorMessage?: string,
103-
resultType?: string
103+
durationMs?: number
104104
): void {
105105
const params: Record<string, string | number | boolean> = {
106106
tool_name: toolName,
@@ -111,8 +111,8 @@ export function trackMCPToolCall(
111111
params.error_message = errorMessage;
112112
}
113113

114-
if (resultType) {
115-
params.result_type = resultType;
114+
if (durationMs !== undefined) {
115+
params.duration_ms = durationMs;
116116
}
117117

118118
trackEvent(AnalyticsEvents.MCP_TOOL_CALL, params);

src/main/server/TalkToFigmaWebSocketServer.ts

Lines changed: 12 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -408,13 +408,12 @@ export class TalkToFigmaWebSocketServer {
408408

409409
this.addLog('DEBUG', `Broadcasting message to channel: ${channelName}`);
410410

411-
// Check if this is a response message (has id in message)
411+
// Check if this is a response message (has result or error, but no command)
412412
// If so, preserve the original structure for MCP server compatibility
413-
const isResponseMessage = messageContent && (
414-
messageContent.id !== undefined ||
415-
messageContent.result !== undefined ||
416-
messageContent.error !== undefined
417-
);
413+
// Note: requests also have messageContent.id, so we must exclude messages with command
414+
const isResponseMessage = messageContent &&
415+
!messageContent.command &&
416+
(messageContent.result !== undefined || messageContent.error !== undefined);
418417

419418
if (isResponseMessage) {
420419
// Track MCP tool call result based on response content
@@ -423,12 +422,12 @@ export class TalkToFigmaWebSocketServer {
423422
const pendingRequest = this.pendingRequests.get(responseId);
424423
if (pendingRequest) {
425424
const hasError = messageContent.error !== undefined;
426-
const resultType = this.getResultType(messageContent.result);
425+
const durationMs = Date.now() - pendingRequest.timestamp;
427426
trackMCPToolCall(
428427
pendingRequest.command,
429428
!hasError,
430429
hasError ? String(messageContent.error) : undefined,
431-
hasError ? undefined : resultType
430+
durationMs
432431
);
433432
this.pendingRequests.delete(responseId);
434433
}
@@ -465,7 +464,7 @@ export class TalkToFigmaWebSocketServer {
465464
: `Active channels (${channels.size}): ${channelList}`;
466465

467466
// Track successful command
468-
trackMCPToolCall('get_active_channels', true, undefined, 'string');
467+
trackMCPToolCall('get_active_channels', true);
469468

470469
this.sendToClient(ws, {
471470
type: 'message',
@@ -518,7 +517,7 @@ export class TalkToFigmaWebSocketServer {
518517
};
519518

520519
// Track successful command
521-
trackMCPToolCall('connection_diagnostics', true, undefined, 'object');
520+
trackMCPToolCall('connection_diagnostics', true);
522521

523522
this.sendToClient(ws, {
524523
type: 'message',
@@ -708,6 +707,7 @@ export class TalkToFigmaWebSocketServer {
708707
return;
709708
}
710709

710+
const startTime = Date.now();
711711
try {
712712
this.addLog('INFO', `Handling REST API tool locally: ${command}`);
713713
const result = await tool.handler(params || {});
@@ -725,7 +725,7 @@ export class TalkToFigmaWebSocketServer {
725725
}
726726

727727
// Track successful REST API tool call
728-
trackMCPToolCall(command, true, undefined, this.getResultType(responseData));
728+
trackMCPToolCall(command, true, undefined, Date.now() - startTime);
729729

730730
this.sendToClient(ws, {
731731
type: 'message',
@@ -740,7 +740,7 @@ export class TalkToFigmaWebSocketServer {
740740
this.addLog('ERROR', `REST API tool ${command} failed: ${errorMessage}`);
741741

742742
// Track failed REST API tool call
743-
trackMCPToolCall(command, false, errorMessage);
743+
trackMCPToolCall(command, false, errorMessage, Date.now() - startTime);
744744

745745
this.sendToClient(ws, {
746746
type: 'message',
@@ -765,28 +765,5 @@ export class TalkToFigmaWebSocketServer {
765765
}
766766
}
767767

768-
/**
769-
* Get the result type for analytics tracking
770-
*/
771-
private getResultType(result: unknown): string {
772-
if (result === null || result === undefined) {
773-
return 'null';
774-
}
775-
if (Array.isArray(result)) {
776-
return 'array';
777-
}
778-
if (typeof result === 'object') {
779-
// Check for common Figma node types
780-
const obj = result as Record<string, unknown>;
781-
if (obj.type && typeof obj.type === 'string') {
782-
return obj.type;
783-
}
784-
if (obj.id && typeof obj.id === 'string') {
785-
return 'node';
786-
}
787-
return 'object';
788-
}
789-
return typeof result;
790-
}
791768
}
792769

0 commit comments

Comments
 (0)