@luquimbo/bi-superpowers 3.2.0 → 4.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/.claude-plugin/marketplace.json +5 -3
- package/.claude-plugin/plugin.json +28 -2
- package/.claude-plugin/skill-manifest.json +22 -6
- package/.plugin/plugin.json +1 -1
- package/AGENTS.md +52 -36
- package/CHANGELOG.md +295 -0
- package/README.md +75 -26
- package/bin/build-plugin.js +11 -4
- package/bin/cli.js +113 -16
- package/bin/commands/build-desktop.js +35 -16
- package/bin/commands/diff.js +31 -13
- package/bin/commands/install.js +7 -3
- package/bin/commands/lint.js +40 -26
- package/bin/commands/mcp-setup.js +3 -10
- package/bin/commands/update-check.js +389 -0
- package/bin/lib/generators/claude-plugin.js +144 -6
- package/bin/lib/generators/shared.js +29 -33
- package/bin/lib/mcp-config.js +168 -12
- package/bin/lib/skills.js +115 -27
- package/bin/postinstall.js +4 -2
- package/bin/utils/mcp-detect.js +2 -2
- package/commands/bi-start.md +218 -0
- package/commands/pbi-connect.md +43 -65
- package/commands/project-kickoff.md +393 -673
- package/commands/report-design.md +403 -0
- package/desktop-extension/manifest.json +3 -3
- package/package.json +7 -5
- package/skills/bi-start/SKILL.md +220 -0
- package/skills/bi-start/scripts/update-check.js +389 -0
- package/skills/pbi-connect/SKILL.md +45 -67
- package/skills/pbi-connect/scripts/update-check.js +389 -0
- package/skills/project-kickoff/SKILL.md +395 -675
- package/skills/project-kickoff/scripts/update-check.js +389 -0
- package/skills/report-design/SKILL.md +405 -0
- package/skills/report-design/references/cli-commands.md +184 -0
- package/skills/report-design/references/cli-setup.md +101 -0
- package/skills/report-design/references/close-write-open-pattern.md +80 -0
- package/skills/report-design/references/layouts/finance.md +65 -0
- package/skills/report-design/references/layouts/generic.md +46 -0
- package/skills/report-design/references/layouts/hr.md +48 -0
- package/skills/report-design/references/layouts/marketing.md +45 -0
- package/skills/report-design/references/layouts/operations.md +44 -0
- package/skills/report-design/references/layouts/sales.md +50 -0
- package/skills/report-design/references/native-visuals.md +341 -0
- package/skills/report-design/references/pbi-desktop-installation.md +87 -0
- package/skills/report-design/references/pbir-preview-activation.md +40 -0
- package/skills/report-design/references/slicer.md +89 -0
- package/skills/report-design/references/textbox.md +101 -0
- package/skills/report-design/references/themes/BISuperpowers.json +915 -0
- package/skills/report-design/references/troubleshooting.md +135 -0
- package/skills/report-design/references/visual-types.md +78 -0
- package/skills/report-design/scripts/apply-theme.js +243 -0
- package/skills/report-design/scripts/create-visual.js +878 -0
- package/skills/report-design/scripts/ensure-pbi-cli.sh +41 -0
- package/skills/report-design/scripts/update-check.js +389 -0
- package/skills/report-design/scripts/validate-pbir.js +322 -0
- package/src/content/base.md +12 -68
- package/src/content/mcp-requirements.json +0 -25
- package/src/content/routing.md +19 -74
- package/src/content/skills/bi-start.md +191 -0
- package/src/content/skills/pbi-connect.md +22 -65
- package/src/content/skills/project-kickoff.md +372 -673
- package/src/content/skills/report-design/SKILL.md +376 -0
- package/src/content/skills/report-design/references/cli-commands.md +184 -0
- package/src/content/skills/report-design/references/cli-setup.md +101 -0
- package/src/content/skills/report-design/references/close-write-open-pattern.md +80 -0
- package/src/content/skills/report-design/references/layouts/finance.md +65 -0
- package/src/content/skills/report-design/references/layouts/generic.md +46 -0
- package/src/content/skills/report-design/references/layouts/hr.md +48 -0
- package/src/content/skills/report-design/references/layouts/marketing.md +45 -0
- package/src/content/skills/report-design/references/layouts/operations.md +44 -0
- package/src/content/skills/report-design/references/layouts/sales.md +50 -0
- package/src/content/skills/report-design/references/native-visuals.md +341 -0
- package/src/content/skills/report-design/references/pbi-desktop-installation.md +87 -0
- package/src/content/skills/report-design/references/pbir-preview-activation.md +40 -0
- package/src/content/skills/report-design/references/slicer.md +89 -0
- package/src/content/skills/report-design/references/textbox.md +101 -0
- package/src/content/skills/report-design/references/themes/BISuperpowers.json +915 -0
- package/src/content/skills/report-design/references/troubleshooting.md +135 -0
- package/src/content/skills/report-design/references/visual-types.md +78 -0
- package/src/content/skills/report-design/scripts/apply-theme.js +243 -0
- package/src/content/skills/report-design/scripts/create-visual.js +878 -0
- package/src/content/skills/report-design/scripts/ensure-pbi-cli.sh +41 -0
- package/src/content/skills/report-design/scripts/validate-pbir.js +322 -0
- package/bin/commands/install.test.js +0 -289
- package/bin/commands/lint.test.js +0 -103
- package/bin/lib/generators/claude-plugin.test.js +0 -111
- package/bin/lib/mcp-config.test.js +0 -310
- package/bin/lib/microsoft-mcp.test.js +0 -115
- package/bin/utils/mcp-detect.test.js +0 -81
- package/bin/utils/tui.test.js +0 -127
|
@@ -0,0 +1,322 @@
|
|
|
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 validateVisual(visual) {
|
|
134
|
+
const errors = [];
|
|
135
|
+
const { data, path: filePath } = visual;
|
|
136
|
+
|
|
137
|
+
// Schema URL check.
|
|
138
|
+
if (data.$schema !== EXPECTED_VISUAL_SCHEMA) {
|
|
139
|
+
errors.push({
|
|
140
|
+
severity: 'warn',
|
|
141
|
+
rule: 'schema-url',
|
|
142
|
+
message: `unexpected $schema (got ${data.$schema || 'none'})`,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// `name` must exist and match the folder.
|
|
147
|
+
if (typeof data.name !== 'string' || !data.name) {
|
|
148
|
+
errors.push({ severity: 'error', rule: 'name', message: 'missing "name"' });
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const vt = data.visual && data.visual.visualType;
|
|
152
|
+
if (!vt) {
|
|
153
|
+
errors.push({ severity: 'error', rule: 'visual-type', message: 'missing visualType' });
|
|
154
|
+
return errors;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// Allowlist: known non-native (like stackedBarChart).
|
|
158
|
+
if (KNOWN_NON_NATIVE_TYPES[vt]) {
|
|
159
|
+
errors.push({
|
|
160
|
+
severity: 'error',
|
|
161
|
+
rule: 'non-native-type',
|
|
162
|
+
visualType: vt,
|
|
163
|
+
message: KNOWN_NON_NATIVE_TYPES[vt],
|
|
164
|
+
});
|
|
165
|
+
return errors;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const def = NATIVE_VISUAL_TYPES[vt];
|
|
169
|
+
if (!def) {
|
|
170
|
+
errors.push({
|
|
171
|
+
severity: 'error',
|
|
172
|
+
rule: 'unknown-type',
|
|
173
|
+
visualType: vt,
|
|
174
|
+
message: `visualType "${vt}" is not in the native allowlist. Run create-visual.js --list-types for the canonical list.`,
|
|
175
|
+
});
|
|
176
|
+
return errors;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// Check required roles are bound (skip for textbox — no roles).
|
|
180
|
+
if (vt !== 'textbox') {
|
|
181
|
+
const bound = boundRoles(data);
|
|
182
|
+
for (const [role, spec] of Object.entries(def.roles)) {
|
|
183
|
+
if (spec.required && !bound.has(role)) {
|
|
184
|
+
errors.push({
|
|
185
|
+
severity: 'error',
|
|
186
|
+
rule: 'missing-required-role',
|
|
187
|
+
visualType: vt,
|
|
188
|
+
role,
|
|
189
|
+
message: `required role "${role}" has no projections (visualType: ${vt})`,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Check that every bound role is valid for this type.
|
|
195
|
+
for (const role of bound) {
|
|
196
|
+
if (!(role in def.roles)) {
|
|
197
|
+
errors.push({
|
|
198
|
+
severity: 'error',
|
|
199
|
+
rule: 'invalid-role',
|
|
200
|
+
visualType: vt,
|
|
201
|
+
role,
|
|
202
|
+
message: `role "${role}" is not valid for visualType ${vt}. Valid: ${Object.keys(def.roles).join(', ') || '(none)'}`,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return errors;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function main() {
|
|
212
|
+
const args = parseArgs(process.argv.slice(2));
|
|
213
|
+
if (args.help) {
|
|
214
|
+
printHelp();
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
217
|
+
if (!args.reportPath) fail('reportPath is required. Run --help for usage.', 2);
|
|
218
|
+
|
|
219
|
+
const reportPath = path.resolve(args.reportPath);
|
|
220
|
+
if (!fs.existsSync(reportPath)) fail(`not found: ${reportPath}`, 2);
|
|
221
|
+
|
|
222
|
+
const pages = listPages(reportPath);
|
|
223
|
+
const results = {
|
|
224
|
+
reportPath,
|
|
225
|
+
pagesChecked: pages.length,
|
|
226
|
+
visualsChecked: 0,
|
|
227
|
+
errors: [],
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
for (const page of pages) {
|
|
231
|
+
const visuals = listVisuals(page.dir);
|
|
232
|
+
// Track visual.name per page so we can flag duplicates. PBI Desktop
|
|
233
|
+
// does not reject a duplicate-name pair on load, but downstream tooling
|
|
234
|
+
// that references visuals by name (filters, bookmarks, selections) gets
|
|
235
|
+
// ambiguous — validate-pbir treats it as a hard error.
|
|
236
|
+
const namesSeenOnPage = new Map();
|
|
237
|
+
for (const v of visuals) {
|
|
238
|
+
results.visualsChecked += 1;
|
|
239
|
+
const { data, err } = readJsonSafe(v.path);
|
|
240
|
+
if (err) {
|
|
241
|
+
results.errors.push({
|
|
242
|
+
page: page.name,
|
|
243
|
+
visual: v.name,
|
|
244
|
+
severity: 'error',
|
|
245
|
+
rule: 'bad-json',
|
|
246
|
+
message: `could not parse visual.json: ${err.message}`,
|
|
247
|
+
});
|
|
248
|
+
continue;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
// Duplicate-name check (page-scoped).
|
|
252
|
+
const declaredName = data && typeof data.name === 'string' ? data.name : null;
|
|
253
|
+
if (declaredName) {
|
|
254
|
+
if (namesSeenOnPage.has(declaredName)) {
|
|
255
|
+
results.errors.push({
|
|
256
|
+
page: page.name,
|
|
257
|
+
visual: v.name,
|
|
258
|
+
severity: 'error',
|
|
259
|
+
rule: 'duplicate-name',
|
|
260
|
+
message: `visual name "${declaredName}" is also used by "${namesSeenOnPage.get(declaredName)}" on this page`,
|
|
261
|
+
});
|
|
262
|
+
} else {
|
|
263
|
+
namesSeenOnPage.set(declaredName, v.name);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const visualErrors = validateVisual({ data, path: v.path });
|
|
268
|
+
for (const e of visualErrors) {
|
|
269
|
+
results.errors.push({
|
|
270
|
+
page: page.name,
|
|
271
|
+
visual: v.name,
|
|
272
|
+
...e,
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
const errorCount = results.errors.filter((e) => e.severity === 'error').length;
|
|
279
|
+
const warnCount = results.errors.filter((e) => e.severity === 'warn').length;
|
|
280
|
+
const valid = errorCount === 0;
|
|
281
|
+
|
|
282
|
+
if (args.json) {
|
|
283
|
+
process.stdout.write(JSON.stringify({ ...results, valid, errorCount, warnCount }, null, 2) + '\n');
|
|
284
|
+
} else {
|
|
285
|
+
const W = 77; // inner width between the | borders
|
|
286
|
+
const padRow = (label, value) => {
|
|
287
|
+
const text = `${label}: ${value}`;
|
|
288
|
+
return `| ${text}${' '.repeat(Math.max(0, W - text.length - 1))}|`;
|
|
289
|
+
};
|
|
290
|
+
const border = `+${'-'.repeat(W)}+`;
|
|
291
|
+
process.stdout.write(border + '\n');
|
|
292
|
+
process.stdout.write(padRow('valid', valid ? 'True' : 'False') + '\n');
|
|
293
|
+
process.stdout.write(padRow('pages_checked', String(results.pagesChecked)) + '\n');
|
|
294
|
+
process.stdout.write(padRow('visuals_checked', String(results.visualsChecked)) + '\n');
|
|
295
|
+
process.stdout.write(padRow('errors', String(errorCount)) + '\n');
|
|
296
|
+
process.stdout.write(padRow('warnings', String(warnCount)) + '\n');
|
|
297
|
+
process.stdout.write(border + '\n');
|
|
298
|
+
if (results.errors.length) {
|
|
299
|
+
process.stdout.write('\nIssues:\n');
|
|
300
|
+
for (const e of results.errors) {
|
|
301
|
+
const icon = e.severity === 'error' ? '✗' : '⚠';
|
|
302
|
+
const loc = `${e.page}/${e.visual}`;
|
|
303
|
+
process.stdout.write(` ${icon} [${e.rule}] ${loc}: ${e.message}\n`);
|
|
304
|
+
}
|
|
305
|
+
process.stdout.write('\n');
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
process.exit(valid ? 0 : 1);
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
module.exports = {
|
|
313
|
+
validateVisual,
|
|
314
|
+
boundRoles,
|
|
315
|
+
listPages,
|
|
316
|
+
listVisuals,
|
|
317
|
+
parseArgs,
|
|
318
|
+
};
|
|
319
|
+
|
|
320
|
+
if (require.main === module) {
|
|
321
|
+
main();
|
|
322
|
+
}
|
package/src/content/base.md
CHANGED
|
@@ -59,67 +59,13 @@ You are a **Business Intelligence Expert** with deep knowledge of:
|
|
|
59
59
|
|
|
60
60
|
---
|
|
61
61
|
|
|
62
|
-
## Available
|
|
63
|
-
|
|
64
|
-
### Library Structure
|
|
65
|
-
|
|
66
|
-
```
|
|
67
|
-
library/
|
|
68
|
-
├── snippets/ # Reusable code patterns
|
|
69
|
-
│ ├── dax/ # DAX patterns and formulas
|
|
70
|
-
│ ├── power-query/ # M language patterns
|
|
71
|
-
│ ├── excel-formulas/ # Excel function patterns
|
|
72
|
-
│ ├── report-design/ # Chart selection, accessibility, layouts
|
|
73
|
-
│ └── governance/ # Naming conventions, review checklists
|
|
74
|
-
├── templates/ # Project templates
|
|
75
|
-
│ ├── power-bi/
|
|
76
|
-
│ ├── excel/
|
|
77
|
-
│ └── data-models/
|
|
78
|
-
├── themes/ # Visual themes
|
|
79
|
-
│ └── power-bi/ # Power BI JSON themes
|
|
80
|
-
└── examples/ # Reference implementations
|
|
81
|
-
├── finance-reporting/
|
|
82
|
-
├── hr-analytics/
|
|
83
|
-
├── retail-analytics/
|
|
84
|
-
├── supply-chain/
|
|
85
|
-
└── marketing-analytics/
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
### Skills (24 Total)
|
|
89
|
-
|
|
90
|
-
#### Command Skills (11 Interactive Wizards)
|
|
62
|
+
## Available Skills (3)
|
|
91
63
|
|
|
92
64
|
| Skill | Purpose | Trigger |
|
|
93
65
|
|-------|---------|---------|
|
|
94
|
-
| `/project-kickoff` | Analyze and
|
|
95
|
-
| `/
|
|
96
|
-
| `/
|
|
97
|
-
| `/rls-design` | Row-level security design | "RLS", "security" |
|
|
98
|
-
| `/pbi-connect` | Connect to Power BI Desktop | "connect Power BI", "MCP" |
|
|
99
|
-
| `/fabric-scripts` | Fabric automation scripts | "Fabric", "scripts" |
|
|
100
|
-
| `/contributions` | Contribution validation | "contribute", "PR" |
|
|
101
|
-
| `/dax-doctor` | DAX debugging wizard | "debug DAX", "fix measure" |
|
|
102
|
-
| `/model-documenter` | Model documentation generator | "document model", "data dictionary" |
|
|
103
|
-
| `/migration-assistant` | Migration and upgrade assistant | "migrate", "convert to PBIP" |
|
|
104
|
-
| `/report-layout` | Report page layout planner | "report layout", "page design" |
|
|
105
|
-
|
|
106
|
-
#### Reference Skills (13 Background Knowledge)
|
|
107
|
-
|
|
108
|
-
| Skill | Purpose |
|
|
109
|
-
|-------|---------|
|
|
110
|
-
| `/dax` | DAX writing and optimization |
|
|
111
|
-
| `/power-query` | Power Query / M language patterns |
|
|
112
|
-
| `/data-modeling` | Star schema theory and patterns |
|
|
113
|
-
| `/excel-formulas` | Modern Excel formula patterns |
|
|
114
|
-
| `/fast-standard` | FAST financial modeling standard |
|
|
115
|
-
| `/query-performance` | Performance optimization |
|
|
116
|
-
| `/data-quality` | Data validation patterns |
|
|
117
|
-
| `/testing-validation` | Testing and validation patterns |
|
|
118
|
-
| `/governance` | Naming conventions and standards |
|
|
119
|
-
| `/semantic-model` | Semantic model best practices |
|
|
120
|
-
| `/report-design` | Report design and visualization |
|
|
121
|
-
| `/deployment` | CI/CD and deployment patterns |
|
|
122
|
-
| `/dax-udf` | DAX user-defined functions (UDFs) |
|
|
66
|
+
| `/project-kickoff` | Analyze a BI project, build the semantic model, and write AGENTS.md | "analyze project", "get started", "kickoff" |
|
|
67
|
+
| `/pbi-connect` | Connect to Power BI Desktop via the official Modeling MCP | "connect Power BI", "MCP" |
|
|
68
|
+
| `/report-design` | Generate 3-page PBIR report via `pbi-cli-tool` (cards, charts, matrix, slicers) | "crear reportes", "report design", "dashboard" |
|
|
123
69
|
|
|
124
70
|
---
|
|
125
71
|
|
|
@@ -177,30 +123,28 @@ in
|
|
|
177
123
|
|
|
178
124
|
### Official Microsoft MCP Stack
|
|
179
125
|
|
|
180
|
-
BI Agent Superpowers
|
|
126
|
+
BI Agent Superpowers ships 2 official Microsoft MCP servers:
|
|
181
127
|
|
|
182
|
-
- `powerbi-
|
|
183
|
-
- `
|
|
184
|
-
- `powerbi-modeling-mcp` for local semantic model work on Windows
|
|
128
|
+
- `powerbi-modeling-mcp` — local stdio MCP for Power BI Desktop on Windows
|
|
129
|
+
- `microsoft-learn` — HTTP MCP for official Power BI / Fabric / DAX docs
|
|
185
130
|
|
|
186
131
|
### Connection model
|
|
187
132
|
|
|
188
|
-
**
|
|
133
|
+
**Local Modeling flow (Windows only)**
|
|
189
134
|
```
|
|
190
|
-
AI Assistant →
|
|
135
|
+
AI Assistant → local launcher → powerbi-modeling-mcp.exe --start → Power BI Desktop / PBIP semantic model
|
|
191
136
|
```
|
|
192
137
|
|
|
193
|
-
**
|
|
138
|
+
**Docs flow (any platform)**
|
|
194
139
|
```
|
|
195
|
-
AI Assistant →
|
|
140
|
+
AI Assistant → microsoft-learn HTTP MCP → learn.microsoft.com docs
|
|
196
141
|
```
|
|
197
142
|
|
|
198
143
|
### Practical guidance
|
|
199
144
|
|
|
200
145
|
- Prefer `.mcp.json` in the plugin root over tool-specific MCP config files.
|
|
201
146
|
- Never invent or hardcode local ports for the official Modeling MCP flow.
|
|
202
|
-
- On macOS/Linux, explain that the local Modeling MCP is unavailable and
|
|
203
|
-
- Excel remains supported as guidance, snippets, and templates, but it is not configured as a default MCP in the main product path.
|
|
147
|
+
- On macOS/Linux, explain that the local Modeling MCP is unavailable and fall back to `microsoft-learn` for docs. Live editing of a local model requires Windows.
|
|
204
148
|
|
|
205
149
|
---
|
|
206
150
|
|
|
@@ -1,30 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"mcps": [
|
|
3
|
-
{
|
|
4
|
-
"name": "powerbi-remote",
|
|
5
|
-
"displayName": "Power BI Remote MCP",
|
|
6
|
-
"source": "http",
|
|
7
|
-
"url": "https://api.fabric.microsoft.com/v1/mcp/powerbi",
|
|
8
|
-
"docs": "https://learn.microsoft.com/en-us/power-bi/developer/mcp/remote-mcp-server-get-started",
|
|
9
|
-
"requiresAuth": true,
|
|
10
|
-
"config": {
|
|
11
|
-
"type": "http",
|
|
12
|
-
"url": "https://api.fabric.microsoft.com/v1/mcp/powerbi"
|
|
13
|
-
}
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"name": "fabric-mcp-server",
|
|
17
|
-
"displayName": "Microsoft Fabric MCP Server",
|
|
18
|
-
"source": "npx",
|
|
19
|
-
"package": "@microsoft/fabric-mcp@latest",
|
|
20
|
-
"docs": "https://github.com/microsoft/mcp/tree/main/servers/Fabric.Mcp.Server",
|
|
21
|
-
"requiresAuth": true,
|
|
22
|
-
"config": {
|
|
23
|
-
"type": "stdio",
|
|
24
|
-
"command": "npx",
|
|
25
|
-
"args": ["-y", "@microsoft/fabric-mcp@latest", "server", "start", "--mode", "all"]
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
3
|
{
|
|
29
4
|
"name": "powerbi-modeling-mcp",
|
|
30
5
|
"displayName": "Power BI Modeling MCP",
|
package/src/content/routing.md
CHANGED
|
@@ -50,15 +50,9 @@ Scan current directory for relevant files:
|
|
|
50
50
|
|
|
51
51
|
| Files Detected | Suggested Skill |
|
|
52
52
|
|----------------|-----------------|
|
|
53
|
-
| `.pbix` files | `/project-kickoff` (if not analyzed) |
|
|
54
|
-
| `.
|
|
55
|
-
| `.
|
|
56
|
-
| `.xlsx` / `.xlsm` files | `/excel-formulas` |
|
|
57
|
-
| `dataflows/` folder | `/fabric-scripts` |
|
|
58
|
-
| `theme.json` | `/theme-tweaker` |
|
|
59
|
-
| `scripts/` with `.py` | `/fabric-scripts` |
|
|
60
|
-
| `.pbip` + no `.git` | `/migration-assistant` (suggest PBIP+Git) |
|
|
61
|
-
| `deployment/` or `.github/workflows/` | `/deployment` |
|
|
53
|
+
| `.pbix` / `.pbip` / `.tmdl` files | `/project-kickoff` (if not analyzed) |
|
|
54
|
+
| `.xlsx` / `.xlsm` files | `/project-kickoff` |
|
|
55
|
+
| No plugin `.mcp.json` found when user asks about Power BI | `/pbi-connect` |
|
|
62
56
|
|
|
63
57
|
### 4. CHECK KEYWORDS
|
|
64
58
|
|
|
@@ -66,31 +60,13 @@ Match user message against skill triggers:
|
|
|
66
60
|
|
|
67
61
|
| Keywords | Skill |
|
|
68
62
|
|----------|-------|
|
|
69
|
-
| "
|
|
70
|
-
| "
|
|
71
|
-
| "
|
|
72
|
-
| "theme", "colors", "branding", "visual style" | `/theme-tweaker` |
|
|
73
|
-
| "Excel", "formula", "XLOOKUP", "dynamic array" | `/excel-formulas` |
|
|
74
|
-
| "kickoff", "analyze project", "project analysis" | `/project-kickoff` |
|
|
75
|
-
| "design model", "create model", "new data model" | `/data-model-design` |
|
|
76
|
-
| "FAST", "financial model", "spreadsheet model" | `/fast-standard` |
|
|
77
|
-
| "RLS", "row-level security", "data security", "user filter" | `/rls-design` |
|
|
78
|
-
| "performance", "optimize", "slow", "DAX Studio" | `/query-performance` |
|
|
79
|
-
| "Fabric", "scripts", "deploy", "sync", "dataflow" | `/fabric-scripts` |
|
|
80
|
-
| "data quality", "validation", "null values", "profiling" | `/data-quality` |
|
|
81
|
-
| "debug DAX", "fix measure", "DAX not working", "wrong result", "DAX error" | `/dax-doctor` |
|
|
82
|
-
| "document model", "data dictionary", "model documentation" | `/model-documenter` |
|
|
83
|
-
| "migrate", "upgrade", "convert to PBIP", "move to Fabric" | `/migration-assistant` |
|
|
84
|
-
| "report layout", "page design", "visual placement", "dashboard layout" | `/report-layout` |
|
|
85
|
-
| "naming convention", "governance", "standards" | `/governance` |
|
|
86
|
-
| "semantic model", "TMDL", "DirectLake", "calculation groups" | `/semantic-model` |
|
|
87
|
-
| "report design", "chart type", "visualization", "IBCS", "accessibility" | `/report-design` |
|
|
88
|
-
| "CI/CD", "pipeline", "ALM", "DevOps", "git integration" | `/deployment` |
|
|
89
|
-
| "UDF", "user defined function", "DEFINE FUNCTION", "DAX Lib", "NAMEOF", "functions.tmdl" | `/dax-udf` |
|
|
63
|
+
| "kickoff", "analyze project", "analizar proyecto", "empezar", "qué tengo aquí?" | `/project-kickoff` |
|
|
64
|
+
| "connect Power BI", "MCP connection", "Power BI Desktop", "conectar Power BI", "modeling mcp" | `/pbi-connect` |
|
|
65
|
+
| "crear reportes", "armar reporte", "report design", "dashboard", "páginas del reporte", "visualizaciones" | `/report-design` |
|
|
90
66
|
|
|
91
67
|
### 5. DEFAULT BEHAVIOR
|
|
92
68
|
|
|
93
|
-
No skill activated → respond as general BI assistant using AGENTS.md context.
|
|
69
|
+
No skill activated → respond as general BI assistant using AGENTS.md context, referencing `library/` snippets when available in the user's project.
|
|
94
70
|
|
|
95
71
|
---
|
|
96
72
|
|
|
@@ -98,7 +74,7 @@ No skill activated → respond as general BI assistant using AGENTS.md context.
|
|
|
98
74
|
|
|
99
75
|
If multiple skills match:
|
|
100
76
|
|
|
101
|
-
1. **Explicit command always wins**
|
|
77
|
+
1. **Explicit command always wins** — `/skill-name` overrides everything
|
|
102
78
|
2. **Context + keyword same skill** → Activate immediately
|
|
103
79
|
3. **Context + keyword different skills** → Ask user which they prefer
|
|
104
80
|
4. **Never activate multiple wizard-style skills** simultaneously
|
|
@@ -122,46 +98,18 @@ Users can customize routing in `config.json`:
|
|
|
122
98
|
| Setting | Effect |
|
|
123
99
|
|---------|--------|
|
|
124
100
|
| `autoSuggestProjectKickoff: false` | Disable first-run auto-suggestion |
|
|
125
|
-
| `disabledSkills: ["
|
|
126
|
-
| `defaultSkill: "
|
|
101
|
+
| `disabledSkills: ["pbi-connect"]` | Never suggest these skills |
|
|
102
|
+
| `defaultSkill: "project-kickoff"` | Suggest this skill when context is ambiguous |
|
|
127
103
|
|
|
128
104
|
---
|
|
129
105
|
|
|
130
|
-
## Available Skills
|
|
131
|
-
|
|
132
|
-
### Interactive Wizards (Command Skills)
|
|
106
|
+
## Available Skills (3)
|
|
133
107
|
|
|
134
108
|
| Skill | Purpose | Typical Duration |
|
|
135
109
|
|-------|---------|-----------------|
|
|
136
|
-
| `/project-kickoff` | Analyze
|
|
137
|
-
| `/
|
|
138
|
-
| `/
|
|
139
|
-
| `/fabric-scripts` | Run Fabric automation scripts | 2-5 min |
|
|
140
|
-
| `/rls-design` | Design row-level security | 10-15 min |
|
|
141
|
-
| `/pbi-connect` | Connect to Power BI Desktop | 2-5 min |
|
|
142
|
-
| `/contributions` | Contribution validation | 2-5 min |
|
|
143
|
-
| `/dax-doctor` | DAX debugging and optimization | 5-15 min |
|
|
144
|
-
| `/model-documenter` | Semantic model documentation | 5-10 min |
|
|
145
|
-
| `/migration-assistant` | Migration and upgrade wizard | 10-20 min |
|
|
146
|
-
| `/report-layout` | Report page layout planner | 10-15 min |
|
|
147
|
-
|
|
148
|
-
### Reference Skills (Background Knowledge)
|
|
149
|
-
|
|
150
|
-
| Skill | Purpose |
|
|
151
|
-
|-------|---------|
|
|
152
|
-
| `/dax` | DAX best practices and patterns |
|
|
153
|
-
| `/power-query` | Power Query/M code patterns |
|
|
154
|
-
| `/data-modeling` | Dimensional modeling guidance |
|
|
155
|
-
| `/excel-formulas` | Modern Excel formula patterns |
|
|
156
|
-
| `/fast-standard` | FAST financial modeling standard |
|
|
157
|
-
| `/query-performance` | Performance optimization |
|
|
158
|
-
| `/data-quality` | Data validation patterns |
|
|
159
|
-
| `/testing-validation` | Testing and validation patterns |
|
|
160
|
-
| `/governance` | Naming conventions and standards |
|
|
161
|
-
| `/semantic-model` | Semantic model best practices |
|
|
162
|
-
| `/report-design` | Report design and visualization |
|
|
163
|
-
| `/deployment` | CI/CD and deployment patterns |
|
|
164
|
-
| `/dax-udf` | DAX user-defined functions (UDFs) |
|
|
110
|
+
| `/project-kickoff` | Analyze a BI project, build the semantic model, and write AGENTS.md | 10-20 min |
|
|
111
|
+
| `/pbi-connect` | Connect to Power BI Desktop via the official Microsoft MCP | 2-5 min |
|
|
112
|
+
| `/report-design` | Generate 3-page PBIR report via `pbi-cli-tool` CLI (requires close-write-open cycle) | 5-15 min |
|
|
165
113
|
|
|
166
114
|
---
|
|
167
115
|
|
|
@@ -170,14 +118,11 @@ Users can customize routing in `config.json`:
|
|
|
170
118
|
After completing a skill, suggest the logical next step:
|
|
171
119
|
|
|
172
120
|
| After Completing | Suggest Next |
|
|
173
|
-
|
|
174
|
-
| `/project-kickoff` | `/
|
|
175
|
-
| `/
|
|
176
|
-
| `/
|
|
177
|
-
| `/
|
|
178
|
-
| `/model-documenter` | `/governance` |
|
|
179
|
-
| `/migration-assistant` | `/fabric-scripts` → `/deployment` |
|
|
180
|
-
| `/rls-design` | `/testing-validation` |
|
|
121
|
+
|-----------------|--------------|
|
|
122
|
+
| `/project-kickoff` (model base ready) | `/report-design` to build the 3 report pages |
|
|
123
|
+
| `/project-kickoff` (MCP not connected) | `/pbi-connect` to set up the connection |
|
|
124
|
+
| `/report-design` | None — hand off to the user for refresh + iteration in Power BI Desktop |
|
|
125
|
+
| `/pbi-connect` | Back to `/project-kickoff` if the project hasn't been analyzed yet |
|
|
181
126
|
|
|
182
127
|
**Suggestion format:**
|
|
183
128
|
```
|