Skip to content

Commit 59fc978

Browse files
julienldclaude
andauthored
fix: add string coercion for numeric parameters (fixes #205, #206) (#217)
* feat: add PyInstaller standalone binary builds Adds support for building standalone executables for Linux, Windows, and macOS: - ha-mcp.spec: PyInstaller spec file with dynamic stdlib path detection - build-binary.yml: GitHub Actions workflow for multi-platform builds The workflow: - Builds in parallel on ubuntu-latest, windows-latest, macos-latest - Tests that each binary starts correctly (FastMCP banner appears) - Uploads artifacts for each platform Binary size: ~52MB (includes Python runtime and all dependencies) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: use Python 3.13 and venv for PyInstaller builds - Change Python version from 3.12 to 3.13 (required by pyproject.toml) - Use proper venv instead of --system install for better package discovery - Add venv to PATH for subsequent steps 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: use portable timeout approach for macOS macOS doesn't have the 'timeout' command. Use background process with sleep and kill instead, which works on all Unix platforms. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: add CD workflow with mcpb packaging and GitHub releases - Convert PR workflow to CD workflow triggered on releases - Add mcpb bundle packaging for Windows and macOS binaries - Add GitHub release publishing for all 3 platform binaries - Create manifest.json template for mcpb specification 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: add explicit permissions block to workflow Addresses CodeQL security warning about missing GITHUB_TOKEN permission restrictions. Sets minimal `contents: read` by default, with the release job already having `contents: write` override. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: add user_config for HA URL and token in mcpb manifest Adds user_config section so mcpb clients will prompt users for: - Home Assistant URL (required) - Long-Lived Access Token (required, sensitive/masked) These are injected as HOMEASSISTANT_URL and HOMEASSISTANT_TOKEN environment variables when the server starts. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: include click module for uvicorn dependency Uvicorn requires click for CLI configuration. Removed click from PyInstaller excludes to fix Windows binary startup error: ModuleNotFoundError: No module named 'click' 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * ci: improve Windows test diagnostics * fix: add idna codec hidden imports for PyInstaller * fix: add more commonly missing PyInstaller hidden imports * fix: add runtime hook to register idna codec at startup * feat: auto-generate mcpb manifest with discovered tools * fix: use UTF-8 encoding in generate_manifest.py for Windows compatibility * feat: polish mcpb manifest for submission - Add 512x512 icon (logo only, no text) - Add PRIVACY.md with future-ready analytics opt-in clause - Add Privacy section to README - Add 5 usage examples showcasing automation management - Update manifest with full metadata: - display_name: 'Home Assistant MCP Server' - Author: Julien Larocque-Dupont - repository, homepage, documentation, support URLs - privacy_policies array pointing to raw GitHub PRIVACY.md - Expanded keywords - long_description with markdown formatting - Update workflow to include icon in mcpb bundle * docs: adjust privacy policy language to use "might collect" Makes telemetry language more conditional/future-oriented rather than stating it as currently active collection. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * feat: reorganize distribution files and add smoke test - Reorganize distribution files into packaging/ folder - packaging/binary/ for PyInstaller spec - packaging/mcpb/ for mcpb packaging files - Add smoke test CLI command (--smoke-test flag) - Replace start-and-grep binary test with proper smoke test - Fix metadata: rename to "Home Assistant MCP" (no Server) - Simplify manifest template (tools are auto-generated) - Fix double newlines in long_description - Add deferred server loading for smoke test support 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: use absolute paths in PyInstaller spec file The spec file paths are now relative to PROJECT_ROOT to work correctly when pyinstaller is invoked from the project root directory. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: correct PROJECT_ROOT calculation in spec file SPECPATH is already the directory containing the spec file, so we only need dirname twice to get the project root. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: move pyinstaller_hooks to packaging/binary/ Keep all PyInstaller-related files together in the packaging/binary directory. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: handle Windows encoding in smoke test Force UTF-8 encoding for stdout/stderr on Windows to support Unicode checkmark characters. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: address security scanner warnings and fix privacy policy - Add explicit permissions to build job to satisfy GitHub security scanner - Update PRIVACY.md to match README claims (no telemetry) - Remove references to hypothetical future telemetry features 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> * fix: add string coercion for numeric parameters in history tools AI tools often pass numeric parameters as strings (e.g., "100" instead of 100), causing validation failures. This adds a shared coerce_int_param() utility that: - Safely converts string/int/None to integers - Handles float strings like "100.0" - Applies min/max constraints - Returns helpful error messages Applied to: - ha_get_history: limit parameter - ha_get_logbook: hours_back, limit, offset parameters Fixes #205, fixes #206 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com>
1 parent 3808907 commit 59fc978

14 files changed

Lines changed: 934 additions & 33 deletions

File tree

.github/workflows/build-binary.yml

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
name: Build and Release Binaries
2+
3+
on:
4+
release:
5+
types: [published]
6+
pull_request:
7+
branches: [master]
8+
paths:
9+
- 'src/**'
10+
- 'packaging/binary/**'
11+
- 'packaging/mcpb/**'
12+
- '.github/workflows/build-binary.yml'
13+
workflow_dispatch:
14+
inputs:
15+
version:
16+
description: 'Version to build (e.g., 4.7.4)'
17+
required: true
18+
default: '0.0.0-dev'
19+
20+
# Restrict permissions by default (security best practice)
21+
permissions:
22+
contents: read
23+
24+
jobs:
25+
build:
26+
permissions:
27+
contents: read
28+
strategy:
29+
fail-fast: false
30+
matrix:
31+
include:
32+
- os: ubuntu-latest
33+
artifact_name: ha-mcp-linux
34+
binary_ext: ''
35+
platform: linux
36+
create_mcpb: false
37+
- os: windows-latest
38+
artifact_name: ha-mcp-windows
39+
binary_ext: '.exe'
40+
platform: win32
41+
create_mcpb: true
42+
- os: macos-latest
43+
artifact_name: ha-mcp-macos-arm64
44+
binary_ext: ''
45+
platform: darwin
46+
create_mcpb: true
47+
48+
runs-on: ${{ matrix.os }}
49+
name: Build on ${{ matrix.os }}
50+
51+
steps:
52+
- name: Checkout code
53+
uses: actions/checkout@v4
54+
55+
- name: Set up Python
56+
uses: actions/setup-python@v5
57+
with:
58+
python-version: '3.13'
59+
60+
- name: Install uv
61+
uses: astral-sh/setup-uv@v4
62+
with:
63+
version: "latest"
64+
65+
- name: Create virtual environment and install dependencies
66+
run: |
67+
uv venv .venv
68+
uv pip install -e . pyinstaller
69+
shell: bash
70+
71+
- name: Activate venv (Unix)
72+
if: runner.os != 'Windows'
73+
run: echo "$PWD/.venv/bin" >> $GITHUB_PATH
74+
75+
- name: Activate venv (Windows)
76+
if: runner.os == 'Windows'
77+
run: echo "$PWD/.venv/Scripts" >> $env:GITHUB_PATH
78+
shell: pwsh
79+
80+
- name: Build binary
81+
run: pyinstaller packaging/binary/ha-mcp.spec
82+
83+
- name: Run smoke test (Unix)
84+
if: runner.os != 'Windows'
85+
run: |
86+
chmod +x dist/ha-mcp
87+
# Run the built-in smoke test to verify all libraries are bundled
88+
./dist/ha-mcp --smoke-test
89+
90+
- name: Run smoke test (Windows)
91+
if: runner.os == 'Windows'
92+
shell: pwsh
93+
run: |
94+
# Run the built-in smoke test to verify all libraries are bundled
95+
& "dist\ha-mcp.exe" --smoke-test
96+
if ($LASTEXITCODE -ne 0) {
97+
Write-Host "Smoke test failed with exit code $LASTEXITCODE"
98+
exit $LASTEXITCODE
99+
}
100+
101+
- name: Set version
102+
id: version
103+
shell: bash
104+
run: |
105+
if [ "${{ github.event_name }}" = "release" ]; then
106+
VERSION="${{ github.event.release.tag_name }}"
107+
# Remove 'v' prefix if present
108+
VERSION="${VERSION#v}"
109+
else
110+
VERSION="${{ github.event.inputs.version }}"
111+
fi
112+
echo "version=$VERSION" >> $GITHUB_OUTPUT
113+
114+
- name: Rename binary for artifact
115+
shell: bash
116+
run: |
117+
mv dist/ha-mcp${{ matrix.binary_ext }} dist/${{ matrix.artifact_name }}${{ matrix.binary_ext }}
118+
119+
- name: Create mcpb bundle (Windows/macOS only)
120+
if: matrix.create_mcpb
121+
shell: bash
122+
run: |
123+
VERSION="${{ steps.version.outputs.version }}"
124+
PLATFORM="${{ matrix.platform }}"
125+
BINARY_EXT="${{ matrix.binary_ext }}"
126+
127+
# Create mcpb directory structure
128+
mkdir -p mcpb-bundle
129+
130+
# Copy binary to bundle
131+
cp dist/${{ matrix.artifact_name }}${{ matrix.binary_ext }} mcpb-bundle/ha-mcp${{ matrix.binary_ext }}
132+
133+
# Copy icon to bundle
134+
cp packaging/mcpb/icon.png mcpb-bundle/icon.png
135+
136+
# Generate manifest.json with auto-discovered tools
137+
python packaging/mcpb/generate_manifest.py "$VERSION" "$PLATFORM" "$BINARY_EXT"
138+
139+
# Create .mcpb file (zip archive)
140+
cd mcpb-bundle
141+
if [ "${{ runner.os }}" = "Windows" ]; then
142+
7z a -tzip "../${{ matrix.artifact_name }}.mcpb" *
143+
else
144+
zip -r "../${{ matrix.artifact_name }}.mcpb" *
145+
fi
146+
cd ..
147+
148+
- name: Upload binary artifact
149+
uses: actions/upload-artifact@v4
150+
with:
151+
name: ${{ matrix.artifact_name }}
152+
path: dist/${{ matrix.artifact_name }}${{ matrix.binary_ext }}
153+
if-no-files-found: error
154+
155+
- name: Upload mcpb artifact
156+
if: matrix.create_mcpb
157+
uses: actions/upload-artifact@v4
158+
with:
159+
name: ${{ matrix.artifact_name }}-mcpb
160+
path: ${{ matrix.artifact_name }}.mcpb
161+
if-no-files-found: error
162+
163+
release:
164+
needs: build
165+
runs-on: ubuntu-latest
166+
if: github.event_name == 'release'
167+
permissions:
168+
contents: write
169+
170+
steps:
171+
- name: Download all artifacts
172+
uses: actions/download-artifact@v4
173+
with:
174+
path: artifacts
175+
176+
- name: List artifacts
177+
run: find artifacts -type f
178+
179+
- name: Upload binaries to release
180+
uses: softprops/action-gh-release@v2
181+
with:
182+
files: |
183+
artifacts/ha-mcp-linux/ha-mcp-linux
184+
artifacts/ha-mcp-windows/ha-mcp-windows.exe
185+
artifacts/ha-mcp-macos-arm64/ha-mcp-macos-arm64
186+
artifacts/ha-mcp-windows-mcpb/ha-mcp-windows.mcpb
187+
artifacts/ha-mcp-macos-arm64-mcpb/ha-mcp-macos-arm64.mcpb

PRIVACY.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Privacy Policy
2+
3+
**Last updated:** November 2024
4+
5+
## Overview
6+
7+
Home Assistant MCP Server ("ha-mcp") runs entirely on your local machine and communicates only with your own Home Assistant instance. We are committed to transparency about any data collection.
8+
9+
## Data Collection
10+
11+
**Ha-mcp does not collect any data.** The server runs entirely locally on your machine and does not send telemetry, analytics, or any information to external servers.
12+
13+
**We do NOT collect:**
14+
- Entity names or IDs
15+
- Home Assistant configuration
16+
- Personal information
17+
- Automation or script content
18+
- Any data from your smart home devices
19+
- Usage statistics or analytics
20+
- Error reports (unless you explicitly send them)
21+
22+
## Bug Reports
23+
24+
Ha-mcp may include a bug reporting feature that allows you to send diagnostic information when you encounter issues. Bug reports are:
25+
26+
- **Only sent with your explicit approval** — the AI assistant will ask before sending
27+
- **Reviewed with you first** — you'll see what information is included
28+
- **Anonymized** — personal data should be replaced with generic values before submission
29+
30+
You are always in control of whether to send a bug report.
31+
32+
## Your Home Assistant Data
33+
34+
When you use ha-mcp, Claude Desktop accesses data from your Home Assistant instance, including entity states, automations, and device information. This data:
35+
36+
- Is processed locally by Claude Desktop
37+
- Is subject to [Anthropic's Privacy Policy](https://www.anthropic.com/privacy)
38+
- Is NOT collected, stored, or transmitted by ha-mcp
39+
40+
## Third-Party Services
41+
42+
Ha-mcp communicates with:
43+
44+
- **Your Home Assistant instance** — via the URL and token you provide
45+
- **Claude Desktop** — the MCP client that runs ha-mcp
46+
47+
Ha-mcp does not communicate with any other external services.
48+
49+
## Data Security
50+
51+
- Your Home Assistant credentials are stored locally by Claude Desktop
52+
- Bug reports are only sent when you explicitly approve
53+
- No data leaves your local network except to your Home Assistant instance
54+
55+
## Changes to This Policy
56+
57+
We may update this privacy policy to reflect changes in our practices. Significant changes will be noted in release notes.
58+
59+
## Contact
60+
61+
For privacy-related questions or concerns:
62+
63+
- **GitHub Issues:** [https://github.com/homeassistant-ai/ha-mcp/issues](https://github.com/homeassistant-ai/ha-mcp/issues)
64+
- **Email:** github@qc-h.net
65+
66+
## Summary
67+
68+
| Aspect | Status |
69+
|--------|--------|
70+
| Telemetry | None |
71+
| Personal data collected | None |
72+
| Bug reports | User-approved only |
73+
| Local processing | Yes |
74+
| Third-party sharing | None |

README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,22 @@
3030

3131
---
3232

33+
## 💬 What Can You Do With It?
34+
35+
Just talk to Claude naturally. Here are some real examples:
36+
37+
| You Say | What Happens |
38+
|---------|--------------|
39+
| *"Turn off all the lights in the living room"* | Finds entities by room using fuzzy search, controls them in bulk |
40+
| *"Is everything healthy? Any devices offline?"* | Checks system health, finds unavailable entities, reports issues |
41+
| *"Create an automation that turns on the porch light at sunset"* | Creates the automation with proper triggers and actions |
42+
| *"The work-from-home automation doesn't work anymore, check what's going on"* | Analyzes execution traces, finds the bug, and auto-fixes it |
43+
| *"Add milk to my shopping list"* | Finds your shopping list and adds the item |
44+
45+
No YAML editing. No entity ID lookups. Just describe what you want.
46+
47+
---
48+
3349
## ✨ Features
3450

3551
### 🔍 Discover, Search and Query
@@ -588,6 +604,18 @@ For future enhancements and planned features, see the [Development Roadmap](http
588604

589605
---
590606

607+
## 🔒 Privacy
608+
609+
Ha-mcp runs **entirely locally** on your machine. We collect no data, send no telemetry, and have no external dependencies beyond your own Home Assistant instance.
610+
611+
- **No analytics or tracking**
612+
- **No cloud services**
613+
- **Your data stays on your network**
614+
615+
For full details, see our [Privacy Policy](PRIVACY.md).
616+
617+
---
618+
591619
## 📄 License
592620

593621
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.

0 commit comments

Comments
 (0)