Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ffb6294aa9 |
47
.cursorignore
Normal file
47
.cursorignore
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# Ignore node_modules directory
|
||||||
|
node_modules/
|
||||||
|
|
||||||
|
# Ignore build output directories
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# Ignore environment variable files
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.development
|
||||||
|
.env.test
|
||||||
|
.env.production
|
||||||
|
|
||||||
|
# Ignore log files
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Ignore Docker files
|
||||||
|
Dockerfile
|
||||||
|
docker-compose.yml
|
||||||
|
|
||||||
|
# Ignore Jest coverage directory
|
||||||
|
coverage/
|
||||||
|
|
||||||
|
# Ignore TypeScript declaration files
|
||||||
|
*.d.ts
|
||||||
|
|
||||||
|
# Ignore temporary files
|
||||||
|
*.tmp
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*.bak
|
||||||
|
|
||||||
|
# Ignore IDE specific files
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# Ignore OS generated files
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
*.~lock.*
|
||||||
|
*.~undo-tree*
|
||||||
|
|
||||||
|
|
||||||
|
coverage/
|
||||||
36
.dockerignore
Normal file
36
.dockerignore
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# Dependencies
|
||||||
|
node_modules
|
||||||
|
npm-debug.log
|
||||||
|
yarn-debug.log
|
||||||
|
yarn-error.log
|
||||||
|
|
||||||
|
# Build output
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Version control
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# IDE files
|
||||||
|
.vscode
|
||||||
|
.idea
|
||||||
|
|
||||||
|
# Test files
|
||||||
|
coverage
|
||||||
|
__tests__
|
||||||
|
jest.config.js
|
||||||
|
jest.setup.js
|
||||||
|
*.test.ts
|
||||||
|
*.spec.ts
|
||||||
|
|
||||||
|
# Other
|
||||||
|
*.md
|
||||||
|
.DS_Store
|
||||||
|
Dockerfile
|
||||||
|
docker-compose.yml
|
||||||
|
.dockerignore
|
||||||
@@ -1,6 +1,3 @@
|
|||||||
NODE_ENV=development
|
NODE_ENV=production
|
||||||
HASS_HOST=http://homeassistant.local:8123
|
HASS_HOST=your_home_assistant_url
|
||||||
HASS_TOKEN=your_home_assistant_token
|
HASS_TOKEN=your_home_assistant_token
|
||||||
PORT=3000
|
|
||||||
HASS_SOCKET_URL=ws://homeassistant.local:8123/api/websocket
|
|
||||||
LOG_LEVEL=debug
|
|
||||||
23
Dockerfile
Normal file
23
Dockerfile
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Use Node.js 20.10.0 as the base image
|
||||||
|
FROM node:20.10.0-slim
|
||||||
|
|
||||||
|
# Create app directory
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# Copy package files
|
||||||
|
COPY package*.json ./
|
||||||
|
|
||||||
|
# Install dependencies
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
# Copy source code
|
||||||
|
COPY . .
|
||||||
|
|
||||||
|
# Build the application
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
# Expose the port your app runs on (if needed)
|
||||||
|
# EXPOSE 3000
|
||||||
|
|
||||||
|
# Start the application
|
||||||
|
CMD ["npm", "start"]
|
||||||
109
README.md
109
README.md
@@ -1,31 +1,7 @@
|
|||||||
# Model Context Protocol Server for Home Assistant
|
# Model Context Protocol Server for Home Assistant
|
||||||
|
|
||||||
*Forked from [tevonsb/homeassistant-mcp](https://github.com/tevonsb/homeassistant-mcp)*
|
|
||||||
|
|
||||||
A powerful bridge between your Home Assistant instance and Language Learning Models (LLMs), enabling natural language control and monitoring of your smart home devices through the Model Context Protocol (MCP).
|
A powerful bridge between your Home Assistant instance and Language Learning Models (LLMs), enabling natural language control and monitoring of your smart home devices through the Model Context Protocol (MCP).
|
||||||
|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||

|
|
||||||
|
|
||||||
## Table of Contents
|
|
||||||
|
|
||||||
- [Key Features](#key-features)
|
|
||||||
- [Prerequisites](#prerequisites)
|
|
||||||
- [Installation](#installation)
|
|
||||||
- [Basic Setup](#basic-setup)
|
|
||||||
- [Docker Setup (Recommended)](#docker-setup-recommended)
|
|
||||||
- [Configuration](#configuration)
|
|
||||||
- [Development](#development)
|
|
||||||
- [Supported Commands](#supported-commands)
|
|
||||||
- [Natural Language Integration](#natural-language-integration)
|
|
||||||
- [Troubleshooting](#troubleshooting)
|
|
||||||
- [Project Status](#project-status)
|
|
||||||
- [Contributing](#contributing)
|
|
||||||
- [Resources](#resources)
|
|
||||||
- [License](#license)
|
|
||||||
|
|
||||||
## Key Features
|
## Key Features
|
||||||
|
|
||||||
- **Smart Device Control** 🎮
|
- **Smart Device Control** 🎮
|
||||||
@@ -45,10 +21,9 @@ A powerful bridge between your Home Assistant instance and Language Learning Mod
|
|||||||
|
|
||||||
## Prerequisites
|
## Prerequisites
|
||||||
|
|
||||||
- **Node.js** 20.10.0 or higher
|
- Node.js 20.10.0 or higher
|
||||||
- **NPM** package manager
|
- NPM package manager
|
||||||
- **Docker Compose** for containerization
|
- Running Home Assistant instance
|
||||||
- Running **Home Assistant** instance
|
|
||||||
- Home Assistant long-lived access token ([How to get token](https://community.home-assistant.io/t/how-to-get-long-lived-access-token/162159))
|
- Home Assistant long-lived access token ([How to get token](https://community.home-assistant.io/t/how-to-get-long-lived-access-token/162159))
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
@@ -67,42 +42,34 @@ npm install
|
|||||||
npm run build
|
npm run build
|
||||||
```
|
```
|
||||||
|
|
||||||
### Docker Setup
|
### Docker Setup (Recommended)
|
||||||
|
|
||||||
> Note: This setup is currently in progress. You can use the `docker` branch to get the latest changes.
|
1. Clone and prepare:
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/jango-blockchained/homeassistant-mcp.git
|
||||||
|
cd homeassistant-mcp
|
||||||
|
```
|
||||||
|
|
||||||
1. **Clone and prepare:**
|
2. Configure environment:
|
||||||
```bash
|
```env
|
||||||
git clone -b docker https://github.com/jango-blockchained/homeassistant-mcp.git
|
NODE_ENV=production
|
||||||
cd homeassistant-mcp
|
HASS_HOST=your_home_assistant_url
|
||||||
cp .env.example .env
|
HASS_TOKEN=your_home_assistant_token
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **Configure environment `.env` file:**
|
3. Launch with Docker Compose:
|
||||||
```env
|
```bash
|
||||||
...
|
docker-compose up -d
|
||||||
HASS_TOKEN=your_home_assistant_token
|
```
|
||||||
...
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Launch with Docker Compose:**
|
|
||||||
```bash
|
|
||||||
docker-compose up -d
|
|
||||||
```
|
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
Copy `.env.example` to `.env`.
|
Create a `.env` file with:
|
||||||
|
|
||||||
```bash
|
|
||||||
cp .env.example .env
|
|
||||||
```
|
|
||||||
|
|
||||||
Configure environment `.env` file:
|
|
||||||
```env
|
```env
|
||||||
...
|
|
||||||
HASS_TOKEN=your_home_assistant_token
|
HASS_TOKEN=your_home_assistant_token
|
||||||
...
|
HASS_HOST=your_home_assistant_url # e.g., http://homeassistant.local:8123
|
||||||
|
PORT=3000 # Optional, defaults to 3000
|
||||||
```
|
```
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
@@ -111,7 +78,7 @@ HASS_TOKEN=your_home_assistant_token
|
|||||||
npm run dev # Development mode
|
npm run dev # Development mode
|
||||||
npm run build # Build project
|
npm run build # Build project
|
||||||
npm run start # Production mode
|
npm run start # Production mode
|
||||||
npx jest --config=jest.config.cjs # Run tests
|
npx jest --config=jest.config.js # Run tests
|
||||||
```
|
```
|
||||||
|
|
||||||
## Supported Commands
|
## Supported Commands
|
||||||
@@ -253,14 +220,14 @@ npx jest --config=jest.config.cjs # Run tests
|
|||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
### Common Issues
|
### Common Issues
|
||||||
1. **Node.js Version (`toSorted is not a function`)**
|
1. Node.js Version (`toSorted is not a function`)
|
||||||
- **Solution:** Update to Node.js 20.10.0+
|
- Solution: Update to Node.js 20.10.0+
|
||||||
2. **Connection Issues**
|
2. Connection Issues
|
||||||
- Verify Home Assistant is running
|
- Verify Home Assistant is running
|
||||||
- Check `HASS_HOST` accessibility
|
- Check HASS_HOST accessibility
|
||||||
- Validate token permissions
|
- Validate token permissions
|
||||||
3. **Entity Control Issues**
|
3. Entity Control Issues
|
||||||
- Verify `entity_id` exists
|
- Verify entity_id exists
|
||||||
- Check entity domain matches command
|
- Check entity domain matches command
|
||||||
- Ensure parameter values are valid
|
- Ensure parameter values are valid
|
||||||
|
|
||||||
@@ -271,27 +238,11 @@ npx jest --config=jest.config.cjs # Run tests
|
|||||||
- Device control (Lights, Climate, Covers, Switches, Contacts)
|
- Device control (Lights, Climate, Covers, Switches, Contacts)
|
||||||
- Basic state management
|
- Basic state management
|
||||||
- Error handling and validation
|
- Error handling and validation
|
||||||
- Docker containerization and configuration
|
|
||||||
- Jest testing setup and TypeScript integration
|
|
||||||
- Environment variable management
|
|
||||||
- Home Assistant API integration
|
|
||||||
- Project documentation and README organization
|
|
||||||
|
|
||||||
🚧 **In Progress**
|
🚧 **In Progress**
|
||||||
- Custom prompt testing and optimization
|
- Custom prompt testing
|
||||||
- Resource context integration
|
- Resource context integration
|
||||||
- Tool organization optimization
|
- Tool organization optimization
|
||||||
- Enhanced macOS integration
|
|
||||||
- Type safety improvements
|
|
||||||
- Testing coverage expansion
|
|
||||||
|
|
||||||
🔜 **Planned**
|
|
||||||
- Multi-platform desktop integration
|
|
||||||
- Advanced error recovery mechanisms
|
|
||||||
- Performance optimization
|
|
||||||
- WebSocket implementation for real-time updates
|
|
||||||
- Enhanced security features
|
|
||||||
- API documentation generation
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
|
|||||||
@@ -1,152 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
|
|
||||||
# macos-setup.sh
|
|
||||||
|
|
||||||
# Colors for output
|
|
||||||
RED='\033[0;31m'
|
|
||||||
GREEN='\033[0;32m'
|
|
||||||
BLUE='\033[0;34m'
|
|
||||||
NC='\033[0m'
|
|
||||||
|
|
||||||
echo -e "${BLUE}Setting up MCP Integration for Claude Desktop${NC}"
|
|
||||||
|
|
||||||
# Function to compare version numbers
|
|
||||||
version_greater_equal() {
|
|
||||||
printf '%s\n' "$2" "$1" | sort -V -C
|
|
||||||
}
|
|
||||||
|
|
||||||
# Check if Homebrew is installed
|
|
||||||
if ! command -v brew &> /dev/null; then
|
|
||||||
echo -e "${RED}Homebrew is not installed. Installing Homebrew...${NC}"
|
|
||||||
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if Node.js is installed
|
|
||||||
if ! command -v node &> /dev/null; then
|
|
||||||
echo -e "${RED}Node.js is not installed. Installing via Homebrew...${NC}"
|
|
||||||
brew install node@20
|
|
||||||
brew link node@20
|
|
||||||
else
|
|
||||||
NODE_VERSION=$(node -v)
|
|
||||||
if ! version_greater_equal "${NODE_VERSION//v/}" "20.10.0"; then
|
|
||||||
echo -e "${RED}Node.js version must be 20.10.0 or higher. Current version: $NODE_VERSION${NC}"
|
|
||||||
echo -e "${BLUE}Installing Node.js 20 via Homebrew...${NC}"
|
|
||||||
brew install node@20
|
|
||||||
brew link node@20
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if npm is installed
|
|
||||||
if ! command -v npm &> /dev/null; then
|
|
||||||
echo -e "${RED}npm is not installed. Please install npm and try again.${NC}"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if jq is installed
|
|
||||||
if ! command -v jq &> /dev/null; then
|
|
||||||
echo -e "${RED}jq is not installed. Installing via Homebrew...${NC}"
|
|
||||||
brew install jq
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Create MCP directory if it doesn't exist
|
|
||||||
MCP_DIR="$HOME/.mcp"
|
|
||||||
mkdir -p "$MCP_DIR"
|
|
||||||
|
|
||||||
# Clone the Home Assistant MCP repository
|
|
||||||
echo -e "${BLUE}Cloning Home Assistant MCP repository...${NC}"
|
|
||||||
git clone https://github.com/jango-blockchained/homeassistant-mcp.git "$MCP_DIR/homeassistant-mcp"
|
|
||||||
cd "$MCP_DIR/homeassistant-mcp"
|
|
||||||
|
|
||||||
# Install dependencies and build
|
|
||||||
echo -e "${BLUE}Installing dependencies and building...${NC}"
|
|
||||||
npm install
|
|
||||||
npm run build
|
|
||||||
|
|
||||||
# Create Claude Desktop config directory (macOS specific path)
|
|
||||||
CLAUDE_CONFIG_DIR="$HOME/Library/Application Support/Claude"
|
|
||||||
mkdir -p "$CLAUDE_CONFIG_DIR"
|
|
||||||
|
|
||||||
# Prompt for configurations
|
|
||||||
echo -e "${BLUE}Please enter your configurations:${NC}"
|
|
||||||
read -p "Home Assistant URL (e.g., http://homeassistant.local:8123): " HASS_HOST
|
|
||||||
read -p "Home Assistant Long-lived access token: " HASS_TOKEN
|
|
||||||
|
|
||||||
# Create .env file for Home Assistant
|
|
||||||
cat > "$MCP_DIR/homeassistant-mcp/.env" << EOL
|
|
||||||
NODE_ENV=production
|
|
||||||
HASS_HOST=$HASS_HOST
|
|
||||||
HASS_TOKEN=$HASS_TOKEN
|
|
||||||
PORT=3000
|
|
||||||
EOL
|
|
||||||
|
|
||||||
# Create base configuration for Home Assistant
|
|
||||||
CONFIG_JSON='{
|
|
||||||
"mcpServers": {
|
|
||||||
"homeassistant": {
|
|
||||||
"command": "node",
|
|
||||||
"args": [
|
|
||||||
"'$MCP_DIR'/homeassistant-mcp/dist/index.js"
|
|
||||||
],
|
|
||||||
"env": {
|
|
||||||
"HASS_TOKEN": "'$HASS_TOKEN'",
|
|
||||||
"HASS_HOST": "'$HASS_HOST'",
|
|
||||||
"NODE_ENV": "production",
|
|
||||||
"PORT": "3000"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}'
|
|
||||||
|
|
||||||
# Prompt for enabling Brave Search
|
|
||||||
read -p "Do you want to enable Brave Search integration? (y/n): " ENABLE_BRAVE_SEARCH
|
|
||||||
|
|
||||||
if [[ $ENABLE_BRAVE_SEARCH =~ ^[Yy]$ ]]; then
|
|
||||||
# Install Brave Search MCP globally only if enabled
|
|
||||||
echo -e "${BLUE}Installing Brave Search MCP...${NC}"
|
|
||||||
npm install -g @modelcontextprotocol/server-brave-search
|
|
||||||
|
|
||||||
read -p "Brave Search API Key: " BRAVE_API_KEY
|
|
||||||
|
|
||||||
# Add Brave Search to the configuration
|
|
||||||
CONFIG_JSON=$(echo $CONFIG_JSON | jq '.mcpServers += {
|
|
||||||
"brave-search": {
|
|
||||||
"command": "npx",
|
|
||||||
"args": ["-y", "@modelcontextprotocol/server-brave-search"],
|
|
||||||
"env": {
|
|
||||||
"BRAVE_API_KEY": "'$BRAVE_API_KEY'"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}')
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Write the final configuration to file
|
|
||||||
echo $CONFIG_JSON | jq '.' > "$CLAUDE_CONFIG_DIR/claude_desktop_config.json"
|
|
||||||
|
|
||||||
# Set proper permissions
|
|
||||||
chmod 600 "$CLAUDE_CONFIG_DIR/claude_desktop_config.json"
|
|
||||||
chmod 600 "$MCP_DIR/homeassistant-mcp/.env"
|
|
||||||
|
|
||||||
echo -e "${GREEN}Installation complete!${NC}"
|
|
||||||
echo -e "${BLUE}Configuration files created at:${NC}"
|
|
||||||
echo " - $CLAUDE_CONFIG_DIR/claude_desktop_config.json"
|
|
||||||
echo " - $MCP_DIR/homeassistant-mcp/.env"
|
|
||||||
echo -e "${BLUE}To use the integration:${NC}"
|
|
||||||
echo "1. Make sure Claude Desktop is installed from https://claude.ai/download"
|
|
||||||
echo "2. Restart Claude Desktop"
|
|
||||||
echo "3. Home Assistant MCP integration is now available"
|
|
||||||
if [[ $ENABLE_BRAVE_SEARCH =~ ^[Yy]$ ]]; then
|
|
||||||
echo "4. Brave Search MCP integration is also available"
|
|
||||||
fi
|
|
||||||
echo -e "${RED}Note: Keep your access tokens and API keys secure and never share them with others${NC}"
|
|
||||||
|
|
||||||
# Optional: Test the installations
|
|
||||||
read -p "Would you like to test the installations? (y/n) " -n 1 -r
|
|
||||||
echo
|
|
||||||
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
||||||
echo -e "${BLUE}Testing Home Assistant MCP connection...${NC}"
|
|
||||||
node "$MCP_DIR/homeassistant-mcp/dist/index.js" test
|
|
||||||
if [[ $ENABLE_BRAVE_SEARCH =~ ^[Yy]$ ]]; then
|
|
||||||
echo -e "${BLUE}Testing Brave Search MCP...${NC}"
|
|
||||||
npx @modelcontextprotocol/server-brave-search test
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
118
claude_desktop_setup.sh
Normal file
118
claude_desktop_setup.sh
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# mcp-setup.sh
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
echo -e "${BLUE}Setting up MCP Integration for Claude Desktop${NC}"
|
||||||
|
|
||||||
|
# Check if Node.js is installed
|
||||||
|
if ! command -v node &> /dev/null; then
|
||||||
|
echo -e "${RED}Node.js is not installed. Installing via nvm...${NC}"
|
||||||
|
|
||||||
|
# Install nvm
|
||||||
|
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
|
||||||
|
|
||||||
|
# Load nvm
|
||||||
|
export NVM_DIR="$HOME/.nvm"
|
||||||
|
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
|
||||||
|
|
||||||
|
# Install Node.js 20.10.0
|
||||||
|
nvm install 20.10.0
|
||||||
|
nvm use 20.10.0
|
||||||
|
else
|
||||||
|
NODE_VERSION=$(node -v)
|
||||||
|
if [[ ${NODE_VERSION//v/} < "20.10.0" ]]; then
|
||||||
|
echo -e "${RED}Node.js version must be 20.10.0 or higher. Current version: $NODE_VERSION${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install Brave Search MCP globally
|
||||||
|
echo -e "${BLUE}Installing Brave Search MCP...${NC}"
|
||||||
|
npm install -g @modelcontextprotocol/server-brave-search
|
||||||
|
|
||||||
|
# Create MCP directory if it doesn't exist
|
||||||
|
MCP_DIR="$HOME/.mcp"
|
||||||
|
mkdir -p "$MCP_DIR"
|
||||||
|
|
||||||
|
# Clone the Home Assistant MCP repository
|
||||||
|
echo -e "${BLUE}Cloning Home Assistant MCP repository...${NC}"
|
||||||
|
git clone https://github.com/jango-blockchained/homeassistant-mcp.git "$MCP_DIR/homeassistant-mcp"
|
||||||
|
cd "$MCP_DIR/homeassistant-mcp"
|
||||||
|
|
||||||
|
# Install dependencies and build
|
||||||
|
npm install
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# Prompt for configurations
|
||||||
|
echo -e "${BLUE}Please enter your configurations:${NC}"
|
||||||
|
read -p "Home Assistant URL (e.g., http://homeassistant.local:8123): " HASS_HOST
|
||||||
|
read -p "Home Assistant Long-lived access token: " HASS_TOKEN
|
||||||
|
read -p "Brave Search API Key: " BRAVE_API_KEY
|
||||||
|
|
||||||
|
# Create .env file for Home Assistant
|
||||||
|
cat > "$MCP_DIR/homeassistant-mcp/.env" << EOL
|
||||||
|
NODE_ENV=production
|
||||||
|
HASS_HOST=$HASS_HOST
|
||||||
|
HASS_TOKEN=$HASS_TOKEN
|
||||||
|
EOL
|
||||||
|
|
||||||
|
# Create Claude Desktop config directory
|
||||||
|
CLAUDE_CONFIG_DIR="$HOME/Library/Application Support/Claude"
|
||||||
|
mkdir -p "$CLAUDE_CONFIG_DIR"
|
||||||
|
|
||||||
|
# Create combined configuration file
|
||||||
|
cat > "$CLAUDE_CONFIG_DIR/claude_desktop_config.json" << EOL
|
||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"homeassistant": {
|
||||||
|
"command": "node",
|
||||||
|
"args": [
|
||||||
|
"$MCP_DIR/homeassistant-mcp/dist/index.js"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"HASS_TOKEN": "$HASS_TOKEN",
|
||||||
|
"HASS_HOST": "$HASS_HOST"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"brave-search": {
|
||||||
|
"command": "npx",
|
||||||
|
"args": [
|
||||||
|
"-y",
|
||||||
|
"@modelcontextprotocol/server-brave-search"
|
||||||
|
],
|
||||||
|
"env": {
|
||||||
|
"BRAVE_API_KEY": "$BRAVE_API_KEY"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EOL
|
||||||
|
|
||||||
|
# Set proper permissions
|
||||||
|
chmod 600 "$CLAUDE_CONFIG_DIR/claude_desktop_config.json"
|
||||||
|
chmod 600 "$MCP_DIR/homeassistant-mcp/.env"
|
||||||
|
|
||||||
|
echo -e "${GREEN}Installation complete!${NC}"
|
||||||
|
echo -e "${BLUE}Configuration file created at:${NC} $CLAUDE_CONFIG_DIR/claude_desktop_config.json"
|
||||||
|
echo -e "${BLUE}To use the integration:${NC}"
|
||||||
|
echo "1. Make sure Claude Desktop is installed from https://claude.ai/download"
|
||||||
|
echo "2. Restart Claude Desktop"
|
||||||
|
echo "3. Both Home Assistant and Brave Search MCP integrations should now be available"
|
||||||
|
echo -e "${RED}Note: Keep your access tokens and API keys secure and never share them with others${NC}"
|
||||||
|
|
||||||
|
# Optional: Test the installations
|
||||||
|
read -p "Would you like to test the installations? (y/n) " -n 1 -r
|
||||||
|
echo
|
||||||
|
if [[ $REPLY =~ ^[Yy]$ ]]
|
||||||
|
then
|
||||||
|
echo -e "${BLUE}Testing Home Assistant MCP connection...${NC}"
|
||||||
|
node "$MCP_DIR/homeassistant-mcp/dist/index.js" test
|
||||||
|
echo -e "${BLUE}Testing Brave Search MCP...${NC}"
|
||||||
|
npx @modelcontextprotocol/server-brave-search test
|
||||||
|
fi
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
/** @type {import('ts-jest').JestConfigWithTsJest} */
|
|
||||||
module.exports = {
|
|
||||||
preset: 'ts-jest',
|
|
||||||
testEnvironment: 'node',
|
|
||||||
moduleNameMapper: {
|
|
||||||
'^@src/(.*)$': '<rootDir>/src/$1',
|
|
||||||
'^@tests/(.*)$': '<rootDir>/__tests__/$1',
|
|
||||||
'^(\\.{1,2}/.*)\\.js$': '$1'
|
|
||||||
},
|
|
||||||
roots: [
|
|
||||||
'<rootDir>/src',
|
|
||||||
'<rootDir>/__tests__'
|
|
||||||
],
|
|
||||||
transform: {
|
|
||||||
'^.+\\.tsx?$': ['ts-jest', {
|
|
||||||
useESM: true,
|
|
||||||
tsconfig: './tsconfig.json'
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
extensionsToTreatAsEsm: ['.ts', '.tsx'],
|
|
||||||
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
|
|
||||||
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
|
|
||||||
resolver: '<rootDir>/jest-resolver.cjs',
|
|
||||||
transformIgnorePatterns: [
|
|
||||||
'node_modules/(?!(@digital-alchemy|litemcp|semver|zod)/)'
|
|
||||||
],
|
|
||||||
modulePathIgnorePatterns: [
|
|
||||||
'<rootDir>/dist/'
|
|
||||||
],
|
|
||||||
testEnvironmentOptions: {
|
|
||||||
experimentalVmModules: true
|
|
||||||
},
|
|
||||||
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
|
|
||||||
globals: {
|
|
||||||
'ts-jest': {
|
|
||||||
useESM: true,
|
|
||||||
tsconfig: {
|
|
||||||
allowJs: true,
|
|
||||||
esModuleInterop: true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
"semver": "^6.3.1",
|
"semver": "^6.3.1",
|
||||||
"ts-jest": "^28.0.8",
|
"ts-jest": "^28.0.8",
|
||||||
"tsx": "^4.19.2",
|
"tsx": "^4.19.2",
|
||||||
"typescript": "^5.7.2"
|
"typescript": "^4.9.5"
|
||||||
},
|
},
|
||||||
"author": "Jango Blockchained",
|
"author": "Jango Blockchained",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
|
|||||||
@@ -7,5 +7,5 @@ export const HASS_CONFIG = {
|
|||||||
BASE_URL: process.env.HASS_HOST || 'http://homeassistant.local:8123',
|
BASE_URL: process.env.HASS_HOST || 'http://homeassistant.local:8123',
|
||||||
TOKEN: process.env.HASS_TOKEN || '',
|
TOKEN: process.env.HASS_TOKEN || '',
|
||||||
SOCKET_URL: process.env.HASS_SOCKET_URL || '',
|
SOCKET_URL: process.env.HASS_SOCKET_URL || '',
|
||||||
SOCKET_TOKEN: process.env.HASS_TOKEN || '',
|
SOCKET_TOKEN: process.env.HASS_SOCKET_TOKEN || '',
|
||||||
};
|
};
|
||||||
17
src/index.ts
17
src/index.ts
@@ -33,19 +33,6 @@ const commonCommands = ['turn_on', 'turn_off', 'toggle'] as const;
|
|||||||
const coverCommands = [...commonCommands, 'open', 'close', 'stop', 'set_position', 'set_tilt_position'] as const;
|
const coverCommands = [...commonCommands, 'open', 'close', 'stop', 'set_position', 'set_tilt_position'] as const;
|
||||||
const climateCommands = [...commonCommands, 'set_temperature', 'set_hvac_mode', 'set_fan_mode', 'set_humidity'] as const;
|
const climateCommands = [...commonCommands, 'set_temperature', 'set_hvac_mode', 'set_fan_mode', 'set_humidity'] as const;
|
||||||
|
|
||||||
interface HassEntity {
|
|
||||||
entity_id: string;
|
|
||||||
state: string;
|
|
||||||
attributes: Record<string, any>;
|
|
||||||
last_changed?: string;
|
|
||||||
last_updated?: string;
|
|
||||||
context?: {
|
|
||||||
id: string;
|
|
||||||
parent_id?: string;
|
|
||||||
user_id?: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const hass = await get_hass();
|
const hass = await get_hass();
|
||||||
|
|
||||||
@@ -70,8 +57,8 @@ async function main() {
|
|||||||
throw new Error(`Failed to fetch devices: ${response.statusText}`);
|
throw new Error(`Failed to fetch devices: ${response.statusText}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const states = await response.json() as HassEntity[];
|
const states = await response.json();
|
||||||
const devices = states.reduce((acc: Record<string, HassEntity[]>, state: HassEntity) => {
|
const devices = states.reduce((acc: any, state: any) => {
|
||||||
const domain = state.entity_id.split('.')[0];
|
const domain = state.entity_id.split('.')[0];
|
||||||
if (!acc[domain]) {
|
if (!acc[domain]) {
|
||||||
acc[domain] = [];
|
acc[domain] = [];
|
||||||
|
|||||||
@@ -4,7 +4,16 @@
|
|||||||
"module": "NodeNext",
|
"module": "NodeNext",
|
||||||
"moduleResolution": "NodeNext",
|
"moduleResolution": "NodeNext",
|
||||||
"outDir": "./dist",
|
"outDir": "./dist",
|
||||||
"rootDir": "./src",
|
"rootDir": "./",
|
||||||
|
"baseUrl": "./",
|
||||||
|
"paths": {
|
||||||
|
"@src/*": [
|
||||||
|
"src/*"
|
||||||
|
],
|
||||||
|
"@tests/*": [
|
||||||
|
"__tests__/*"
|
||||||
|
]
|
||||||
|
},
|
||||||
"strict": true,
|
"strict": true,
|
||||||
"esModuleInterop": true,
|
"esModuleInterop": true,
|
||||||
"skipLibCheck": true,
|
"skipLibCheck": true,
|
||||||
@@ -18,21 +27,20 @@
|
|||||||
"jest"
|
"jest"
|
||||||
],
|
],
|
||||||
"typeRoots": [
|
"typeRoots": [
|
||||||
"./node_modules/@types"
|
"./node_modules/@types",
|
||||||
|
"./node_modules/@types/node"
|
||||||
],
|
],
|
||||||
"lib": [
|
"lib": [
|
||||||
"ES2022"
|
"ES2022",
|
||||||
|
"DOM"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"include": [
|
"include": [
|
||||||
"src/**/*"
|
"src/**/*",
|
||||||
|
"__tests__/**/*.test.ts"
|
||||||
],
|
],
|
||||||
"exclude": [
|
"exclude": [
|
||||||
"node_modules",
|
"node_modules",
|
||||||
"dist",
|
"dist"
|
||||||
"**/*.test.ts",
|
|
||||||
"**/*.spec.ts",
|
|
||||||
"jest.config.js",
|
|
||||||
"jest.setup.js"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user