powerbi-visuals-tools 7.0.3 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Changelog.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  This page contains information about changes to the PowerBI Visual Tools (pbiviz).
4
4
 
5
+ ## 7.1.0
6
+ * Added MCP (Model Context Protocol) server support via `pbiviz mcp` command, providing AI-powered tools for visual development.
7
+ * Added MCP tools: available APIs, best practices, certification guidance, visual info, and vulnerabilities detection.
8
+ * Added MCP configuration template for new visuals (`.vscode/mcp.json`).
9
+ * Added unit tests for MCP tools.
10
+ * Updated packages.
11
+
12
+ ## 7.0.4
13
+ * Treated renderingEvents issue as an error when certification-audit and certification-fix are used.
14
+ * Switched to a new webpack plugin.
15
+ * Added rendering events to the visual templates.
16
+ * Updated packages.
17
+
5
18
  ## 7.0.3
6
19
  * Fixed missing validation for `author` object in pbiviz.json. The `author` object with `name` and `email` fields is now required.
7
20
  * Updated packages.
package/MCP.md ADDED
@@ -0,0 +1,234 @@
1
+ # Power BI Visuals Tools - MCP Server
2
+
3
+ This document describes the MCP (Model Context Protocol) server integration for Power BI Custom Visual Tools, inspired by the Angular 21 MCP implementation.
4
+
5
+ ## What is MCP?
6
+
7
+ Model Context Protocol (MCP) is an open protocol that allows AI assistants (like GitHub Copilot, Cursor, Claude) to interact with development tools directly. The MCP server exposes "tools" that AI can call to get context-aware information about your project.
8
+
9
+ ## Quick Start
10
+
11
+ ### Option 1: Using VS Code with Copilot
12
+
13
+ 1. Add this to your VS Code settings or create `.vscode/mcp.json`:
14
+
15
+ ```json
16
+ {
17
+ "servers": {
18
+ "pbiviz": {
19
+ "command": "npx",
20
+ "args": ["-y", "powerbi-visuals-tools", "mcp"]
21
+ }
22
+ }
23
+ }
24
+ ```
25
+
26
+ 2. Restart VS Code
27
+ 3. In Copilot Chat, you can now ask questions like:
28
+ - "Check my visual for certification readiness"
29
+ - "What are the best practices for Power BI visuals?"
30
+ - "Show me available Power BI Visual APIs"
31
+
32
+ ### Option 2: Using Cursor
33
+
34
+ Add to Cursor settings (`~/.cursor/mcp.json`):
35
+
36
+ ```json
37
+ {
38
+ "mcpServers": {
39
+ "pbiviz": {
40
+ "command": "npx",
41
+ "args": ["-y", "powerbi-visuals-tools", "mcp"]
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ ### Option 3: Run Manually (for testing)
48
+
49
+ ```bash
50
+ cd /path/to/your/visual-project
51
+ pbiviz mcp
52
+ ```
53
+
54
+ The server runs on STDIO, so you won't see output, but it will respond to MCP requests.
55
+
56
+ ## Available Tools
57
+
58
+ | Tool | Description | Local | Read-only |
59
+ |------|-------------|-------|-----------|
60
+ | `get_best_practices` | Returns best practice guidelines for Power BI visual development | ✅ | ✅ |
61
+ | `check_vulnerabilities` | Scans project for security vulnerabilities in dependencies and code | ✅ | ✅ |
62
+ | `prepare_certification` | Audits visual for Power BI certification readiness | ✅ | ✅ |
63
+ | `list_visual_info` | Returns info about current visual (name, GUID, API version, capabilities) | ✅ | ✅ |
64
+ | `get_available_apis` | Lists available Power BI Visual APIs with examples | ✅ | ✅ |
65
+
66
+ ### Tool Details
67
+
68
+ #### `get_best_practices`
69
+
70
+ Returns comprehensive guidelines including:
71
+ - API version management
72
+ - Performance optimization tips
73
+ - Security guidelines
74
+ - Accessibility requirements
75
+ - Project structure recommendations
76
+ - Testing best practices
77
+
78
+ #### `check_vulnerabilities`
79
+
80
+ Analyzes:
81
+ - `package.json` dependencies for known vulnerable packages
82
+ - Source code for dangerous patterns (`eval()`, `innerHTML`, external fetch calls)
83
+ - Returns severity-categorized results (critical/high/medium/low/info)
84
+
85
+ #### `prepare_certification`
86
+
87
+ Checks:
88
+ - Required files (pbiviz.json, capabilities.json, package.json)
89
+ - Visual configuration (name, GUID, version format, API version)
90
+ - Capabilities (data roles, accessibility support)
91
+ - Assets (icon.png)
92
+
93
+ #### `list_visual_info`
94
+
95
+ Extracts from project files:
96
+ - Visual name, display name, GUID
97
+ - Version and API version
98
+ - Author information
99
+ - Defined data roles and format objects
100
+ - Supported features (highlight, keyboard focus, etc.)
101
+ - Dependencies list
102
+
103
+ #### `get_available_apis`
104
+
105
+ Provides documentation for:
106
+ - **Data APIs**: fetchMoreData, persistProperties
107
+ - **Formatting APIs**: colorPalette, getFormattingModel, high contrast
108
+ - **Interaction APIs**: selectionManager, tooltipService, contextMenu, drilldown
109
+ - **Utility APIs**: localization, storage, events, modal dialog
110
+
111
+ Accepts optional `category` parameter: `data`, `formatting`, `interaction`, `utility`, or `all`.
112
+
113
+ ## Example Interactions
114
+
115
+ ### With GitHub Copilot (Agent Mode)
116
+
117
+ **You:** "Is my visual ready for certification?"
118
+
119
+ **Copilot:** *calls `prepare_certification` tool*
120
+
121
+ > Based on the certification check, your visual has:
122
+ > - ✅ 12 passed checks
123
+ > - ⚠️ 2 warnings: Missing keyboard focus support, no README.md
124
+ > - ❌ 1 failed: API version 2.6.0 is outdated
125
+ >
126
+ > Recommendation: Update to API version 5.x and add `"supportsKeyboardFocus": true` to capabilities.json.
127
+
128
+ ---
129
+
130
+ **You:** "What APIs can I use for tooltips and selection?"
131
+
132
+ **Copilot:** *calls `get_available_apis` with category="interaction"*
133
+
134
+ > For tooltips, use `host.tooltipService.show()`:
135
+ > ```typescript
136
+ > host.tooltipService.show({
137
+ > dataItems: tooltipData,
138
+ > coordinates: [x, y]
139
+ > });
140
+ > ```
141
+ > For selection, use `selectionManager`:
142
+ > ```typescript
143
+ > const selectionManager = host.createSelectionManager();
144
+ > selectionManager.select(selectionId);
145
+ > ```
146
+
147
+ ## How It Works
148
+
149
+ ```
150
+ ┌─────────────────┐ STDIO ┌─────────────────┐
151
+ │ VS Code / │ ◄───────────► │ pbiviz mcp │
152
+ │ Copilot │ (MCP) │ (MCP Server) │
153
+ └─────────────────┘ └─────────────────┘
154
+
155
+
156
+ ┌─────────────────┐
157
+ │ Visual Project │
158
+ │ - pbiviz.json │
159
+ │ - capabilities │
160
+ │ - package.json │
161
+ │ - src/ │
162
+ └─────────────────┘
163
+ ```
164
+
165
+ 1. VS Code starts `pbiviz mcp` as a subprocess
166
+ 2. Copilot sends `ListTools` request → pbiviz returns available tools
167
+ 3. When you ask a question, Copilot may call a tool
168
+ 4. pbiviz executes the tool (reads project files, runs checks)
169
+ 5. Results are returned to Copilot as structured text
170
+ 6. Copilot presents the information in a helpful way
171
+
172
+ ## Development
173
+
174
+ ### Building from Source
175
+
176
+ ```bash
177
+ git clone https://github.com/Microsoft/PowerBI-visuals-tools.git
178
+ cd PowerBI-visuals-tools
179
+ npm install
180
+ npm run build
181
+ ```
182
+
183
+ ### Testing MCP Server Locally
184
+
185
+ ```bash
186
+ # In your visual project directory:
187
+ node /path/to/PowerBI-visuals-tools/bin/pbiviz.js mcp
188
+ ```
189
+
190
+ ### Adding New Tools
191
+
192
+ 1. Create a new file in `src/mcp/tools/`
193
+ 2. Export a function that returns a string result
194
+ 3. Register the tool in `src/mcp/McpServer.ts`
195
+
196
+ Example:
197
+ ```typescript
198
+ // src/mcp/tools/myTool.ts
199
+ export function myTool(rootPath: string): string {
200
+ // Read files, perform checks, return markdown result
201
+ return "# My Tool Result\n...";
202
+ }
203
+
204
+ // In McpServer.ts
205
+ this.server.tool(
206
+ "my_tool",
207
+ "Description for AI",
208
+ {},
209
+ async () => ({
210
+ content: [{ type: "text", text: myTool(this.rootPath) }]
211
+ })
212
+ );
213
+ ```
214
+
215
+ ## Comparison with Angular 21 MCP
216
+
217
+ | Feature | Angular CLI | pbiviz (this implementation) |
218
+ |---------|-------------|------------------------------|
219
+ | Best practices | `get_best_practices` | `get_best_practices` |
220
+ | Project info | `list_projects` | `list_visual_info` |
221
+ | Code examples | `find_examples` | `get_available_apis` |
222
+ | Documentation search | `search_documentation` (online) | ❌ (offline only) |
223
+ | Migration tools | `onpush_zoneless_migration` | `prepare_certification` |
224
+ | Build/Run | `build`, `serve` | Use regular CLI commands |
225
+
226
+ ## Requirements
227
+
228
+ - Node.js >= 18.0.0
229
+ - VS Code with GitHub Copilot (for Chat integration)
230
+ - Or Cursor / other MCP-compatible AI assistant
231
+
232
+ ## License
233
+
234
+ MIT - Microsoft Corporation
package/bin/pbiviz.js CHANGED
@@ -111,4 +111,16 @@ pbiviz
111
111
  CommandManager.package(options, rootPath);
112
112
  });
113
113
 
114
+ pbiviz
115
+ .command('mcp')
116
+ .description('Start MCP (Model Context Protocol) server for AI assistant integration')
117
+ .option('--init', 'Initialize MCP configuration in current project (.vscode/mcp.json)')
118
+ .action((options) => {
119
+ if (options.init) {
120
+ CommandManager.mcpInit(rootPath);
121
+ } else {
122
+ CommandManager.mcp(rootPath);
123
+ }
124
+ });
125
+
114
126
  program.parse(process.argv);
@@ -1,6 +1,7 @@
1
1
  import { createCertificate } from './CertificateTools.js';
2
2
  import ConsoleWriter from './ConsoleWriter.js';
3
3
  import VisualManager from './VisualManager.js';
4
+ import { startMcpServer, initMcpConfig } from './mcp/McpServer.js';
4
5
  export default class CommandManager {
5
6
  static async start(options, rootPath) {
6
7
  const webpackOptions = {
@@ -50,12 +51,13 @@ export default class CommandManager {
50
51
  verbose: options.verbose,
51
52
  fix: options.fix,
52
53
  };
54
+ const certificationMode = options.certificationAudit || options.certificationFix;
53
55
  const visualManager = new VisualManager(rootPath);
54
56
  const visual = await visualManager.prepareVisual(options.pbivizFile);
55
57
  await visual.runLintValidation(lintOptions);
56
58
  await visual.validateVisual(options.verbose);
57
59
  await visual.initializeWebpack(webpackOptions)
58
- .then(manager => manager.generatePackage(options.verbose));
60
+ .then(manager => manager.generatePackage(options.verbose, certificationMode));
59
61
  }
60
62
  static new({ force, template }, name, rootPath) {
61
63
  const generateOptions = {
@@ -72,4 +74,10 @@ export default class CommandManager {
72
74
  static async installCert() {
73
75
  await createCertificate();
74
76
  }
77
+ static async mcp(rootPath) {
78
+ await startMcpServer(rootPath);
79
+ }
80
+ static async mcpInit(rootPath) {
81
+ await initMcpConfig(rootPath);
82
+ }
75
83
  }
@@ -42,6 +42,10 @@ export default class ConsoleWriter {
42
42
  static blank() {
43
43
  console.info(preferredChalk.reset(' '));
44
44
  }
45
+ /** Outputs a separator line */
46
+ static separator() {
47
+ console.log(preferredChalk.white('--------------------------------'));
48
+ }
45
49
  /**
46
50
  * Outputs arguments with the "done" tag / colors
47
51
  *
@@ -7,21 +7,27 @@ export var Status;
7
7
  })(Status || (Status = {}));
8
8
  export class FeatureManager {
9
9
  features = Object.keys(features).map(key => features[key]);
10
- validate(stage, sourceInstance) {
10
+ validate(stage, sourceInstance, certificationMode = false) {
11
11
  const result = {
12
12
  status: Status.Success,
13
13
  logs: {
14
14
  errors: [],
15
15
  warnings: [],
16
16
  info: [],
17
- deprecation: []
17
+ deprecation: [],
18
+ certificationErrors: []
18
19
  }
19
20
  };
20
21
  this.features
21
22
  .filter(feature => feature.stage == stage)
22
23
  .filter(feature => feature.visualFeatureType & sourceInstance.visualFeatureType)
23
24
  .filter(feature => !feature.isSupported(sourceInstance))
24
- .forEach(({ errorMessage, severity }) => {
25
+ .forEach(({ errorMessage, severity, certificationRequired }) => {
26
+ if (certificationMode && certificationRequired && severity === Severity.Warning) {
27
+ result.status = Status.Error;
28
+ result.logs.certificationErrors.push(errorMessage);
29
+ return;
30
+ }
25
31
  switch (severity) {
26
32
  case Severity.Error:
27
33
  result.status = Status.Error;
@@ -90,12 +90,15 @@ export default class VisualManager {
90
90
  this.compiler = webpack(this.webpackConfig);
91
91
  return this;
92
92
  }
93
- generatePackage(verbose = false) {
93
+ generatePackage(verbose = false, certificationMode = false) {
94
94
  const callback = (err, stats) => {
95
95
  this.parseCompilationResults(err, stats);
96
96
  this.createPackageInstance();
97
- const logs = this.validatePackage();
97
+ const { status, logs } = this.validatePackage(certificationMode);
98
98
  this.outputResults(logs, verbose);
99
+ if (certificationMode && status === Status.Error) {
100
+ process.exit(1);
101
+ }
99
102
  };
100
103
  this.compiler.run(callback);
101
104
  }
@@ -144,15 +147,15 @@ export default class VisualManager {
144
147
  /**
145
148
  * Validates the visual package
146
149
  */
147
- validatePackage() {
150
+ validatePackage(certificationMode = false) {
148
151
  const featureManager = new FeatureManager();
149
- const { logs } = featureManager.validate(Stage.PostBuild, this.package);
150
- return logs;
152
+ const { status, logs } = featureManager.validate(Stage.PostBuild, this.package, certificationMode);
153
+ return { status, logs };
151
154
  }
152
155
  /**
153
156
  * Outputs the results of the validation
154
157
  */
155
- outputResults({ errors, deprecation, warnings, info }, verbose) {
158
+ outputResults({ errors, deprecation, warnings, info, certificationErrors }, verbose) {
156
159
  const headerMessage = {
157
160
  error: `Visual doesn't support some features required for all custom visuals:`,
158
161
  deprecation: `Some features are going to be required soon, please update the visual:`,
@@ -160,6 +163,9 @@ export default class VisualManager {
160
163
  verboseInfo: `Visual can be improved by adding some features:`,
161
164
  shortInfo: `Visual can be improved by adding ${info.length} more optional features.`
162
165
  };
166
+ if (certificationErrors.length) {
167
+ this.outputCertificationSection(certificationErrors);
168
+ }
163
169
  this.outputLogsWithHeadMessage(headerMessage.error, errors, Severity.Error);
164
170
  this.outputLogsWithHeadMessage(headerMessage.deprecation, deprecation, Severity.Deprecation);
165
171
  this.outputLogsWithHeadMessage(headerMessage.warning, warnings, Severity.Warning);
@@ -179,6 +185,16 @@ export default class VisualManager {
179
185
  ConsoleWriter.error('Unable to load visual info. Please ensure the package is valid.');
180
186
  }
181
187
  }
188
+ /**
189
+ * Outputs certification-required issues in a formatted section with separators
190
+ */
191
+ outputCertificationSection(certificationErrors) {
192
+ ConsoleWriter.separator();
193
+ ConsoleWriter.info('Certification audit:');
194
+ certificationErrors.forEach(error => ConsoleWriter.error(error));
195
+ ConsoleWriter.error(`Found ${certificationErrors.length} certification issue(s). Fix them before submitting for certification.`);
196
+ ConsoleWriter.separator();
197
+ }
182
198
  /**
183
199
  * Creates a new visual
184
200
  */
@@ -5,5 +5,6 @@ export default class BaseFeature {
5
5
  static featureName;
6
6
  static documentationLink;
7
7
  static errorMessage;
8
+ static certificationRequired = false;
8
9
  static isSupported() { }
9
10
  }
@@ -5,6 +5,7 @@ export default class RenderingEvents {
5
5
  static severity = Severity.Warning;
6
6
  static stage = Stage.PostBuild;
7
7
  static visualFeatureType = VisualFeatureType.All;
8
+ static certificationRequired = true;
8
9
  static errorMessage = `${this.featureName} - ${this.documentationLink}`;
9
10
  static isSupported(packageInstance) {
10
11
  const keywords = [".eventService", ".renderingStarted", ".renderingFinished"];
@@ -0,0 +1,122 @@
1
+ /*
2
+ * Power BI Visual CLI - MCP Server
3
+ *
4
+ * Copyright (c) Microsoft Corporation
5
+ * All rights reserved.
6
+ * MIT License
7
+ */
8
+ "use strict";
9
+ import { McpServer as MCPServerSDK } from "@modelcontextprotocol/sdk/server/mcp.js";
10
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
11
+ import { z } from "zod";
12
+ import fs from "fs-extra";
13
+ import path from "path";
14
+ import ConsoleWriter from "../ConsoleWriter.js";
15
+ import { getBestPractices } from "./tools/bestPractices.js";
16
+ import { checkVulnerabilities } from "./tools/vulnerabilities.js";
17
+ import { prepareCertification } from "./tools/certification.js";
18
+ import { getVisualInfo } from "./tools/visualInfo.js";
19
+ import { getAvailableApis } from "./tools/availableApis.js";
20
+ export class McpServer {
21
+ server;
22
+ rootPath;
23
+ constructor(rootPath) {
24
+ this.rootPath = rootPath;
25
+ this.server = new MCPServerSDK({
26
+ name: "pbiviz-mcp-server",
27
+ version: "1.0.0",
28
+ });
29
+ this.registerTools();
30
+ }
31
+ registerTools() {
32
+ // Tool 1: Get Best Practices
33
+ this.server.tool("get_best_practices", "Returns best practice guidelines for Power BI custom visual development. Covers: API version management, performance optimization (update loop, lazy loading, data processing), security (eval, innerHTML, XSS, sanitization, external call/calls, network request/requests), accessibility (keyboard navigation, high contrast, screen reader, ARIA label/labels), project structure (module/modules, error handling), formatting pane (format model, formatting model), testing (unit test/tests, E2E test/tests, edge case/cases), and documentation (README, changelog, comment/comments).", {}, async () => {
34
+ const practices = await getBestPractices(this.rootPath);
35
+ return {
36
+ content: [{ type: "text", text: practices }],
37
+ };
38
+ });
39
+ // Tool 2: Check Vulnerabilities
40
+ this.server.tool("check_vulnerabilities", "Scans the visual project source code for security vulnerability/vulnerabilities and dangerous code pattern/patterns. Detects: eval(), new Function(), innerHTML assignment, document.write, external fetch/HTTP call/calls, XMLHttpRequest. Also checks for commented-out dangerous code and ESLint configuration. Reports issue/issues by severity (critical, high, medium, low, info) with file path and line number.", {}, async () => {
41
+ const result = await checkVulnerabilities(this.rootPath);
42
+ return {
43
+ content: [{ type: "text", text: result }],
44
+ };
45
+ });
46
+ // Tool 3: Prepare Certification
47
+ this.server.tool("prepare_certification", "Audits the visual for Power BI certification readiness. Checks: required file/files (pbiviz.json, capabilities.json, package.json, tsconfig.json), visual configuration (name, GUID, version, API version, author, support URL), capability/capabilities (data role/roles, data view mapping/mappings, keyboard focus, highlight support, web access privilege/privileges), and asset/assets (icon.png). Reports pass/fail/warning status for each check.", {}, async () => {
48
+ const result = await prepareCertification(this.rootPath);
49
+ return {
50
+ content: [{ type: "text", text: result }],
51
+ };
52
+ });
53
+ // Tool 4: List Visual Info
54
+ this.server.tool("list_visual_info", "Returns detailed information about the current Power BI visual project. Shows: visual name, display name, GUID, version, API version, author, description, support URL, data role/roles, data view mapping/mappings, format object/objects (setting/settings), supported feature/features (highlight, keyboard focus, landing page, multi-visual selection), dependency/dependencies from package.json, and quick command/commands.", {}, async () => {
55
+ const result = await getVisualInfo(this.rootPath);
56
+ return {
57
+ content: [{ type: "text", text: result }],
58
+ };
59
+ });
60
+ // Tool 5: Get Available APIs
61
+ this.server.tool("get_available_apis", "Lists available Power BI Visual API/APIs and feature/features with code example/examples and documentation link/links. Categories: 'data' (fetchMoreData, data snapshot, persist property/properties), 'formatting' (color palette, format pane, formatting model, custom color/colors, high contrast), 'interaction' (selection manager, tooltip/tooltips, tooltip service, context menu, launch URL, drill down/drilldown, warning icon), 'utility' (localization, local storage, file download, rendering event/events, modal dialog, authentication), or 'all'.", {
62
+ category: z.string().optional().describe("Filter APIs by category: 'data' (fetchMoreData, persist, snapshot), 'formatting' (color palette, format pane, high contrast), 'interaction' (selection, tooltip/tooltips, context menu, drill down, launch URL, warning icon), 'utility' (localization, storage, download, event/events, dialog, auth), or 'all' (default)")
63
+ }, async ({ category }) => {
64
+ const result = await getAvailableApis(category || "all", this.rootPath);
65
+ return {
66
+ content: [{ type: "text", text: result }],
67
+ };
68
+ });
69
+ }
70
+ async start() {
71
+ const transport = new StdioServerTransport();
72
+ await this.server.connect(transport);
73
+ // Keep the server running
74
+ process.on("SIGINT", async () => {
75
+ await this.server.close();
76
+ process.exit(0);
77
+ });
78
+ }
79
+ }
80
+ export async function startMcpServer(rootPath) {
81
+ const server = new McpServer(rootPath);
82
+ await server.start();
83
+ }
84
+ const MCP_CONFIG = {
85
+ servers: {
86
+ pbiviz: {
87
+ command: "npx",
88
+ args: ["-y", "powerbi-visuals-tools", "mcp"]
89
+ }
90
+ }
91
+ };
92
+ export async function initMcpConfig(rootPath) {
93
+ const vscodeDir = path.join(rootPath, ".vscode");
94
+ const mcpConfigPath = path.join(vscodeDir, "mcp.json");
95
+ try {
96
+ // Check if mcp.json already exists
97
+ if (fs.existsSync(mcpConfigPath)) {
98
+ ConsoleWriter.warning("MCP configuration already exists at .vscode/mcp.json");
99
+ ConsoleWriter.info("To reconfigure, delete the file and run this command again.");
100
+ return;
101
+ }
102
+ // Create .vscode directory if it doesn't exist
103
+ fs.ensureDirSync(vscodeDir);
104
+ // Write mcp.json
105
+ fs.writeJsonSync(mcpConfigPath, MCP_CONFIG, { spaces: 4 });
106
+ ConsoleWriter.done("MCP configuration created successfully!");
107
+ ConsoleWriter.blank();
108
+ ConsoleWriter.info("Created: .vscode/mcp.json");
109
+ ConsoleWriter.blank();
110
+ ConsoleWriter.info("Next steps:");
111
+ ConsoleWriter.info("1. Restart VS Code to activate MCP server");
112
+ ConsoleWriter.info("2. Open Copilot Chat and ask questions like:");
113
+ ConsoleWriter.info(' - "Check my visual for certification readiness"');
114
+ ConsoleWriter.info(' - "What are the best practices for Power BI visuals?"');
115
+ ConsoleWriter.info(' - "Show me available APIs for tooltips"');
116
+ ConsoleWriter.blank();
117
+ }
118
+ catch (error) {
119
+ ConsoleWriter.error(`Failed to create MCP configuration: ${(error instanceof Error) ? error.message : String(error)}`);
120
+ process.exit(1);
121
+ }
122
+ }