@luquimbo/bi-superpowers 4.1.6 → 5.0.1
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/.claude-plugin/marketplace.json +8 -6
- package/.claude-plugin/plugin.json +1 -1
- package/.claude-plugin/skill-manifest.json +35 -19
- package/.plugin/plugin.json +1 -1
- package/AGENTS.md +150 -26
- package/CHANGELOG.md +489 -14
- package/README.md +103 -114
- package/bin/cli.js +7 -1
- package/bin/commands/diff.js +2 -2
- package/bin/commands/install.js +58 -45
- package/bin/commands/lint.js +2 -2
- package/bin/commands/validate-projects.js +425 -0
- package/bin/lib/generators/claude-plugin.js +31 -7
- package/bin/lib/generators/shared.js +11 -7
- package/bin/lib/mcp-config.js +22 -2
- package/bin/lib/skills.js +8 -8
- package/bin/mcp/powerbi-modeling-launcher.js +8 -4
- package/bin/postinstall.js +14 -12
- package/bin/utils/mcp-detect.js +11 -11
- package/commands/bi-connect.md +418 -0
- package/commands/bi-dax.md +385 -0
- package/commands/{project-kickoff.md → bi-kickoff.md} +78 -47
- package/commands/bi-modeling.md +395 -0
- package/commands/bi-performance.md +455 -0
- package/commands/bi-start.md +39 -27
- package/desktop-extension/manifest.json +2 -2
- package/package.json +3 -2
- package/skills/bi-connect/SKILL.md +420 -0
- package/skills/{pbi-connect → bi-connect}/scripts/update-check.js +1 -1
- package/skills/bi-dax/SKILL.md +387 -0
- package/skills/{report-design → bi-dax}/scripts/update-check.js +1 -1
- package/skills/{project-kickoff → bi-kickoff}/SKILL.md +79 -48
- package/skills/{project-kickoff → bi-kickoff}/scripts/update-check.js +1 -1
- package/skills/bi-modeling/SKILL.md +397 -0
- package/skills/bi-modeling/scripts/update-check.js +403 -0
- package/skills/bi-performance/SKILL.md +457 -0
- package/skills/bi-performance/scripts/install-tabular-editor.ps1 +90 -0
- package/skills/bi-performance/scripts/run-bpa.ps1 +161 -0
- package/skills/bi-performance/scripts/update-check.js +403 -0
- package/skills/bi-start/SKILL.md +40 -28
- package/skills/bi-start/scripts/update-check.js +1 -1
- package/src/content/base.md +15 -10
- package/src/content/routing.md +15 -18
- package/src/content/skills/bi-connect.md +391 -0
- package/src/content/skills/bi-dax.md +358 -0
- package/src/content/skills/{project-kickoff.md → bi-kickoff.md} +75 -44
- package/src/content/skills/bi-modeling.md +368 -0
- package/src/content/skills/bi-performance/SKILL.md +428 -0
- package/src/content/skills/bi-performance/scripts/install-tabular-editor.ps1 +90 -0
- package/src/content/skills/bi-performance/scripts/run-bpa.ps1 +161 -0
- package/src/content/skills/bi-start.md +39 -27
- package/theme/BISuperpowers.json +3888 -0
- package/commands/pbi-connect.md +0 -253
- package/commands/report-design.md +0 -403
- package/skills/pbi-connect/SKILL.md +0 -255
- package/skills/report-design/SKILL.md +0 -405
- package/skills/report-design/references/cli-commands.md +0 -184
- package/skills/report-design/references/cli-setup.md +0 -101
- package/skills/report-design/references/close-write-open-pattern.md +0 -80
- package/skills/report-design/references/layouts/finance.md +0 -65
- package/skills/report-design/references/layouts/generic.md +0 -46
- package/skills/report-design/references/layouts/hr.md +0 -48
- package/skills/report-design/references/layouts/marketing.md +0 -45
- package/skills/report-design/references/layouts/operations.md +0 -44
- package/skills/report-design/references/layouts/sales.md +0 -50
- package/skills/report-design/references/native-visuals.md +0 -341
- package/skills/report-design/references/pbi-desktop-installation.md +0 -87
- package/skills/report-design/references/pbir-preview-activation.md +0 -40
- package/skills/report-design/references/slicer.md +0 -89
- package/skills/report-design/references/textbox.md +0 -101
- package/skills/report-design/references/themes/BISuperpowers.json +0 -915
- package/skills/report-design/references/troubleshooting.md +0 -135
- package/skills/report-design/references/visual-types.md +0 -78
- package/skills/report-design/scripts/apply-theme.js +0 -243
- package/skills/report-design/scripts/create-visual.js +0 -942
- package/skills/report-design/scripts/ensure-pbi-cli.sh +0 -41
- package/skills/report-design/scripts/validate-pbir.js +0 -351
- package/src/content/skills/pbi-connect.md +0 -226
- package/src/content/skills/report-design/SKILL.md +0 -376
- package/src/content/skills/report-design/references/cli-commands.md +0 -184
- package/src/content/skills/report-design/references/cli-setup.md +0 -101
- package/src/content/skills/report-design/references/close-write-open-pattern.md +0 -80
- package/src/content/skills/report-design/references/layouts/finance.md +0 -65
- package/src/content/skills/report-design/references/layouts/generic.md +0 -46
- package/src/content/skills/report-design/references/layouts/hr.md +0 -48
- package/src/content/skills/report-design/references/layouts/marketing.md +0 -45
- package/src/content/skills/report-design/references/layouts/operations.md +0 -44
- package/src/content/skills/report-design/references/layouts/sales.md +0 -50
- package/src/content/skills/report-design/references/native-visuals.md +0 -341
- package/src/content/skills/report-design/references/pbi-desktop-installation.md +0 -87
- package/src/content/skills/report-design/references/pbir-preview-activation.md +0 -40
- package/src/content/skills/report-design/references/slicer.md +0 -89
- package/src/content/skills/report-design/references/textbox.md +0 -101
- package/src/content/skills/report-design/references/themes/BISuperpowers.json +0 -915
- package/src/content/skills/report-design/references/troubleshooting.md +0 -135
- package/src/content/skills/report-design/references/visual-types.md +0 -78
- package/src/content/skills/report-design/scripts/apply-theme.js +0 -243
- package/src/content/skills/report-design/scripts/create-visual.js +0 -942
- package/src/content/skills/report-design/scripts/ensure-pbi-cli.sh +0 -41
- package/src/content/skills/report-design/scripts/validate-pbir.js +0 -351
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# ensure-pbi-cli.sh — idempotent installer for pbi-cli-tool + pywin32
|
|
3
|
-
# Run from any directory. Requires Python 3.10+ and pip on PATH.
|
|
4
|
-
# Exit code 0 = ready, 1 = install failed
|
|
5
|
-
|
|
6
|
-
set -e
|
|
7
|
-
|
|
8
|
-
check_python() {
|
|
9
|
-
python --version 2>/dev/null | grep -qE "Python 3\.(1[0-9]|[2-9][0-9])" && return 0
|
|
10
|
-
python3 --version 2>/dev/null | grep -qE "Python 3\.(1[0-9]|[2-9][0-9])" && return 0
|
|
11
|
-
echo "❌ Python 3.10+ required. Install from Microsoft Store or python.org."
|
|
12
|
-
exit 1
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
check_pipx() {
|
|
16
|
-
pipx --version 2>/dev/null && return 0
|
|
17
|
-
python -m pipx --version 2>/dev/null && return 0
|
|
18
|
-
echo "📦 Installing pipx..."
|
|
19
|
-
pip install --user pipx 2>/dev/null || python -m pip install --user pipx
|
|
20
|
-
python -m pipx ensurepath
|
|
21
|
-
echo "⚠ Close and reopen your terminal, then re-run this script."
|
|
22
|
-
exit 1
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
check_pbi() {
|
|
26
|
-
pbi --version 2>/dev/null && return 0
|
|
27
|
-
echo "📦 Installing pbi-cli-tool..."
|
|
28
|
-
python -m pipx install pbi-cli-tool
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
inject_pywin32() {
|
|
32
|
-
python -m pipx inject pbi-cli-tool pywin32 2>/dev/null || true
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
echo "Checking pbi-cli-tool environment..."
|
|
36
|
-
check_python
|
|
37
|
-
check_pipx
|
|
38
|
-
check_pbi
|
|
39
|
-
inject_pywin32
|
|
40
|
-
echo "✅ pbi-cli-tool is ready."
|
|
41
|
-
pbi --version
|
|
@@ -1,351 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* validate-pbir.js — allowlist-driven PBIR validator.
|
|
4
|
-
*
|
|
5
|
-
* Complements `pbi report validate` (which does schema sanity) by enforcing
|
|
6
|
-
* the native-visuals allowlist maintained in create-visual.js. Catches:
|
|
7
|
-
*
|
|
8
|
-
* - visualType that's not a native PBIR type (e.g. `stackedBarChart`,
|
|
9
|
-
* typos) — Desktop renders these as "objeto visual personalizado" but
|
|
10
|
-
* the CLI validate passes them. This is the exact bug F1 that motivated
|
|
11
|
-
* the migration away from the CLI.
|
|
12
|
-
*
|
|
13
|
-
* - bindings on roles that the type doesn't declare (e.g. `--bind size`
|
|
14
|
-
* on a funnelChart) — CLI validate doesn't catch these either.
|
|
15
|
-
*
|
|
16
|
-
* - missing required roles (e.g. a barChart with no Category).
|
|
17
|
-
*
|
|
18
|
-
* - visualContainer schema drift (wrong $schema URL or missing `name`).
|
|
19
|
-
*
|
|
20
|
-
* Usage:
|
|
21
|
-
* node validate-pbir.js <reportPath>
|
|
22
|
-
* node validate-pbir.js --json <reportPath> # machine-readable output
|
|
23
|
-
*
|
|
24
|
-
* Exit codes:
|
|
25
|
-
* 0 valid
|
|
26
|
-
* 1 validation errors found
|
|
27
|
-
* 2 I/O error (bad path, corrupt JSON)
|
|
28
|
-
*
|
|
29
|
-
* NOT a replacement for `pbi report validate` — run both. This validator
|
|
30
|
-
* trusts that the .Report folder is structurally correct (has definition/,
|
|
31
|
-
* pages/, etc.) and focuses on visual-level correctness that the CLI misses.
|
|
32
|
-
*/
|
|
33
|
-
|
|
34
|
-
'use strict';
|
|
35
|
-
|
|
36
|
-
const fs = require('fs');
|
|
37
|
-
const path = require('path');
|
|
38
|
-
|
|
39
|
-
const { NATIVE_VISUAL_TYPES, KNOWN_NON_NATIVE_TYPES } = require('./create-visual.js');
|
|
40
|
-
|
|
41
|
-
const EXPECTED_VISUAL_SCHEMA =
|
|
42
|
-
'https://developer.microsoft.com/json-schemas/fabric/item/report/definition/visualContainer/2.7.0/schema.json';
|
|
43
|
-
|
|
44
|
-
function fail(msg, code = 2) {
|
|
45
|
-
process.stderr.write(`validate-pbir: ${msg}\n`);
|
|
46
|
-
process.exit(code);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
function parseArgs(argv) {
|
|
50
|
-
const out = {};
|
|
51
|
-
const positional = [];
|
|
52
|
-
for (let i = 0; i < argv.length; i += 1) {
|
|
53
|
-
const a = argv[i];
|
|
54
|
-
if (a === '--json') out.json = true;
|
|
55
|
-
else if (a === '-h' || a === '--help') out.help = true;
|
|
56
|
-
else if (a.startsWith('-')) fail(`unknown flag: ${a}`, 2);
|
|
57
|
-
else positional.push(a);
|
|
58
|
-
}
|
|
59
|
-
out.reportPath = positional[0];
|
|
60
|
-
return out;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function printHelp() {
|
|
64
|
-
process.stdout.write(
|
|
65
|
-
[
|
|
66
|
-
'Usage: validate-pbir.js [--json] <reportPath>',
|
|
67
|
-
'',
|
|
68
|
-
'Arguments:',
|
|
69
|
-
' reportPath Path to a .Report folder',
|
|
70
|
-
'',
|
|
71
|
-
'Options:',
|
|
72
|
-
' --json Emit JSON instead of human-readable output',
|
|
73
|
-
' -h, --help Show this help',
|
|
74
|
-
'',
|
|
75
|
-
'Exit codes:',
|
|
76
|
-
' 0 valid',
|
|
77
|
-
' 1 validation errors found',
|
|
78
|
-
' 2 I/O error',
|
|
79
|
-
'',
|
|
80
|
-
].join('\n')
|
|
81
|
-
);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function listPages(reportPath) {
|
|
85
|
-
const pagesDir = path.join(reportPath, 'definition', 'pages');
|
|
86
|
-
if (!fs.existsSync(pagesDir)) {
|
|
87
|
-
fail(`pages directory not found: ${pagesDir}`, 2);
|
|
88
|
-
}
|
|
89
|
-
const out = [];
|
|
90
|
-
for (const entry of fs.readdirSync(pagesDir, { withFileTypes: true })) {
|
|
91
|
-
if (!entry.isDirectory()) continue;
|
|
92
|
-
const pageJsonPath = path.join(pagesDir, entry.name, 'page.json');
|
|
93
|
-
if (!fs.existsSync(pageJsonPath)) continue;
|
|
94
|
-
out.push({ name: entry.name, dir: path.join(pagesDir, entry.name) });
|
|
95
|
-
}
|
|
96
|
-
return out;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function listVisuals(pageDir) {
|
|
100
|
-
const visualsDir = path.join(pageDir, 'visuals');
|
|
101
|
-
if (!fs.existsSync(visualsDir)) return [];
|
|
102
|
-
const out = [];
|
|
103
|
-
for (const entry of fs.readdirSync(visualsDir, { withFileTypes: true })) {
|
|
104
|
-
if (!entry.isDirectory()) continue;
|
|
105
|
-
const visualJsonPath = path.join(visualsDir, entry.name, 'visual.json');
|
|
106
|
-
if (!fs.existsSync(visualJsonPath)) continue;
|
|
107
|
-
out.push({ name: entry.name, path: visualJsonPath });
|
|
108
|
-
}
|
|
109
|
-
return out;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
function readJsonSafe(filePath) {
|
|
113
|
-
try {
|
|
114
|
-
const raw = fs.readFileSync(filePath, 'utf8');
|
|
115
|
-
return { data: JSON.parse(raw), err: null };
|
|
116
|
-
} catch (err) {
|
|
117
|
-
return { data: null, err };
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Extracts the set of roles that have at least one projection bound.
|
|
122
|
-
function boundRoles(visualData) {
|
|
123
|
-
const qs = visualData && visualData.visual && visualData.visual.query && visualData.visual.query.queryState;
|
|
124
|
-
if (!qs || typeof qs !== 'object') return new Set();
|
|
125
|
-
const bound = new Set();
|
|
126
|
-
for (const [role, spec] of Object.entries(qs)) {
|
|
127
|
-
const projections = spec && spec.projections;
|
|
128
|
-
if (Array.isArray(projections) && projections.length > 0) bound.add(role);
|
|
129
|
-
}
|
|
130
|
-
return bound;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function validatePosition(position) {
|
|
134
|
-
const errors = [];
|
|
135
|
-
const requiredFields = ['x', 'y', 'z', 'height', 'width', 'tabOrder'];
|
|
136
|
-
|
|
137
|
-
if (!position || typeof position !== 'object') {
|
|
138
|
-
return requiredFields.map((field) => ({
|
|
139
|
-
severity: 'error',
|
|
140
|
-
rule: 'position-number',
|
|
141
|
-
field,
|
|
142
|
-
message: `position.${field} must be a finite number`,
|
|
143
|
-
}));
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
for (const field of requiredFields) {
|
|
147
|
-
if (!Number.isFinite(position[field])) {
|
|
148
|
-
errors.push({
|
|
149
|
-
severity: 'error',
|
|
150
|
-
rule: 'position-number',
|
|
151
|
-
field,
|
|
152
|
-
message: `position.${field} must be a finite number`,
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
return errors;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function validateVisual(visual) {
|
|
161
|
-
const errors = [];
|
|
162
|
-
const { data, path: filePath } = visual;
|
|
163
|
-
|
|
164
|
-
// Schema URL check.
|
|
165
|
-
if (data.$schema !== EXPECTED_VISUAL_SCHEMA) {
|
|
166
|
-
errors.push({
|
|
167
|
-
severity: 'warn',
|
|
168
|
-
rule: 'schema-url',
|
|
169
|
-
message: `unexpected $schema (got ${data.$schema || 'none'})`,
|
|
170
|
-
});
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// `name` must exist and match the folder.
|
|
174
|
-
if (typeof data.name !== 'string' || !data.name) {
|
|
175
|
-
errors.push({ severity: 'error', rule: 'name', message: 'missing "name"' });
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
errors.push(...validatePosition(data.position));
|
|
179
|
-
|
|
180
|
-
const vt = data.visual && data.visual.visualType;
|
|
181
|
-
if (!vt) {
|
|
182
|
-
errors.push({ severity: 'error', rule: 'visual-type', message: 'missing visualType' });
|
|
183
|
-
return errors;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Allowlist: known non-native (like stackedBarChart).
|
|
187
|
-
if (KNOWN_NON_NATIVE_TYPES[vt]) {
|
|
188
|
-
errors.push({
|
|
189
|
-
severity: 'error',
|
|
190
|
-
rule: 'non-native-type',
|
|
191
|
-
visualType: vt,
|
|
192
|
-
message: KNOWN_NON_NATIVE_TYPES[vt],
|
|
193
|
-
});
|
|
194
|
-
return errors;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
const def = NATIVE_VISUAL_TYPES[vt];
|
|
198
|
-
if (!def) {
|
|
199
|
-
errors.push({
|
|
200
|
-
severity: 'error',
|
|
201
|
-
rule: 'unknown-type',
|
|
202
|
-
visualType: vt,
|
|
203
|
-
message: `visualType "${vt}" is not in the native allowlist. Run create-visual.js --list-types for the canonical list.`,
|
|
204
|
-
});
|
|
205
|
-
return errors;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
// Check required roles are bound (skip for textbox — no roles).
|
|
209
|
-
if (vt !== 'textbox') {
|
|
210
|
-
const bound = boundRoles(data);
|
|
211
|
-
for (const [role, spec] of Object.entries(def.roles)) {
|
|
212
|
-
if (spec.required && !bound.has(role)) {
|
|
213
|
-
errors.push({
|
|
214
|
-
severity: 'error',
|
|
215
|
-
rule: 'missing-required-role',
|
|
216
|
-
visualType: vt,
|
|
217
|
-
role,
|
|
218
|
-
message: `required role "${role}" has no projections (visualType: ${vt})`,
|
|
219
|
-
});
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// Check that every bound role is valid for this type.
|
|
224
|
-
for (const role of bound) {
|
|
225
|
-
if (!(role in def.roles)) {
|
|
226
|
-
errors.push({
|
|
227
|
-
severity: 'error',
|
|
228
|
-
rule: 'invalid-role',
|
|
229
|
-
visualType: vt,
|
|
230
|
-
role,
|
|
231
|
-
message: `role "${role}" is not valid for visualType ${vt}. Valid: ${Object.keys(def.roles).join(', ') || '(none)'}`,
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
return errors;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
function main() {
|
|
241
|
-
const args = parseArgs(process.argv.slice(2));
|
|
242
|
-
if (args.help) {
|
|
243
|
-
printHelp();
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
if (!args.reportPath) fail('reportPath is required. Run --help for usage.', 2);
|
|
247
|
-
|
|
248
|
-
const reportPath = path.resolve(args.reportPath);
|
|
249
|
-
if (!fs.existsSync(reportPath)) fail(`not found: ${reportPath}`, 2);
|
|
250
|
-
|
|
251
|
-
const pages = listPages(reportPath);
|
|
252
|
-
const results = {
|
|
253
|
-
reportPath,
|
|
254
|
-
pagesChecked: pages.length,
|
|
255
|
-
visualsChecked: 0,
|
|
256
|
-
errors: [],
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
for (const page of pages) {
|
|
260
|
-
const visuals = listVisuals(page.dir);
|
|
261
|
-
// Track visual.name per page so we can flag duplicates. PBI Desktop
|
|
262
|
-
// does not reject a duplicate-name pair on load, but downstream tooling
|
|
263
|
-
// that references visuals by name (filters, bookmarks, selections) gets
|
|
264
|
-
// ambiguous — validate-pbir treats it as a hard error.
|
|
265
|
-
const namesSeenOnPage = new Map();
|
|
266
|
-
for (const v of visuals) {
|
|
267
|
-
results.visualsChecked += 1;
|
|
268
|
-
const { data, err } = readJsonSafe(v.path);
|
|
269
|
-
if (err) {
|
|
270
|
-
results.errors.push({
|
|
271
|
-
page: page.name,
|
|
272
|
-
visual: v.name,
|
|
273
|
-
severity: 'error',
|
|
274
|
-
rule: 'bad-json',
|
|
275
|
-
message: `could not parse visual.json: ${err.message}`,
|
|
276
|
-
});
|
|
277
|
-
continue;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// Duplicate-name check (page-scoped).
|
|
281
|
-
const declaredName = data && typeof data.name === 'string' ? data.name : null;
|
|
282
|
-
if (declaredName) {
|
|
283
|
-
if (namesSeenOnPage.has(declaredName)) {
|
|
284
|
-
results.errors.push({
|
|
285
|
-
page: page.name,
|
|
286
|
-
visual: v.name,
|
|
287
|
-
severity: 'error',
|
|
288
|
-
rule: 'duplicate-name',
|
|
289
|
-
message: `visual name "${declaredName}" is also used by "${namesSeenOnPage.get(declaredName)}" on this page`,
|
|
290
|
-
});
|
|
291
|
-
} else {
|
|
292
|
-
namesSeenOnPage.set(declaredName, v.name);
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
|
|
296
|
-
const visualErrors = validateVisual({ data, path: v.path });
|
|
297
|
-
for (const e of visualErrors) {
|
|
298
|
-
results.errors.push({
|
|
299
|
-
page: page.name,
|
|
300
|
-
visual: v.name,
|
|
301
|
-
...e,
|
|
302
|
-
});
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
const errorCount = results.errors.filter((e) => e.severity === 'error').length;
|
|
308
|
-
const warnCount = results.errors.filter((e) => e.severity === 'warn').length;
|
|
309
|
-
const valid = errorCount === 0;
|
|
310
|
-
|
|
311
|
-
if (args.json) {
|
|
312
|
-
process.stdout.write(JSON.stringify({ ...results, valid, errorCount, warnCount }, null, 2) + '\n');
|
|
313
|
-
} else {
|
|
314
|
-
const W = 77; // inner width between the | borders
|
|
315
|
-
const padRow = (label, value) => {
|
|
316
|
-
const text = `${label}: ${value}`;
|
|
317
|
-
return `| ${text}${' '.repeat(Math.max(0, W - text.length - 1))}|`;
|
|
318
|
-
};
|
|
319
|
-
const border = `+${'-'.repeat(W)}+`;
|
|
320
|
-
process.stdout.write(border + '\n');
|
|
321
|
-
process.stdout.write(padRow('valid', valid ? 'True' : 'False') + '\n');
|
|
322
|
-
process.stdout.write(padRow('pages_checked', String(results.pagesChecked)) + '\n');
|
|
323
|
-
process.stdout.write(padRow('visuals_checked', String(results.visualsChecked)) + '\n');
|
|
324
|
-
process.stdout.write(padRow('errors', String(errorCount)) + '\n');
|
|
325
|
-
process.stdout.write(padRow('warnings', String(warnCount)) + '\n');
|
|
326
|
-
process.stdout.write(border + '\n');
|
|
327
|
-
if (results.errors.length) {
|
|
328
|
-
process.stdout.write('\nIssues:\n');
|
|
329
|
-
for (const e of results.errors) {
|
|
330
|
-
const icon = e.severity === 'error' ? '✗' : '⚠';
|
|
331
|
-
const loc = `${e.page}/${e.visual}`;
|
|
332
|
-
process.stdout.write(` ${icon} [${e.rule}] ${loc}: ${e.message}\n`);
|
|
333
|
-
}
|
|
334
|
-
process.stdout.write('\n');
|
|
335
|
-
}
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
process.exit(valid ? 0 : 1);
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
module.exports = {
|
|
342
|
-
validateVisual,
|
|
343
|
-
boundRoles,
|
|
344
|
-
listPages,
|
|
345
|
-
listVisuals,
|
|
346
|
-
parseArgs,
|
|
347
|
-
};
|
|
348
|
-
|
|
349
|
-
if (require.main === module) {
|
|
350
|
-
main();
|
|
351
|
-
}
|
|
@@ -1,226 +0,0 @@
|
|
|
1
|
-
# Power BI MCP Connection Skill
|
|
2
|
-
|
|
3
|
-
## Trigger
|
|
4
|
-
Activate this skill when user mentions:
|
|
5
|
-
- "connect Power BI", "PBI connection", "MCP connection", "Power BI MCP"
|
|
6
|
-
- "modeling mcp", "Power BI Modeling MCP"
|
|
7
|
-
- "Power BI Desktop", "PBIP", "semantic model"
|
|
8
|
-
- "conectar Power BI", "MCP de Power BI", "modeling mcp"
|
|
9
|
-
- "can't connect to Power BI", "connection error", "MCP not working"
|
|
10
|
-
|
|
11
|
-
## Identity
|
|
12
|
-
You are a **Power BI MCP Connection Specialist**. Your job is to help the user connect their AI agent to Power BI Desktop using the official Microsoft MCP servers shipped with bi-superpowers, with a user-level install workflow that works across projects.
|
|
13
|
-
|
|
14
|
-
## MANDATORY RULES
|
|
15
|
-
1. **USER-LEVEL FIRST.** Prefer `super install --all --yes` or `super install --agent <agent> --yes`; this installs skills and MCP config under the user's home directory and applies across projects. `.mcp.json` is only for an optional repo-local Claude Code plugin.
|
|
16
|
-
2. **OFFICIAL SERVERS ONLY.** Use `powerbi-modeling-mcp` (local) and `microsoft-learn` (HTTP). Do not invent or recommend unofficial MCPs.
|
|
17
|
-
3. **WINDOWS LIMITATION.** Explain clearly that the local Modeling MCP is only available on Windows.
|
|
18
|
-
4. **NO PORT INVENTION.** Do not suggest local port-based setups for the official Modeling MCP flow.
|
|
19
|
-
5. **ONE QUESTION AT A TIME.** Follow the wizard pattern.
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
## PHASE 0: Initial Triage
|
|
24
|
-
|
|
25
|
-
Start with:
|
|
26
|
-
|
|
27
|
-
```text
|
|
28
|
-
POWER BI MCP CONNECTION
|
|
29
|
-
=======================
|
|
30
|
-
|
|
31
|
-
I'll help you connect your AI agent using the official Microsoft MCP servers.
|
|
32
|
-
|
|
33
|
-
What do you need?
|
|
34
|
-
|
|
35
|
-
1. Connect to Power BI Desktop on this machine (Windows)
|
|
36
|
-
2. Verify that my agent MCP config is installed correctly
|
|
37
|
-
3. Verify an optional local Claude Code plugin `.mcp.json`
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## PHASE 1: Local Modeling MCP (Windows)
|
|
43
|
-
|
|
44
|
-
If the user chooses option 1:
|
|
45
|
-
|
|
46
|
-
```text
|
|
47
|
-
LOCAL MODELING MCP
|
|
48
|
-
==================
|
|
49
|
-
|
|
50
|
-
This path uses Microsoft's official `powerbi-modeling-mcp` executable.
|
|
51
|
-
|
|
52
|
-
Before we continue:
|
|
53
|
-
|
|
54
|
-
1. Are you on Windows?
|
|
55
|
-
2. Did you install the "Power BI Modeling MCP" extension in VS Code or Cursor?
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
### If the user is on Windows and installed the extension
|
|
59
|
-
|
|
60
|
-
Guide them to the user-level install:
|
|
61
|
-
|
|
62
|
-
1. Run `super install --all --yes`, or for one agent run `super install --agent codex --yes` / `super install --agent claude-code --yes` / etc.
|
|
63
|
-
2. Confirm the agent config contains `powerbi-modeling-mcp` and `microsoft-learn`.
|
|
64
|
-
3. Restart or refresh the AI agent so it reloads skills and MCP servers.
|
|
65
|
-
|
|
66
|
-
Use these config locations:
|
|
67
|
-
|
|
68
|
-
| Agent | Skill path | MCP config |
|
|
69
|
-
| --- | --- | --- |
|
|
70
|
-
| Claude Code | `~/.claude/skills` or `~/.agents/skills` | `~/.claude.json` |
|
|
71
|
-
| GitHub Copilot | `~/.copilot/skills` | `~/.copilot/mcp-config.json` |
|
|
72
|
-
| Codex | `~/.agents/skills` | `~/.codex/config.toml` |
|
|
73
|
-
| Gemini CLI | `~/.gemini/skills` | `~/.gemini/settings.json` |
|
|
74
|
-
| Kilo Code | `~/.kilo/skills` | `~/.kilo/mcp_settings.json` |
|
|
75
|
-
|
|
76
|
-
Use this explanation:
|
|
77
|
-
|
|
78
|
-
```text
|
|
79
|
-
BI Agent Superpowers does not launch the Modeling MCP with `uvx`.
|
|
80
|
-
Instead, it uses a local wrapper that finds the official Microsoft executable
|
|
81
|
-
and starts it with `--start`.
|
|
82
|
-
```
|
|
83
|
-
|
|
84
|
-
If the user wants a config example, show:
|
|
85
|
-
|
|
86
|
-
```toml
|
|
87
|
-
[mcp_servers.powerbi-modeling-mcp]
|
|
88
|
-
command = "node"
|
|
89
|
-
args = ["<package-dir>/bin/mcp/powerbi-modeling-launcher.js"]
|
|
90
|
-
|
|
91
|
-
[mcp_servers.microsoft-learn]
|
|
92
|
-
url = "https://learn.microsoft.com/api/mcp"
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### If the user installed the executable manually
|
|
96
|
-
|
|
97
|
-
Tell them to set:
|
|
98
|
-
|
|
99
|
-
```text
|
|
100
|
-
BI_SUPERPOWERS_POWERBI_MODELING_MCP_PATH
|
|
101
|
-
```
|
|
102
|
-
|
|
103
|
-
Then re-run:
|
|
104
|
-
|
|
105
|
-
```bash
|
|
106
|
-
super install --all --yes
|
|
107
|
-
```
|
|
108
|
-
|
|
109
|
-
If they are intentionally maintaining a repo-local Claude Code plugin, they can run `super mcp-setup` inside that plugin project instead.
|
|
110
|
-
|
|
111
|
-
### If the user is on macOS or Linux
|
|
112
|
-
|
|
113
|
-
Say:
|
|
114
|
-
|
|
115
|
-
```text
|
|
116
|
-
The official local Power BI Modeling MCP is only available on Windows.
|
|
117
|
-
|
|
118
|
-
You still have `microsoft-learn` (HTTP) available on every platform for
|
|
119
|
-
docs, and you can work with Power BI files using the skills library.
|
|
120
|
-
For live editing of a local semantic model, you need a Windows environment.
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
---
|
|
124
|
-
|
|
125
|
-
## PHASE 2: Verify Agent MCP Config
|
|
126
|
-
|
|
127
|
-
If the user chooses option 2:
|
|
128
|
-
|
|
129
|
-
Check the config for the agent they use:
|
|
130
|
-
|
|
131
|
-
- Claude Code: `~/.claude.json`
|
|
132
|
-
- GitHub Copilot: `~/.copilot/mcp-config.json`
|
|
133
|
-
- Codex: `~/.codex/config.toml`
|
|
134
|
-
- Gemini CLI: `~/.gemini/settings.json`
|
|
135
|
-
- Kilo Code: `~/.kilo/mcp_settings.json`
|
|
136
|
-
|
|
137
|
-
Confirm:
|
|
138
|
-
|
|
139
|
-
- skills are installed under the agent's user-level skill directory
|
|
140
|
-
- config includes `powerbi-modeling-mcp`
|
|
141
|
-
- config includes `microsoft-learn`
|
|
142
|
-
|
|
143
|
-
If anything is missing, recommend:
|
|
144
|
-
|
|
145
|
-
```bash
|
|
146
|
-
super install --agent <agent-id> --yes
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
Then restart or refresh the agent.
|
|
150
|
-
|
|
151
|
-
## PHASE 3: Verify Optional Local Claude Code Plugin Config
|
|
152
|
-
|
|
153
|
-
If the user chooses option 3, or explicitly says they use `super kickoff` / `claude --plugin-dir`:
|
|
154
|
-
|
|
155
|
-
Check these files in order:
|
|
156
|
-
|
|
157
|
-
1. `.claude-plugin/plugin.json`
|
|
158
|
-
2. `.mcp.json`
|
|
159
|
-
3. `.bi-superpowers.json`
|
|
160
|
-
|
|
161
|
-
Confirm:
|
|
162
|
-
|
|
163
|
-
- plugin name is `bi-superpowers`
|
|
164
|
-
- `.mcp.json` includes `powerbi-modeling-mcp`
|
|
165
|
-
- `.mcp.json` includes `microsoft-learn`
|
|
166
|
-
|
|
167
|
-
If anything is missing, recommend:
|
|
168
|
-
|
|
169
|
-
```bash
|
|
170
|
-
super recharge
|
|
171
|
-
super mcp-setup
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
Then:
|
|
175
|
-
|
|
176
|
-
```bash
|
|
177
|
-
claude --plugin-dir .
|
|
178
|
-
```
|
|
179
|
-
|
|
180
|
-
---
|
|
181
|
-
|
|
182
|
-
## TROUBLESHOOTING
|
|
183
|
-
|
|
184
|
-
| Problem | What to do |
|
|
185
|
-
| --- | --- |
|
|
186
|
-
| Modeling MCP missing on Windows | Install the Microsoft extension in VS Code or Cursor |
|
|
187
|
-
| Modeling MCP installed manually | Set `BI_SUPERPOWERS_POWERBI_MODELING_MCP_PATH` |
|
|
188
|
-
| Agent not loading MCPs | Re-run `super install --agent <agent-id> --yes` and restart the agent |
|
|
189
|
-
| Local Claude Code plugin not loading MCPs | Re-run `super mcp-setup` inside the plugin project and restart Claude Code |
|
|
190
|
-
| macOS/Linux local modeling request | Use `microsoft-learn` for docs; live editing requires Windows |
|
|
191
|
-
| User asks about Excel MCP | Explain Excel remains supported through skills and library content, not a default MCP |
|
|
192
|
-
|
|
193
|
-
---
|
|
194
|
-
|
|
195
|
-
## ANTI-PATTERNS
|
|
196
|
-
|
|
197
|
-
| Don't Do This | Why | Do This Instead |
|
|
198
|
-
| --- | --- | --- |
|
|
199
|
-
| Recommend `uvx` for Modeling MCP | Not the official Microsoft installation path | Use the official executable via the local launcher |
|
|
200
|
-
| Ask the user to find a localhost port | Not required in the new flow | Use the official Modeling MCP launcher |
|
|
201
|
-
| Run `super kickoff` for Codex/GitHub Copilot/Gemini/Kilo setup | `kickoff` creates repo-local Claude Code plugin files | Use `super install --agent <agent-id> --yes` |
|
|
202
|
-
| Treat `.mcp.json` as the default install target | It is only for optional local Claude Code plugins | Use the agent's user-level MCP config |
|
|
203
|
-
| Invent unofficial MCPs (remote, fabric, etc.) | This plugin only ships 2 official MCPs | Only use the 2 official MCPs we ship (`powerbi-modeling-mcp` and `microsoft-learn`) |
|
|
204
|
-
|
|
205
|
-
---
|
|
206
|
-
|
|
207
|
-
## Complexity Adaptation
|
|
208
|
-
|
|
209
|
-
Adjust depth based on `config.json → experienceLevel`:
|
|
210
|
-
- **beginner**: Step-by-step with explanations, reference library examples
|
|
211
|
-
- **intermediate**: Standard depth, explain non-obvious decisions
|
|
212
|
-
- **advanced**: Concise, skip basics, focus on edge cases and optimization
|
|
213
|
-
|
|
214
|
-
---
|
|
215
|
-
|
|
216
|
-
## Related Skills
|
|
217
|
-
|
|
218
|
-
- `/project-kickoff` — Analyze a BI project and plan next steps
|
|
219
|
-
|
|
220
|
-
---
|
|
221
|
-
|
|
222
|
-
## RELATED RESOURCES
|
|
223
|
-
|
|
224
|
-
- [Power BI MCP overview](https://learn.microsoft.com/en-us/power-bi/developer/mcp/mcp-servers-overview)
|
|
225
|
-
- [Power BI Modeling MCP on GitHub](https://github.com/microsoft/powerbi-modeling-mcp)
|
|
226
|
-
- [Microsoft Learn MCP](https://learn.microsoft.com/en-us/training/support/mcp)
|