pbix-mcp 0.2.0__tar.gz

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.
Files changed (60) hide show
  1. pbix_mcp-0.2.0/.coveragerc +14 -0
  2. pbix_mcp-0.2.0/.github/ISSUE_TEMPLATE/bug_report.yml +63 -0
  3. pbix_mcp-0.2.0/.github/ISSUE_TEMPLATE/feature_request.yml +46 -0
  4. pbix_mcp-0.2.0/.github/workflows/ci.yml +49 -0
  5. pbix_mcp-0.2.0/.github/workflows/release.yml +67 -0
  6. pbix_mcp-0.2.0/.gitignore +30 -0
  7. pbix_mcp-0.2.0/CHANGELOG.md +59 -0
  8. pbix_mcp-0.2.0/CONTRIBUTING.md +66 -0
  9. pbix_mcp-0.2.0/LICENSE +21 -0
  10. pbix_mcp-0.2.0/PKG-INFO +442 -0
  11. pbix_mcp-0.2.0/README.md +406 -0
  12. pbix_mcp-0.2.0/SUPPORT.md +59 -0
  13. pbix_mcp-0.2.0/docs/architecture.md +74 -0
  14. pbix_mcp-0.2.0/docs/development.md +66 -0
  15. pbix_mcp-0.2.0/docs/limitations.md +63 -0
  16. pbix_mcp-0.2.0/docs/supported-dax.md +39 -0
  17. pbix_mcp-0.2.0/docs/tool-contracts.md +97 -0
  18. pbix_mcp-0.2.0/examples/create_all_types.py +40 -0
  19. pbix_mcp-0.2.0/examples/create_directquery.py +62 -0
  20. pbix_mcp-0.2.0/examples/create_from_csv.py +82 -0
  21. pbix_mcp-0.2.0/examples/create_from_sqlite.py +79 -0
  22. pbix_mcp-0.2.0/examples/create_star_schema.py +90 -0
  23. pbix_mcp-0.2.0/pyproject.toml +87 -0
  24. pbix_mcp-0.2.0/scripts/build_fixtures.py +212 -0
  25. pbix_mcp-0.2.0/scripts/create_demo_report.py +142 -0
  26. pbix_mcp-0.2.0/scripts/download_test_corpus.py +92 -0
  27. pbix_mcp-0.2.0/src/pbix_mcp/__init__.py +3 -0
  28. pbix_mcp-0.2.0/src/pbix_mcp/builder.py +2346 -0
  29. pbix_mcp-0.2.0/src/pbix_mcp/cli.py +34 -0
  30. pbix_mcp-0.2.0/src/pbix_mcp/dax/__init__.py +1 -0
  31. pbix_mcp-0.2.0/src/pbix_mcp/dax/calc_tables.py +639 -0
  32. pbix_mcp-0.2.0/src/pbix_mcp/dax/engine.py +3607 -0
  33. pbix_mcp-0.2.0/src/pbix_mcp/errors.py +128 -0
  34. pbix_mcp-0.2.0/src/pbix_mcp/formats/__init__.py +1 -0
  35. pbix_mcp-0.2.0/src/pbix_mcp/formats/abf_rebuild.py +860 -0
  36. pbix_mcp-0.2.0/src/pbix_mcp/formats/datamodel_roundtrip.py +219 -0
  37. pbix_mcp-0.2.0/src/pbix_mcp/formats/vertipaq_encoder.py +1677 -0
  38. pbix_mcp-0.2.0/src/pbix_mcp/logging_config.py +52 -0
  39. pbix_mcp-0.2.0/src/pbix_mcp/models/__init__.py +1 -0
  40. pbix_mcp-0.2.0/src/pbix_mcp/models/requests.py +47 -0
  41. pbix_mcp-0.2.0/src/pbix_mcp/models/responses.py +116 -0
  42. pbix_mcp-0.2.0/src/pbix_mcp/server.py +3620 -0
  43. pbix_mcp-0.2.0/src/pbix_mcp/templates/__init__.py +0 -0
  44. pbix_mcp-0.2.0/src/pbix_mcp/templates/minimal_datamodel.bin +0 -0
  45. pbix_mcp-0.2.0/src/pbix_mcp/templates/minimal_template.pbix +0 -0
  46. pbix_mcp-0.2.0/test_samples/.gitkeep +0 -0
  47. pbix_mcp-0.2.0/tests/__init__.py +0 -0
  48. pbix_mcp-0.2.0/tests/fixtures/expected/basic_layout.json +12 -0
  49. pbix_mcp-0.2.0/tests/fixtures/expected/dax_golden.json +49 -0
  50. pbix_mcp-0.2.0/tests/fixtures/pbix/basic_layout.pbix +0 -0
  51. pbix_mcp-0.2.0/tests/fixtures/pbix/basic_measures.pbix +0 -0
  52. pbix_mcp-0.2.0/tests/fixtures/pbix/from_scratch.pbix +0 -0
  53. pbix_mcp-0.2.0/tests/fixtures/pbix/with_data.pbix +0 -0
  54. pbix_mcp-0.2.0/tests/test_beta_features.py +207 -0
  55. pbix_mcp-0.2.0/tests/test_cross_report.py +312 -0
  56. pbix_mcp-0.2.0/tests/test_dax_accuracy.py +494 -0
  57. pbix_mcp-0.2.0/tests/test_dax_engine.py +515 -0
  58. pbix_mcp-0.2.0/tests/test_errors_and_models.py +248 -0
  59. pbix_mcp-0.2.0/tests/test_fixtures.py +260 -0
  60. pbix_mcp-0.2.0/tests/test_golden.py +587 -0
@@ -0,0 +1,14 @@
1
+ [run]
2
+ source = src/pbix_mcp
3
+ branch = true
4
+ omit =
5
+ tests/*
6
+ */__pycache__/*
7
+
8
+ [report]
9
+ show_missing = true
10
+ fail_under = 25
11
+ exclude_lines =
12
+ pragma: no cover
13
+ if __name__ == .__main__.
14
+ pass
@@ -0,0 +1,63 @@
1
+ name: Bug Report
2
+ description: Report something that isn't working correctly
3
+ labels: ["bug"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Thanks for taking the time to report a bug!
9
+
10
+ - type: textarea
11
+ id: description
12
+ attributes:
13
+ label: What happened?
14
+ description: Describe what went wrong. Include error messages if any.
15
+ validations:
16
+ required: true
17
+
18
+ - type: textarea
19
+ id: expected
20
+ attributes:
21
+ label: What did you expect?
22
+ validations:
23
+ required: true
24
+
25
+ - type: textarea
26
+ id: reproduce
27
+ attributes:
28
+ label: Steps to reproduce
29
+ placeholder: |
30
+ 1. Create a PBIX with ...
31
+ 2. Call pbix_create with ...
32
+ 3. Open in PBI Desktop ...
33
+ validations:
34
+ required: true
35
+
36
+ - type: dropdown
37
+ id: category
38
+ attributes:
39
+ label: Category
40
+ options:
41
+ - PBIX Creation (builder)
42
+ - Data Sources (CSV/SQLite/SQL Server/MySQL/PostgreSQL)
43
+ - DirectQuery
44
+ - DAX Evaluation
45
+ - Report Layout / Visuals
46
+ - DataModel Read/Write
47
+ - File Open/Save
48
+ - MCP Server
49
+ - Other
50
+ validations:
51
+ required: true
52
+
53
+ - type: input
54
+ id: version
55
+ attributes:
56
+ label: pbix-mcp version
57
+ placeholder: "0.2.0"
58
+
59
+ - type: input
60
+ id: python
61
+ attributes:
62
+ label: Python version
63
+ placeholder: "3.12"
@@ -0,0 +1,46 @@
1
+ name: Feature Request
2
+ description: Suggest an improvement or new capability
3
+ labels: ["enhancement"]
4
+ body:
5
+ - type: markdown
6
+ attributes:
7
+ value: |
8
+ Have an idea to make pbix-mcp better? We'd love to hear it!
9
+
10
+ - type: textarea
11
+ id: description
12
+ attributes:
13
+ label: What would you like?
14
+ description: Describe the feature or improvement.
15
+ validations:
16
+ required: true
17
+
18
+ - type: textarea
19
+ id: use_case
20
+ attributes:
21
+ label: Use case
22
+ description: How would you use this? What problem does it solve?
23
+ validations:
24
+ required: true
25
+
26
+ - type: dropdown
27
+ id: category
28
+ attributes:
29
+ label: Category
30
+ options:
31
+ - New data source type
32
+ - New DAX function
33
+ - New data type
34
+ - Report creation / builder
35
+ - MCP tool
36
+ - Performance
37
+ - Documentation
38
+ - Other
39
+ validations:
40
+ required: true
41
+
42
+ - type: textarea
43
+ id: alternatives
44
+ attributes:
45
+ label: Alternatives considered
46
+ description: Have you tried any workarounds?
@@ -0,0 +1,49 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python ${{ matrix.python-version }}
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+
24
+ - name: Install package and dev dependencies
25
+ run: pip install -e ".[dev]"
26
+
27
+ - name: Lint with ruff
28
+ run: ruff check src/ tests/
29
+
30
+ - name: Type check with mypy (baseline 149 errors, fail if new errors added)
31
+ shell: bash
32
+ run: |
33
+ COUNT=$(mypy src/pbix_mcp/ --ignore-missing-imports --no-error-summary 2>&1 | grep -c "error:" || true)
34
+ echo "mypy errors: $COUNT (baseline: 149)"
35
+ if [ "$COUNT" -gt 149 ]; then
36
+ echo "FAIL: mypy errors ($COUNT) exceed baseline (149)"
37
+ exit 1
38
+ fi
39
+
40
+ - name: Run unit tests with coverage
41
+ run: pytest -m "not slow and not integration" -v --tb=short --cov=src/pbix_mcp --cov-report=term-missing --cov-fail-under=28
42
+
43
+ - name: Build package
44
+ run: python -m build
45
+
46
+ - name: Verify wheel installs cleanly
47
+ run: |
48
+ pip install dist/*.whl --force-reinstall --no-deps
49
+ python -c "from pbix_mcp.server import mcp; print('Import OK')"
@@ -0,0 +1,67 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+
8
+ jobs:
9
+ build:
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - name: Set up Python
15
+ uses: actions/setup-python@v5
16
+ with:
17
+ python-version: "3.12"
18
+
19
+ - name: Install build tools
20
+ run: pip install build
21
+
22
+ - name: Build package
23
+ run: python -m build
24
+
25
+ - name: Upload artifacts
26
+ uses: actions/upload-artifact@v4
27
+ with:
28
+ name: dist
29
+ path: dist/
30
+
31
+ publish-pypi:
32
+ needs: build
33
+ runs-on: ubuntu-latest
34
+ permissions:
35
+ id-token: write
36
+ environment:
37
+ name: pypi
38
+ url: https://pypi.org/p/pbix-mcp
39
+ steps:
40
+ - name: Download artifacts
41
+ uses: actions/download-artifact@v4
42
+ with:
43
+ name: dist
44
+ path: dist/
45
+
46
+ - name: Publish to PyPI
47
+ uses: pypa/gh-action-pypi-publish@release/v1
48
+
49
+ github-release:
50
+ needs: build
51
+ runs-on: ubuntu-latest
52
+ permissions:
53
+ contents: write
54
+ steps:
55
+ - uses: actions/checkout@v4
56
+
57
+ - name: Download artifacts
58
+ uses: actions/download-artifact@v4
59
+ with:
60
+ name: dist
61
+ path: dist/
62
+
63
+ - name: Create GitHub Release
64
+ uses: softprops/action-gh-release@v2
65
+ with:
66
+ files: dist/*
67
+ generate_release_notes: true
@@ -0,0 +1,30 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ *.py[cod]
5
+ *.egg-info/
6
+ dist/
7
+ build/
8
+ .eggs/
9
+ *.egg
10
+ .env
11
+ .venv
12
+ venv/
13
+ test_samples/*.pbix
14
+ !test_samples/.gitkeep
15
+ # Generated PBIX files (keep templates and fixtures)
16
+ *.pbix
17
+ !src/pbix_mcp/templates/*.pbix
18
+ !tests/fixtures/pbix/*.pbix
19
+ *.abf
20
+ *.tmp
21
+ *.bak
22
+ .claude/
23
+ *.so
24
+ .mypy_cache/
25
+ .pytest_cache/
26
+ .ruff_cache/
27
+ test_samples/temp_dl/
28
+ .coverage
29
+ test_corpus/
30
+ tools/
@@ -0,0 +1,59 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.2.0] - 2026-03-23
9
+
10
+ ### Added
11
+ - **DirectQuery mode**: `mode='directquery'` creates live database connections (SQL Server verified with LocalDB)
12
+ - **SQL Server data source**: `source_db={'type': 'sqlserver', ...}` for Import and DirectQuery
13
+ - **SQLite data source**: `source_db={'type': 'sqlite', ...}` with ODBC driver
14
+ - **MySQL data source**: `source_db={'type': 'mysql', ...}` (same M pattern as SQL Server)
15
+ - **CSV refreshable sources**: `source_csv` parameter creates M expressions for Refresh in PBI Desktop
16
+ - **Boolean data type**: full support (IsOperatingOn32=1, 0/1 values)
17
+ - **Decimal data type**: full support (value × 10000, IsOperatingOn32=1)
18
+ - **NoSplit<N> encoder**: reverse-engineered binary format for R$ relationship INDEX and H$ hierarchy tables
19
+ - **R$ relationship system tables**: cross-table RELATED() and filtering work in PBI Desktop
20
+ - **H$ attribute hierarchy tables**: NoSplit<32> POS_TO_ID/ID_TO_POS for DAX dimension support
21
+ - **RowNumber AttributeHierarchy**: fixes MDNaiveCoordCell::InitPrototype assertion
22
+ - **Template neutralization**: template external file references auto-neutralized on build
23
+ - Example scripts in `examples/` directory
24
+
25
+ ### Fixed
26
+ - Compression class IDs fully reverse-engineered from xmsrv.dll via Ghidra (u32_a/u32_b selectors)
27
+ - DictionaryStorage.IsOperatingOn32=1 for Int64/Decimal/Boolean (was causing PFE_FILESTORE_CORRUPTION)
28
+ - Double column support: added "Double" to encoder type mappings
29
+ - DirectQuery detection: Mode=1 (not Type=6 which is PolicyRange)
30
+ - SMS.Type=2 for H$ tables (was 3, causing DBCC_SEGMENT_CORRUPT)
31
+ - Zero-division error when building tables with 0 distinct values
32
+
33
+ ## [0.1.0] - 2026-03-20
34
+
35
+ ### Added
36
+ - Initial release as installable Python package (`pip install -e .`)
37
+ - 60 MCP tools for full PBIX/PBIT read/write access
38
+ - `pbix_create`: build PBIX files from scratch with actual row data
39
+ - `pbix_add_visual` / `pbix_remove_visual`: visual management
40
+ - `pbix_get_rls_roles` / `pbix_set_rls_role` / `pbix_evaluate_rls`: Row-Level Security (beta)
41
+ - `pbix_get_password`: extract embedded passwords (beta)
42
+ - `pbix_doctor`: 8-point diagnostic health check (beta)
43
+ - DAX evaluation engine with 156 functions (best-effort evaluator)
44
+ - Calculated table support (DATATABLE, GENERATESERIES, CALENDAR, field parameters)
45
+ - Calculated column evaluation (beta; per-row DAX expressions)
46
+ - Auto-applied default slicer filters from report layout (legacy + PBIR)
47
+ - Smart SELECTEDVALUE/ISFILTERED fallback for parameter-driven measures
48
+ - VertiPaq table data read/write (String, Int64, Double, DateTime, Decimal)
49
+ - XPress9 DataModel decompress/recompress (byte-exact round-trip)
50
+ - ABF archive build from scratch / manipulation
51
+ - PBIXBuilder: programmatic PBIX creation with row data
52
+ - Pydantic response models (ToolResponse, DAXEvalResponse, DAXResult)
53
+ - Typed exception hierarchy (errors.py with 12 exception classes)
54
+ - Diagnostic logging (normal/debug/trace via PBIX_MCP_LOG_LEVEL or --log-level)
55
+ - CI pipeline for Python 3.10-3.13 (ruff, mypy, pytest, coverage)
56
+ - ~163 passing tests from fresh clone, ~8 skip without private files
57
+ - 19 cross-report integration tests (require private PBIX corpus)
58
+ - Public PBIX fixtures (basic_layout, basic_measures)
59
+ - SUPPORT.md, CONTRIBUTING.md, issue templates
@@ -0,0 +1,66 @@
1
+ # Contributing
2
+
3
+ ## Setup
4
+
5
+ ```bash
6
+ git clone https://github.com/d0nk3yhm/pbix-mcp.git
7
+ cd pbix-mcp
8
+ pip install -e ".[dev]"
9
+ ```
10
+
11
+ ## Running Tests
12
+
13
+ ```bash
14
+ # Fast unit tests only (~163 pass from fresh clone, ~8 skip without test corpus)
15
+ pytest -m "not slow"
16
+
17
+ # Download public test corpus, then run integration tests
18
+ python scripts/download_test_corpus.py
19
+ PBIX_TEST_SAMPLES=test_corpus pytest -v
20
+
21
+ # With coverage
22
+ pytest --cov=src/pbix_mcp --cov-report=term-missing -m "not slow"
23
+ ```
24
+
25
+ ## Code Style
26
+
27
+ - Linting: `ruff check src/ tests/`
28
+ - Type checking: `mypy src/pbix_mcp/`
29
+
30
+ ## Project Layout
31
+
32
+ ```
33
+ src/pbix_mcp/
34
+ server.py # MCP server (60 tools)
35
+ cli.py # Entry point (pbix-mcp-server --log-level debug)
36
+ builder.py # PBIX file builder (create from scratch with row data)
37
+ errors.py # Typed exceptions with stable error codes (12 classes)
38
+ logging_config.py # Diagnostic logging (normal/debug/trace)
39
+ dax/
40
+ engine.py # DAX evaluator (156 functions, best-effort)
41
+ calc_tables.py # Calculated table + column support
42
+ formats/
43
+ abf_rebuild.py # ABF archive format (read, modify, build from scratch)
44
+ datamodel_roundtrip.py # XPress9 compress/decompress
45
+ vertipaq_encoder.py # VertiPaq column encoding (5 data types)
46
+ models/
47
+ requests.py # Tool input models (FilterContext, DimensionRef)
48
+ responses.py # Tool output models (ToolResponse, DAXEvalResponse)
49
+ tests/
50
+ test_dax_engine.py # Unit tests (55; 6 skip without private files)
51
+ test_dax_accuracy.py # Accuracy tests (50)
52
+ test_golden.py # Golden tests (15; 2 skip without private files)
53
+ test_fixtures.py # Fixture tests (18; ships with repo)
54
+ test_beta_features.py # Beta feature tests (10; RLS, password, doctor)
55
+ test_cross_report.py # Integration tests (19; requires 4 private PBIX files)
56
+ ```
57
+
58
+ ## Commit Messages
59
+
60
+ Use conventional format:
61
+ - `feat:` new feature or tool
62
+ - `fix:` bug fix
63
+ - `refactor:` code restructure without behavior change
64
+ - `test:` test additions
65
+ - `docs:` documentation only
66
+ - `chore:` build/CI changes
pbix_mcp-0.2.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Hans
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.