Skip to main content
Glama
ethanj2k

tuya-local-mcp

by ethanj2k

tuya-local-mcp

An MCP server that controls Tuya / Smart Life smart home devices over your local network. Once set up, no request touches Tuya's cloud — commands go straight to the device on your LAN, so they keep working with the internet down and aren't subject to cloud API rate limits.

Built on tinytuya.

The one catch, up front

"Local control" still requires one trip through Tuya's cloud. Each device has a 16-character local_key that's provisioned during pairing and is never broadcast on the network — you can't sniff it, derive it, or guess it. You fetch it once from the Tuya IoT Platform, and after that everything is local, forever.

There is no way around this short of reflashing the hardware with ESPHome or Tasmota. If you'd rather avoid the developer-console setup entirely, use a cloud-based Tuya MCP server instead; this project won't save you that step.

Related MCP server: mcp-server-tuya

Install

Requires Python 3.10+.

git clone https://github.com/ethanj2k/tuya-local-mcp
cd tuya-local-mcp
python -m venv .venv && . .venv/bin/activate    # Windows: .venv\Scripts\activate
pip install -e .

Setup

1. Check your devices are visible

Before touching any credentials, confirm the devices are actually reachable. This listens for the UDP beacons Tuya devices broadcast every few seconds and sends nothing:

python scripts/passive_scan.py 15
3 device(s):

  192.168.1.50    udp/6667  beacons=3   proto=3.3   id=bf0000000000000000aaaa
  192.168.1.51    udp/6667  beacons=2   proto=3.4   id=bf0000000000000000bbbb
  192.168.1.52    udp/6667  beacons=3   proto=3.3   id=bf0000000000000000cccc

No output? See Troubleshooting discovery — on Windows the usual cause is the firewall, not the devices.

2. Get your local keys

  1. Create an account at iot.tuya.com.

  2. Cloud → Development → Create Cloud Project. Pick the data centre matching your region and "Smart Home" as the industry.

  3. In the project, Devices → Link App Account and scan the QR code with the Smart Life / Tuya Smart app. This imports the devices you already own.

  4. Grab one device's Virtual ID from the app: tap the device → pencil icon → Device Information. tinytuya needs one id to bootstrap the list.

  5. Fetch the keys. Either the stock interactive wizard:

python -m tinytuya wizard

…or the non-interactive fetcher bundled here, which takes the same inputs from a .env file. Useful in containers, CI, or anywhere a prompt is awkward:

cp .env.example .env    # fill in the four values
python scripts/fetch_keys.py
querying Tuya Cloud (region us)...
cloud returned 6 device(s), 6 with a local key
listening 20s for LAN addresses (transmitting nothing)...
matched 6 device(s) to a LAN address

wrote devices.json  (contains local keys - do not commit)

  Living Room Lamp             192.168.1.50    v3.3  key=yes
  Desk Plug                    192.168.1.51    v3.4  key=yes

Either way you end up with devices.json. It contains your local keys — never commit it. This repo's .gitignore already excludes it, along with .env.

3. Point the server at the file

The server looks for snapshot.json then devices.json in the current directory, your home directory, and ~/.tinytuya/. Override with TUYA_DEVICES_FILE.

4. Wire it into your MCP client

{
  "mcpServers": {
    "tuya-local": {
      "command": "/absolute/path/to/.venv/bin/python",
      "args": ["-m", "tuya_local_mcp"],
      "env": {
        "TUYA_DEVICES_FILE": "/absolute/path/to/devices.json"
      }
    }
  }
}

On Windows the command is C:\\path\\to\\.venv\\Scripts\\python.exe.

Tools

Tool

Writes?

Description

list_devices

no

Every device in the registry — names, ids, IPs, protocol versions. Local keys are never returned.

discover_devices

no

Passively listen for devices broadcasting on the LAN. Flags any not in your registry.

get_status

no

Read one device's datapoints, plus a decoded reading of the common ones.

get_all_status

no

Read every device; per-device errors don't fail the whole call.

set_power

yes

Turn a device on or off.

set_brightness

yes

Set a light's brightness, 0–100%.

set_color

yes

Set a light's colour from hex (#FF8800 or f80).

set_color_temp

yes

White mode at a colour temperature, 0 (warm) to 100 (cool).

set_datapoint

yes

Write a raw datapoint — the escape hatch for fans, curtains, valves, heaters.

Devices are addressed by friendly name, device id, or IP. Name matching is case-insensitive and accepts unique substrings, so "desk" finds "Desk Plug". Ambiguous matches raise an error listing the candidates rather than picking one.

Read-only mode

Set TUYA_READ_ONLY=1 and every write tool refuses. Discovery and status reads still work. Useful when you want an assistant that can answer "is the garage light on?" without being able to act, or while you're still building trust in a setup.

Configuration

Variable

Default

Meaning

TUYA_DEVICES_FILE

auto-detected

Path to devices.json or snapshot.json.

TUYA_READ_ONLY

0

1 blocks all state changes.

TUYA_CONNECT_TIMEOUT

5

Per-device socket timeout, seconds.

TUYA_CACHE_TTL

10

Seconds to cache status reads. 0 disables.

TUYA_DISCOVERY_TIMEOUT

12

Default listen window for discover_devices.

Troubleshooting discovery

If passive_scan.py hears nothing, work down this list before concluding the devices are offline.

Windows: allow the base interpreter, not the venv one. This is the single easiest thing to lose an hour to, and the obvious fix is the wrong one.

Windows Firewall allows inbound traffic per program path. A venv's Scripts\python.exe on Windows is only a shim — the process that actually binds the socket is the base interpreter it was created from. So a rule naming .venv\Scripts\python.exe matches nothing, and your scan stays empty with no prompt and no error.

Confirm the real image path of whatever interpreter you're running:

.\.venv\Scripts\python.exe -c "import ctypes,sys; b=ctypes.create_unicode_buffer(1024); ctypes.windll.kernel32.GetModuleFileNameW(None,b,1024); print('reported:',sys.executable); print('actual  :',b.value)"
reported: C:\...\project\.venv\Scripts\python.exe
actual  : C:\Users\you\AppData\Local\Programs\Python\Python313\python.exe

Write the rule against the actual path (elevated PowerShell):

New-NetFirewallRule -DisplayName "Tuya LAN discovery" -Direction Inbound `
  -Program "C:\Users\you\AppData\Local\Programs\Python\Python313\python.exe" `
  -Protocol UDP -LocalPort 6666,6667,7000 -Action Allow

Because the rule lands on the base interpreter, it applies to every venv built from that install — convenient, but worth knowing you're opening those ports for all of them.

To see which interpreters are already allowed:

Get-NetFirewallApplicationFilter | Where-Object { $_.Program -like '*python*' } |
  ForEach-Object { $_.Program }

Note this only affects discovery. Device control is outbound TCP on port 6668 and works fine without any inbound rule — so a blocked scan does not mean a broken install. If your registry already has current IPs, everything else works.

Devices on another network segment. Beacons are broadcast and do not cross subnets or VLANs. IoT devices parked on a guest network won't be visible from your main one.

Another listener holds the ports. Home Assistant, a second copy of this script, or tinytuya's own scanner will contend for UDP 6666/6667. passive_scan raises if it can't bind anything.

Beacons are periodic. A 5-second window can genuinely miss a device. Try 30 seconds before worrying.

Notes and known limits

Protocol 3.4 / 3.5 devices use a session-key handshake rather than the local key directly. tinytuya supports them, but they're less battle-tested than 3.3 — if exactly one device misbehaves, check its version first.

Local keys rotate whenever a device is removed and re-paired in the app. Symptom is error 914; fix is re-running the wizard.

One connection at a time. Most Tuya devices accept a single TCP connection, so this server opens and closes a socket per call rather than holding one open. If a call times out, check nothing else (Home Assistant, another script) is polling that device continuously.

Datapoint numbering is per-product. The bulb helpers cover the two common layouts (datapoints 1–5 on older bulbs, 20–24 on newer). For anything else, get_status shows the raw datapoints and set_datapoint writes them.

Discovery is best-effort. Beacons are periodic, so a short listen window may miss devices that are simply between broadcasts. Increase the timeout rather than concluding a device is offline.

Development

pip install -e ".[dev]"
pytest

The test suite runs entirely offline — no device, no network, no credentials. It includes a guard test asserting that passive_scan never calls send, sendto, sendall, or connect on a socket.

License

MIT

Available Tools

9 tools
discover_devicesA

Passively listen for Tuya devices broadcasting on the local network.

This transmits nothing - it only receives the beacons devices emit every few seconds. Useful for finding a device whose IP has changed, or for spotting devices that are on the network but missing from the registry.

ParametersJSON Schema
NameRequiredDescriptionDefault
timeoutNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full behavioral burden. It explicitly states the tool 'transmits nothing' and only receives beacons, which is important safety and side-effect information. However, it does not explain the behavior or purpose of the timeout parameter, which is the tool's only configuration.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and well-structured: the core action is front-loaded in the first sentence, the passive behavior is clarified in the second, and the practical use cases are given in the third. Every sentence adds distinct value with no redundant wording.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple and has an output schema, so return values are already covered. However, the sole parameter 'timeout' is entirely undocumented in both the schema and the description, leaving a meaningful gap in what the agent needs to know to invoke the tool correctly. The use cases help, but this missing parameter semantics makes it incomplete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema provides only the name 'timeout' with no description, and schema description coverage is 0%. The description never mentions the timeout parameter at all, so an agent cannot know what it controls, what its units are, or what happens if it is null. This is a critical gap because it is the only parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('listen'), a precise resource ('Tuya devices broadcasting on the local network'), and a distinctly passive mechanism ('it only receives beacons'). This differentiates it clearly from sibling tools like list_devices, which imply a registry query rather than active network discovery.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives concrete use cases: finding a device whose IP changed, or discovering devices missing from the registry. It does not explicitly name an alternative or say when not to use it, but the context strongly implies this is the discovery tool as opposed to the registry-based list_devices.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_all_statusA

Read the state of every device in the registry.

Devices that fail are reported individually rather than failing the call, so one offline device does not hide the rest.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden of behavioral disclosure. It reveals a key behavior: failures are reported individually rather than failing the call, which is valuable. However, it does not mention response format (though output schema exists), potential latency, or any side effects, leaving the safety profile somewhat implicit.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences with zero wasted words. The primary purpose is front-loaded, and the second sentence adds a critical behavioral note. Efficient and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given an output schema exists and there are no parameters, the description covers the core purpose and a key failure mode. It does not explicitly differentiate from list_devices or get_status, but the name and description make the distinction clear enough. The only minor gap is explicit usage routing, which is already scored under usage_guidelines.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters, and the input schema is empty. The description correctly focuses on the operation itself. With no params, the baseline is 4, and the description adds no unnecessary parameter information.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Read'), a clear resource ('the state of every device in the registry'), and a scope (all devices). This distinguishes it from siblings like get_status (single device) and list_devices (likely just identifiers) without needing to open schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies its use case: retrieve the state of all devices at once, contrasted with single-device tools. However, it does not explicitly name alternatives or state when NOT to use it, leaving some inference to the agent.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_statusA

Read the current state of a device.

device may be a friendly name, a device id, or an IP address. Returns the raw Tuya datapoints plus a best-effort interpretation of the common ones.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full disclosure burden. It discloses the read-only nature ('Read'), the return format (raw Tuya datapoints plus best-effort interpretation), and the three accepted device identifier forms. It does not cover error behavior, what 'best-effort' means, or network/auth implications, but this is adequate for a simple read tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two tight sentences with the core purpose front-loaded. The code-formatted note packs parameter formats and return behavior with zero filler. Every clause earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

An output schema exists, so return values are already covered; the description adds the raw-vs-interpreted distinction on top. For a single-parameter read tool this is nearly complete — the only gap is explicit routing between get_status and get_all_status.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% — the `device` parameter has no schema description. The description fully compensates by specifying that device may be a friendly name, a device id, or an IP address, adding meaning well beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb+resource pair — 'Read the current state of a device' — which clearly differentiates it from the set_* write siblings. The phrase 'a device' implies single-device scope, distinguishing it from get_all_status, though it doesn't name that sibling explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied: read a specific device's state. However, there is no explicit guidance on when to choose this over get_all_status, and no alternatives or exclusions are named. An agent must infer the single-vs-all distinction from the word 'a device'.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_devicesA

List every Tuya device in the local registry.

Returns names, device ids, IPs and protocol versions. Local keys are never returned. Use the name field when calling the other tools.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations are absent, so the description carries the full burden for behavioral disclosure. It explicitly states that local keys are never returned, which is a security-relevant behavior important for the agent to know. It also mentions the return fields (names, device ids, IPs, protocol versions), but does not mention potential side effects (none likely) or performance implications. Given it is a read-only list operation, this is adequate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is brief (three sentences) and front-loaded with the main purpose. It immediately states what the tool does, then describes the output, and ends with a practical tip for using the results. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool has no parameters and an output schema, the description covers all essential aspects: what it lists, what fields are returned, and a crucial privacy note (local keys never returned). It is complete for an agent to invoke correctly without further information.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are zero parameters, and the schema has no properties, so the description has all the responsibility. It does not need to explain parameters, but it does describe the output content, which is a substitute. Since there are no parameters, the description is sufficient, and the baseline of 4 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states what the tool does: 'List every Tuya device in the local registry.' It specifies the resource (devices) and the scope (local registry), and it is distinct from siblings like discover_devices, which likely handles network discovery rather than listing an existing registry.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides clear context for when to use the tool: listing devices from the local registry, and it notes that the returned 'name' field is used when calling other tools, which implicitly suggests this is a prerequisite for other operations. It doesn't explicitly contrast with discover_devices but the mention of 'local registry' vs 'discover' implies the distinction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_brightnessA

Set a light's brightness as a percentage (0-100).

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceYes
percentYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.5/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It only states the basic effect, but doesn't mention side effects, failure modes, prerequisites (e.g., device must be a dimmable light), reversibility, or return behavior. This is a significant gap for a mutation tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, front-loaded sentence with no filler. It states the action, target, and value range efficiently, earning its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The output schema exists, so return values are presumably covered. However, the description lacks guidance on edge cases (device not found, non-dimmable device), prerequisites, or when to prefer this over set_datapoint. It is minimally adequate for a simple tool but leaves room for agent error.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description compensates partially: it clarifies that 'percent' is a percentage 0-100 and implies 'device' identifies a light. However, it doesn't explain how device is addressed (e.g., ID vs name) or whether percent accepts any integer outside 0-100.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Set'), resource ('a light's brightness'), and value range (0-100), making it instantly distinguishable from sibling tools like set_power, set_color, and set_color_temp. An agent can understand exactly what this tool does without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies use when adjusting brightness ('Set a light's brightness'), but provides no explicit when/when-not guidance or comparison to alternatives. It doesn't mention that this applies only to dimmable lights or that other set_* tools exist for different properties.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_colorA

Set a light's colour from a hex string such as '#FF8800' or 'f80'.

ParametersJSON Schema
NameRequiredDescriptionDefault
colorYes
deviceYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.5/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries the full burden of behavioral disclosure, but it only states the basic mutation 'Set'. It does not mention side effects such as changing color mode, turning the light on, invalid hex handling, device reachability, or reversibility.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, front-loaded sentence with no wasted words. The action is stated first, and the format examples are compact and immediately useful.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple two-parameter setter with an output schema, the core call is understandable, but the description is not fully self-contained. It lacks guidance on device identifier provenance and important behavioral caveats, though the low complexity and clear color format keep it minimally viable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema only provides parameter names with no descriptions, so the description adds real value by specifying that color is a hex string and giving examples like '#FF8800' and 'f80'. It also clarifies that device refers to a light, though it doesn't explain where the device identifier comes from.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly names the verb 'Set', the resource 'a light's colour', and the input format 'hex string'. It is immediately distinguishable from siblings like set_brightness, set_power, and set_color_temp because it is specific about color and hex encoding.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives no explicit guidance on when to use this tool instead of set_color_temp, set_brightness, or set_power, and no prerequisites are mentioned. Usage is only implied by the action of setting a color, so an agent gets no direction about alternatives or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_color_tempA

Set a light to white mode at a colour temperature percentage (0 warm, 100 cool).

Optionally set brightness in the same call.

ParametersJSON Schema
NameRequiredDescriptionDefault
deviceYes
percentYes
brightnessNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the burden. It discloses the key behavior: setting white mode and the temperature scale (0 warm, 100 cool). However, it doesn't mention what happens to the light's current color, whether the light must be on, or any side effects. The description is honest but minimal.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core action and scale. The optional brightness note is a useful addition without bloat. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple 3-parameter tool with an output schema, the description covers the essential semantics. It lacks explicit notes on edge cases (e.g., invalid percent values, behavior when brightness is null) but these are minor given the schema's defaults and the tool's simplicity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains the 'percent' parameter's meaning (0 warm, 100 cool) and that 'brightness' is optional. It doesn't explain 'device' but that's self-evident from the name and sibling context. The description adds meaningful semantics beyond the raw schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: setting a light to white mode at a color temperature percentage, with a specific range (0 warm, 100 cool). It also mentions an optional brightness parameter. This distinguishes it from siblings like set_color (which likely sets RGB/color) and set_brightness (which only sets brightness).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use this tool: when you want to set a light to white mode with a specific color temperature. It doesn't explicitly state when not to use it or name alternatives, but the sibling list and the clear scope (white mode + temperature) provide enough context. The optional brightness note also clarifies a combined use case.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_datapointA

Write a raw Tuya datapoint.

The escape hatch for products whose datapoints the helper tools do not cover - fans, curtains, heaters, valves. Call get_status first to see which datapoints a device exposes and what types they hold.

ParametersJSON Schema
NameRequiredDescriptionDefault
dpYes
valueYes
deviceYes

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description must disclose all behavioral traits, but it only states the mutating action ('Write') and gives a prerequisite. It does not mention potential risks, error handling, whether setting an invalid type/value is destructive, or any side effects. The phrase 'escape hatch' hints at advanced use but is not an explicit warning.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is brief and to the point. The core purpose is in the first sentence, and the usage guidance is concise. No extraneous words or redundant details.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

It provides the critical prerequisite (get_status) and contextualizes the tool as a fallback, which is helpful. However, it omits details about error handling, what the output schema returns (though an output schema exists), and any cautionary notes about irreversible changes. For a raw write tool, this feels incomplete but not severely lacking.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has zero description coverage, so the description must compensate. It mentions 'datapoints' and 'types' and advises calling get_status, which implies dp is the datapoint ID and value must match the expected type, but it does not explain the format or acceptable values for dp or value. This is insufficient for an unannotated schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action: 'Write a raw Tuya datapoint.' It also defines the scope by naming the product categories it serves (fans, curtains, heaters, valves) and explicitly positions it as an 'escape hatch' relative to helper tools, which differentiates it from the sibling setter tools like set_power and set_brightness.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly tells when to use this tool ('escape hatch for products whose datapoints the helper tools do not cover') and provides a prerequisite step ('Call get_status first to see which datapoints a device exposes and what types they hold'). This gives clear context and implies the alternative is to use the specialized setters when they apply.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_powerA

Turn a device on or off.

switch_dp overrides the datapoint carrying the relay/switch. Leave it unset to let tinytuya pick, which is correct for the large majority of plugs, switches and bulbs.

ParametersJSON Schema
NameRequiredDescriptionDefault
onYes
deviceYes
switch_dpNo

Output Schema

ParametersJSON Schema
NameRequiredDescription

No output parameters

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden. It discloses the core effect (power on/off) and an implementation behavior (switch_dp override/default behavior), which goes beyond the bare schema. However, it does not mention permissions, reversibility, edge cases, or failure behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loads the main action in the first sentence. The second paragraph adds necessary parameter nuance without waste. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple three-parameter tool with an output schema, the description covers the core purpose and the one non-obvious parameter. It could briefly mention that 'device' refers to a device identifier from list_devices, but the tool name and sibling context make that inferable.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It explains switch_dp's override function and the recommended 'unset' default for most devices, but does not clarify the 'device' parameter beyond its name and type. 'on' is self-explanatory but still undocumented in the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states an explicit action ('Turn a device on or off') on a clear resource (a device). This is distinct from sibling tools like set_brightness or set_color, which target different aspects of device control.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies when to use the tool by defining its function, but it does not explicitly contrast with alternatives such as set_datapoint, nor does it state when not to use it. The switch_dp guidance is parameter-level, not tool-selection-level.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 9 tool updatesv0.1.0
    • First observeddiscover_devices
    • First observedget_all_status
    • First observedget_status
    • First observedlist_devices
    • First observedset_brightness
    • First observedset_color
    • First observedset_color_temp
    • First observedset_datapoint
    • First observedset_power

TDQS

A4/5.0

Scored across 9 tools

Disambiguation5/5

Each tool has a clearly distinct purpose: enumeration of registered devices (list_devices), passive network discovery (discover_devices), reading state for one or all devices (get_status/get_all_status), and distinct control actions (power, brightness, color, color temp, raw datapoint). The get_* and set_* families are parallel but not overlapping.

Naming Consistency5/5

All tool names follow a consistent lowercase snake_case verb_noun pattern: list_devices, discover_devices, get_status, get_all_status, set_power, set_brightness, set_color, set_color_temp, set_datapoint. No mixed conventions or vague verbs.

Tool Count5/5

Nine tools is well-scoped for a Tuya local control server: two device discovery/listing, two status reads, five control operations including a raw escape hatch. Each tool earns its place without redundancy or bloat.

Completeness4/5

The surface covers the core lifecycle of interacting with local Tuya devices: discovery, listing, status reading, and common control actions. The raw set_datapoint tool fills gaps for unsupported product types. A minor gap is the lack of a tool to add discovered devices to the registry or update device metadata.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Enables discovery and control of Philips Hue lighting devices via a local bridge using the CLIP v2 API, without any cloud dependency.
    10
    MIT
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables control of Tuvio/Tuya robot vacuum cleaners via a local hub, supporting commands such as start, pause, home, set mode, suction, water level, and more.
    -