Skip to content

Commit 333d071

Browse files
authored
fix: add telemetry for fetching MCP and add preview label to MCP temp… (#14623)
* fix: add telemetry for fetching MCP and add preview label to MCP template * fix: tests
1 parent bb82314 commit 333d071

File tree

6 files changed

+70
-37
lines changed

6 files changed

+70
-37
lines changed

packages/fx-core/src/question/scaffold/vsc/CapabilityOptions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -625,6 +625,7 @@ export class ActionStartOptions {
625625
id: "mcp",
626626
label: getLocalizedString("core.createProjectQuestion.mcpForDa.label"),
627627
detail: getLocalizedString("core.createProjectQuestion.mcpForDa.detail"),
628+
description: getLocalizedString("core.createProjectQuestion.option.description.preview"),
628629
data: TemplateNames.DeclarativeAgentWithActionFromMCP,
629630
};
630631
}

packages/vscode-extension/src/codeLensProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -990,7 +990,7 @@ export class WorkspaceMCPConfigCodeLensProvider implements vscode.CodeLensProvid
990990
const command: vscode.Command = {
991991
title: `⚡ ATK: Fetch action from MCP`,
992992
command: "fx-extension.updateActionWithMCP",
993-
arguments: [{ serverName, serverConfig }],
993+
arguments: [{ serverName, serverConfig }, TelemetryTriggerFrom.CodeLens],
994994
};
995995
codeLenses.push(new vscode.CodeLens(range, command));
996996
}

packages/vscode-extension/src/handlers/updateActionWithMCP.ts

Lines changed: 54 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
UserError,
1111
} from "@microsoft/teamsfx-api";
1212
import { getSystemInputs } from "../utils/systemEnvUtils";
13+
import { ExtTelemetry } from "../telemetry/extTelemetry";
14+
import { TelemetryEvent } from "../telemetry/extTelemetryEvents";
1315
import path from "path";
1416
import * as fs from "fs-extra";
1517
import { QuestionNames } from "@microsoft/teamsfx-core";
@@ -20,6 +22,7 @@ import { VS_CODE_UI } from "../qm/vsc_ui";
2022
import * as parser from "jsonc-parser";
2123
import { getDefaultString, localize } from "../utils/localizeUtils";
2224
import { ExtensionErrors } from "../error/error";
25+
import { getTriggerFromProperty } from "../utils/telemetryUtils";
2326

2427
function sanitizeMCPName(name: string): string {
2528
// Replace special characters except "-" with "_", but if two special characters are adjacent,
@@ -31,6 +34,10 @@ function sanitizeMCPName(name: string): string {
3134
}
3235

3336
export async function updateActionWithMCP(args?: any[]): Promise<Result<any, FxError>> {
37+
ExtTelemetry.sendTelemetryEvent(
38+
TelemetryEvent.UpdateActionWithMCPStart,
39+
getTriggerFromProperty(args && args.length > 1 ? [args[1]] : undefined)
40+
);
3441
const inputs = getSystemInputs();
3542
let mcpName = args && args.length > 0 ? args[0].serverName : undefined;
3643
let server = args && args.length > 0 ? args[0].serverConfig?.url : undefined;
@@ -44,42 +51,42 @@ export async function updateActionWithMCP(args?: any[]): Promise<Result<any, FxE
4451
const mcpFile = path.join(inputs.projectPath!, ".vscode", "mcp.json");
4552
if (!fs.pathExistsSync(mcpFile)) {
4653
void vscode.window.showErrorMessage(localize("teamstoolkit.MCP.FileNotFound"));
47-
return err(
48-
new UserError(
49-
"da-mcp",
50-
ExtensionErrors.MCPFileNotFound,
51-
getDefaultString("teamstoolkit.MCP.FileNotFound"),
52-
localize("teamstoolkit.MCP.FileNotFound")
53-
)
54+
const error = new UserError(
55+
"da-mcp",
56+
ExtensionErrors.MCPFileNotFound,
57+
getDefaultString("teamstoolkit.MCP.FileNotFound"),
58+
localize("teamstoolkit.MCP.FileNotFound")
5459
);
60+
ExtTelemetry.sendTelemetryErrorEvent(TelemetryEvent.UpdateActionWithMCP, error);
61+
return err(error);
5562
}
5663
// const mcpContent = await fs.readJSON(mcpFile);
5764
const mcpOriginalContent = fs.readFileSync(mcpFile, "utf-8");
5865
const mcpContent = parser.parse(mcpOriginalContent);
5966
if (!mcpContent || !mcpContent.servers) {
6067
void vscode.window.showErrorMessage(localize("teamstoolkit.MCP.ContentInvalid"));
61-
return err(
62-
new UserError(
63-
"da-mcp",
64-
ExtensionErrors.MCPContentInvalid,
65-
getDefaultString("teamstoolkit.MCP.ContentInvalid"),
66-
localize("teamstoolkit.MCP.ContentInvalid")
67-
)
68+
const error = new UserError(
69+
"da-mcp",
70+
ExtensionErrors.MCPContentInvalid,
71+
getDefaultString("teamstoolkit.MCP.ContentInvalid"),
72+
localize("teamstoolkit.MCP.ContentInvalid")
6873
);
74+
ExtTelemetry.sendTelemetryErrorEvent(TelemetryEvent.UpdateActionWithMCP, error);
75+
return err(error);
6976
}
7077

7178
// TODO: support multiple MCP servers
7279
const mcpNames = Object.keys(mcpContent.servers);
7380
if (mcpNames.length === 0) {
7481
void vscode.window.showErrorMessage(localize("teamstoolkit.MCP.ServerNotFound"));
75-
return err(
76-
new UserError(
77-
"da-mcp",
78-
ExtensionErrors.MCPServerNotFound,
79-
getDefaultString("teamstoolkit.MCP.ServerNotFound"),
80-
localize("teamstoolkit.MCP.ServerNotFound")
81-
)
82+
const error = new UserError(
83+
"da-mcp",
84+
ExtensionErrors.MCPServerNotFound,
85+
getDefaultString("teamstoolkit.MCP.ServerNotFound"),
86+
localize("teamstoolkit.MCP.ServerNotFound")
8287
);
88+
ExtTelemetry.sendTelemetryErrorEvent(TelemetryEvent.UpdateActionWithMCP, error);
89+
return err(error);
8390
}
8491
if (mcpNames.length === 1) {
8592
mcpName = sanitizeMCPName(mcpNames[0]);
@@ -99,6 +106,7 @@ export async function updateActionWithMCP(args?: any[]): Promise<Result<any, FxE
99106
void vscode.window.showErrorMessage(
100107
result.error.message || localize("teamstoolkit.MCP.SelectServerFailed")
101108
);
109+
ExtTelemetry.sendTelemetryErrorEvent(TelemetryEvent.UpdateActionWithMCP, result.error);
102110
return err(result.error);
103111
}
104112
const originalMcpName = result.value.result as string;
@@ -107,14 +115,14 @@ export async function updateActionWithMCP(args?: any[]): Promise<Result<any, FxE
107115
}
108116
} else if (!mcpName || !server) {
109117
void vscode.window.showErrorMessage(localize("teamstoolkit.MCP.NameOrServerUrlMissing"));
110-
return err(
111-
new UserError(
112-
"da-mcp",
113-
ExtensionErrors.MCPNameOrServerUrlMissing,
114-
getDefaultString("teamstoolkit.MCP.NameOrServerUrlMissing"),
115-
localize("teamstoolkit.MCP.NameOrServerUrlMissing")
116-
)
118+
const error = new UserError(
119+
"da-mcp",
120+
ExtensionErrors.MCPNameOrServerUrlMissing,
121+
getDefaultString("teamstoolkit.MCP.NameOrServerUrlMissing"),
122+
localize("teamstoolkit.MCP.NameOrServerUrlMissing")
117123
);
124+
ExtTelemetry.sendTelemetryErrorEvent(TelemetryEvent.UpdateActionWithMCP, error);
125+
return err(error);
118126
}
119127

120128
inputs[QuestionNames.MCPForDAServerUrl] = server;
@@ -136,15 +144,14 @@ export async function updateActionWithMCP(args?: any[]): Promise<Result<any, FxE
136144
});
137145
if (tools.length === 0) {
138146
void vscode.window.showErrorMessage(localize("teamstoolkit.MCP.ToolsNotFound"));
139-
// Return an error result
140-
return err(
141-
new UserError(
142-
"da-mcp",
143-
ExtensionErrors.MCPToolsNotFound,
144-
getDefaultString("teamstoolkit.MCP.ToolsNotFound"),
145-
localize("teamstoolkit.MCP.ToolsNotFound")
146-
)
147+
const error = new UserError(
148+
"da-mcp",
149+
ExtensionErrors.MCPToolsNotFound,
150+
getDefaultString("teamstoolkit.MCP.ToolsNotFound"),
151+
localize("teamstoolkit.MCP.ToolsNotFound")
147152
);
153+
ExtTelemetry.sendTelemetryErrorEvent(TelemetryEvent.UpdateActionWithMCP, error);
154+
return err(error);
148155
}
149156
inputs[QuestionNames.MCPForDAAvailableTools] = tools;
150157

@@ -178,5 +185,16 @@ export async function updateActionWithMCP(args?: any[]): Promise<Result<any, FxE
178185
inputs[QuestionNames.MCPForDAAuth] = auth;
179186
inputs[QuestionNames.MCPForDAAuthMetadataUrl] = oauthMetadataUrl;
180187
const result = await runCommand(Stage.updateActionWithMCP, inputs);
188+
if (result.isErr()) {
189+
ExtTelemetry.sendTelemetryErrorEvent(TelemetryEvent.UpdateActionWithMCP, result.error, {
190+
"auth-type": auth,
191+
"tool-number": tools.length.toString(),
192+
});
193+
} else {
194+
ExtTelemetry.sendTelemetryEvent(TelemetryEvent.UpdateActionWithMCP, {
195+
"auth-type": auth,
196+
"tool-number": tools.length.toString(),
197+
});
198+
}
181199
return result;
182200
}

packages/vscode-extension/src/telemetry/extTelemetryEvents.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
// Licensed under the MIT license.
33

44
export enum TelemetryEvent {
5+
UpdateActionWithMCPStart = "update-action-with-mcp-start",
6+
UpdateActionWithMCP = "update-action-with-mcp",
7+
58
ManageAccount = "manage-account",
69
CreateAccountStart = "create-account-start",
710
CreateAccount = "create-account",

packages/vscode-extension/test/extension/codeLensProvider.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,6 +1382,7 @@ publish:
13821382
},
13831383
},
13841384
},
1385+
"CodeLens",
13851386
]);
13861387
});
13871388

@@ -1431,6 +1432,7 @@ publish:
14311432
args: ["app.py"],
14321433
},
14331434
},
1435+
"CodeLens",
14341436
]);
14351437

14361438
chai.expect(codelens[1].command?.title).to.equal("⚡ ATK: Fetch action from MCP");
@@ -1443,6 +1445,7 @@ publish:
14431445
args: ["index.js"],
14441446
},
14451447
},
1448+
"CodeLens",
14461449
]);
14471450
});
14481451

@@ -1491,6 +1494,7 @@ publish:
14911494
args: ["start"],
14921495
},
14931496
},
1497+
"CodeLens",
14941498
]);
14951499
});
14961500

@@ -1718,6 +1722,7 @@ publish:
17181722
args: ["-m", "server"],
17191723
},
17201724
},
1725+
"CodeLens",
17211726
]);
17221727

17231728
chai.expect(codelens[1].command?.arguments).to.deep.equal([
@@ -1728,6 +1733,7 @@ publish:
17281733
args: ["start"],
17291734
},
17301735
},
1736+
"CodeLens",
17311737
]);
17321738
});
17331739

@@ -1768,6 +1774,7 @@ publish:
17681774
serverName: "null-server",
17691775
serverConfig: null,
17701776
},
1777+
"CodeLens",
17711778
]);
17721779

17731780
chai.expect(codelens[1].command?.arguments).to.deep.equal([
@@ -1777,6 +1784,7 @@ publish:
17771784
command: "node",
17781785
},
17791786
},
1787+
"CodeLens",
17801788
]);
17811789
});
17821790
});

packages/vscode-extension/test/handlers/updateActionWithMCP.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { Stage, err, ok, UserError, Inputs, Platform } from "@microsoft/teamsfx-
1313
import { updateActionWithMCP } from "../../src/handlers/updateActionWithMCP";
1414
import * as systemEnvUtils from "../../src/utils/systemEnvUtils";
1515
import * as sharedOpts from "../../src/handlers/sharedOpts";
16+
import { ExtTelemetry } from "../../src/telemetry/extTelemetry";
1617
import * as vscUI from "../../src/qm/vsc_ui";
1718
import { QuestionNames } from "@microsoft/teamsfx-core";
1819
import { MockCore } from "../mocks/mockCore";
@@ -32,6 +33,8 @@ describe("updateActionWithMCP", () => {
3233
sandbox.stub(systemEnvUtils, "getSystemInputs").returns(mockInputs);
3334
sandbox.stub(vscode.window, "showErrorMessage");
3435
sandbox.stub(globalVariables, "core").value(new MockCore());
36+
sandbox.stub(ExtTelemetry, "sendTelemetryEvent");
37+
sandbox.stub(ExtTelemetry, "sendTelemetryErrorEvent");
3538
});
3639

3740
afterEach(() => {

0 commit comments

Comments
 (0)