mcp-server-sigma 1.0.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 (68) hide show
  1. mcp_server_sigma-1.0.0/.coderabbit.yaml +35 -0
  2. mcp_server_sigma-1.0.0/.dockerignore +22 -0
  3. mcp_server_sigma-1.0.0/.env.example +4 -0
  4. mcp_server_sigma-1.0.0/.github/CODEOWNERS +2 -0
  5. mcp_server_sigma-1.0.0/.github/ISSUE_TEMPLATE/bug_report.md +54 -0
  6. mcp_server_sigma-1.0.0/.github/ISSUE_TEMPLATE/feature_request.md +31 -0
  7. mcp_server_sigma-1.0.0/.github/PULL_REQUEST_TEMPLATE.md +19 -0
  8. mcp_server_sigma-1.0.0/.github/dependabot.yml +22 -0
  9. mcp_server_sigma-1.0.0/.github/workflows/ci.yml +173 -0
  10. mcp_server_sigma-1.0.0/.github/workflows/dependabot-automerge.yml +24 -0
  11. mcp_server_sigma-1.0.0/.github/workflows/release.yml +110 -0
  12. mcp_server_sigma-1.0.0/.gitignore +17 -0
  13. mcp_server_sigma-1.0.0/AGENTS.md +75 -0
  14. mcp_server_sigma-1.0.0/CHANGELOG.md +59 -0
  15. mcp_server_sigma-1.0.0/CODE_OF_CONDUCT.md +43 -0
  16. mcp_server_sigma-1.0.0/CONTRIBUTING.md +160 -0
  17. mcp_server_sigma-1.0.0/Dockerfile +33 -0
  18. mcp_server_sigma-1.0.0/LICENSE +21 -0
  19. mcp_server_sigma-1.0.0/PKG-INFO +403 -0
  20. mcp_server_sigma-1.0.0/README.md +365 -0
  21. mcp_server_sigma-1.0.0/SECURITY.md +64 -0
  22. mcp_server_sigma-1.0.0/TESTING.md +244 -0
  23. mcp_server_sigma-1.0.0/docs/architecture.md +118 -0
  24. mcp_server_sigma-1.0.0/docs/errors.md +167 -0
  25. mcp_server_sigma-1.0.0/docs/formulas.md +9 -0
  26. mcp_server_sigma-1.0.0/docs/multi-tenant.md +149 -0
  27. mcp_server_sigma-1.0.0/docs/recipes.md +41 -0
  28. mcp_server_sigma-1.0.0/examples/bulk_member_ops.py +107 -0
  29. mcp_server_sigma-1.0.0/examples/deploy_template.py +82 -0
  30. mcp_server_sigma-1.0.0/examples/export_and_download.py +59 -0
  31. mcp_server_sigma-1.0.0/examples/multi_tenant_sync.py +87 -0
  32. mcp_server_sigma-1.0.0/examples/onboard_team.py +106 -0
  33. mcp_server_sigma-1.0.0/examples/promote_workbook.py +111 -0
  34. mcp_server_sigma-1.0.0/pyproject.toml +81 -0
  35. mcp_server_sigma-1.0.0/scripts/check_openapi_drift.py +156 -0
  36. mcp_server_sigma-1.0.0/scripts/check_tool_contract.py +218 -0
  37. mcp_server_sigma-1.0.0/scripts/drift_allowlist.txt +6 -0
  38. mcp_server_sigma-1.0.0/scripts/write_ops_check.py +250 -0
  39. mcp_server_sigma-1.0.0/server.json +21 -0
  40. mcp_server_sigma-1.0.0/skills/sigma-mcp/SKILL.md +78 -0
  41. mcp_server_sigma-1.0.0/src/sigma_mcp/__init__.py +3 -0
  42. mcp_server_sigma-1.0.0/src/sigma_mcp/client.py +1130 -0
  43. mcp_server_sigma-1.0.0/src/sigma_mcp/errors.py +46 -0
  44. mcp_server_sigma-1.0.0/src/sigma_mcp/py.typed +1 -0
  45. mcp_server_sigma-1.0.0/src/sigma_mcp/reference/formulas.md +100 -0
  46. mcp_server_sigma-1.0.0/src/sigma_mcp/reference/sigma_api_index.txt +1052 -0
  47. mcp_server_sigma-1.0.0/src/sigma_mcp/server.py +2808 -0
  48. mcp_server_sigma-1.0.0/src/sigma_mcp/webhooks.py +100 -0
  49. mcp_server_sigma-1.0.0/tests/smoke_test.py +266 -0
  50. mcp_server_sigma-1.0.0/tests/test_additional_coverage.py +61 -0
  51. mcp_server_sigma-1.0.0/tests/test_all_tools_coverage.py +99 -0
  52. mcp_server_sigma-1.0.0/tests/test_client_internals.py +349 -0
  53. mcp_server_sigma-1.0.0/tests/test_enterprise_assertion.py +67 -0
  54. mcp_server_sigma-1.0.0/tests/test_full_100_coverage.py +215 -0
  55. mcp_server_sigma-1.0.0/tests/test_integration_live.py +428 -0
  56. mcp_server_sigma-1.0.0/tests/test_mcp_features.py +78 -0
  57. mcp_server_sigma-1.0.0/tests/test_no_transport_bypass.py +102 -0
  58. mcp_server_sigma-1.0.0/tests/test_pagination.py +144 -0
  59. mcp_server_sigma-1.0.0/tests/test_polling.py +133 -0
  60. mcp_server_sigma-1.0.0/tests/test_recipe_error_coverage.py +117 -0
  61. mcp_server_sigma-1.0.0/tests/test_safety.py +292 -0
  62. mcp_server_sigma-1.0.0/tests/test_security_hardening.py +71 -0
  63. mcp_server_sigma-1.0.0/tests/test_server_100_percent_final.py +184 -0
  64. mcp_server_sigma-1.0.0/tests/test_server_missing_lines.py +86 -0
  65. mcp_server_sigma-1.0.0/tests/test_server_uncovered_branches.py +233 -0
  66. mcp_server_sigma-1.0.0/tests/test_tools_mocked.py +261 -0
  67. mcp_server_sigma-1.0.0/tests/test_unit.py +472 -0
  68. mcp_server_sigma-1.0.0/tests/test_webhooks.py +235 -0
@@ -0,0 +1,35 @@
1
+ language: "en-US"
2
+
3
+ reviews:
4
+ # 'chill' provides balanced feedback without nitpicky noise ('quiet' = critical only)
5
+ profile: "chill"
6
+
7
+ # Auto-Review Settings
8
+ auto_review:
9
+ enabled: true
10
+ drafts: false
11
+ # Skip automatic reviews when PR title contains 'dependabot' or 'bump'
12
+ ignore_title_keywords:
13
+ - "dependabot"
14
+ - "bump"
15
+
16
+ # Path Filters: Exclude lockfiles, virtualenvs, and log files from review
17
+ path_filters:
18
+ - "!poetry.lock"
19
+ - "!package-lock.json"
20
+ - "!.venv/**"
21
+ - "!**.log"
22
+
23
+ # Domain Path Instructions: Enforce project-specific architectural rules automatically
24
+ path_instructions:
25
+ - path: "src/sigma_mcp/server.py"
26
+ instructions: "Ensure all newly added tools declare read_only_hint, destructive_hint, or idempotent_hint annotations, and enforce explicit confirm=True parameters on all delete, archive, deactivate, and bulk-removal endpoints."
27
+ - path: "src/sigma_mcp/client.py"
28
+ instructions: "Verify HTTP 429 retry backoff includes jitter and preserves Retry-After minimum delay."
29
+
30
+ # Enables '🤖 Prompt for AI Agents' blocks in review comments for one-click resolution
31
+ enable_prompt_for_ai_agents: true
32
+
33
+ # Clean presentation settings
34
+ poem: false
35
+ collapse_walkthrough: true
@@ -0,0 +1,22 @@
1
+ .venv/
2
+ dist/
3
+ __pycache__/
4
+ *.pyc
5
+ .git/
6
+ .github/
7
+ tests/
8
+ docs/
9
+ examples/
10
+ scripts/
11
+ skills/
12
+ .env
13
+ .env.example
14
+ .coverage
15
+ htmlcov/
16
+ .mypy_cache/
17
+ .ruff_cache/
18
+ *.md
19
+ !README.md
20
+ .coderabbit.yaml
21
+ .dockerignore
22
+ Dockerfile
@@ -0,0 +1,4 @@
1
+ export SIGMA_CLIENT_ID='your_client_id_here'
2
+ export SIGMA_CLIENT_SECRET='your_client_secret_here'
3
+ # Must match your org's region — Administration > Developer Access > API base URL
4
+ export SIGMA_API_BASE_URL='https://api.us-a.aws.sigmacomputing.com'
@@ -0,0 +1,2 @@
1
+ # Default owner for everything in this repository.
2
+ * @christianclaudio
@@ -0,0 +1,54 @@
1
+ ---
2
+ name: Bug Report
3
+ about: Report a bug or unexpected behavior
4
+ title: "[Bug] "
5
+ labels: bug
6
+ assignees: ''
7
+ ---
8
+
9
+ ## Description
10
+
11
+ A clear description of the bug.
12
+
13
+ ## Steps to Reproduce
14
+
15
+ 1. Configure environment with `...`
16
+ 2. Call tool `sigma_...` with parameters `...`
17
+ 3. Observe error
18
+
19
+ ## Expected Behavior
20
+
21
+ What you expected to happen.
22
+
23
+ ## Actual Behavior
24
+
25
+ What actually happened. Include the JSON error response if available.
26
+
27
+ > **Before pasting:** redact any credentials, tokens, cookies, personal data,
28
+ > and private resource identifiers (member IDs, org IDs, etc.) from the response.
29
+
30
+ ```json
31
+ {
32
+ "type": "sigma_api_error",
33
+ "status_code": ...,
34
+ "method": "...",
35
+ "path": "...",
36
+ "detail": ...,
37
+ "request_id": "..."
38
+ }
39
+ ```
40
+
41
+ > If your report contains sensitive information that cannot be safely redacted,
42
+ > use the [private security advisory](https://github.com/christianclaudio/mcp-server-sigma/security/advisories/new)
43
+ > instead of a public issue.
44
+
45
+ ## Environment
46
+
47
+ - Python version:
48
+ - OS:
49
+ - Sigma region (e.g., aws-us-east):
50
+ - MCP host (e.g., Claude Desktop, Cursor):
51
+
52
+ ## Additional Context
53
+
54
+ Any other relevant information.
@@ -0,0 +1,31 @@
1
+ ---
2
+ name: Feature Request
3
+ about: Suggest a new tool or enhancement
4
+ title: "[Feature] "
5
+ labels: enhancement
6
+ assignees: ''
7
+ ---
8
+
9
+ ## Summary
10
+
11
+ A concise description of the feature or enhancement.
12
+
13
+ ## Use Case
14
+
15
+ Describe the problem this would solve or the workflow it would enable.
16
+
17
+ ## Proposed Solution
18
+
19
+ How you envision this working. For new tools, include:
20
+
21
+ - Sigma API endpoint(s) involved
22
+ - Proposed tool name (e.g., `sigma_...`)
23
+ - Parameters and return value
24
+
25
+ ## Alternatives Considered
26
+
27
+ Other approaches you've considered and why they're less ideal.
28
+
29
+ ## Additional Context
30
+
31
+ Links to Sigma API docs, related issues, or examples.
@@ -0,0 +1,19 @@
1
+ ## What changed
2
+
3
+ <!-- One or two sentences. Focus on why, not just what. -->
4
+
5
+ ## Checklist
6
+
7
+ - [ ] `mypy --strict src/` is clean
8
+ - [ ] `ruff check .` and `ruff format --check .` are clean
9
+ - [ ] `pytest tests/test_unit.py tests/test_tools_mocked.py tests/test_enterprise_assertion.py` passes **without a live Sigma org**
10
+ - [ ] `python scripts/check_openapi_drift.py` exits 0 (no wrong-path drift)
11
+ - [ ] If tools were added/removed: tool-count and annotation assertions updated
12
+ - [ ] If a tool writes or deletes: correct annotation (`destructiveHint`) and, where relevant, `dry_run`/`confirm` gating
13
+ - [ ] If behavior changed: README / `docs/` updated
14
+ - [ ] `CHANGELOG.md` updated
15
+ - [ ] No secrets, tokens, or real org IDs committed
16
+
17
+ ## Verification
18
+
19
+ <!-- Paste the actual command output you ran. -->
@@ -0,0 +1,22 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: pip
4
+ directory: "/"
5
+ schedule:
6
+ interval: weekly
7
+ open-pull-requests-limit: 5
8
+ groups:
9
+ # Batch low-risk bumps into one PR to keep review noise down.
10
+ minor-and-patch:
11
+ patterns: ["*"]
12
+ update-types: ["minor", "patch"]
13
+
14
+ - package-ecosystem: github-actions
15
+ directory: "/"
16
+ schedule:
17
+ interval: weekly
18
+ open-pull-requests-limit: 5
19
+ groups:
20
+ actions-minor-and-patch:
21
+ patterns: ["*"]
22
+ update-types: ["minor", "patch"]
@@ -0,0 +1,173 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ permissions:
10
+ contents: read
11
+ security-events: write
12
+ actions: read
13
+
14
+ jobs:
15
+ lint:
16
+ name: Lint and types
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
20
+ - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
21
+ with:
22
+ python-version: "3.12"
23
+ cache: "pip"
24
+ - name: Install
25
+ run: |
26
+ python -m pip install --upgrade pip
27
+ pip install -e ".[dev]" pip-licenses
28
+ - name: Ruff lint
29
+ run: ruff check .
30
+ - name: Ruff format
31
+ run: ruff format --check .
32
+ - name: Mypy strict
33
+ run: mypy --strict src/
34
+ - name: License compliance
35
+ run: pip-licenses --fail-on="GNU General Public License" --partial-match --order=license --ignore-packages docutils
36
+
37
+ test:
38
+ name: Tests (py${{ matrix.python-version }})
39
+ runs-on: ubuntu-latest
40
+ strategy:
41
+ fail-fast: false
42
+ matrix:
43
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
44
+ steps:
45
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
46
+ - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
47
+ with:
48
+ python-version: ${{ matrix.python-version }}
49
+ cache: "pip"
50
+ - name: Install
51
+ run: |
52
+ python -m pip install --upgrade pip
53
+ pip install -e ".[dev]"
54
+ - name: Unit and mocked tests
55
+ run: pytest --cov=src/sigma_mcp --cov-report=term-missing --cov-fail-under=100 -q
56
+
57
+ contract:
58
+ name: Tool contract and env gating
59
+ runs-on: ubuntu-latest
60
+ steps:
61
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
62
+ - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
63
+ with:
64
+ python-version: "3.12"
65
+ cache: "pip"
66
+ - name: Install
67
+ run: |
68
+ python -m pip install --upgrade pip
69
+ pip install -e ".[dev]"
70
+ # Guards the counts published in README against silent drift, and proves
71
+ # the safety env vars actually change what gets registered.
72
+ - name: Assert tool counts and safety gating
73
+ run: python scripts/check_tool_contract.py
74
+
75
+ openapi-drift:
76
+ name: OpenAPI drift
77
+ runs-on: ubuntu-latest
78
+ steps:
79
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
80
+ - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
81
+ with:
82
+ python-version: "3.12"
83
+ cache: "pip"
84
+ - name: Install
85
+ run: |
86
+ python -m pip install --upgrade pip
87
+ pip install -e .
88
+ # Fails the build if any client path is absent from Sigma's published
89
+ # OpenAPI spec. This is the guard against the wrong-path class of bug.
90
+ - name: Check client paths against Sigma spec
91
+ run: python scripts/check_openapi_drift.py
92
+
93
+ build:
94
+ name: Build and package check
95
+ runs-on: ubuntu-latest
96
+ steps:
97
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
98
+ - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
99
+ with:
100
+ python-version: "3.12"
101
+ cache: "pip"
102
+ - name: Install build tooling
103
+ run: |
104
+ python -m pip install --upgrade pip
105
+ pip install build twine
106
+ - name: Build
107
+ run: python -m build
108
+ - name: Twine check
109
+ run: twine check dist/*
110
+ - name: Upload build artifacts
111
+ uses: actions/upload-artifact@v4
112
+ with:
113
+ name: dist-${{ github.sha }}
114
+ path: dist/
115
+ retention-days: 14
116
+
117
+ docker:
118
+ name: Docker build
119
+ runs-on: ubuntu-latest
120
+ steps:
121
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
122
+ - name: Build Docker image
123
+ run: docker build -t mcp-server-sigma:ci-${{ github.sha }} .
124
+ - name: Verify entrypoint
125
+ run: docker run --rm mcp-server-sigma:ci-${{ github.sha }} --help
126
+
127
+ codeql:
128
+ name: CodeQL
129
+ runs-on: ubuntu-latest
130
+ permissions:
131
+ security-events: write
132
+ contents: read
133
+ steps:
134
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
135
+ - uses: github/codeql-action/init@v3
136
+ with:
137
+ languages: python
138
+ - uses: github/codeql-action/analyze@v3
139
+ # SARIF upload may fail with "Resource not accessible by integration" on
140
+ # repos where the default GITHUB_TOKEN lacks security-events write access.
141
+ # The scan itself still runs; this only affects result visibility in the
142
+ # Security tab. Safe to suppress until GitHub fixes token propagation.
143
+ continue-on-error: true
144
+
145
+ live-smoke:
146
+ name: Live smoke (main only, requires secrets)
147
+ runs-on: ubuntu-latest
148
+ needs: [lint, test, contract, openapi-drift]
149
+ # Never runs on forks or PRs: it needs org credentials and touches a real
150
+ # Sigma organization.
151
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main' && github.repository_owner == 'christianclaudio'
152
+ steps:
153
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
154
+ - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
155
+ with:
156
+ python-version: "3.12"
157
+ cache: "pip"
158
+ - name: Install
159
+ run: |
160
+ python -m pip install --upgrade pip
161
+ pip install -e ".[dev]"
162
+ - name: Live smoke test
163
+ env:
164
+ SIGMA_CLIENT_ID: ${{ secrets.SIGMA_CLIENT_ID }}
165
+ SIGMA_CLIENT_SECRET: ${{ secrets.SIGMA_CLIENT_SECRET }}
166
+ SIGMA_API_BASE_URL: ${{ secrets.SIGMA_API_BASE_URL }}
167
+ # Skips cleanly rather than failing when secrets are unavailable.
168
+ run: |
169
+ if [ -z "$SIGMA_CLIENT_ID" ] || [ -z "$SIGMA_CLIENT_SECRET" ] || [ -z "$SIGMA_API_BASE_URL" ]; then
170
+ echo "One or more Sigma secrets not set; skipping live smoke."
171
+ exit 0
172
+ fi
173
+ PYTHONPATH=src python tests/smoke_test.py
@@ -0,0 +1,24 @@
1
+ name: Dependabot Auto-Merge
2
+
3
+ on: pull_request_target
4
+
5
+ permissions:
6
+ contents: write
7
+ pull-requests: write
8
+
9
+ jobs:
10
+ dependabot:
11
+ runs-on: ubuntu-latest
12
+ if: github.actor == 'dependabot[bot]'
13
+ steps:
14
+ - name: Dependabot metadata
15
+ id: metadata
16
+ uses: dependabot/fetch-metadata@21025c705c08248db411dc16f3619e6b5f9ea21a # v2
17
+ with:
18
+ github-token: "${{ secrets.GITHUB_TOKEN }}"
19
+
20
+ - name: Enable auto-merge for Dependabot PRs
21
+ run: gh pr merge --auto --squash "$PR_URL"
22
+ env:
23
+ PR_URL: ${{ github.event.pull_request.html_url }}
24
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
@@ -0,0 +1,110 @@
1
+ name: Release
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+
7
+ permissions:
8
+ contents: read
9
+
10
+ jobs:
11
+ build:
12
+ name: Build distributions
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
16
+ - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5.3.0
17
+ with:
18
+ python-version: "3.12"
19
+ cache: "pip"
20
+
21
+ - name: Install build tooling & runtime dependencies
22
+ run: |
23
+ python -m pip install --upgrade pip
24
+ pip install build twine cyclonedx-bom
25
+ pip install .
26
+
27
+ - name: Verify tag matches package version
28
+ run: |
29
+ TAG="${GITHUB_REF_NAME#v}"
30
+ PKG=$(python -c "import tomllib,pathlib; print(tomllib.loads(pathlib.Path('pyproject.toml').read_text())['project']['version'])")
31
+ if [ "$TAG" != "$PKG" ]; then
32
+ echo "Tag $TAG does not match pyproject version $PKG" >&2
33
+ exit 1
34
+ fi
35
+ echo "Tag and version agree: $PKG"
36
+
37
+ - name: Build
38
+ run: python -m build
39
+
40
+ - name: Twine check
41
+ run: twine check dist/*
42
+
43
+ - name: Generate CycloneDX SBOM
44
+ run: cyclonedx-py environment -o sbom.cdx.json
45
+
46
+ - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65822d53b0323c2227 # v4.4.3
47
+ with:
48
+ name: dist
49
+ path: |
50
+ dist/
51
+ sbom.cdx.json
52
+
53
+ publish:
54
+ name: Publish to PyPI
55
+ needs: build
56
+ runs-on: ubuntu-latest
57
+ environment: pypi
58
+ permissions:
59
+ id-token: write # Trusted Publishing (OIDC) — no API token stored
60
+ attestations: write # build provenance
61
+ contents: write # attach assets to the GitHub Release
62
+ steps:
63
+ - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
64
+ with:
65
+ name: dist
66
+
67
+ - name: Attest build provenance
68
+ uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1
69
+ with:
70
+ subject-path: "dist/*"
71
+
72
+ # SHA-pinned deliberately: all actions in this workflow use immutable
73
+ # commit SHAs to protect against supply-chain tag mutations.
74
+ - name: Publish to PyPI
75
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
76
+
77
+ - name: Attach SBOM to release
78
+ uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3.0.2
79
+ with:
80
+ files: sbom.cdx.json
81
+
82
+ docker:
83
+ name: Publish Docker image
84
+ needs: build
85
+ runs-on: ubuntu-latest
86
+ permissions:
87
+ contents: read
88
+ packages: write
89
+ steps:
90
+ - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
91
+
92
+ - name: Log in to GHCR
93
+ uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
94
+ with:
95
+ registry: ghcr.io
96
+ username: ${{ github.actor }}
97
+ password: ${{ secrets.GITHUB_TOKEN }}
98
+
99
+ - name: Extract version from tag
100
+ id: version
101
+ run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
102
+
103
+ - name: Build and push
104
+ uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6.9.0
105
+ with:
106
+ context: .
107
+ push: true
108
+ tags: |
109
+ ghcr.io/${{ github.repository }}:${{ steps.version.outputs.version }}
110
+ ghcr.io/${{ github.repository }}:latest
@@ -0,0 +1,17 @@
1
+ .env
2
+ __pycache__/
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .venv/
7
+ .pytest_cache/
8
+ .coverage
9
+ htmlcov/
10
+
11
+ # Tool caches
12
+ .mypy_cache/
13
+ .ruff_cache/
14
+
15
+ # Local code-review artifacts
16
+ coderabbit-review*.txt
17
+ uv.lock
@@ -0,0 +1,75 @@
1
+ # AGENTS.md
2
+
3
+ Instructions for AI coding agents (Claude Code, Copilot, Cursor, Windsurf, etc.) working on this repository.
4
+
5
+ ## Project Overview
6
+
7
+ This is `mcp-server-sigma` — a Python MCP server exposing 155 tools for Sigma Computing's REST API. It runs over stdio and is consumed by AI clients (Claude Desktop, VS Code, etc.).
8
+
9
+ ## Architecture
10
+
11
+ ```
12
+ src/sigma_mcp/
13
+ ├── server.py # MCP tool definitions (2600+ lines, all @mcp.tool() handlers)
14
+ ├── client.py # Async HTTP client (OAuth2, retries, rate-limiting, tenant token exchange)
15
+ ├── errors.py # Error formatting with secret redaction
16
+ ├── webhooks.py # Webhook signature verification + in-memory event buffer
17
+ └── __init__.py # Version only
18
+ ```
19
+
20
+ ## Key Patterns
21
+
22
+ - **Every tool** is an `async def` decorated with `@mcp.tool()` and `@sigma_tool`
23
+ - `@sigma_tool` is a decorator that adds timing, structured logging, and error handling
24
+ - **Destructive tools** require `confirm: bool = False` — reject if not `True`
25
+ - **Composite tools** (promote, deploy, onboard) orchestrate multiple API calls
26
+ - **Annotations** are applied post-registration via `mcp._tool_manager._tools` (private API, pinned SDK version)
27
+
28
+ ## Development Commands
29
+
30
+ ```bash
31
+ # Install
32
+ pip install -e ".[dev]"
33
+
34
+ # Lint + format
35
+ ruff check . && ruff format --check .
36
+
37
+ # Type check
38
+ mypy --strict src/
39
+
40
+ # Tests (100% coverage required)
41
+ pytest --cov=src/sigma_mcp --cov-fail-under=100 -q
42
+
43
+ # Tool contract validation
44
+ python scripts/check_tool_contract.py
45
+
46
+ # OpenAPI drift check
47
+ python scripts/check_openapi_drift.py
48
+ ```
49
+
50
+ ## Testing Conventions
51
+
52
+ - Tests use `unittest.mock.AsyncMock` to mock `SigmaClient` methods
53
+ - Monkeypatch `srv._client` to inject a mock client
54
+ - No `conftest.py` — each test file is self-contained
55
+ - Coverage must stay at 100% — CI enforces this
56
+
57
+ ## Adding a New Tool
58
+
59
+ 1. Add the client method in `client.py` (async, typed)
60
+ 2. Add the `@mcp.tool()` handler in `server.py` with proper docstring
61
+ 3. Add the tool name to the appropriate annotation set (`_DESTRUCTIVE_NAMES`, `_IDEMPOTENT_NAMES`, or let it default to `_WRITE_SAFE`)
62
+ 4. Update `scripts/check_tool_contract.py` expected counts
63
+ 5. Update `README.md` tool count
64
+ 6. Add test coverage (must maintain 100%)
65
+
66
+ ## Safety Rules
67
+
68
+ - Never remove `confirm=True` gates from destructive tools
69
+ - Never expose credentials in error messages (secret redaction is automatic)
70
+ - Bulk-destructive tools are gated behind `SIGMA_MCP_ALLOW_BULK_DESTRUCTIVE=1`
71
+ - Read-only mode (`SIGMA_MCP_READONLY=1`) filters out all write tools at registration time
72
+
73
+ ## CI Pipeline
74
+
75
+ The CI runs 7 jobs: lint, test (4 Python versions), contract validation, OpenAPI drift, build+twine, CodeQL, and live smoke (main-only with secrets). All must pass for merge.
@@ -0,0 +1,59 @@
1
+ # Changelog
2
+
3
+ ## 1.0.0 (2026-08-02)
4
+
5
+ ### Breaking Changes
6
+ - **Bulk-destructive tools are no longer registered by default.** `sigma_bulk_deactivate_members` and `sigma_bulk_remove_team_members` require `SIGMA_MCP_ALLOW_BULK_DESTRUCTIVE=1` to appear in the tool list. Without it, they do not exist from the model's perspective. This is intentional: an unprompted "clean up inactive users" from a model should not have access to bulk deactivation.
7
+ - **Single-Delete Confirmation Gating**: Mandatory `confirm: bool = False` opt-in parameter required on all atomic delete, archive, deactivate, and bulk-remove tools. Callers performing destructive operations must explicitly pass `confirm=True`.
8
+
9
+ ### Added
10
+ - **Native MCP Resources**: Registered `sigma://reference/formulas`, `sigma://reference/capabilities`, `sigma://reference/docs-index`, and `sigma://webhooks/recent` native resources.
11
+ - **Native MCP Prompts**: Registered `provision_tenant_dashboard`, `audit_organization_permissions`, `prepare_data_model`, `onboard_team_member`, `swap_warehouse_source`, and `audit_tenant_connections` native prompts.
12
+ - **Documentation tools**: `sigma_search_docs` (AI-powered semantic search via Sigma's docs MCP) and `sigma_get_doc_page` (fetch any docs page as Markdown).
13
+ - **Structured JSON Logging**: Support for `SIGMA_MCP_LOG_FORMAT=json` with structured log records including execution duration (`duration_ms`).
14
+ - **Network Transport CLI Flags**: Added `--host` and `--port` CLI options for network transport server deployment.
15
+ - **Path Segment Sanitization**: Automated path parameter quoting (`quote(seg, safe="").replace("..", "%2E%2E")`) across all 217 client API methods to prevent path traversal attacks.
16
+ - **Secret & Token Redaction**: Multi-pattern regex scrubbing (`Bearer` tokens, `client_secret`, `access_token`, `subject_token`, and raw JWT `eyJ...`) across error responses and log payloads.
17
+ - **Multi-Tenant Security**: Added `SIGMA_ALLOWED_TENANTS` allowlist check and `SIGMA_STRICT_TENANT_ALLOWLIST=1` fail-closed enforcement for RFC 8693 token exchange.
18
+ - **Single-Delete Confirmation Gating**: Mandatory `confirm: bool = False` opt-in parameter required on all atomic delete, archive, deactivate, and bulk-remove tool calls.
19
+ - **Safety gating**: `SIGMA_MCP_READONLY=1` removes all non-read-only tools from registration (83 tools remain). Composes with profiles (e.g. `admin` + `readonly` = read-only subset of admin tools).
20
+ - **`embed` profile**: `SIGMA_MCP_PROFILE=embed` (55 tools) for embedded analytics workflows — core + embeds, user attributes, tenants, source swap, workspace grants.
21
+ - **Catch-all regex rejection** in `sigma_bulk_deactivate_members`: patterns like `.*`, `.+`, `^.*$`, `.`, or empty string are refused because they would match every member in the org.
22
+ - **10-member hard cap** on `sigma_bulk_deactivate_members`: if the pattern matches more than 10 members, the tool refuses and reports the match list. Prevents accidental org-wide deactivation.
23
+ - **`sigma_formula_pitfalls` tool**: returns a curated Sigma formula reference to prevent hallucinated function names and type errors. Backed by `src/sigma_mcp/reference/formulas.md`.
24
+ - **11 new endpoints**: reports (CRUD, schedules, elements, queries, lineage, sources, duplicate, export), source-swap policies, deployment documents, workbook version history, report schedules.
25
+ - **Tool count now 155** (default), 157 with bulk-destructive opt-in, 83 read-only.
26
+ - **Expanded test suite** covering profile composition, readonly filtering, bulk-gating, annotation completeness, and catch-all regex rejection.
27
+ - **OSS files**: SECURITY.md, CONTRIBUTING.md, CODE_OF_CONDUCT.md, LICENSE.
28
+ - **`scripts/check_tool_contract.py`**: validates counts, annotations, profiles, and gating. Runs in CI.
29
+ - **docs/formulas.md**: full Sigma formula reference for agent consumption.
30
+
31
+ ### Fixed
32
+ - Annotation counts corrected: 83 read-only, 16 destructive, 8 idempotent.
33
+ - `sigma_promote_workbook` now creates the tag if it doesn't already exist (idempotent).
34
+
35
+ ## 0.2.0 (2026-08-01)
36
+
37
+ ### Breaking Changes
38
+ - Client is now fully async (`httpx.AsyncClient`). All methods are `async def`.
39
+ - All MCP tools are now `async def`. Requires MCP SDK >= 2.0.0.
40
+
41
+ ### Added
42
+ - **Structured error handling**: `SigmaAPIError` class with status, path, method, detail, request_id. `@sigma_tool` decorator wraps all tools — no raw exceptions escape.
43
+ - **8 recipe tools**: export+download, ownership transfer, shared workbooks, input table scan, bulk deactivate, change email, bulk team remove, tenant connection sync.
44
+ - **Multi-tenant auth**: RFC 8693 token exchange via `SigmaClient.for_tenant()`. Per-tenant token cache with auto-refresh.
45
+ - **MCP 2.0 annotations**: All 141 tools annotated with `readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`.
46
+ - **Tool profiles**: `SIGMA_MCP_PROFILE=core|admin|full` to control tool registration.
47
+ - **OpenAPI drift detection**: `scripts/check_openapi_drift.py` compares client paths against official spec.
48
+ - **GitHub Actions CI**: Matrix on Python 3.10-3.13 with ruff + pytest.
49
+ - **Auto-pagination tools**: `sigma_list_all_*` tools that follow pagination tokens.
50
+ - **PyJWT dependency** for tenant token exchange.
51
+ - Secret redaction in all error messages.
52
+
53
+ ### Fixed
54
+ - `download_query()` now routes through `_request()` for retry/rate-limit handling.
55
+ - `time.sleep` replaced with `await asyncio.sleep` throughout.
56
+
57
+ ## 0.1.0 (2025-06-15)
58
+
59
+ Initial release. 131 tools covering the Sigma v2 API surface.