SmartThingsMCP

by technohead

Not rated
GitHub

About

A comprehensive FastMCP 2.0 server and client for interacting with SmartThings devices, locations, rooms, modes, scenes, and automation rules through the SmartThings API.

Details

Author
technohead
Categories
Other, API

Setup

Install SmartThingsMCP in your MCP client (Claude Desktop, Cursor, Windsurf, and others).

Repository: https://github.com/technohead/smartthings-mcp

Follow the installation instructions in the repository README, then restart your MCP client.

A comprehensive FastMCP 2.0 server and client for interacting with SmartThings devices, locations, rooms, modes, scenes, and automation rules through the SmartThings API.

- FastMCP 2.0 Server: Exposes SmartThings API functionality as MCP tools
- Smart Client: Python client with intelligent caching, async support, and multiple transport options
- Modular Architecture: Organized by functionality (devices, locations, rooms, modes, scenes, rules)
- Two-Level Caching: Both client and server-side caching for optimal performance
- Multiple Transports: HTTP, SSE (Server-Sent Events), and STDIO support
- OAuth 2.0 Authentication: Secure token-based authentication with SmartThings API

- SmartThingsMCPServer.py: FastMCP 2.0 server exposing SmartThings API as MCP tools
- modules/server/: Server tool implementations

- devices.py: Device management tools (list, get, update, delete, execute commands, etc.)
- locations.py: Location management tools (create, read, update, delete locations and rooms)
- rooms.py: Room management tools (list, create, update, delete rooms)
- modes.py: Mode management tools (list, get, set location modes)
- scenes.py: Scene management tools (list, get, execute, create, update, delete scenes)
- rules.py: Automation rule tools (list, get, create, update, delete, execute rules)
- structure_tools.py: Structure generation tools for LLM integration
- common.py: Shared utilities for API requests, URL building, and parameter filtering

- SmartThingsMCPClient.py: CLI for interacting with the MCP server
- modules/client/: Client implementation

- main.py: Main SmartThingsMCPClient class combining all mixins
- base.py: BaseClient with transport handling and tool invocation
- cache.py: CacheMixin with LRU caching, TTL management, and cache statistics
- devices.py: DevicesMixin with device operation methods
- locations.py: LocationsMixin with location and room methods
- rooms.py: RoomsMixin with room-specific methods
- modes.py: ModesMixin with mode management methods
- rules.py: RulesMixin with rule management methods
- scenes.py: ScenesMixin with scene management methods
- utils.py: Utility functions for tool conversion and action execution
- utils_ext.py: Extended utilities (note: currently unused)

SmartThingsMCP exposes the following API endpoints as MCP tools:

- list_devices: Get a list of all devices (supports filtering by capability, location, room, or device ID)
- get_device: Get details of a specific device
- update_device: Update a device's label
- delete_device: Delete a device
- execute_command: Execute a command on a device component
- get_device_status: Get the current status of a device
- get_device_components: Get all components of a device
- get_device_capabilities: Get capabilities of a device component
- get_device_health: Get the health/connectivity status of a device
- get_device_presentation: Get the UI presentation details of a device

- list_locations: Get a list of all locations
- get_location: Get details of a specific location
- create_location: Create a new location with coordinates and address information
- update_location: Update location details (name, coordinates, address)
- delete_location: Delete a location
- get_location_rooms: Get all rooms in a location (convenience method)

- list_rooms: Get all rooms in a location
- get_room: Get details of a specific room
- create_room: Create a new room in a location
- update_room: Update a room's name
- delete_room: Delete a room from a location

- list_modes: Get all available modes for a location
- get_mode: Get details of a specific mode
- get_current_mode: Get the currently active mode for a location
- set_mode: Change the current mode for a location

- list_scenes: Get all scenes (optionally filtered by location)
- get_scene: Get details of a specific scene
- execute_scene: Execute/run a scene
- create_scene: Create a new scene with actions and visual properties
- update_scene: Update an existing scene (name, icon, colors, actions)
- delete_scene: Delete a scene

- list_rules: Get all automation rules (optionally filtered by location)
- get_rule: Get details of a specific rule
- create_rule: Create a new automation rule with conditions and actions
- update_rule: Update an existing rule (name, triggers, actions, enabled state)
- delete_rule: Delete an automation rule
- execute_rule: Manually trigger execution of a rule

Both the SmartThingsMCPClient and SmartThingsMCPServer include comprehensive caching to improve performance:

- Automatic cachingof read-only operations (list_devices, list_locations, etc.)
- TTL-based expiration(default: 5 minutes, configurable)
- Smart cache invalidationon write operations (execute_command, update_device, etc.)
- LRU evictionwhen cache is full
- Cache statisticstracking (hits, misses, hit rate)
- Green visual feedback:✓ Cache hit: list_locations

SeeCACHING.mdfor detailed documentation.

- Automatic cachingof all GET requests to SmartThings API
- TTL-based expiration(default: 5 minutes)
- Full cache invalidationon write operations (POST, PUT, DELETE)
- LRU evictionwhen cache is full
- Cache statisticstracking
- Green visual feedback:✓ Server cache hit: GET devices

SeeSERVER_CACHING.mdfor detailed documentation.

Two-Level Caching:When both client and server caching are active, you get maximum performance with two layers of caching!

- 60-80% reduction in API calls
- 5-10x faster response times for cached data
- Lower rate limit usage

The server provides comprehensive rule management capabilities:

- list_rules: List all automation rules for a location
- get_rule: Get details of a specific rule
- create_rule: Create a new automation rule with conditions and actions
- update_rule: Update an existing rule (name, triggers, actions, or enabled state)
- delete_rule: Delete a rule
- execute_rule: Manually execute a rule

# Disable a rule client.update_rule(auth=token, rule_id="abc-123", enabled=False) # Enable a rule client.update_rule(auth=token, rule_id="abc-123", enabled=True)

Theenabledparameter was added in December 2025 to support toggling rule state without deleting the rule.

- Python 3.8 or higher
- pip or another Python package manager

- fastmcp>=2.0.0: FastMCP 2.0 framework for MCP server/client
- requests>=2.28.0: HTTP library for SmartThings API calls
- Obtain a SmartThings API Token:

- VisitSmartThings Developer Portal
- Create a new API token with the following scopes:

- r:devices:(read devices)
- w:devices:
(control devices)
- r:locations:(read locations)
- w:locations:
(create/update locations)
- r:rules:(read rules, requires Enterprise account)
- w:rules:
(write rules, requires Enterprise account)
- r:scenes:(read scenes)
- x:scenes:
(execute scenes)

SmartThingsMCP uses OAuth 2.0 bearer tokens for authentication with the SmartThings API.

- Must be a valid SmartThings API token (OAuth 2.0 bearer token)
- Token must have appropriate scopes for the operations you want to perform
- Token never expires when obtained from the SmartThings Developer Portal
- Keep your token secure and never commit it to version control

Error calling tool list_devices: 401 Unauthorized

- Verify the token is valid and not expired
- Check that the token has been generated from SmartThings Developer Portal
- Ensure you're passing the token with the--authflag

Error calling tool list_devices: 403 Forbidden

- The token exists but lacks required scopes
- Some features (like Rules) require an Enterprise SmartThings account
- Grant additional scopes to the token in SmartThings Developer Portal

# Start with HTTP transport (default) on port 8000 python SmartThingsMCPServer.py # Custom port python SmartThingsMCPServer.py -port 9000 # Using SSE transport python SmartThingsMCPServer.py -transport sse # Using STDIO transport python SmartThingsMCPServer.py -transport stdio # With auth token override (if needed) python SmartThingsMCPServer.py -auth YOUR_TOKEN

The SmartThingsMCPClient.py provides a CLI interface:

# List available tools python SmartThingsMCPClient.py --transport http --port 8000 --action list_tools # List all devices (requires auth token) python SmartThingsMCPClient.py --auth YOUR_TOKEN --action list_devices # List devices with pretty-printed output python SmartThingsMCPClient.py --auth YOUR_TOKEN --action list_devices --pretty # Get a specific device python SmartThingsMCPClient.py --auth YOUR_TOKEN --action get_device --params '{"device_id": "DEVICE_ID"}' # Get device status python SmartThingsMCPClient.py --auth YOUR_TOKEN --action get_device_status --params '{"device_id": "DEVICE_ID"}' # Execute a device command python SmartThingsMCPClient.py --auth YOUR_TOKEN --action execute_command --params '{ "device_id": "DEVICE_ID", "component": "main", "capability": "switch", "command": "on" }' # List all locations python SmartThingsMCPClient.py --auth YOUR_TOKEN --action list_locations # List all scenes python SmartThingsMCPClient.py --auth YOUR_TOKEN --action list_scenes # Execute a scene python SmartThingsMCPClient.py --auth YOUR_TOKEN --action execute_scene --params '{"scene_id": "SCENE_ID"}' # Create a new location python SmartThingsMCPClient.py --auth YOUR_TOKEN --action create_location --params '{ "name": "Office", "country_code": "US", "region_code": "CA", "locality": "San Francisco" }' # List all modes for a location python SmartThingsMCPClient.py --auth YOUR_TOKEN --action list_modes --params '{"location_id": "LOCATION_ID"}' # Set mode for a location python SmartThingsMCPClient.py --auth YOUR_TOKEN --action set_mode --params '{ "location_id": "LOCATION_ID", "mode_id": "MODE_ID" }' # List all rules python SmartThingsMCPClient.py --auth YOUR_TOKEN --action list_rules # Enable/disable a rule python SmartThingsMCPClient.py --auth YOUR_TOKEN --action update_rule --params '{ "rule_id": "RULE_ID", "enabled": false }'
--host: MCP server host (default: localhost) --port: MCP server port (default: 8000) --auth: SmartThings API authentication token (required for most operations) --transport: Transport type - http, sse, or stdio (default: http) --action: Action/tool to execute (required) --params: JSON string of parameters for the action (default: {}) --pretty: Pretty-print JSON output (flag)
import asyncio from modules.client.main import SmartThingsMCPClient async def main(): # Create client with caching enabled (default) client = SmartThingsMCPClient( host="localhost", port=8000, auth_token="YOUR_TOKEN", transport="http", enable_cache=True, # Enable automatic caching cache_ttl=300, # Cache for 5 minutes max_cache_size=1000 # Store up to 1000 cache entries ) # List all devices devices = await client.list_devices(auth="YOUR_TOKEN") print(f"Found {len(devices['items'])} devices") # Get specific device device = await client.get_device(auth="YOUR_TOKEN", device_id="DEVICE_ID") print(f"Device: {device['label']}") # Execute device command result = await client.execute_command( auth="YOUR_TOKEN", device_id="DEVICE_ID", component="main", capability="switch", command="on" ) # List locations locations = await client.list_locations(auth="YOUR_TOKEN") for loc in locations['items']: print(f"Location: {loc['name']}") # List and execute scenes scenes = await client.list_scenes(auth="YOUR_TOKEN") if scenes['items']: scene_id = scenes['items'][0]['sceneId'] await client.execute_scene(auth="YOUR_TOKEN", scene_id=scene_id) # Manage rules rules = await client.list_rules(auth="YOUR_TOKEN") for rule in rules['items']: print(f"Rule: {rule['name']} - Enabled: {rule.get('enabled', True)}") # Check cache statistics (when caching is enabled) if hasattr(client, 'get_cache_stats'): stats = client.get_cache_stats() print(f"Cache hits: {stats['hits']}, misses: {stats['misses']}") if __name__ == "__main__": asyncio.run(main())

SmartThingsMCP supports three transport mechanisms for client-server communication:

HTTP Transport (Recommended for most use cases)

- Default port: 8000
- URL pattern:http://localhost:8000/mcp
- Best for: External integrations, LLM tools, web services
- Advantages:

- Simple HTTP/REST interface
- Easy to debug with standard tools
- Compatible with most firewalls
- Stateless connections

# Server python SmartThingsMCPServer.py -transport http -port 8000 # Client python SmartThingsMCPClient.py --transport http --port 8000

- Default port: 8000
- URL pattern:http://localhost:8000/sse
- Best for: Real-time updates, event streaming, server push
- Advantages:

- Bidirectional communication
- Event-driven architecture
- Lower latency for updates

# Server python SmartThingsMCPServer.py -transport sse -port 8000 # Client python SmartThingsMCPClient.py --transport sse --port 8000

- No network overhead
- Best for: Direct Python integration, embedded systems
- Advantages:

- No port/network configuration needed
- Direct process communication
- Lowest latency

# Server (runs in foreground) python SmartThingsMCPServer.py -transport stdio # Client python SmartThingsMCPClient.py --transport stdio

The SmartThingsMCPClient includes intelligent caching with full control:

client = SmartThingsMCPClient( host="localhost", port=8000, auth_token="YOUR_TOKEN", enable_cache=True, # Enable caching cache_ttl=300, # TTL in seconds (default: 5 min) max_cache_size=1000 # Max entries (default: 1000) ) # Get cache statistics stats = client.get_cache_stats() print(f"Hit rate: {stats['hit_rate']:.2%}") # Clear cache manually client.clear_cache()

Cacheable Operations(automatic caching):

- list_devices
- get_device
- list_locations
- get_location
- list_rooms
- get_room
- list_modes
- get_mode
- get_current_mode
- list_scenes
- get_scene
- list_rules
- get_rule

Cache-Invalidating Operations(automatic cache clearing):

- update_device
- delete_device
- execute_command
- create_location
- update_location
- delete_location
- create_room
- update_room
- delete_room
- set_mode
- create_scene
- update_scene
- delete_scene
- create_rule
- update_rule
- delete_rule
- execute_rule
- execute_scene

SmartThingsMCP uses Python's standard logging module:

import logging # Enable debug logging logging.basicConfig(level=logging.DEBUG) logger = logging.getLogger('smartthings_mcp') # Create client - will now output detailed logs client = SmartThingsMCPClient(...)

- DEBUG: Detailed diagnostic information
- INFO: General informational messages (default)
- WARNING: Warning messages
- ERROR: Error messages
- CRITICAL: Critical errors

Error:Client failed to connect: Session terminated

Error calling tool list_devices: Client failed to connect: Session terminated

- Server is not running: Start the server withpython SmartThingsMCPServer.py
- Wrong transport type: Ensure client and server use same transport (http, sse, or stdio)
- Wrong port: Verify port matches between client and server
- Wrong host: Check hostname/IP address is correct
- Network/firewall: Ensure port is open and accessible

# Check if server is running on expected port netstat -tuln | grep 8000 # Test HTTP connectivity curl http://localhost:8000/mcp # View server logs python SmartThingsMCPServer.py 2>&1 | head -20

Error:1 validation error for list_devicesArguments: auth: Field required

Error executing tool list_devices: 1 validation error for list_devicesArguments auth: Field required

- Provide auth token with--auth YOUR_TOKENflag
- Ensure token is valid: verify in SmartThings Developer Portal
- Check token has not expired
- Verify token has required scopes

python SmartThingsMCPClient.py --auth "YOUR_VALID_TOKEN" --action list_devices
Error calling tool list_devices: 401 Unauthorized

- Token is invalid or expired
- Token format is incorrect (must be OAuth 2.0 bearer token)
- Generate new token from SmartThings Developer Portal

Error calling tool create_rule: 403 Forbidden - Access Denied

- Token lacks required scopes for the operation
- SmartThings account doesn't have access to feature (e.g., Rules API requires Enterprise)
- Grant additional scopes in SmartThings Developer Portal

{ "error": "Device not found", "message": "No device found with ID: invalid-id" }

- Device ID doesn't exist
- Device has been deleted
- List devices first to get valid IDs:list_devicesaction

{ "error": "Component not found", "message": "Component 'main' not found on device" }

- Check valid components: Useget_device_componentsto list available components
- Check valid capabilities: Useget_device_capabilitieswith correct component_id
- Device doesn't support the command you're trying to execute

Error calling tool list_devices: 429 Too Many Requests

- SmartThings API rate limit exceeded
- Enable cachingto reduce API calls (enabled by default)
- Increase cache TTL to keep data longer
- Implement request throttling in your code

stats = client.get_cache_stats() print(f"Cache hits: {stats['hits']}") print(f"Cache misses: {stats['misses']}") print(f"Hit rate: {stats['hit_rate']:.2%}")

- Reduce cache TTL:cache_ttl=60(1 minute)
- Manually clear cache:client.clear_cache()
- Disable cache if data must be real-time:enable_cache=False

Problem: Cache causing high memory usage

- Reduce max cache size:max_cache_size=100
- Reduce cache TTL to expire entries sooner
- Periodically clear cache:client.clear_cache()

You can extend SmartThingsMCP with custom tools by modifying the server modules:

# In modules/server/devices.py, add: @server_instance.tool() def custom_device_operation(auth: str, device_id: str) -> Dict[str, Any]: """Your custom operation description""" # Your implementation here return make_request(auth, "GET", build_device_url(device_id))

SmartThingsMCP tools are designed to work with Language Models:

# Get formatted tool descriptions for LLM tools = await client.list_tools() tool_descriptions = [ { "name": tool["name"], "description": tool["description"], "params": tool["parameters"] } for tool in tools ]
No reviews yet — be the first

Sign in to leave a review

Use Google, GitHub, or an email account so ratings stay tied to real people.

Email sign in

No reviews posted yet.