@coffeerunhobby/mcp-ha-connect 2.2.1 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (281) hide show
  1. package/.env.example +1 -1
  2. package/README.md +11 -2
  3. package/dist/omadaClient/client.d.ts +6 -1
  4. package/dist/omadaClient/client.js +12 -1
  5. package/dist/omadaClient/client.js.map +1 -1
  6. package/dist/omadaClient/diagnose.d.ts +68 -0
  7. package/dist/omadaClient/diagnose.js +164 -0
  8. package/dist/omadaClient/diagnose.js.map +1 -0
  9. package/dist/omadaClient/index.d.ts +6 -0
  10. package/dist/omadaClient/index.js +15 -0
  11. package/dist/omadaClient/index.js.map +1 -1
  12. package/dist/omadaClient/macGroups.d.ts +58 -0
  13. package/dist/omadaClient/macGroups.js +124 -0
  14. package/dist/omadaClient/macGroups.js.map +1 -0
  15. package/dist/tools/infra/actions.d.ts +1 -1
  16. package/dist/tools/infra/actions.js +1 -1
  17. package/dist/tools/omada/index.js +6 -0
  18. package/dist/tools/omada/index.js.map +1 -1
  19. package/dist/tools/omada/macGroups.d.ts +19 -0
  20. package/dist/tools/omada/macGroups.js +77 -0
  21. package/dist/tools/omada/macGroups.js.map +1 -0
  22. package/dist/tools/omada/namespace.js +8 -0
  23. package/dist/tools/omada/namespace.js.map +1 -1
  24. package/dist/version.d.ts +1 -1
  25. package/dist/version.js +1 -1
  26. package/package.json +5 -1
  27. package/.codex/review-rules.md +0 -16
  28. package/.dockerignore +0 -8
  29. package/.gitattributes +0 -30
  30. package/.github/workflows/ci.yml +0 -193
  31. package/AGENTS.md +0 -389
  32. package/Dockerfile +0 -50
  33. package/docker-compose.yml +0 -23
  34. package/docs/CHANGELOG.md +0 -341
  35. package/docs/COVERAGE.md +0 -219
  36. package/docs/QUICK_START.md +0 -240
  37. package/eslint.config.js +0 -33
  38. package/n8n/ai-agent-safety-monitor.json +0 -355
  39. package/openapi.json +0 -1259
  40. package/scripts/check-version-sync.mjs +0 -69
  41. package/scripts/generate-jwt.ts +0 -121
  42. package/src/config.ts +0 -440
  43. package/src/haClient/automations.ts +0 -261
  44. package/src/haClient/calendars.ts +0 -94
  45. package/src/haClient/config.ts +0 -52
  46. package/src/haClient/devices.ts +0 -653
  47. package/src/haClient/entities.ts +0 -128
  48. package/src/haClient/events.ts +0 -689
  49. package/src/haClient/history.ts +0 -73
  50. package/src/haClient/index.ts +0 -336
  51. package/src/haClient/request.ts +0 -142
  52. package/src/haClient/services.ts +0 -45
  53. package/src/haClient/states.ts +0 -60
  54. package/src/haClient/updates.ts +0 -58
  55. package/src/haClient/wsCommand.ts +0 -44
  56. package/src/index.ts +0 -164
  57. package/src/localAI/index.ts +0 -88
  58. package/src/localAI/prompts.ts +0 -50
  59. package/src/localAI/providers/base.ts +0 -120
  60. package/src/localAI/providers/ollama.ts +0 -78
  61. package/src/localAI/providers/openai.ts +0 -86
  62. package/src/localAI/types.ts +0 -67
  63. package/src/omadaClient/auth.ts +0 -178
  64. package/src/omadaClient/client.ts +0 -337
  65. package/src/omadaClient/device.ts +0 -118
  66. package/src/omadaClient/index.ts +0 -310
  67. package/src/omadaClient/network.ts +0 -284
  68. package/src/omadaClient/request.ts +0 -365
  69. package/src/omadaClient/security.ts +0 -51
  70. package/src/omadaClient/site.ts +0 -344
  71. package/src/ownerQuestions/service.ts +0 -536
  72. package/src/permissions/index.ts +0 -143
  73. package/src/resources/index.ts +0 -213
  74. package/src/server/auth.ts +0 -175
  75. package/src/server/chatFace.ts +0 -789
  76. package/src/server/chatSlice.ts +0 -57
  77. package/src/server/common.ts +0 -170
  78. package/src/server/eventSubscription.ts +0 -343
  79. package/src/server/http.ts +0 -626
  80. package/src/server/instructions.ts +0 -97
  81. package/src/server/rateLimiter.ts +0 -227
  82. package/src/server/stdio.ts +0 -41
  83. package/src/server/stream.ts +0 -205
  84. package/src/tools/ai/analyzeSensors.ts +0 -33
  85. package/src/tools/ai/index.ts +0 -20
  86. package/src/tools/common.ts +0 -442
  87. package/src/tools/homeassistant/askOwner.ts +0 -133
  88. package/src/tools/homeassistant/automationControls.ts +0 -66
  89. package/src/tools/homeassistant/calendar.ts +0 -97
  90. package/src/tools/homeassistant/callService.ts +0 -25
  91. package/src/tools/homeassistant/controlClimate.ts +0 -68
  92. package/src/tools/homeassistant/controlCover.ts +0 -48
  93. package/src/tools/homeassistant/controlFan.ts +0 -44
  94. package/src/tools/homeassistant/controlLight.ts +0 -38
  95. package/src/tools/homeassistant/controlMediaPlayer.ts +0 -50
  96. package/src/tools/homeassistant/createAutomation.ts +0 -35
  97. package/src/tools/homeassistant/deleteAutomation.ts +0 -24
  98. package/src/tools/homeassistant/entityAction.ts +0 -35
  99. package/src/tools/homeassistant/entityGuard.ts +0 -28
  100. package/src/tools/homeassistant/getAllSensors.ts +0 -46
  101. package/src/tools/homeassistant/getAutomationTrace.ts +0 -30
  102. package/src/tools/homeassistant/getDomainSummary.ts +0 -29
  103. package/src/tools/homeassistant/getEntitiesByDomain.ts +0 -56
  104. package/src/tools/homeassistant/getHistory.ts +0 -24
  105. package/src/tools/homeassistant/getState.ts +0 -24
  106. package/src/tools/homeassistant/getStates.ts +0 -46
  107. package/src/tools/homeassistant/getVersion.ts +0 -21
  108. package/src/tools/homeassistant/index.ts +0 -121
  109. package/src/tools/homeassistant/listAutomations.ts +0 -35
  110. package/src/tools/homeassistant/listEntities.ts +0 -44
  111. package/src/tools/homeassistant/listPersons.ts +0 -46
  112. package/src/tools/homeassistant/sceneAndScript.ts +0 -53
  113. package/src/tools/homeassistant/searchEntities.ts +0 -58
  114. package/src/tools/homeassistant/sendNotification.ts +0 -179
  115. package/src/tools/homeassistant/systemTools.ts +0 -52
  116. package/src/tools/homeassistant/triggerAutomation.ts +0 -24
  117. package/src/tools/index.ts +0 -78
  118. package/src/tools/infra/actions.ts +0 -95
  119. package/src/tools/infra/index.ts +0 -138
  120. package/src/tools/omada/blockClient.ts +0 -28
  121. package/src/tools/omada/cyclePoePort.ts +0 -32
  122. package/src/tools/omada/deleteClient.ts +0 -27
  123. package/src/tools/omada/disableClientRateLimit.ts +0 -23
  124. package/src/tools/omada/getClient.ts +0 -14
  125. package/src/tools/omada/getDevice.ts +0 -14
  126. package/src/tools/omada/getFirewallSetting.ts +0 -14
  127. package/src/tools/omada/getInternetInfo.ts +0 -14
  128. package/src/tools/omada/getLanNetworkList.ts +0 -14
  129. package/src/tools/omada/getLanProfileList.ts +0 -14
  130. package/src/tools/omada/getPortForwardingStatus.ts +0 -26
  131. package/src/tools/omada/getRateLimitProfiles.ts +0 -14
  132. package/src/tools/omada/getSiteNtpStatus.ts +0 -14
  133. package/src/tools/omada/getSsidDetail.ts +0 -22
  134. package/src/tools/omada/getSsidList.ts +0 -21
  135. package/src/tools/omada/getSwitchStackDetail.ts +0 -14
  136. package/src/tools/omada/getThreatList.ts +0 -42
  137. package/src/tools/omada/getWlanGroupList.ts +0 -14
  138. package/src/tools/omada/graph.ts +0 -187
  139. package/src/tools/omada/index.ts +0 -153
  140. package/src/tools/omada/listBlockedClients.ts +0 -17
  141. package/src/tools/omada/listClients.ts +0 -14
  142. package/src/tools/omada/listClientsActivity.ts +0 -25
  143. package/src/tools/omada/listClientsPastConnections.ts +0 -44
  144. package/src/tools/omada/listDevices.ts +0 -14
  145. package/src/tools/omada/listDevicesStats.ts +0 -41
  146. package/src/tools/omada/listMostActiveClients.ts +0 -14
  147. package/src/tools/omada/listSites.ts +0 -18
  148. package/src/tools/omada/namespace.ts +0 -1164
  149. package/src/tools/omada/searchDevices.ts +0 -20
  150. package/src/tools/omada/setClientRateLimit.ts +0 -26
  151. package/src/tools/omada/setClientRateLimitProfile.ts +0 -25
  152. package/src/tools/omada/setSiteNtpServers.ts +0 -36
  153. package/src/tools/omada/setSsidEnabled.ts +0 -38
  154. package/src/tools/omada/unblockClient.ts +0 -26
  155. package/src/tools/types.ts +0 -11
  156. package/src/tools/utils/pagination-schema.ts +0 -27
  157. package/src/types/ai/index.ts +0 -11
  158. package/src/types/ai/types.ts +0 -67
  159. package/src/types/homeassistant/automations.ts +0 -43
  160. package/src/types/homeassistant/calendars.ts +0 -26
  161. package/src/types/homeassistant/config.ts +0 -14
  162. package/src/types/homeassistant/entities.ts +0 -14
  163. package/src/types/homeassistant/errors.ts +0 -33
  164. package/src/types/homeassistant/haConfig.ts +0 -7
  165. package/src/types/homeassistant/history.ts +0 -13
  166. package/src/types/homeassistant/index.ts +0 -46
  167. package/src/types/homeassistant/request.ts +0 -6
  168. package/src/types/homeassistant/serviceCall.ts +0 -18
  169. package/src/types/homeassistant/states.ts +0 -58
  170. package/src/types/homeassistant/updates.ts +0 -28
  171. package/src/types/index.ts +0 -12
  172. package/src/types/omada/activeClientInfo.ts +0 -17
  173. package/src/types/omada/clientActivity.ts +0 -32
  174. package/src/types/omada/clientBlockStatus.ts +0 -11
  175. package/src/types/omada/clientPastConnection.ts +0 -82
  176. package/src/types/omada/index.ts +0 -14
  177. package/src/types/omada/omadaApiResponse.ts +0 -5
  178. package/src/types/omada/omadaClientInfo.ts +0 -11
  179. package/src/types/omada/omadaDeviceInfo.ts +0 -11
  180. package/src/types/omada/omadaDeviceStats.ts +0 -31
  181. package/src/types/omada/omadaSiteSummary.ts +0 -5
  182. package/src/types/omada/oswStackDetail.ts +0 -11
  183. package/src/types/omada/paginatedResult.ts +0 -6
  184. package/src/types/omada/rateLimitProfile.ts +0 -58
  185. package/src/types/omada/threatInfo.ts +0 -38
  186. package/src/types/omada/tokenResult.ts +0 -6
  187. package/src/types.ts +0 -2
  188. package/src/utils/config-validations.ts +0 -68
  189. package/src/utils/jwt.ts +0 -112
  190. package/src/utils/logger.ts +0 -121
  191. package/src/utils/plainText.ts +0 -48
  192. package/src/utils/redact.ts +0 -59
  193. package/src/utils/sanitizeError.ts +0 -18
  194. package/src/utils/tlsDispatcher.ts +0 -69
  195. package/src/version.ts +0 -5
  196. package/tests/bdd/automation-creation.spec.ts +0 -214
  197. package/tests/bdd/automation-management.spec.ts +0 -267
  198. package/tests/bdd/calendar.spec.ts +0 -190
  199. package/tests/bdd/configuration.spec.ts +0 -283
  200. package/tests/bdd/device-control.spec.ts +0 -344
  201. package/tests/bdd/entity-listing.spec.ts +0 -208
  202. package/tests/bdd/entity-search.spec.ts +0 -183
  203. package/tests/bdd/history-retrieval.spec.ts +0 -195
  204. package/tests/bdd/notifications.spec.ts +0 -238
  205. package/tests/bdd/service-calls.spec.ts +0 -144
  206. package/tests/bdd/state-retrieval.spec.ts +0 -204
  207. package/tests/bench/hotpaths.bench.ts +0 -68
  208. package/tests/config.test.ts +0 -355
  209. package/tests/features/automation-creation.feature +0 -36
  210. package/tests/features/automation-management.feature +0 -54
  211. package/tests/features/calendar.feature +0 -37
  212. package/tests/features/configuration.feature +0 -70
  213. package/tests/features/device-control.feature +0 -100
  214. package/tests/features/entity-listing.feature +0 -51
  215. package/tests/features/entity-search.feature +0 -44
  216. package/tests/features/history-retrieval.feature +0 -38
  217. package/tests/features/notifications.feature +0 -37
  218. package/tests/features/service-calls.feature +0 -35
  219. package/tests/features/state-retrieval.feature +0 -37
  220. package/tests/fixtures/openapi-default-slice.json +0 -290
  221. package/tests/haClient/automationTrace.test.ts +0 -59
  222. package/tests/haClient/automations.test.ts +0 -149
  223. package/tests/haClient/config.test.ts +0 -117
  224. package/tests/haClient/entities.test.ts +0 -188
  225. package/tests/haClient/events.test.ts +0 -455
  226. package/tests/haClient/eventsTls.test.ts +0 -52
  227. package/tests/haClient/history.test.ts +0 -228
  228. package/tests/haClient/index.test.ts +0 -243
  229. package/tests/haClient/request.test.ts +0 -217
  230. package/tests/haClient/services.test.ts +0 -120
  231. package/tests/haClient/states.test.ts +0 -119
  232. package/tests/haClient/updates.test.ts +0 -193
  233. package/tests/index.test.ts +0 -160
  234. package/tests/integration/homeassistant.test.ts +0 -144
  235. package/tests/integration/omada.test.ts +0 -167
  236. package/tests/integration/server.test.ts +0 -151
  237. package/tests/localAI/index.test.ts +0 -177
  238. package/tests/localAI/ollama.test.ts +0 -187
  239. package/tests/localAI/openai.test.ts +0 -257
  240. package/tests/omadaClient/actions.test.ts +0 -161
  241. package/tests/omadaClient/clientBlocks.test.ts +0 -170
  242. package/tests/omadaClient/ntp.test.ts +0 -381
  243. package/tests/omadaClient/site.test.ts +0 -37
  244. package/tests/ownerQuestions/service.test.ts +0 -499
  245. package/tests/ownerQuestions/tools.test.ts +0 -186
  246. package/tests/permissions/index.test.ts +0 -217
  247. package/tests/resources/index.test.ts +0 -288
  248. package/tests/scripts/generateJwt.test.ts +0 -44
  249. package/tests/security/accessControl.test.ts +0 -223
  250. package/tests/security/authentication.test.ts +0 -117
  251. package/tests/security/configuration.test.ts +0 -170
  252. package/tests/security/cryptoTransport.test.ts +0 -172
  253. package/tests/security/dependencies.test.ts +0 -152
  254. package/tests/security/injection.test.ts +0 -117
  255. package/tests/security/insecureDesign.test.ts +0 -121
  256. package/tests/security/logging.test.ts +0 -131
  257. package/tests/security/resourceConsumption.test.ts +0 -142
  258. package/tests/server/auth.test.ts +0 -249
  259. package/tests/server/chatFace.test.ts +0 -320
  260. package/tests/server/common.test.ts +0 -84
  261. package/tests/server/http.test.ts +0 -561
  262. package/tests/server/instructions.test.ts +0 -152
  263. package/tests/server/memoizeJsonSchema.test.ts +0 -71
  264. package/tests/server/stdio.test.ts +0 -99
  265. package/tests/server/stream.test.ts +0 -285
  266. package/tests/server/toolVisibility.http.test.ts +0 -111
  267. package/tests/server/toolVisibility.test.ts +0 -129
  268. package/tests/tools/ai/analyzeSensors.test.ts +0 -227
  269. package/tests/tools/common.test.ts +0 -123
  270. package/tests/tools/homeassistant/handlers.test.ts +0 -872
  271. package/tests/tools/infra/invokeAction.test.ts +0 -280
  272. package/tests/tools/omada/graph.test.ts +0 -385
  273. package/tests/tools/omada/handlers.test.ts +0 -897
  274. package/tests/tools/omada/namespace.test.ts +0 -483
  275. package/tests/tools/registry.test.ts +0 -168
  276. package/tests/utils/config-validations.test.ts +0 -352
  277. package/tests/utils/jwt.test.ts +0 -115
  278. package/tests/utils/logger.test.ts +0 -327
  279. package/tests/utils/redact.test.ts +0 -105
  280. package/tsconfig.json +0 -24
  281. package/vitest.config.ts +0 -38
package/docs/CHANGELOG.md DELETED
@@ -1,341 +0,0 @@
1
- ### 2.2.1
2
- - **Security — secrets are redacted from every tool response.** Omada read tools returned the household Wi-Fi password in plain text (`pskSetting.securityKey` in the SSID detail, via `omada_getSsidDetail` and `omada_read /wifi/ssids`), and other paths could do the same for RADIUS / CoA / SNMP secrets, PPSK and VPN keys, portal passwords and tokens. Every tool response now passes through one redaction step (in `toToolResult`, so MCP and the REST bridge alike): non-empty text values under secret-looking names become `"<redacted>"` (empty values stay empty; flags and numbers with similar names such as `hidePwd` or `encryptionPsk` are untouched), and `token=` / `access_token=` values inside URLs (Home Assistant camera images) are masked. Internal read-modify-write paths are unaffected; redaction happens only at the response.
3
- - **Fix — `omada_unblockClient` on clients the controller no longer treats as current.** Omada's unblock endpoint fails with "This client does not exist" once a blocked (and therefore offline) client drops out of the controller's current set. The tool now checks the known-clients list: if the client is there and no longer blocked (e.g. unblocked in the web UI), it reports success; otherwise it returns a clear error saying what to do. A client the controller has no record of is never reported as unblocked, because its access points may still refuse it (an orphaned block). This works whether the controller reports the error with HTTP 200 or an HTTP error status (controller errors now carry their `errorCode`).
4
- - **New: `omada_listBlockedClients`** (QUERY) lists blocked clients from the known-clients list, offline ones included, so automations can check block state. Graph mode gets `omada_read /clients/known` instead: one page of known clients with their `block` field (the controller cannot filter by block state, so a single-page "blocked" view would miss entries).
5
- - **New: `omada_deleteClient`** (**CONFIGURE**) deletes the controller's record of a client (name, history, block state), to clear a block the unblock endpoint can no longer reach.
6
- - `omada_blockClient`'s description now warns that a long block can become impossible to undo through the API and recommends a controller-side time-range rule for schedules such as a curfew.
7
- - README: the two new Omada tools are listed (32).
8
- - +30 tests (redaction across SSID, RADIUS, PPSK, VPN, SNMP, portal, webhook and camera shapes, and through `omada_read`; the unblock fallback including the orphaned-record case and a record without block state; the blocked list; deleteClient and its permission; mutation-checked).
9
-
10
- ### 2.2.0
11
- - **New: owner questions — approve or deny from the phone.** `askOwner` sends a sticky, persistent notification with 1-3 buttons (default Approve / Deny) and returns a `requestId` at once; `getOwnerAnswer` waits up to 50 s per call and returns `answered` (button index and label, `answeredAt`, the HA user who tapped), `pending`, `timeout`, `cancelled` or `unknown`; `cancelOwnerQuestion` withdraws a question and marks the notification "Cancelled". Two calls rather than one long one because Cloudflare cuts requests at ~100 s. Questions stay open up to 7 days (default 10 min); the phone removes the notification at expiry by itself.
12
- - **No database, restart-proof:** the requestId carries the question, buttons, target, expiry and asking client, signed with a key derived from `MCP_AUTH_SECRET`; each button's action id is signed separately and cannot be derived from the requestId. After a restart the server still recognises open questions and the taps on them. Only a tap during the restart itself is lost (the question then expires as NO).
13
- - **Security:** a tap counts only with origin REMOTE and a user (the mobile app webhook), so an automation firing a fake `mobile_app_notification_action` cannot approve anything; tampered ids, extended expiries and swapped button indexes are rejected; only the asking token `sub` can read or cancel; at most 3 open questions and 30 per hour per client; first tap wins; late taps are ignored. Needs `NOTIFY`.
14
- - **Plain text only:** question at most 256 characters (line breaks allowed), title 60, button labels 20. Text is NFC-normalized (Romanian diacritics are fine), then emoji, control and invisible characters (zero-width joiners, bidi overrides), variation selectors and stacked combining marks are refused with the offending character named — never silently stripped or cut.
15
- - **`MCP_OWNER_QUESTIONS_HA_USERS`**: comma-separated HA user ids allowed to answer (the `answeredBy` of an answer); unset = any HA user, with a startup warning.
16
- - Known limit, accepted: cancellations and answers are kept in memory only. After a restart, someone with a Home Assistant login could re-send an old button id through HA's API and answer a question that had been cancelled or denied (the phone no longer shows its buttons; that access already controls the house).
17
- - Needs HTTP mode, an **admin** Home Assistant token (button taps are not on HA's non-admin event allowlist) and `MCP_AUTH_SECRET`. If Home Assistant refuses the tap subscription at startup, the three tools are not offered (logged); if it refuses later, `askOwner` returns an error saying so instead of sending questions nobody can answer. New `MCP_OWNER_QUESTIONS_ENABLED` (default `true`).
18
- - **Fix — `getAutomationTrace` always answered "Not Found".** Home Assistant has no REST trace endpoint; traces exist only over the WebSocket (`trace/list`, admin-only) and are keyed by the automation's `id` attribute, not its entity id. The tool now uses a one-off WebSocket command, returns the newest runs first (new `limit`, default 5, max 20) with trigger, state and errors, and explains when an automation defined in YAML without an `id` has no traces.
19
- - **Fix — Home Assistant events stopped after an HA restart.** The WebSocket client reconnected but never re-sent its subscriptions (HA forgets them with the connection), so `/subscribe_events` went silent after every HA restart. Subscriptions are now restored on reconnect; the client keeps retrying with the delay capped at 60 s instead of giving up after 10 attempts; commands are matched to their results by id (they were matched in arrival order); connecting has a deadline and fails at once if HA closes before authenticating; and a subscription made while Home Assistant is unreachable (also at server startup) is queued and sent once HA is back, instead of failing (an SSE client stays connected and receives events when HA returns; previously owner questions and SSE stayed unavailable until a server restart). Unsubscribing works while HA is offline (the subscription is forgotten for good, never restored on reconnect), and a subscription cancelled before HA confirmed it is cancelled on HA's side too. A subscription HA refuses (e.g. a non-admin token) is reported and dropped; one whose confirmation is lost is cancelled and retried (no duplicate subscriptions on HA); and an event HA sends right after confirming a subscription is no longer dropped. Errors from these WebSocket commands reach callers and logs as HA's error code only (e.g. `Home Assistant rejected 'trace/list' (unauthorized)`), never HA's free text or the internal address; the detail stays in the server log. The WebSocket connections now follow `HA_STRICT_SSL` like the REST client.
20
- - **Fix — duplicate events.** With two subscriptions to the same event type, each received every event twice (HA sends one copy per subscription). Each copy now goes only to its own subscription.
21
- - **Logging — tool arguments are logged at debug level only.** The info-level `Tool invoked` line now carries just the tool and session; the arguments (message and question text, entity names, MAC addresses) appear only with `LOG_LEVEL=debug`.
22
- - README: `MCP_SSE_EVENTS_ENABLED` defaults to `true` (the README said `false`).
23
- - +88 tests (owner question service and tools incl. a real MCP round trip and concurrent rate limits, plain-text validation, WebSocket client against a fake HA server incl. reconnects, deadlines and the TLS policy, trace lookup; the security checks are mutation-tested).
24
-
25
- ### 2.1.1
26
- - **Fix — `omada_setSiteNtpServers` was rejected by the controller on sites with daylight saving off.** Omada returns the DST start/end as empty objects when DST is off, but rejects them on write ("Daylight saving parameter [month] should not be null"). The site update now sends DST start/end only when complete; with DST on and an incomplete start/end it refuses to write. The rejected 2.1.0 call changed nothing (the controller validates before saving).
27
- - +2 tests (the live DST-off shape; DST on with an incomplete start/end).
28
-
29
- ### 2.1.0
30
- - **New: site NTP tools for Omada.** `omada_getSiteNtpStatus` (QUERY; also `omada_read /network/ntp` in graph mode) reads the NTP configuration and status. `omada_setSiteNtpServers` (**CONFIGURE**, not CONTROL: it changes site-wide configuration) replaces the site NTP server list (hostnames or IPv4, at most 5) and can turn NTP on or off. Omada has no NTP-only write: NTP lives in the site settings, so the tool reads the site, changes only the NTP fields and writes the whole site back (`PUT /sites/{siteId}`), translating the read and write shapes (servers are strings on read, `{ address }` objects on write; read-only DST fields are dropped). It refuses to write if the site lacks a required field, validates every address before contacting the controller, supports `dryRun` to preview the exact request, and reports the before/after lists as the controller holds them. The controller has no conditional update, so writes are serialized per site and the site is re-read just before the PUT: if a non-NTP setting changed in between, nothing is written and the call fails with a conflict. Not exposed on the Open WebUI REST bridge.
31
- - README: the Omada tool list was stale (said 24, missed the block/unblock, PoE and SSID action tools); it now lists all 30.
32
- - +42 tests (address validation, the update body, dry run, read-modify-write, conflict refusal, per-site serialization, controller rejection, the `/network/ntp` graph read, and RBAC: a CONTROL token cannot change NTP; mutation-checked).
33
-
34
- ### 2.0.0
35
- - **Major version for the two major dependency upgrades below (MCP SDK v2, zod 4).** No configuration changes are needed and MCP clients are unaffected: same tools, same protocol versions, same auth.
36
- - **MCP SDK v2 (split packages).** `@modelcontextprotocol/sdk` 1.x → `@modelcontextprotocol/server` 2.2 + `@modelcontextprotocol/node` 2.1. The production dependency tree shrinks from **95 packages to 8**: Express, body-parser, qs, cors, cross-spawn (Socket "shell access"), ajv (Socket "uses eval"), eventsource and the long tail of unmaintained Express helpers are gone. `npm audit` (incl. dev) reports 0. Client compatibility is unchanged: v2 still negotiates `2025-11-25` and older protocol versions (verified with `mcp-remote`, the Claude Desktop client, plus raw `2025-06-18` initialize). Applied with the official codemod, then by hand: tool `inputSchema`s pass schema objects (raw shapes are deprecated), and the REST bridge's synthetic request context moved to the v2 shape (`http.authInfo`) — without that, Open WebUI's tool calls would have been denied.
37
- - **zod 3 → 4** (SDK v2 requires zod ≥ 4.2). `zodToOpenApiSchema` was ported to zod 4 internals (the generated OpenAPI spec is byte-identical). The JSON Schemas in `tools/list` change only cosmetically (key order, explicit safe-integer `maximum`, no top-level `additionalProperties: false`), except `createAutomation` now correctly advertises `trigger` and `action` as required.
38
- - **Performance — schema conversion is memoized.** SDK v2 converts every tool schema to JSON Schema inside `registerTool`; with the stateless per-request server that made a full request ~60% slower (2.2 → 3.6 ms). `memoizeJsonSchema` caches each schema's conversion for the process (deep-cloned results, validation untouched, `tools/list` byte-identical), bringing a full request to **1.9 ms — faster than on v1**.
39
- - **New: `npm run bench`** — vitest benchmarks of the per-request hot paths (server build, full `createServer`+`tools/list` round trip, JWT verify, argument validation), used to catch and fix the regression above.
40
- - +6 tests (memoization, mutation-checked); test mocks moved to the v2 context shape.
41
-
42
- ### 1.7.6
43
- - **`omada_read` is hidden from callers who can read no Omada resource.** It has no single static permission (it checks per resource path), so 1.7.5 still listed it to every caller, including unmapped tokens that could read nothing. A new per-tool visibility rule lists it only when the caller holds the permission of at least one readable node (e.g. a `QUERY` or an `ADMIN`-only mask); a `NONE`/`NOTIFY`-only caller no longer sees it. Per-path checks are unchanged.
44
- - **CI: `actions/checkout` and `actions/setup-node` v4 → v7** (Node 24 runtime; v4 targeted the deprecated Node 20 action runtime). No workflow changes were needed: the breaking changes in v5–v7 concern automatic caching (not triggered — no `packageManager` field) and credential persistence (CI never pushes with git).
45
- - `AGENTS.md`: the GHCR push token is fetched from the maintainer's password manager at push time — never stored as an environment variable.
46
- - +4 tests (`omada_read` visibility for NONE / QUERY / ADMIN-only / NOTIFY-only masks).
47
-
48
- ### 1.7.5
49
- - **Security — `tools/list` is filtered by the caller's permissions.** A token is only offered the tools it may call (e.g. a `readonly` token no longer sees `restartHomeAssistant`, `deleteAutomation`, `invokeAction` or the Omada write tools). Previously every valid token was shown all tools; calls were already denied, but LLM clients planned around tools they could not use and the admin surface was disclosed. Each tool's static permission is recorded by `wrapToolHandler`; `createServer({ callerPermissions })` disables the rest, so the SDK omits them from the list and rejects calls to them. Per-call RBAC is unchanged; stdio (local trust) is unfiltered; `omada_read`/`omada_browse` stay listed (they gate per resource path).
50
- - **Fix — control tools no longer report success for a non-existent entity.** Home Assistant silently ignores service calls to unknown `entity_id`s, so `entityAction`, `controlLight`, `controlClimate`, `controlFan`, `controlCover`, `controlMediaPlayer`, `activateScene` and `runScript` returned `success: true` for typos. They now check existence first and return `isError` "Entity not found" ("No action was performed") without calling the service.
51
- - **Warning — permissive `defaultRole`.** With bearer auth, the server logs a startup warning when `MCP_PERMISSIONS_CONFIG` `defaultRole` grants anything, since it applies to every valid token with an unmapped `sub`. README now recommends `defaultRole: NONE` plus one `users` entry per client (and fixes the `ADMIN` role row, which wrongly said "all except AI").
52
- - **Fix — `generate:jwt` prints the token once.** stdout carries only the bare token; details go to stderr, so `TOKEN=$(npm run -s generate:jwt -- ...)` captures exactly one token.
53
- - Added `.codex/review-rules.md` (the repo's hard rules for pre-release code review).
54
- - +26 tests: permission-filtered `tools/list` over an MCP client and over the real HTTP path (bearer auth → stream transport, incl. interleaved callers), the entity guard for all eight tools, `defaultRoleWarning` and its wiring in the auth middleware, and the `generate:jwt` stdout contract (subprocess).
55
-
56
- ### 1.7.4
57
- - **Security — cleared every advisory in the dependency tree** (`npm audit` and `npm audit --omit=dev` both report 0). Runtime range declarations are unchanged; all fixes are in-range lockfile bumps:
58
- - Production: `undici` 6.28.0→6.29.0 (WebSocket DoS ×2, retry-interceptor response splitting), `fast-uri` 3.1.6→3.1.8 (authority injection / host confusion; via ajv), `hono` 4.13.3→4.13.11, `ip-address` 10.5.0→10.7.2, `qs` 6.15.3→6.16.0 (all three transitive under the SDK's express stack).
59
- - Dev-only: `vitest` + `@vitest/coverage-v8` 4.1.10→4.1.11 (devDependency floor raised to `^4.1.11`), `brace-expansion`, `js-yaml`, `nanoid`, `postcss`; `esbuild` pinned back to 0.27.2 (the advisory covers 0.27.3–0.28.0).
60
- - None of the production advisories were reachable here — the vulnerable surfaces (undici's WebSocket/retry interceptor, hono/express/qs request parsing, ip-address) are never imported by this server — but they failed the `npm audit` CI gate.
61
- - **Image rebuilt on the current base**: Node 24.19.0→24.21.0 (bundled OpenSSL 3.5.7→3.5.8, bundled undici 7.29.0→7.29.1), Alpine 3.24.1→3.24.2, `curl` 8.21.0→8.22.0, `libssl3`/`libcrypto3` 3.5.8. No source changes.
62
-
63
- ### 1.7.3
64
- - **Fix — stateless `GET /mcp` now returns `405 Method Not Allowed` instead of hanging forever.** In stateless mode every request gets a fresh transport, so the SDK's standalone SSE GET opened a stream that never emitted a byte and never ended. That eternal zero-byte response pinned the Cloudflare→origin keep-alive socket, and HTTP/1.1 serial semantics stalled every request queued behind it — mcp-remote's own `WWW-Authenticate` probe GET poisoned the socket its `initialize` POST was then queued on, surfacing as intermittent "Request timed out" (and occasional CF 502) for Claude Desktop / Cowork sessions. Also fixes the resource leak (each hung GET pinned a socket + a full McpServer instance). Stateful mode is unchanged. +4 regression tests (`isStatelessMcpGet`).
65
- - Removed `src/wrapper.ts` — a dead legacy HTTP wrapper (unauthenticated, spawn-per-request) that nothing referenced but still compiled into the shipped image. Verified unused: n8n calls the native `/mcp` endpoint; the live server already 404'd the wrapper's `POST /` route.
66
- - `openapi.json`: dropped the stale `POST /` "raw JSON-RPC passthrough" advertisement (the endpoint 404s; n8n uses `/mcp`).
67
- - Removed the unused `customRequestSchema` export (never registered as a tool).
68
- - `parsePermissionsConfig` now logs a warning when `MCP_PERMISSIONS_CONFIG` is invalid JSON instead of silently resolving every caller to NONE (still fail-closed).
69
- - Track `AGENTS.md` (agent instructions for the repo), updated to the current release process (CI OIDC npm publish, WSL Docker build) and current facts (REST bridge is RBAC-gated).
70
-
71
- ### 1.7.2
72
- - Fix: a malformed JSON request body now returns `400 Bad Request` (was `500`) — `parseBody` tags the parse failure and the handler returns the parse detail; oversize bodies still `413`, genuine faults still `500`.
73
- - Security: cleared every high/moderate advisory in the production tree via already-in-range bumps (no `overrides`, no hard-dep downgrades, `package.json` unchanged; `npm audit --omit=dev` now 0): `ip-address` 10.2.0→10.5.0 (SSRF), `fast-uri` 3.1.3→3.1.6, `@hono/node-server` 1.19.14→1.19.17 (serve-static path traversal), `hono` 4.12.29→4.13.3 (middleware DoS), `undici` 6.27.0→6.28.0.
74
- - Remaining `npm audit` findings are dev-only tooling (esbuild/vitest/tsx) that never ships.
75
-
76
- ### 1.7.1
77
- - Per-action cooldown on `invokeAction`: a minimum interval between firings (default 60s, 0 disables) so an injected model can't loop a *legitimate* remote-hands action into a deploy storm / endpoint DoS. Check-and-claim runs before the fetch; a failed call still consumes the slot.
78
- - Fix: undici pairing — dispatcher requests now use undici's own `fetch`. An npm-undici-6 `Agent` passed to Node's built-in fetch broke on Node 26 ("invalid onError method" → "fetch failed"); the real root cause of the v1.5.5 crash-loop.
79
- - README npm badge → shields.io (badge.fury.io served a stale cached version).
80
-
81
- ### 1.7.0
82
- - Unified chat-face registry: one source generates the OpenAPI spec and the `MCP_CHAT_TOOLS` slice; Omada tools made chat-eligible.
83
- - Fix two stale OC200-v6 integration tests (totalTraffic rename, required threat-list params).
84
-
85
- ### 1.6.0
86
- - Remote-hands actions: `invokeAction` fires pre-registered REST actions (`MCP_REST_ACTIONS`) — deploy triggers / webhooks, each individually gated (name-only lookup, no arbitrary URLs).
87
- - package.json: add repository / homepage / bugs metadata.
88
-
89
- ### 1.5.6
90
- - Runtime base → `node:24-alpine` LTS (node:26 broke the old-kernel NAS's first fetch); npm stripped from the runtime image.
91
- - CI: boot-test the built image (mock HA + `/health`) so a release is never the image's first run; auto-create the GitHub Release on `v*` tags; tokenless npm publish via OIDC trusted publishing; also test on Node 26 (the image runtime).
92
-
93
- ### 1.5.5
94
- - CVE patch: refresh dependencies, `node:26` base (node:25 EOL), `apk upgrade`, drop unused `--experimental-quic`.
95
- - Fix: regenerate the lockfile on Linux — a Windows-generated lock omitted `@emnapi/*` optional deps, failing `npm ci` in the Docker/CI build.
96
-
97
- ### 1.5.4
98
- - Actionable error hints so agents self-correct: `getState` / `entityAction` / `hass://entities/{id}` return a `hint` toward `searchEntities` on a missing/malformed `entity_id`; Omada `resolveSiteId` with no site hints to `omada_browse /`; corrected stale Omada SSID getter refs to graph paths (`omada_read /wifi/groups`, `/wifi/ssids`). Additive — error text only, no API/behavior change.
99
-
100
- ### 1.5.3
101
- - Fix: add `x-session-id` to `Access-Control-Allow-Headers` so Open WebUI's OpenAPI tool calls pass CORS preflight (the browser was blocking every call on the unlisted header → "NetworkError"). Final piece with v1.5.1 (https scheme) + v1.5.2 (CORS on 401/429) to make `/api/*` calls complete.
102
-
103
- ### 1.5.2
104
- - Fix: apply REST-bridge CORS (`/openapi.json`, `/api/*`, SSE path) **before** auth / rate-limit, so a `401` / `429` still carries `Access-Control-Allow-Origin`. A browser discards a header-less cross-origin response and reports "NetworkError", hiding the real `401` — making an auth misconfig look like a tunnel failure. Path test extracted to `isRestApiCorsPath()`; 200s unchanged.
105
-
106
- ### 1.5.1
107
- - Fix: `/openapi.json` honors `X-Forwarded-Proto` so `servers[0].url` advertises `https` behind the TLS-terminating Cloudflare tunnel (was hardcoded `http://`, blocked as mixed content on an https page → "NetworkError"). New `resolveForwardedProto()` validates against an allowlist (spoof-safe; first hop of a comma chain). No change for plain-HTTP.
108
-
109
- ### 1.5.0
110
- - Feature — Omada resource graph Tier 4 reads (still just `omada_browse` + `omada_read`, zero tool-schema cost), grounded in the reference API client, over the existing `OmadaClient.readResource()`:
111
- - VPN (`/vpn`): `/site-to-site` (list or single via `id`), `/client-to-site/servers`, `/client-to-site/clients`, `/wireguard`, paginated `/ipsec-stats`.
112
- - Profiles (`/profiles`): `/ppsk` (**requires** `params.type` 0/1) and `/time-range`.
113
- - Schedules (`/schedules`): `/poe`, `/port`, `/upgrade`.
114
- - Backup (`/backup`): `/files`, `/result`.
115
- - Audit (`/audit`) — **ADMIN-gated**: `/site` and `/global`, paginated with optional epoch-ms `startTime`/`endTime` + `searchKey` (new `auditFilters` helper).
116
- - First ADMIN subtree beyond `/security`, further exercising per-path RBAC.
117
-
118
- ### 1.4.0
119
- - Feature — Omada resource graph widened from ~33 to **54 readable nodes** at the same two-tool surface (`omada_browse` + `omada_read`), zero tool-schema cost; every node grounded in the controller OpenAPI spec + reference client, over `OmadaClient.readResource()`:
120
- - Typed-read parity: `/devices/search`, `/network/load-balance` — every typed getter now has a graph node.
121
- - Tier 2 (insight): `/devices/cable-test` (requires `switchMac`), `/network/port-forwarding/rules`, `/network/dhcp-leases`, dashboard `/client-distribution`, `/traffic-distribution`, `/traffic-activities`.
122
- - Tier 3 (home subset, skipping enterprise gear): `/devices/poe`, `/lldp`, `/network/dhcp-reservations`, `/static-routes`, `/ip-mac-binding`, `/attack-defense`, `/acls/{gateway,switch,eap}`, `/url-filters/{gateway,eap}`, `/mac-filters/{allow,deny}`, `/wifi/band-steering` — all read-only, QUERY-gated.
123
- - Paginated nodes forward one `page`/`pageSize` (no page-walking).
124
-
125
- ### 1.3.4
126
- - Feature — Omada resource-graph tool registration (`MCP_TOOL_REGISTRATION_MODE=graph`): registers `omada_browse` (permission-filtered tree of resource **types**) + `omada_read` (per-path-RBAC fetch, single-page pagination) + the 5 typed write/action tools, replacing ~21 read getters; `eager` (default) unchanged. One `OmadaClient.readResource()` primitive backs the newly-exposed endpoints. `graph` is now a complete superset of `eager` reads, incl. the ADMIN-gated IDS/IPS log at `/security/threats` (required epoch `startTime`/`endTime`) — first node above QUERY. New `namespace.ts`/`graph.ts`, `getCallerPermissions()` extracted; +47 tests.
127
- - Fix — `OMADA_SITE_ID` validated against the live controller at startup: an id not present on the controller (drift after migration, like `OMADA_OMADAC_ID`) now disables the Omada plugin with an error naming the bad value + valid sites, instead of silently scoping reads to a dead site (later "user does not have permissions to access this site"). HA/AI keep working; valid default still auto-resolves. New `checkConfiguredSite()` + 4 tests.
128
- - Fix — graph reads that require query params now send them: `/events` + `/events/alerts` send `filters.timeStart`/`timeEnd` (epoch ms, default last 7d, `params.module`/`resolved` optional); `/dashboard/cpu` + `/memory` send `start`/`end` (epoch s, default last 24h); `/wifi/rogue`, `/wifi/wids` (Pro-only), `/devices/pending` marked paginated. Surfaces the controller's `errorCode`/`msg` in thrown HTTP errors (was a bare `400`). Window helpers `resolveLogWindowMs`/`resolveUsageWindowSec`; +10 tests.
129
-
130
- ### 1.3.1
131
- - Patch — RBAC role-name case-insensitivity (follow-up to v1.3.0 fail-closed change): `getUserPermissions` resolves per-user `role` and `defaultRole` case-insensitively, so lowercase `"operator"`/`"admin"` in `MCP_PERMISSIONS_CONFIG` map correctly instead of collapsing to an empty mask; unknown roles still fail closed to `NONE`. Tests under `tests/permissions/`.
132
-
133
- ### 1.3.0
134
- - **Security hardening release** — OWASP-aligned audit (API Top 10 2023 + Top 10 2021), every fix with regression tests under `tests/security/`; external behavior unchanged for correct configs. Suite → 908 tests; `npm audit --omit=dev` clean.
135
- - Access control: REST `/api/*` gated by the same RBAC bits as their MCP twins (`403` on insufficient perms); SSE `/subscribe_events` requires `QUERY`, dead `?token=` removed, SSE CORS constrained to the allowlist.
136
- - Authentication: opt-in `MCP_AUTH_REQUIRE_EXP` (reject no-`exp` tokens, default off + startup warning); optional `MCP_AUTH_ISSUER`/`AUDIENCE` + `nbf`/clock-skew; signing secret must be ≥32 chars for `bearer` (fail-fast).
137
- - Injection/SSRF: every interpolated HA path segment `encodeURIComponent`-encoded and schema-validated.
138
- - Crypto/transport: removed process-global `NODE_TLS_REJECT_UNAUTHORIZED=0` (per-client `undici` dispatcher only when `strictSsl=false`); SSE IDs via `randomUUID()`.
139
- - Configuration: `MCP_AUTH_METHOD=none` throws on non-loopback bind; opt-in DNS-rebinding Host validation via `MCP_HTTP_ALLOWED_HOSTS` (unset = off); removed `ALLOWED_ORIGINS=*` from compose; container runs non-root (`USER node`); static security headers on every response.
140
- - Resource limits: rate-limit keying trusts forwarding headers only from `MCP_RATE_LIMIT_TRUSTED_PROXIES` peers (else socket addr); 1 MB body cap (`413` + socket destroy); slow-loris headers/request/keep-alive timeouts.
141
- - Logging: client-facing `500`/SSE errors generic (detail server-side only); `/health` returns only `{"status":"healthy"}`.
142
- - Design: tool authz fails **closed** (missing mask denies, was `0xFF`); stdio opts into local full-trust explicitly.
143
- - Dependencies: bumped `@modelcontextprotocol/sdk`→`^1.29.0`, `ws`→`^8.21.0` (cleared 8 prod advisories, 5 high); CI gate asserts zero high/critical.
144
-
145
- ### 1.2.0
146
- - **Omada Client Block/Unblock**: Block or unblock a network client by MAC address
147
- - New tool `omada_blockClient`: denies a client all network access until unblocked
148
- - New tool `omada_unblockClient`: restores a previously blocked client's access
149
- - Backed by the Omada Open API `POST .../clients/{mac}/block` and `/unblock` endpoints
150
- - Both require the `CONTROL` permission and return a `{ mac, siteId, blocked }` status object
151
- - Total Omada tools: 23 → 25
152
- - All tests passing
153
-
154
- ### 1.1.0
155
- - **Performance: Paginated Entity Queries**: Reduced response sizes by ~98% for entity queries
156
- - New `LightweightEntity` type returns only essential fields (entity_id, state, friendly_name, unit_of_measurement, last_changed)
157
- - Default response size reduced from ~800KB-1MB to ~15KB for typical queries
158
- - Pagination with configurable page size (1-200, default 50)
159
- - Tools updated: `getStates`, `getAllSensors`, `searchEntities`, `getEntitiesByDomain`, `listEntities`
160
- - New parameters: `page`, `pageSize`, `includeAttributes` (set `includeAttributes=true` for full entity data)
161
- - Backward compatible: tools work without parameters using sensible defaults
162
- - **MCP Server Instructions**: Added server instructions for improved LLM tool selection
163
- - Instructions are sent during MCP initialization to guide LLMs on optimal tool usage
164
- - Dynamically generated based on enabled plugins (HA, Omada, AI)
165
- - Covers entity queries, device control, automation workflows, Omada operations, and cross-plugin integration
166
- - Follows MCP best practices for concise, actionable guidance
167
- - **Fix: Graceful Omada startup degradation**: Server no longer crashes when Omada credentials are invalid or controller is unreachable
168
- - Omada plugin disables itself with a warning instead of taking down the whole server
169
- - Home Assistant and AI plugins continue working normally
170
- - **Fix: Omada auth error clarity**: Error code `-44106` now explicitly hints to check `OMADA_OMADAC_ID` in addition to client credentials, since Omada returns the same code for both invalid credentials and an incorrect controller ID (e.g. after a controller version upgrade)
171
- - All 829 tests passing
172
-
173
- ### 1.0.0
174
- - **TP-Link Omada Network Integration**: Full support for Omada SDN controller
175
- - 24 new tools for network management (total tools: 60)
176
- - Site management: `omada_listSites`
177
- - Device management: `omada_listDevices`, `omada_getDevice`, `omada_searchDevices`, `omada_getSwitchStackDetail`, `omada_listDevicesStats`
178
- - Client management: `omada_listClients`, `omada_getClient`, `omada_listMostActiveClients`, `omada_listClientsActivity`, `omada_listClientsPastConnections`
179
- - Rate limiting: `omada_getRateLimitProfiles`, `omada_setClientRateLimit`, `omada_setClientRateLimitProfile`, `omada_disableClientRateLimit`
180
- - Security: `omada_getThreatList`
181
- - Network config: `omada_getInternetInfo`, `omada_getPortForwardingStatus`, `omada_getLanNetworkList`, `omada_getLanProfileList`, `omada_getWlanGroupList`, `omada_getSsidList`, `omada_getSsidDetail`, `omada_getFirewallSetting`
182
- - OAuth2 authentication with automatic token refresh
183
- - New environment variables: `OMADA_PLUGIN_ENABLED`, `OMADA_BASE_URL`, `OMADA_CLIENT_ID`, `OMADA_CLIENT_SECRET`, `OMADA_OMADAC_ID`, `OMADA_SITE_ID`, `OMADA_STRICT_SSL`, `OMADA_TIMEOUT`
184
- - **JWT Authentication**: Replaced static bearer tokens with JWT-based authentication
185
- - `MCP_AUTH_SECRET`: JWT signing secret (min 32 chars, HS256 algorithm)
186
- - Token validation with expiration support (`exp` claim)
187
- - User identification via `sub` claim for permission lookup
188
- - **Permission System**: Role-based access control with binary masks
189
- - Permission binary masks: ADMIN (1), CONFIGURE (2), CONTROL (4), QUERY (8), NOTIFY (16), AI (32) (sorted by criticality)
190
- - Role presets: NONE, READONLY, OPERATOR, CONTRIBUTOR, ADMIN, SUPERUSER
191
- - User-to-role mapping with id/sub based authentication
192
- - `MCP_PERMISSIONS_CONFIG` environment variable for configuration
193
- - Case-insensitive role lookup in configuration
194
- - **MCP SDK AuthInfo Integration**: Proper integration with MCP SDK authentication
195
- - Permissions passed via `authInfo.extra.permissions` to tool handlers
196
- - Tools enforce permission requirements (e.g., READONLY users denied CONTROL tools)
197
- - **Plugin Architecture**: Modular plugin system for extensibility
198
- - Home Assistant plugin (`HA_PLUGIN_ENABLED`)
199
- - Local AI plugin (`AI_PLUGIN_ENABLED`)
200
- - Omada network plugin (`OMADA_PLUGIN_ENABLED`)
201
- - **Environment Variable Cleanup**: Standardized naming conventions
202
- - Renamed `LOCALAI_PLUGIN_ENABLED` to `AI_PLUGIN_ENABLED`
203
- - Deprecated `MCP_SERVER_MODE`, `MCP_SERVER_PORT`, `MCP_SERVER_HOST`
204
- - **Minimal Logger**: Replaced pino with lightweight built-in logger
205
- - Supports plain, JSON, and GCP-JSON log formats
206
- - Zero external logging dependencies
207
- - All 688 unit tests + 44 integration tests passing
208
-
209
- ### 0.9.0
210
- - **Streamable HTTP Only**: Removed deprecated SSE transport, keeping only Streamable HTTP
211
- - Real-time HA event subscriptions still available at `/subscribe_events`
212
- - Preparing for future QUIC transport (Node.js 25+ experimental support)
213
- - All 648 tests passing
214
-
215
- ### 0.8.0
216
- - **Bearer Token Authentication**: Secure HTTP endpoints with bearer tokens
217
- - `MCP_AUTH_METHOD`: Set to `bearer` to enable authentication
218
- - `MCP_AUTH_TOKEN`: Comma-separated tokens for multiple clients
219
- - `WWW-Authenticate` header on 401 responses
220
- - Health check and OpenAPI endpoints skip authentication
221
- - **Server-Timing Header**: Response timing on all HTTP responses
222
- - `Server-Timing: total;dur=X` header (integer milliseconds)
223
- - Visible in browser DevTools Network tab
224
- - **Modular Auth Middleware**: Clean separation in `src/server/auth.ts`
225
- - All 648 tests passing
226
-
227
- ### 0.7.0
228
- - **Calendar Tools**: Access Home Assistant calendar entities
229
- - `listCalendars`: Get all calendar entities
230
- - `getCalendarEvents`: Get events from one or all calendars with date filtering
231
- - **Person Tracking Tool**: Track household members
232
- - `listPersons`: List all person entities with location state (home/away)
233
- - Optimized description for small LLM tool selection
234
- - Returns onsite/away counts and linked device trackers
235
- - Total tools increased from 34 to 37
236
-
237
- ### 0.6.0
238
- - **Mobile App Notifications**: Full support for Home Assistant mobile app notifications
239
- - `sendNotification`: Enhanced with action buttons, priority, images, videos
240
- - `listNotificationTargets`: Discover available mobile app notification targets
241
- - Android-specific options: priority, channel, LED color, vibration patterns
242
- - iOS-specific options: interruption level, badge count, critical alerts
243
- - Sticky and persistent notification support
244
- - **Fixed Automation API**: `createAutomation` now works correctly
245
- - Uses correct endpoint: `POST /config/automation/config/{id}`
246
- - Auto-generates timestamp-based IDs (like HA UI)
247
- - Auto-reloads automations after creation
248
- - Added optional `id` field to AutomationConfig type
249
- - **Refactored Tools Architecture**: Split monolithic registry into individual tool files
250
- - Each tool now in its own file under `src/tools/`
251
- - Improved maintainability and code organization
252
- - Shared schemas and utilities in `src/tools/common.ts`
253
- - Switched to NodeNext module resolution for TypeScript
254
- - All 310 tests passing
255
-
256
- ### 0.5.0
257
- - **Real-time SSE Event Subscription**: Subscribe to Home Assistant events via Server-Sent Events
258
- - Filter by domain, entity_id, or event types
259
- - Automatic WebSocket connection to Home Assistant
260
- - Keep-alive support for persistent connections
261
- - **Enhanced Automation Management**: Full automation lifecycle support
262
- - `triggerAutomation`: Manually trigger automations with variables
263
- - `enableAutomation`/`disableAutomation`/`toggleAutomation`: Control automation state
264
- - `createAutomation`: Create new automations via API
265
- - `deleteAutomation`: Remove automations
266
- - `reloadAutomations`: Reload from configuration
267
- - `getAutomationTrace`: View execution history
268
- - **Advanced Device Control Tools**:
269
- - `controlLight`: Brightness, color, color temperature, transitions
270
- - `controlClimate`: Temperature, HVAC mode, fan mode, presets
271
- - `controlMediaPlayer`: Playback, volume, mute controls
272
- - `controlCover`: Position and tilt control
273
- - `controlFan`: Speed, oscillation, direction
274
- - `activateScene`: Scene activation
275
- - `runScript`: Script execution with variables
276
- - `sendNotification`: Send notifications through Home Assistant
277
- - **Rate Limiting**: Built-in token bucket rate limiter
278
- - Configurable window and request limits
279
- - Per-IP tracking with automatic cleanup
280
- - Skip paths for health checks
281
- - **New Configuration Options**:
282
- - `MCP_SSE_EVENTS_ENABLED`: Enable/disable SSE
283
- - `MCP_SSE_EVENTS_PATH`: Customize SSE endpoint
284
- - `MCP_RATE_LIMIT_ENABLED`: Enable/disable rate limiting
285
- - `MCP_RATE_LIMIT_WINDOW_MS`: Rate limit window
286
- - `MCP_RATE_LIMIT_MAX_REQUESTS`: Max requests per window
287
- - Total tools increased from 16 to 33
288
-
289
- ### 0.4.0
290
- - **Extensible AI Provider System**: Refactored AI client to support multiple providers
291
- - New `src/localAI/` folder with provider-based architecture
292
- - Supports Ollama (native API) and OpenAI-compatible APIs (LocalAI, LM Studio, vLLM)
293
- - New environment variables: `AI_PROVIDER`, `AI_URL`, `AI_MODEL`, `AI_TIMEOUT`, `AI_API_KEY`
294
- - Refactored `haClient.ts` into modular folder structure (`src/haClient/`)
295
- - Split monolithic client into dedicated operation classes:
296
- - `request.ts` - HTTP request handler
297
- - `states.ts` - State operations (getStates, getState, getAllSensors)
298
- - `services.ts` - Service operations (callService, restartServer)
299
- - `entities.ts` - Entity operations (getEntitiesByDomain, searchEntities, listEntities, getDomainSummary)
300
- - `automations.ts` - Automation operations (getAutomations)
301
- - `history.ts` - History operations (getHistory, getSystemLog)
302
- - `updates.ts` - Update operations (getAvailableUpdates)
303
- - `config.ts` - Config operations (getVersion, getConfig, checkApi)
304
- - `index.ts` - Main HaClient class composing all operations
305
- - Improved code organization following modular architecture pattern
306
- - No changes to public API or tools - fully backward compatible
307
- - All 325 tests pass
308
-
309
- ### 0.3.0
310
- - Added 8 new tools: `getVersion`, `entityAction`, `listEntities`, `getDomainSummary`, `listAutomations`, `restartHomeAssistant`, `getSystemLog`, `checkUpdates`
311
- - Added MCP Resources support with 5 URI-based endpoints (`hass://entities`, etc.)
312
- - Added `entityAction` tool for simplified turn_on/turn_off/toggle operations
313
- - Added `listEntities` tool with domain, state, search, and limit filtering
314
- - Added `getDomainSummary` tool for domain statistics
315
- - Added `listAutomations` tool for automation management
316
- - Added `restartHomeAssistant` tool for server control
317
- - Added `getSystemLog` tool for viewing logbook entries (events, state changes)
318
- - Added `checkUpdates` tool to check for available updates (Core, Supervisor, OS, add-ons)
319
- - Total tools increased from 8 to 16
320
- - Enhanced type definitions for Automation, DomainSummary, HaVersion, LogbookEntry, UpdateInfo
321
-
322
- ### 0.2.0
323
- - Added AI-powered sensor analysis with Ollama
324
- - Added `getAllSensors` tool
325
- - Added `analyzeSensors` tool
326
- - Added `getHistory` tool
327
- - Added phi4:14b as recommended model (9.5/10, 6.65s avg)
328
- - Added qwen3:14b support (10/10 accuracy, 12.5s avg)
329
- - Added comprehensive security documentation
330
- - Added UFW firewall configuration guide
331
- - Added n8n workflow examples and import instructions
332
- - Updated to Node.js 20+ (v20.19.6) and npm 10.8+
333
- - Updated installation instructions with verified versions
334
- - Added Docker CLI workflow import method
335
- - Enhanced troubleshooting with network/firewall diagnostics
336
-
337
- ### 0.1.0
338
- - Basic Home Assistant integration
339
- - 5 core tools (getStates, getState, callService, getEntitiesByDomain, searchEntities)
340
- - Multiple transport modes (stdio, SSE, HTTP streaming)
341
- - Full TypeScript support
package/docs/COVERAGE.md DELETED
@@ -1,219 +0,0 @@
1
- # Test Coverage Report
2
-
3
- **Generated:** 2026-01-17
4
- **Tests:** 692 passed
5
- **Overall:** 61.14% statements, 54.14% branches, 56.47% functions, 62.52% lines
6
-
7
- ## Summary by Directory
8
-
9
- | Directory | Statements | Branches | Functions | Lines |
10
- |-----------|------------|----------|-----------|-------|
11
- | src | 85.00% | 93.61% | 78.57% | 86.11% |
12
- | src/haClient | 76.38% | 76.29% | 68.29% | 76.17% |
13
- | src/localAI | 100.00% | 100.00% | 100.00% | 100.00% |
14
- | src/localAI/providers | 100.00% | 83.33% | 100.00% | 100.00% |
15
- | src/permissions | 100.00% | 86.36% | 100.00% | 100.00% |
16
- | src/resources | 0.00% | 0.00% | 0.00% | 0.00% |
17
- | src/server | 93.22% | 82.75% | 100.00% | 93.10% |
18
- | src/tools | 95.16% | 76.19% | 100.00% | 95.16% |
19
- | src/tools/ai | 53.84% | 0.00% | 66.66% | 53.84% |
20
- | src/tools/homeassistant | 27.93% | 0.00% | 43.37% | 31.39% |
21
- | src/tools/omada | 9.47% | 0.00% | 0.00% | 9.47% |
22
- | src/tools/utils | 100.00% | 100.00% | 100.00% | 100.00% |
23
- | src/types | 0.00% | 0.00% | 0.00% | 0.00% |
24
- | src/types/homeassistant | 83.33% | 100.00% | 75.00% | 83.33% |
25
- | src/utils | 98.64% | 100.00% | 100.00% | 98.52% |
26
-
27
- ## Detailed Coverage
28
-
29
- ### src/
30
-
31
- | File | Statements | Branches | Functions | Lines | Uncovered |
32
- |------|------------|----------|-----------|-------|-----------|
33
- | config.ts | 84.61% | 93.61% | 78.57% | 85.71% | 106-107,116,323 |
34
- | version.ts | 100.00% | 100.00% | 100.00% | 100.00% | |
35
-
36
- ### src/haClient/
37
-
38
- | File | Statements | Branches | Functions | Lines | Uncovered |
39
- |------|------------|----------|-----------|-------|-----------|
40
- | automations.ts | 69.64% | 63.15% | 85.71% | 69.64% | 197,206,220-227 |
41
- | calendars.ts | 90.47% | 83.33% | 100.00% | 90.00% | 86-87 |
42
- | config.ts | 100.00% | 100.00% | 100.00% | 100.00% | |
43
- | devices.ts | 41.66% | 21.42% | 41.46% | 41.66% | 337-439,478-643 |
44
- | entities.ts | 100.00% | 95.23% | 100.00% | 100.00% | 116 |
45
- | history.ts | 100.00% | 90.00% | 100.00% | 100.00% | 34 |
46
- | index.ts | 68.29% | 100.00% | 56.66% | 68.29% | 167-230,294-315 |
47
- | request.ts | 100.00% | 95.65% | 100.00% | 100.00% | 107 |
48
- | services.ts | 100.00% | 100.00% | 100.00% | 100.00% | |
49
- | states.ts | 100.00% | 100.00% | 100.00% | 100.00% | |
50
- | updates.ts | 100.00% | 78.57% | 100.00% | 100.00% | 36,42 |
51
-
52
- ### src/localAI/
53
-
54
- | File | Statements | Branches | Functions | Lines | Uncovered |
55
- |------|------------|----------|-----------|-------|-----------|
56
- | index.ts | 100.00% | 100.00% | 100.00% | 100.00% | |
57
- | prompts.ts | 100.00% | 100.00% | 100.00% | 100.00% | |
58
-
59
- ### src/localAI/providers/
60
-
61
- | File | Statements | Branches | Functions | Lines | Uncovered |
62
- |------|------------|----------|-----------|-------|-----------|
63
- | base.ts | 100.00% | 87.50% | 100.00% | 100.00% | 90 |
64
- | ollama.ts | 100.00% | 75.00% | 100.00% | 100.00% | 61 |
65
- | openai.ts | 100.00% | 83.33% | 100.00% | 100.00% | 69 |
66
-
67
- ### src/permissions/
68
-
69
- | File | Statements | Branches | Functions | Lines | Uncovered |
70
- |------|------------|----------|-----------|-------|-----------|
71
- | index.ts | 100.00% | 86.36% | 100.00% | 100.00% | 46,51,61 |
72
-
73
- ### src/resources/
74
-
75
- | File | Statements | Branches | Functions | Lines | Uncovered |
76
- |------|------------|----------|-----------|-------|-----------|
77
- | index.ts | 0.00% | 0.00% | 0.00% | 0.00% | 16-213 |
78
-
79
- ### src/server/
80
-
81
- | File | Statements | Branches | Functions | Lines | Uncovered |
82
- |------|------------|----------|-----------|-------|-----------|
83
- | auth.ts | 91.11% | 81.48% | 100.00% | 90.90% | 126-129 |
84
- | common.ts | 100.00% | 100.00% | 100.00% | 100.00% | |
85
- | stdio.ts | 100.00% | 100.00% | 100.00% | 100.00% | |
86
-
87
- ### src/tools/
88
-
89
- | File | Statements | Branches | Functions | Lines | Uncovered |
90
- |------|------------|----------|-----------|-------|-----------|
91
- | common.ts | 98.00% | 76.47% | 100.00% | 98.00% | 39 |
92
- | index.ts | 83.33% | 75.00% | 100.00% | 83.33% | 40-41 |
93
-
94
- ### src/tools/ai/
95
-
96
- | File | Statements | Branches | Functions | Lines | Uncovered |
97
- |------|------------|----------|-----------|-------|-----------|
98
- | analyzeSensors.ts | 14.28% | 0.00% | 50.00% | 14.28% | 20-30 |
99
- | index.ts | 100.00% | 100.00% | 100.00% | 100.00% | |
100
-
101
- ### src/tools/homeassistant/
102
-
103
- | File | Statements | Branches | Functions | Lines | Uncovered |
104
- |------|------------|----------|-----------|-------|-----------|
105
- | automationControls.ts | 33.33% | 100.00% | 50.00% | 33.33% | 35,48-49,62-63 |
106
- | calendar.ts | 10.00% | 0.00% | 25.00% | 10.52% | 20-21,45-85 |
107
- | callService.ts | 20.00% | 0.00% | 50.00% | 20.00% | 18-22 |
108
- | controlClimate.ts | 6.66% | 0.00% | 50.00% | 6.66% | 20-62 |
109
- | controlCover.ts | 11.11% | 0.00% | 50.00% | 11.11% | 20-42 |
110
- | controlFan.ts | 6.66% | 0.00% | 50.00% | 8.33% | 20-38 |
111
- | controlLight.ts | 8.33% | 0.00% | 50.00% | 12.50% | 20-32 |
112
- | controlMediaPlayer.ts | 11.11% | 0.00% | 50.00% | 11.11% | 20-44 |
113
- | createAutomation.ts | 20.00% | 0.00% | 50.00% | 20.00% | 21-32 |
114
- | deleteAutomation.ts | 33.33% | 100.00% | 50.00% | 33.33% | 20-21 |
115
- | entityAction.ts | 16.66% | 0.00% | 50.00% | 16.66% | 20-29 |
116
- | getAllSensors.ts | 33.33% | 100.00% | 50.00% | 33.33% | 17-18 |
117
- | getAutomationTrace.ts | 33.33% | 0.00% | 50.00% | 33.33% | 20-21 |
118
- | getDomainSummary.ts | 33.33% | 100.00% | 50.00% | 33.33% | 17-18 |
119
- | getEntitiesByDomain.ts | 33.33% | 100.00% | 50.00% | 33.33% | 17-18 |
120
- | getHistory.ts | 33.33% | 0.00% | 50.00% | 33.33% | 20-21 |
121
- | getState.ts | 20.00% | 0.00% | 50.00% | 20.00% | 17-21 |
122
- | getStates.ts | 33.33% | 100.00% | 50.00% | 33.33% | 17-18 |
123
- | getVersion.ts | 33.33% | 100.00% | 50.00% | 33.33% | 17-18 |
124
- | index.ts | 100.00% | 100.00% | 100.00% | 100.00% | |
125
- | listAutomations.ts | 16.66% | 0.00% | 33.33% | 20.00% | 20-24 |
126
- | listEntities.ts | 33.33% | 100.00% | 50.00% | 33.33% | 20-21 |
127
- | listPersons.ts | 11.11% | 0.00% | 20.00% | 16.66% | 26-38 |
128
- | sceneAndScript.ts | 33.33% | 100.00% | 50.00% | 33.33% | 21-26,39-45 |
129
- | searchEntities.ts | 33.33% | 100.00% | 50.00% | 33.33% | 19-20 |
130
- | sendNotification.ts | 2.94% | 0.00% | 25.00% | 4.16% | 89-106,128-172 |
131
- | systemTools.ts | 33.33% | 0.00% | 50.00% | 33.33% | 20-21,34-35,48-49 |
132
- | triggerAutomation.ts | 33.33% | 100.00% | 50.00% | 33.33% | 20-21 |
133
-
134
- ### src/tools/omada/
135
-
136
- | File | Statements | Branches | Functions | Lines | Uncovered |
137
- |------|------------|----------|-----------|-------|-----------|
138
- | disableClientRateLimit.ts | 0.00% | 100.00% | 0.00% | 0.00% | 7-18 |
139
- | getClient.ts | 0.00% | 100.00% | 0.00% | 0.00% | 7-13 |
140
- | getDevice.ts | 0.00% | 100.00% | 0.00% | 0.00% | 7-13 |
141
- | getFirewallSetting.ts | 0.00% | 100.00% | 0.00% | 0.00% | 7-13 |
142
- | getInternetInfo.ts | 0.00% | 100.00% | 0.00% | 0.00% | 7-13 |
143
- | getLanNetworkList.ts | 0.00% | 100.00% | 0.00% | 0.00% | 7-13 |
144
- | getLanProfileList.ts | 0.00% | 100.00% | 0.00% | 0.00% | 7-13 |
145
- | getPortForwardingStatus.ts | 33.33% | 0.00% | 0.00% | 33.33% | 15-21 |
146
- | getRateLimitProfiles.ts | 0.00% | 100.00% | 0.00% | 0.00% | 7-13 |
147
- | getSsidDetail.ts | 33.33% | 100.00% | 0.00% | 33.33% | 14-20 |
148
- | getSsidList.ts | 33.33% | 100.00% | 0.00% | 33.33% | 13-19 |
149
- | getSwitchStackDetail.ts | 0.00% | 100.00% | 0.00% | 0.00% | 7-13 |
150
- | getThreatList.ts | 25.00% | 100.00% | 0.00% | 25.00% | 20-39 |
151
- | getWlanGroupList.ts | 0.00% | 100.00% | 0.00% | 0.00% | 7-13 |
152
- | index.ts | 0.00% | 100.00% | 0.00% | 0.00% | 35-81 |
153
- | listClients.ts | 0.00% | 100.00% | 0.00% | 0.00% | 7-13 |
154
- | listClientsActivity.ts | 33.33% | 100.00% | 0.00% | 33.33% | 14-20 |
155
- | listClientsPastConnections.ts | 33.33% | 100.00% | 0.00% | 33.33% | 22-28 |
156
- | listDevices.ts | 0.00% | 100.00% | 0.00% | 0.00% | 7-13 |
157
- | listDevicesStats.ts | 33.33% | 100.00% | 0.00% | 33.33% | 19-25 |
158
- | listMostActiveClients.ts | 0.00% | 100.00% | 0.00% | 0.00% | 7-13 |
159
- | listSites.ts | 33.33% | 100.00% | 0.00% | 33.33% | 10-16 |
160
- | searchDevices.ts | 33.33% | 100.00% | 0.00% | 33.33% | 12-18 |
161
- | setClientRateLimit.ts | 0.00% | 100.00% | 0.00% | 0.00% | 8-21 |
162
- | setClientRateLimitProfile.ts | 0.00% | 100.00% | 0.00% | 0.00% | 8-20 |
163
-
164
- ### src/tools/utils/
165
-
166
- | File | Statements | Branches | Functions | Lines | Uncovered |
167
- |------|------------|----------|-----------|-------|-----------|
168
- | pagination-schema.ts | 100.00% | 100.00% | 100.00% | 100.00% | |
169
-
170
- ### src/types/
171
-
172
- | File | Statements | Branches | Functions | Lines | Uncovered |
173
- |------|------------|----------|-----------|-------|-----------|
174
- | index.ts | 0.00% | 0.00% | 0.00% | 0.00% | |
175
-
176
- ### src/types/ai/
177
-
178
- | File | Statements | Branches | Functions | Lines | Uncovered |
179
- |------|------------|----------|-----------|-------|-----------|
180
- | index.ts | 0.00% | 0.00% | 0.00% | 0.00% | |
181
-
182
- ### src/types/homeassistant/
183
-
184
- | File | Statements | Branches | Functions | Lines | Uncovered |
185
- |------|------------|----------|-----------|-------|-----------|
186
- | errors.ts | 83.33% | 100.00% | 75.00% | 83.33% | 30-31 |
187
- | index.ts | 0.00% | 0.00% | 0.00% | 0.00% | |
188
-
189
- ### src/types/omada/
190
-
191
- | File | Statements | Branches | Functions | Lines | Uncovered |
192
- |------|------------|----------|-----------|-------|-----------|
193
- | index.ts | 0.00% | 0.00% | 0.00% | 0.00% | |
194
-
195
- ### src/utils/
196
-
197
- | File | Statements | Branches | Functions | Lines | Uncovered |
198
- |------|------------|----------|-----------|-------|-----------|
199
- | validations.ts | 100.00% | 100.00% | 100.00% | 100.00% | |
200
- | jwt.ts | 95.45% | 100.00% | 100.00% | 95.45% | 52 |
201
- | logger.ts | 100.00% | 100.00% | 100.00% | 100.00% | |
202
-
203
- ## Coverage Gaps
204
-
205
- ### High Priority (0% coverage)
206
- - `src/resources/index.ts` - MCP resources
207
- - `src/tools/omada/` - Most Omada tools (unit tests needed)
208
- - `src/types/` - Type re-exports (low priority)
209
-
210
- ### Medium Priority (<50% coverage)
211
- - `src/haClient/devices.ts` - 41.66%
212
- - `src/tools/homeassistant/` - Most tools 6-33%
213
- - `src/tools/ai/analyzeSensors.ts` - 14.28%
214
-
215
- ### Integration Tests
216
- - HomeAssistant: 21 tests
217
- - Omada: 19 tests
218
- - AI: 4 tests
219
- - **Total integration: 44 tests**