Skip to main content
Glama

SmartThingsMCP Server and 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.

Overview

SmartThingsMCP provides:

  • 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

Components

Server

  • 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

Client

  • 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)

API Endpoints

SmartThingsMCP exposes the following API endpoints as MCP tools:

Device Management

  • 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

Location Management

  • 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)

Room Management

  • 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

Mode Management

  • 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

Scene Management

  • 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

Rule Management

  • 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

Features

Intelligent Caching

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

Client-Side Caching

The SmartThingsMCPClient provides:

  • Automatic caching of read-only operations (list_devices, list_locations, etc.)

  • TTL-based expiration (default: 5 minutes, configurable)

  • Smart cache invalidation on write operations (execute_command, update_device, etc.)

  • LRU eviction when cache is full

  • Cache statistics tracking (hits, misses, hit rate)

  • Green visual feedback: ✓ Cache hit: list_locations

See CACHING.md for detailed documentation.

Server-Side Caching

The SmartThingsMCPServer provides:

  • Automatic caching of all GET requests to SmartThings API

  • TTL-based expiration (default: 5 minutes)

  • Full cache invalidation on write operations (POST, PUT, DELETE)

  • LRU eviction when cache is full

  • Cache statistics tracking

  • Green visual feedback: ✓ Server cache hit: GET devices

See SERVER_CACHING.md for detailed documentation.

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

Performance Benefits:

  • 60-80% reduction in API calls

  • 5-10x faster response times for cached data

  • Lower rate limit usage

Rule Management

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

Enable/Disable Rules:

# 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)

The enabled parameter was added in December 2025 to support toggling rule state without deleting the rule.

Installation

Prerequisites

  • Python 3.8 or higher

  • pip or another Python package manager

Setup

  1. Install dependencies:

pip install -r requirements.txt

Required packages:

  • fastmcp>=2.0.0: FastMCP 2.0 framework for MCP server/client

  • requests>=2.28.0: HTTP library for SmartThings API calls

  1. Obtain a SmartThings API Token:

    • Visit SmartThings 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)

Authentication

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

Token Requirements

  • 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

Common Authentication Issues

401 Unauthorized:

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 --auth flag

403 Forbidden:

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

Scopes Required by Feature

Feature

Required Scopes

List/Get Devices

r:devices:*

Control Devices

w:devices:*

List/Get Locations

r:locations:*

Create/Update/Delete Locations

w:locations:*

List/Get Scenes

r:scenes:*

Execute Scenes

x:scenes:*

Create/Update/Delete Scenes

w:scenes:*

List/Get Rules

r:rules:*

Create/Update/Delete Rules

w:rules:*

List/Get/Set Modes

r:locations:*

Getting Started

Starting the Server

  1. Start the SmartThingsMCP server:

# 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

Using the Command-Line Client

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 }'

Client Options

--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)

Using Python Client Programmatically

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())

Troubleshooting

Transport Configuration

SmartThingsMCP supports three transport mechanisms for client-server communication:

  • 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

SSE Transport (Server-Sent Events)

  • 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

STDIO Transport (Direct integration)

  • 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

Client Configuration

Cache Configuration

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

Logging

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(...)

Log levels:

  • DEBUG: Detailed diagnostic information

  • INFO: General informational messages (default)

  • WARNING: Warning messages

  • ERROR: Error messages

  • CRITICAL: Critical errors

Common Errors and Solutions

Common Errors and Solutions

Connection Errors

Error:

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

Causes and solutions:

  • Server is not running: Start the server with python 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

Debugging:

# 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

Authentication Errors

Error:

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

Solutions:

  • Provide auth token with --auth YOUR_TOKEN flag

  • Ensure token is valid: verify in SmartThings Developer Portal

  • Check token has not expired

  • Verify token has required scopes

Example:

python SmartThingsMCPClient.py --auth "YOUR_VALID_TOKEN" --action list_devices

Error:

Error calling tool list_devices: 401 Unauthorized

Solutions:

  • Token is invalid or expired

  • Token format is incorrect (must be OAuth 2.0 bearer token)

  • Generate new token from SmartThings Developer Portal

Error:

Error calling tool create_rule: 403 Forbidden - Access Denied

Solutions:

  • 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

API Response Errors

Error:

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

Solutions:

  • Device ID doesn't exist

  • Device has been deleted

  • List devices first to get valid IDs: list_devices action

Error:

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

Solutions:

  • Check valid components: Use get_device_components to list available components

  • Check valid capabilities: Use get_device_capabilities with correct component_id

  • Device doesn't support the command you're trying to execute

Rate Limiting

Error:

Error calling tool list_devices: 429 Too Many Requests

Solutions:

  • SmartThings API rate limit exceeded

  • Enable caching to reduce API calls (enabled by default)

  • Increase cache TTL to keep data longer

  • Implement request throttling in your code

Check cache effectiveness:

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%}")

Cache Issues

Problem: Stale data in cache

Solutions:

  • 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

Solutions:

  • Reduce max cache size: max_cache_size=100

  • Reduce cache TTL to expire entries sooner

  • Periodically clear cache: client.clear_cache()

Advanced Usage

Custom Tool Implementation

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))

Integration with LLMs

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 ]

Error Handling

import asyncio async def safe_device_operation(): client = SmartThingsMCPClient( host="localhost", port=8000, auth_token="YOUR_TOKEN" ) try: result = await client.get_device( auth="YOUR_TOKEN", device_id="DEVICE_ID" ) return result except ValueError as e: print(f"Invalid input: {e}") except ConnectionError as e: print(f"Connection failed: {e}") except Exception as e: print(f"Unexpected error: {e}") asyncio.run(safe_device_operation())

Performance Optimization

  1. Enable caching (default: enabled):

    # Already enabled by default client = SmartThingsMCPClient(enable_cache=True)
  2. Adjust cache TTL for your use case:

    # More frequent updates needed client = SmartThingsMCPClient(cache_ttl=60) # 1 minute # Stable data, longer TTL client = SmartThingsMCPClient(cache_ttl=900) # 15 minutes
  3. Use appropriate transport:

    • HTTP: Best for most scenarios

    • STDIO: Best latency for local integration

    • SSE: Best for real-time updates

  4. Batch operations:

    # Get all data at once rather than in loops devices = await client.list_devices(auth=token) for device in devices['items']: # Use data from the single list_devices call # Don't call get_device for each one if not needed

API Response Format

All API responses follow a consistent structure:

Success response:

{ "items": [...], "pageProperties": { "currentPage": 1, "pageSize": 50, "totalCount": 100 } }

Single item response:

{ "id": "unique-id", "label": "Device Name", "deviceTypeId": "type-id" }

Error response:

{ "requestId": "request-id", "errors": [ { "code": "INVALID_PARAMETER", "message": "Detailed error message" } ] }

Example Scripts

Monitor Device Status

import asyncio from modules.client.main import SmartThingsMCPClient async def monitor_devices(token): client = SmartThingsMCPClient(auth_token=token) # Get all devices devices = await client.list_devices(auth=token) for device in devices['items']: try: status = await client.get_device_status( auth=token, device_id=device['deviceId'] ) print(f"{device['label']}: {status}") except Exception as e: print(f"Error getting status for {device['label']}: {e}") asyncio.run(monitor_devices("YOUR_TOKEN"))

Control Multiple Devices

import asyncio from modules.client.main import SmartThingsMCPClient async def control_devices(token, device_ids, command): client = SmartThingsMCPClient(auth_token=token) for device_id in device_ids: try: result = await client.execute_command( auth=token, device_id=device_id, component="main", capability="switch", command=command ) print(f"Device {device_id}: {result}") except Exception as e: print(f"Error controlling {device_id}: {e}") asyncio.run(control_devices("YOUR_TOKEN", ["device1", "device2"], "on"))

Scene Execution

import asyncio from modules.client.main import SmartThingsMCPClient async def execute_morning_routine(token): client = SmartThingsMCPClient(auth_token=token) # Get morning scene scenes = await client.list_scenes(auth=token) morning_scene = next( (s for s in scenes['items'] if 'morning' in s.get('sceneName', '').lower()), None ) if morning_scene: result = await client.execute_scene( auth=token, scene_id=morning_scene['sceneId'] ) print(f"Executed scene: {result}") asyncio.run(execute_morning_routine("YOUR_TOKEN"))

Environment Variables

You can optionally use environment variables for common settings:

export SMARTTHINGS_TOKEN="your-token-here" export MCP_SERVER_HOST="localhost" export MCP_SERVER_PORT="8000" export MCP_TRANSPORT="http"

API Reference

Complete API reference is available through the MCP tools system. List all available tools:

python SmartThingsMCPClient.py --action list_tools --pretty

This will display all available tools with their parameters and descriptions.

Contributing

When extending SmartThingsMCP:

  1. Follow the existing module structure

  2. Add tools to appropriate module (devices.py, locations.py, etc.)

  3. Include proper docstrings with parameter and return descriptions

  4. Test with the client

  5. Update README.md with new tool documentation

License

See LICENSE file for license information.

-
security - not tested
A
license - permissive license
-
quality - not tested

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/technohead/smartthings-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server