@microsoft/powerbi-modeling-mcp-linux-arm64 0.5.0-beta.13 → 0.5.0-beta.15
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 +27 -1
- package/LICENSE +21 -99
- package/NOTICE.txt +15014 -0
- package/README.md +33 -8
- package/dist/Resources/calendar_instructions_and_examples.md +249 -0
- package/dist/Resources/dax_query_instructions_and_examples.md +714 -0
- package/dist/Resources/dax_udf_instructions_and_examples.md +270 -0
- package/dist/Resources/powerbi_project_instructions.md +84 -0
- package/dist/Resources/tools/tool-metadata.override.yaml +7 -0
- package/dist/Resources/tools/tool-metadata.yaml +495 -0
- package/dist/powerbi-modeling-mcp +2 -2
- package/package.json +3 -3
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: 'DAX UDF Instructions and Examples'
|
|
3
|
+
description: 'Guidelines for creating Power BI DAX user-defined functions (UDFs)'
|
|
4
|
+
uriTemplate: 'resource://dax_udf_instructions_and_examples'
|
|
5
|
+
---
|
|
6
|
+
# DAX User-Defined Functions (UDFs) Guide
|
|
7
|
+
|
|
8
|
+
## Overview
|
|
9
|
+
|
|
10
|
+
DAX User-Defined Functions (UDFs) allow you to create reusable function definitions in Power BI semantic models. This guide explains the syntax, type system, and best practices for defining UDFs.
|
|
11
|
+
|
|
12
|
+
## Basic Syntax
|
|
13
|
+
|
|
14
|
+
A UDF definition consists of a function name and a function definition with parameters and a body:
|
|
15
|
+
|
|
16
|
+
```yaml
|
|
17
|
+
FunctionName: MyFunction
|
|
18
|
+
FunctionDefinition: |-
|
|
19
|
+
(param1 [: Type [Scalar Subtype] [Val|Expr]],
|
|
20
|
+
param2 [: Type [Scalar Subtype] [Val|Expr]],
|
|
21
|
+
...
|
|
22
|
+
) =>
|
|
23
|
+
<Function body>
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Type System
|
|
27
|
+
|
|
28
|
+
### Parameter Types
|
|
29
|
+
|
|
30
|
+
DAX UDFs support three main parameter types:
|
|
31
|
+
|
|
32
|
+
* **Scalar**: A single value (number, text, date/time, boolean)
|
|
33
|
+
* **Table**: A DAX table expression
|
|
34
|
+
* **AnyRef**: A direct reference to an existing semantic model object without pre-evaluation
|
|
35
|
+
|
|
36
|
+
#### Scalar Subtypes
|
|
37
|
+
|
|
38
|
+
When using `Scalar` type, you can optionally specify a subtype:
|
|
39
|
+
|
|
40
|
+
* `Int64`: Integer values
|
|
41
|
+
* `Decimal`: Decimal numbers
|
|
42
|
+
* `Double`: Double-precision floating-point numbers
|
|
43
|
+
* `String`: Text values
|
|
44
|
+
* `DateTime`: Date and time values
|
|
45
|
+
* `Boolean`: True/false values
|
|
46
|
+
* `Numeric`: Any numeric type (Int64, Decimal, or Double)
|
|
47
|
+
* `Variant`: Any scalar type (use when the expression may yield different types)
|
|
48
|
+
|
|
49
|
+
**Note**: `BLANK()` is valid for any subtype.
|
|
50
|
+
|
|
51
|
+
### AnyRef Type
|
|
52
|
+
|
|
53
|
+
Use `AnyRef` when you need a direct reference to a model object rather than its evaluated value. This is useful for functions that need to pass references to functions like CALCULATE, TREATAS, or SAMEPERIODLASTYEAR.
|
|
54
|
+
|
|
55
|
+
Allowed reference forms:
|
|
56
|
+
|
|
57
|
+
* Column reference: `'Table'[Column]`
|
|
58
|
+
* Table reference: `'Table'`
|
|
59
|
+
* Measure reference: `[Measure]`
|
|
60
|
+
* Calendar reference: `MyCalendar`
|
|
61
|
+
|
|
62
|
+
### Parameter Modes
|
|
63
|
+
|
|
64
|
+
Parameters can be evaluated in two modes:
|
|
65
|
+
|
|
66
|
+
* **Val** (value mode - default): The argument expression is evaluated at the call site before entering the function. The resulting value is substituted wherever the parameter is used.
|
|
67
|
+
* **Expr** (expression mode): The raw argument expression is substituted into the function body and evaluated in its inner context. Use this when you want the expression to be re-evaluated within inner contexts created by CALCULATE, FILTER, or iteration functions.
|
|
68
|
+
|
|
69
|
+
## Example Schema
|
|
70
|
+
|
|
71
|
+
The following examples reference this sample data model:
|
|
72
|
+
|
|
73
|
+
```yaml
|
|
74
|
+
Tables:
|
|
75
|
+
- Name: Sales
|
|
76
|
+
Measures:
|
|
77
|
+
- Name: Total Amount
|
|
78
|
+
Type: Decimal
|
|
79
|
+
- Name: Total Quantity
|
|
80
|
+
Type: Integer
|
|
81
|
+
Columns:
|
|
82
|
+
- Name: CustomerKey
|
|
83
|
+
Type: Text
|
|
84
|
+
- Name: ProductKey
|
|
85
|
+
Type: Text
|
|
86
|
+
- Name: OrderDate
|
|
87
|
+
Type: Date
|
|
88
|
+
- Name: Product
|
|
89
|
+
Columns:
|
|
90
|
+
- Name: ProductKey
|
|
91
|
+
Type: Text
|
|
92
|
+
- Name: Name
|
|
93
|
+
Type: Text
|
|
94
|
+
- Name: Color
|
|
95
|
+
Type: Text
|
|
96
|
+
- Name: Customer
|
|
97
|
+
Columns:
|
|
98
|
+
- Name: CustomerKey
|
|
99
|
+
Type: Text
|
|
100
|
+
- Name: Name
|
|
101
|
+
Type: Text
|
|
102
|
+
- Name: Calendar
|
|
103
|
+
Columns:
|
|
104
|
+
- Name: Date
|
|
105
|
+
Type: Date
|
|
106
|
+
- Name: Month
|
|
107
|
+
Type: Text
|
|
108
|
+
SortByColumnName: MonthNumberOfYear
|
|
109
|
+
- Name: MonthNumberOfYear
|
|
110
|
+
Type: Integer
|
|
111
|
+
- Name: Year
|
|
112
|
+
Type: Integer
|
|
113
|
+
Active Relationships:
|
|
114
|
+
- PK: 'Product'[ProductKey]
|
|
115
|
+
FK: 'Sales'[ProductKey]
|
|
116
|
+
Unidirectional Filter Propagation: "'Product' filters 'Sales'"
|
|
117
|
+
- PK: 'Customer'[CustomerKey]
|
|
118
|
+
FK: 'Sales'[CustomerKey]
|
|
119
|
+
Unidirectional Filter Propagation: "'Customer' filters 'Sales'"
|
|
120
|
+
- PK: 'Calendar'[Date]
|
|
121
|
+
FK: 'Sales'[OrderDate]
|
|
122
|
+
Unidirectional Filter Propagation: "'Calendar' filters 'Sales'"
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## Examples
|
|
126
|
+
|
|
127
|
+
### Example 1: Simple Numeric Calculation
|
|
128
|
+
|
|
129
|
+
Calculate the area of a circle from its radius.
|
|
130
|
+
|
|
131
|
+
```yaml
|
|
132
|
+
FunctionName: CircleArea
|
|
133
|
+
FunctionDefinition: |-
|
|
134
|
+
(radius : Scalar Numeric) =>
|
|
135
|
+
PI() * radius * radius
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Usage**: `CircleArea(5)` returns approximately 78.54
|
|
139
|
+
|
|
140
|
+
### Example 2: Basic Value Transformation
|
|
141
|
+
|
|
142
|
+
Double an input value.
|
|
143
|
+
|
|
144
|
+
```yaml
|
|
145
|
+
FunctionName: DoubleValue
|
|
146
|
+
FunctionDefinition: |-
|
|
147
|
+
(inputValue : Scalar Numeric Val) =>
|
|
148
|
+
inputValue * 2
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Usage**: `DoubleValue(10)` returns 20
|
|
152
|
+
|
|
153
|
+
### Example 3: Working with AnyRef - Statistical Function
|
|
154
|
+
|
|
155
|
+
Returns the most frequently occurring value in a column.
|
|
156
|
+
|
|
157
|
+
```yaml
|
|
158
|
+
FunctionName: Mode
|
|
159
|
+
FunctionDefinition: |-
|
|
160
|
+
(tab : AnyRef,
|
|
161
|
+
col : AnyRef
|
|
162
|
+
) =>
|
|
163
|
+
MINX(
|
|
164
|
+
TOPN(
|
|
165
|
+
1,
|
|
166
|
+
ADDCOLUMNS(
|
|
167
|
+
VALUES(col),
|
|
168
|
+
"Freq", CALCULATE(COUNTROWS(tab))
|
|
169
|
+
),
|
|
170
|
+
[Freq], DESC
|
|
171
|
+
),
|
|
172
|
+
col
|
|
173
|
+
)
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**Explanation**: This function uses `AnyRef` for both parameters because it needs to pass the table and column references to DAX functions like VALUES and CALCULATE. The function finds the value that appears most frequently by counting occurrences.
|
|
177
|
+
|
|
178
|
+
**Usage**: `Mode('Sales', 'Sales'[ProductKey])`
|
|
179
|
+
|
|
180
|
+
### Example 4: Using Expr Mode for Time Intelligence
|
|
181
|
+
|
|
182
|
+
Evaluate any scalar expression in the prior year.
|
|
183
|
+
|
|
184
|
+
```yaml
|
|
185
|
+
FunctionName: PriorYearValue
|
|
186
|
+
FunctionDefinition: |-
|
|
187
|
+
(expression : Scalar Variant Expr,
|
|
188
|
+
dateColumn : AnyRef
|
|
189
|
+
) =>
|
|
190
|
+
CALCULATE(
|
|
191
|
+
expression,
|
|
192
|
+
SAMEPERIODLASTYEAR(dateColumn)
|
|
193
|
+
)
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
**Explanation**: The `expression` parameter uses `Expr` mode so it's evaluated within the CALCULATE context with the prior year filter applied. The `dateColumn` uses `AnyRef` to pass the column reference to SAMEPERIODLASTYEAR.
|
|
197
|
+
|
|
198
|
+
**Usage**: `PriorYearValue([Total Amount], 'Calendar'[Date])`
|
|
199
|
+
|
|
200
|
+
### Example 5: Returning a Table Filter
|
|
201
|
+
|
|
202
|
+
Return today's date as a one-row table for filtering.
|
|
203
|
+
|
|
204
|
+
```yaml
|
|
205
|
+
FunctionName: TodayAsDate
|
|
206
|
+
FunctionDefinition: |-
|
|
207
|
+
() =>
|
|
208
|
+
TREATAS(
|
|
209
|
+
{ TODAY() },
|
|
210
|
+
'Date'[Date]
|
|
211
|
+
)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
**Explanation**: This function demonstrates a UDF that returns a table. It uses TREATAS to convert the single-value table into a filter compatible with the Date table.
|
|
215
|
+
|
|
216
|
+
**Usage**: `CALCULATE([Total Amount], TodayAsDate())`
|
|
217
|
+
|
|
218
|
+
### Example 6: Table-Returning Function
|
|
219
|
+
|
|
220
|
+
Return a table of the top 3 Products by the [Sales] measure.
|
|
221
|
+
|
|
222
|
+
```yaml
|
|
223
|
+
FunctionName: Top3ProductsBySales
|
|
224
|
+
FunctionDefinition: |-
|
|
225
|
+
() =>
|
|
226
|
+
TOPN(
|
|
227
|
+
3,
|
|
228
|
+
VALUES('Product'[ProductKey]),
|
|
229
|
+
[Sales], DESC
|
|
230
|
+
)
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Explanation**: This parameterless function returns a table containing the top 3 products. It can be used anywhere a table expression is expected.
|
|
234
|
+
|
|
235
|
+
**Usage**: `CALCULATE([Total Amount], Top3ProductsBySales())`
|
|
236
|
+
|
|
237
|
+
### Example 7: String Manipulation with Table Return
|
|
238
|
+
|
|
239
|
+
Split a text by a delimiter and return a single-column table.
|
|
240
|
+
|
|
241
|
+
```yaml
|
|
242
|
+
FunctionName: SplitString
|
|
243
|
+
FunctionDefinition: |-
|
|
244
|
+
(s : Scalar String,
|
|
245
|
+
delimiter : Scalar String
|
|
246
|
+
) =>
|
|
247
|
+
VAR str =
|
|
248
|
+
SUBSTITUTE(s, delimiter, "|")
|
|
249
|
+
VAR len =
|
|
250
|
+
PATHLENGTH(str)
|
|
251
|
+
RETURN
|
|
252
|
+
SELECTCOLUMNS(
|
|
253
|
+
GENERATESERIES(1, len),
|
|
254
|
+
"Value", PATHITEM(str, [Value], TEXT)
|
|
255
|
+
)
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**Explanation**: This function uses variables (VAR) and demonstrates how to build complex logic. It converts the delimiter to a path separator, counts the parts, and returns a table with each part as a row.
|
|
259
|
+
|
|
260
|
+
**Usage**: `SplitString("apple,banana,cherry", ",")`
|
|
261
|
+
|
|
262
|
+
## Best Practices
|
|
263
|
+
|
|
264
|
+
1. **Use appropriate type hints**: Specify types and subtypes to make your functions more robust and self-documenting
|
|
265
|
+
2. **Choose the right parameter mode**: Use `Expr` when you need the expression to be evaluated in the function's context, otherwise use `Val` (default)
|
|
266
|
+
3. **Use AnyRef for references**: When passing columns, tables, or measures to DAX functions that expect references, use `AnyRef`
|
|
267
|
+
4. **Document your functions**: Include clear descriptions of what each function does
|
|
268
|
+
5. **Test with edge cases**: Consider BLANK values and empty tables in your function logic
|
|
269
|
+
6. **Keep functions focused**: Each function should have a single, well-defined purpose
|
|
270
|
+
7. **Use variables**: For complex functions, use VAR to break down logic and improve readability
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: 'PowerBI Project Instructions'
|
|
3
|
+
description: 'Instructions for structuring Power BI projects'
|
|
4
|
+
uriTemplate: 'resource://powerbi_project_instructions'
|
|
5
|
+
---
|
|
6
|
+
You are an expert in Power BI Project (PBIP) file structure.
|
|
7
|
+
|
|
8
|
+
If the `powerbi-modeling-mcp` MCP server is available, **do not create or edit the TMDL files directly**.
|
|
9
|
+
|
|
10
|
+
## PBIP structure
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
root/
|
|
14
|
+
├── [Name].SemanticModel/
|
|
15
|
+
| ├── /definition # The semantic model definition using TMDL language
|
|
16
|
+
| ├── definition.pbism # The semantic model definition file
|
|
17
|
+
├── [Name].Report/
|
|
18
|
+
| ├── /definition # The report definition using PBIR format
|
|
19
|
+
| ├── definition.pbir # The report definition file with a byPath relative reference to the semantic model folder
|
|
20
|
+
└── [Name].pbip # A shortcut file to the report folder
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Example of a definition.pbism file**
|
|
24
|
+
|
|
25
|
+
No modifications are needed—just create the file exactly as shown in the example.
|
|
26
|
+
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"$schema": "https://developer.microsoft.com/json-schemas/fabric/item/semanticModel/definitionProperties/1.0.0/schema.json",
|
|
30
|
+
"version": "4.2",
|
|
31
|
+
"settings": {
|
|
32
|
+
"qnaEnabled": true
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Example of a definition.pbir file**
|
|
38
|
+
|
|
39
|
+
The `byPath` property should reference the semantic model folder using a relative path like below.
|
|
40
|
+
|
|
41
|
+
```json
|
|
42
|
+
{
|
|
43
|
+
"$schema": "https://developer.microsoft.com/json-schemas/fabric/item/report/definitionProperties/2.0.0/schema.json",
|
|
44
|
+
"version": "4.0",
|
|
45
|
+
"datasetReference": {
|
|
46
|
+
"byPath": {
|
|
47
|
+
"path": "../{Name of the Semantic Model}.SemanticModel"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Example of a {Name of the Semantic Model}.pbip file**
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"$schema": "https://developer.microsoft.com/json-schemas/fabric/pbip/pbipProperties/1.0.0/schema.json",
|
|
58
|
+
"version": "1.0",
|
|
59
|
+
"artifacts": [
|
|
60
|
+
{
|
|
61
|
+
"report": {
|
|
62
|
+
"path": "{Name of the Semantic Model}.Report"
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
],
|
|
66
|
+
"settings": {
|
|
67
|
+
"enableAutoRecovery": true
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Open from PBIP
|
|
73
|
+
|
|
74
|
+
When asked to open/load the semantic model from a PBIP, you must only load the `[Name].SemanticModel/definition` folder. No other folder is suitable to load from semantic model developer tools.
|
|
75
|
+
|
|
76
|
+
## Save to PBIP
|
|
77
|
+
|
|
78
|
+
When asked to save to a new PBIP folder make sure you create the folder and files from the structure above using the provided examples.
|
|
79
|
+
|
|
80
|
+
## Creation of new semantic model
|
|
81
|
+
|
|
82
|
+
1. Create a PBIP folder for the semantic model following the structure above
|
|
83
|
+
2. Use the `database_operations` tool of the MCP server to `Create` a new database.
|
|
84
|
+
3. In the end of the authoring session, serialize as TMDL to the `definition/` folder in the PBIP
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
tools:
|
|
2
|
+
accept_eula:
|
|
3
|
+
description: >-
|
|
4
|
+
Accepts the Power BI Authoring MCP End User License Agreement (EULA) at https://github.com/microsoft/powerbi-modeling-mcp. This tool must not be called automatically or speculatively by an AI agent. Only call it after a human user has reviewed the EULA at that URL and explicitly instructed you to accept it on their behalf.
|
|
5
|
+
request:
|
|
6
|
+
EulaUrl: >-
|
|
7
|
+
The exact EULA URL the user reviewed. Must be https://github.com/microsoft/powerbi-modeling-mcp
|