SmartThingsMCP
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
Jump to
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 ]
Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.




