deco-mcp
Provides local control of TP-Link Deco mesh routers without cloud or app, enabling mesh overview (nodes, backhaul type, signal strength, firmware, connected clients), reading router settings such as DHCP reservations, port forwards, DNS servers, and WPS, and performing graded write operations like LED night mode with read-back verification.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@deco-mcpGive me an overview of my mesh and flag any weak wireless backhaul."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
deco-local
Local control of TP-Link Deco mesh routers: no cloud, no app. A Python library, a small CLI, and an MCP server so Claude (or any MCP client) can look at your mesh and, carefully, change it.
(an illustration)
You: Which of my Deco nodes is on wireless backhaul, and how good is its link?
Claude: (mesh_overview) One node is: "Attic", an M5 hanging off "Hallway" over 5 GHz and
2.4 GHz, both at signal 2 of 3. The other four are wired. Attic has 3 clients...What it does that others don't
Two interfaces, one answer. The Deco has a control port (the TMP protocol the app uses, SSH on port 20001) and a local web interface on port 80. The control port can do far more, but it locks up: for 60-90 s after every write, and sometimes much longer. When it does, the reads the web interface also offers (nodes, clients, WAN, CPU/memory) come from there instead, reshaped into the same names and fields. Every read says which interface answered.
Writes are graded by evidence. Each write is
verified(proven live with a before/after read-back),upstream(seen in real app captures by pydeco-tmp, not re-tested),noop(proven to ACK and do nothing, like HomeShield's toggle) orinferred(an opcode-numbering guess). Anything not verified is refused unless you opt in, and every write returns the router's read-back, not just its ACK.It knows the router's moods. After a write the router drops the control port for ~60-90 s. Connecting during that window keeps it shut longer, so a shared lockout makes every caller on the machine (MCP server, scripts) wait instead of hammering it.
Safe to hand to an AI. Secrets are redacted by default, refusals say why (so the model asks you instead of guessing), and
DECO_MCP_READONLY=1gives a server with no write tools at all, for anything unattended.
Related MCP server: ax11000-mcp
Tested on
Deco X55 (hardware 1.0, firmware 1.11.1) as the main router, with M5 satellites.
The control port is on the main Deco only; it reports the whole mesh. Other Deco models very likely speak the same protocol (the app is the same), but they haven't been tried. If you try one, please open an issue with what worked.
Credentials
The control port logs in with your TP-Link account email and password, the ones you use in the Deco
app. The Deco checks them itself, locally; nothing is sent to TP-Link's cloud. The web interface uses
the same password on app-managed Decos (DECO_WEB_PASSWORD if yours differs).
Variable | |
| the main Deco's LAN address (default |
| TP-Link account email |
| TP-Link account password |
| optional, if the web interface password differs |
|
|
| optional; lockout state and the web session (default |
Use it with Claude
Needs uv (uvx runs it without installing anything permanently).
Claude Code:
claude mcp add deco -e DECO_HOST=192.168.68.1 -e DECO_EMAIL=you@example.com -e DECO_PASSWORD='...' \
-- uvx --from git+https://github.com/ukbodypilot/deco-local deco-mcpAdd -e DECO_MCP_READONLY=1 for a read-only server.
Claude Desktop: Settings, Developer, Edit Config, and add:
{
"mcpServers": {
"deco": {
"command": "uvx",
"args": ["--from", "git+https://github.com/ukbodypilot/deco-local", "deco-mcp"],
"env": {
"DECO_HOST": "192.168.68.1",
"DECO_EMAIL": "you@example.com",
"DECO_PASSWORD": "...",
"DECO_MCP_READONLY": "1"
}
}
}
}Leave out DECO_MCP_READONLY if you want Claude to be able to change settings. It will still refuse
unverified writes unless you say so.
Things to ask:
"Give me an overview of my mesh." / "Which node is my laptop on, and how's its signal?"
"Is any node on wireless backhaul? How strong is it?"
"What firmware are my Decos on?" / "Show my DHCP reservations and port forwards."
"Which clients are on 2.4 GHz?" / "What DNS servers is the router using?"
"Turn the LED night mode on." (a verified write: Claude reads the setting, changes one field, writes it, and shows you the read-back)
Tools
Tool | |
| nodes (online, backhaul, signal, upstream, firmware, client count) and online clients (node, band, signal) |
| one named read, secrets redacted; falls back to the web interface where it can |
| every read name, and which the web fallback covers |
| whether the router is still applying a write (no router contact) |
| a read with secrets included (not in read-only mode) |
| every read in one paced pass, over a minute (not in read-only mode) |
| every write with its tier and note (not in read-only mode) |
| a write, with the read-back (not in read-only mode) |
Library
from deco_local import DecoClient, WRITE
with DecoClient("192.168.68.1", "you@example.com", "password") as deco:
nodes = deco.get("device_list")["device_list"]
led = deco.get("led_schedule")
deco.set("led_set", dict(led, enable_night_mode=True), confirm=True) # verified write
print(deco.get("led_schedule")["enable_night_mode"]) # read it back
# the control port is now locked ~60-90 s; deco_local.busy.wait() blocks until it is back
from deco_local import web
reads = web.snapshot("192.168.68.1", "password", ["device_list", "client_list"]) # web interfaceDecoClient.set needs confirm=True, and allow_unverified=True for anything but a verified write.
Reads come back in the router's own shapes; deco_local/tmp.py lists every read and write.
CLI
deco reads # every read name
deco writes # every write and its tier
deco read device_list wps # over the control port (JSON)
deco read --web client_list # over the web interface
deco status # post-write lockout (no router contact)The CLI only reads. Writes go through the library or the MCP server.
Writes: what's known
Only led_set is verified so far. 12 more are upstream (seen in app captures, including UPnP,
DoH, DHCP reservations, DDNS, IPv6, WPS, 802.11r, DNS servers), one is a proven no-op, and the rest are
guesses from the opcode numbering. Verifying one is simple and the most useful contribution: read the
setting, write a harmless change, read it back, write the original back, and open an issue or PR
moving it to verified, with your model and firmware. Avoid WAN-affecting ones (ipv6_set,
internet_backup_set, mac_clone_set, operation_mode_set) unless you can get to the router
another way if it goes wrong.
The lockout
Measured on the X55: a write ACKs and reads back within ~3 s; then the control port closes ~5-14 s later and stays closed until ~64-95 s after the write. Probing every 0.5 s kept it shut longer, so the watcher probes every 5 s. The control port has also been seen to stay closed for 45+ min after a node reboot from the app, while the web interface kept working; that is what the fallback is for. The lock is a small state file, so every process on the machine respects it. A short-lived script's watcher dies with it; the lock then simply expires after 150 s.
No warranty
This talks to your router with undocumented protocols. Reads are harmless; writes change real settings, and unverified ones may do something unexpected. MIT licensed, as is.
Credits
Built on two projects' protocol work. No code from either is used here; the clients are reimplementations from their descriptions:
mthsg/pydeco-tmp (MIT): the Deco TMP protocol (SSH transport, framing, login, opcode tables) and the app-capture list behind the
upstreamtier.tplinkrouterc6u (GPL-3.0): the encrypted login of TP-Link's local web interface. Compared line by line: no code in common, only the protocol.
License
MIT
Available Tools
8 toolsget_router_dataB
Read one named value from the Deco (see list_reads). Secrets (Wi-Fi passwords, VPN private keys) are redacted. Returns {source, result} and, when the web interface answered, why.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose two important behaviors: sensitive values are redacted, and the return includes a source/result pair plus an explanation when the web interface responded. It omits error behavior for unknown names, permission requirements, and confirmation that the operation is read-only beyond the verb 'Read.'
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences, front-loaded with the core action and with zero filler. The final clause about the web interface answering is slightly cryptic but still earns its place by describing return behavior.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter read tool with no output schema and no annotations, the description covers the essentials: what it reads, what is redacted, and roughly what is returned. Missing details on failure modes and the meaning of 'source' keep it from being fully complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0%, so the schema only declares a bare string 'name.' The description partially compensates by clarifying that it is a single named value and by pointing to list_reads for valid names, but it does not describe the expected naming format or case sensitivity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Read one named value from the Deco,' which is clear and actionable. It implicitly distinguishes itself from get_router_data_unredacted via the redaction note and from list_reads via the pointer, though it never names the unredacted sibling explicitly.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides a prerequisite by directing the agent to list_reads to discover valid names, which is useful usage context. However, it does not explicitly state when to choose this tool over get_router_data_unredacted or router_snapshot, leaving selection to inference.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_router_data_unredactedA
Like get_router_data but includes secrets (e.g. Wi-Fi passwords, a WireGuard private key). Only use this when the user specifically needs the secret, and don't write it anywhere without asking.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does disclose the key behavioral trait: output contains live credentials and must not be persisted without asking. It does not state read-only semantics, permission requirements, or what the response looks like, which leaves a modest gap for a credential-returning tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the differentiator against the sibling, then the safety constraint. Every clause earns its place with no repetition of structured fields.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a one-parameter read tool with no output schema or annotations, the description covers purpose, selection criteria, and handling caution adequately. The remaining gap is the meaning of 'name' and any hint about returned structure, though the get_router_data sibling likely fills that in.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 0% and the single 'name' parameter is undocumented in both schema and description. The description never clarifies whether 'name' is a router label, a network identifier, or something else, and adds no format or constraint hints to compensate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific action (retrieve router data) and a precise scope modifier (unredacted, including Wi-Fi passwords and a WireGuard private key). It explicitly anchors against the sibling get_router_data, so an agent can tell the two apart without opening either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives an explicit gate: 'Only use this when the user specifically needs the secret.' That is a when-to-use rule plus an implicit when-not (use the redacted sibling otherwise), and it names the alternative surface (get_router_data) in the first clause.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_readsA
Every read this router exposes (client list, Wi-Fi config, QoS, port forwarding, DHCP, VPN config, firmware, ...), and which of them the web-interface fallback can also provide. Use get_router_data to read one.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations exist, so the description carries the full behavioral burden. It does disclose a non-obvious trait: the output also tells you which reads the web-interface fallback can serve, which is genuine value beyond the schema. However, it says nothing about whether the list is static or device-dependent, its shape (flat names vs. objects), or whether it is safe/cheap to call repeatedly.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with the core claim and followed by the actionable routing hint. The parenthetical category list is long but earns its place as a preview of output in the absence of an output schema, though the trailing '...' makes it slightly open-ended.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no annotations, the description must convey enough about the response. It conveys the subject matter and the fallback annotation but not the structure of each entry (identifiers, flags, nesting), which an agent needs to consume the result without guessing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline is 4. The description correctly implies a parameterless discovery call and requires no argument explanation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names the resource (every read the router exposes) and previews the categories returned (client list, Wi-Fi config, QoS, port forwarding, DHCP, VPN, firmware), so an agent knows it is a catalog of read operations rather than a data fetch. It partially differentiates from get_router_data ('Use get_router_data to read one'), but never contrasts itself with the sibling list_writes.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It gives an explicit routing rule: call this to discover reads, call get_router_data to actually read one. That removes the main ambiguity. It stops short of stating when-not to use it (e.g., if you already know the read name) or how it relates to the fallback path it mentions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_writesA
Every write this server can attempt: verified (proven live with a read-back), upstream (seen in real app captures, not re-tested), noop (proven to do nothing) or inferred (opcode-numbering guess), with a note.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description still discloses the reliability model: verified means a live read-back, upstream means captured but not retested, noop means proven inert, and inferred means a guess. It also says each entry carries a note, though it does not state side effects, permissions, or rate limits.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single front-loaded sentence introduces the resource and then defines the four statuses; every clause is needed to interpret the output. No filler or redundant restatement of the name.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a no-parameter list tool with an output schema, the description supplies enough context to understand what the list contains and what the status labels mean. It could add an explicit read-only/side-effect statement, but the output schema can carry return-value detail.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
There are zero input parameters, so parameter semantics are not a concern; baseline 4 applies. The description adds no parameter details, which is appropriate for a no-argument listing tool.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The opening clause states it enumerates every write the server can attempt, and the parentheticals define the verification statuses attached to each write. It implicitly distinguishes itself from list_reads by scoping to writes, though it does not name that sibling.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is only implied: the all-writes scope suggests calling it to inventory available writes, and the status labels suggest using it to assess reliability. It never states when to choose this over list_reads or a specific write tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
lockout_statusA
Whether the router is still applying a write (control port locked), and how the last lockout went. No router contact.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the burden and usefully discloses that it makes no router contact and explains the lockout concept. Still, it does not clarify freshness, caching, read-only implications, or the exact return shape, which leaves meaningful behavioral gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two tight sentences with no filler. It front-loads the core status question and adds only the important 'No router contact' operational detail.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter status tool, the description gives enough context to understand what is returned: lockout state and last lockout outcome. Without an output schema, the exact response format is not specified, but the low complexity keeps this from being a major gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so parameter semantics are not applicable and the baseline is 4. The description does not need to explain any input values.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific status query: whether the router is still applying a write via a locked control port, plus the outcome of the last lockout. It is clear what the tool reports, but it does not explicitly distinguish itself from siblings such as list_writes or router_snapshot.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Usage is implied by the name and description: check lockout status when investigating write application state. However, there is no explicit guidance on when to use this versus list_writes or router_snapshot, and no stated prerequisites or exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
mesh_overviewA
The mesh at a glance: each node (name, model, online, wired or wireless backhaul with signal 0-3, upstream node, IP, firmware, client count) and each online client (name, IP, node, band, signal). Two reads, with the web-interface fallback.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the behavioral burden and does add useful context by disclosing that it performs 'two reads, with the web-interface fallback.' It does not explicitly state read-only safety, permissions, or fallback conditions, but the operational behavior is more transparent than a bare schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single dense sentence that front-loads the core purpose and enumerates returned fields efficiently. It is appropriately sized, though the long parenthetical listing makes it slightly harder to scan than a more structured breakdown.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema and no annotations, the description fully enumerates the node and client fields an agent would receive. It gives enough return-value detail to understand the response shape without unnecessary repetition.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so the baseline score is 4. The description correctly does not invent parameter details, and no input parameters require additional semantic explanation.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the resource and contents: a mesh overview with detailed per-node and per-client fields. It is specific about what data is returned, but it does not explicitly differentiate itself from sibling tools such as get_router_data or router_snapshot.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The phrase 'at a glance' implies a summary use case, but the description never states when to prefer this tool over alternatives like get_router_data or router_snapshot. Usage is only implied, not explicitly guided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
router_snapshotA
Read every known value in one pass (~70 reads, paced 1 s apart, so over a minute). Heavy on the router; use get_router_data for what you actually need.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description carries the full burden and does well: it quantifies ~70 reads, the 1 s pacing, a duration over a minute, and the load on the router. It does not describe the shape or arrangement of the returned values, which matters for a bulk read.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two short sentences, front-loaded with the scope and immediately followed by the cost and the alternative. Every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Cost, pacing and duration are covered, which is what an agent most needs before invoking a minute-long bulk read. The absence of an output schema leaves the return contents ('every known value') underspecified, a minor remaining gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool takes zero parameters, so there is nothing for the description to clarify; baseline 4 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and scope (read every known value in one pass) and explicitly positions it against the sibling get_router_data, so an agent can distinguish the two without inspecting either schema.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Names the alternative (get_router_data) and the reason to prefer it ('what you actually need'), which routes the agent away from over-reading. The positive case for using this tool – needing the complete state at once – is only implied by 'every known value'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
write_router_settingA
Write a setting (see list_writes). Pass the whole object as read from the matching read, with
your change made (e.g. read led_schedule, flip enable_night_mode, send it to led_set). Refuses
unverified writes unless allow_unverified=True -- ask the user first. Returns the read-back
(after); report that, not just success. The router then locks for ~60-90 s.
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| params | Yes | ||
| allow_unverified | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations at all, the description carries full burden and does it well: it discloses the refusal behavior for unverified writes, the required user confirmation, the ~60-90 s router lock side effect, and the requirement to report the read-back rather than just 'success'. These are exactly the operational traits an agent cannot infer from the schema.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Dense and front-loaded: the core action comes first, then the workflow, then the guardrail, then the return contract and side effect. Slightly fragmented by parentheticals, but every sentence carries information an agent needs.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a three-parameter mutation tool with no annotations and no output schema, the description covers the mutation workflow, the safety gate, the post-write side effect, and what is returned ('after' read-back) — enough to invoke it correctly and report results faithfully. Nothing critical is left to guess.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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, and it mostly does: 'name' is illustrated (led_set, led_schedule), 'params' is defined as the whole object as read from the matching read with the change applied, and allow_unverified is explained behaviorally. It never explicitly maps these to the parameter names, so an agent must infer the correspondence.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource ('Write a setting') and points to list_writes for the valid settings, which distinguishes it from read-side siblings like get_router_data and list_reads. It stops short of naming the other siblings it competes with, so identification is solid but not fully framed.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives a concrete read-modify-write workflow ('read led_schedule, flip enable_night_mode, send it to led_set') and an explicit gate: refuses unverified writes unless allow_unverified=True, and the user must be asked first. It doesn't contrast with read-only alternatives (e.g., when a snapshot is preferable), but the when-to-use path is clear.
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.
8 tool updates
v0.1.0- First observed
get_router_data - First observed
get_router_data_unredacted - First observed
list_reads - First observed
list_writes - First observed
lockout_status - First observed
mesh_overview - First observed
router_snapshot - First observed
write_router_setting
TDQS
Scored across 8 tools
The read/write catalogs are cleanly separated from the execute tools, and lockout_status is unique. Overlap remains between get_router_data and get_router_data_unredacted (a flag could have been a parameter) and to a lesser degree between mesh_overview and router_snapshot, so an agent can occasionally hesitate.
All names are descriptive snake_case with no style mixing, and most start with clear verbs (list_, get_, write_). Three names are noun phrases (mesh_overview, router_snapshot, lockout_status), so the verb_noun pattern is not fully uniform.
Eight tools for a router-management server is well within the ideal range. Each has a distinct role: catalog, read, write, overview, lockout status, snapshot, and secrets access.
Reads are comprehensively enumerated via list_reads and router_snapshot, and writes via list_writes plus read-modify-write. The surface lacks explicit action tools for non-setting operations (e.g. reboot or firmware action) if those exist, but core lifecycle coverage is strong.
Maintenance
Related MCP Connectors
Read-only MCP access to a documented IT fleet: state, changes, posture. 15 tools.
Network, domain and website diagnostics for AI clients via MCP.
See which AI models fall for traps in everyday jobs, and check or scan any MCP server, skill or package before your agent installs it. No sign-in; read-only; returns structured data.
- sentinelOAuthio.rootstuff
Uptime, SSL, DNS and domain monitoring you can talk to from Claude or any MCP client.
Related MCP Servers
- AlicenseAqualityDmaintenanceA Model Context Protocol server that enables AI assistants to read and safely modify TP-Link Omada networks through capability-gated tools, with a default read-only profile and dry-run writes for security.111MIT
- AlicenseBqualityBmaintenanceEnables Claude Code and other MCP clients to inspect and manage a TP-Link router over stdio, including device lists, DHCP leases and reservations, Wi-Fi settings, firmware and IP status, mesh nodes, and safe raw endpoint requests with confirmation for writes and secret masking.16MIT
- AlicenseNot gradedqualityBmaintenanceEnables LLM/MCP clients to read and, when explicitly allowed, modify TP-Link Archer AX53 router settings directly over the LAN using the router's own web protocol, without a browser or cloud account. It is read-first, write-gated, and lockout-aware, with tools for clients, DHCP, Wi-Fi, access control, presence history, and other router operations.MIT
- AlicenseBqualityCmaintenanceEnables an AI assistant to answer plain-language questions about a TP-Link Omada network — why Wi-Fi drops, which switch port a device is on, which VLAN it uses, and whether radar or interference is at play — by reading switches, access points, SSIDs, clients, topology and logs through 59 tools. It stays read-only unless two separate gates are opened, and any change is dry-run first, then read back and diffed.59MIT