@coffeerunhobby/mcp-ha-connect 2.4.6 → 2.4.7

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.
package/README.md CHANGED
@@ -77,7 +77,7 @@ high-value questions an LLM can actually answer about your network:
77
77
  > above through two tools — `omada_browse` + `omada_read` — keeping the tool-schema budget
78
78
  > small for low-context models. See the Omada tool tables below for the full eager surface.
79
79
 
80
- ## Available Tools (69 Total)
80
+ ## Available Tools (75 Total)
81
81
 
82
82
  ### Home Assistant Tools (38)
83
83
 
@@ -251,7 +251,7 @@ Lets the controller enforce a schedule itself (e.g. a curfew) instead of a daily
251
251
  | `omada_getSiteNtpStatus` | Get the site's NTP server configuration and status |
252
252
  | `omada_setSiteNtpServers` | Replace the site's NTP server list (needs `CONFIGURE`; `dryRun` previews the change) |
253
253
 
254
- ### Vendor-neutral Network Tools (9)
254
+ ### Vendor-neutral Network Tools (15)
255
255
 
256
256
  The `net_` tools describe networks the same way for every controller vendor: one shared model, with an adapter per
257
257
  vendor (TP-Link Omada today; UniFi and MikroTik are planned). Each adapter says per feature whether it is native,
@@ -268,9 +268,16 @@ one is set in the controller's web UI. Reads need `QUERY`, changes `CONFIGURE`.
268
268
  | `net_createNetwork` / `net_updateNetwork` / `net_deleteNetwork` | Create or change a VLAN with its gateway and DHCP range. The network the controller is on is protected; delete is refused while a Wi-Fi network, port profile, reservation or rule uses it |
269
269
  | `net_listWifi` | Wi-Fi networks: network, bands, security, isolation, MAC filter |
270
270
  | `net_createWifi` / `net_updateWifi` / `net_deleteWifi` | Create or change an SSID on a given network (bands, WPA2/WPA3, PMF, isolation, hidden, 802.11r, MAC filter), or reset its password to a random one |
271
-
272
- On Omada, network isolation, a "guest" network type, switching IPv6 on, and WPA2/WPA3 mixed mode are not available
273
- through the API and are refused. Rules arrive in 2.4.7, switch ports and mDNS in 2.4.8.
271
+ | `net_listRules` | Traffic rules in evaluation order (the first match decides); rules the model can't express are shown read-only (`foreign`, with the reason) |
272
+ | `net_createRule` / `net_updateRule` / `net_deleteRule` / `net_moveRule` | Allow or block traffic from networks, a group or addresses to networks, a group, addresses (optionally on ports) or the internet, at a chosen position. **Stateful:** a block stops new connections, replies to connections started from the other side still pass ("block IoT → Home" lets Home still reach IoT). Addresses given in a rule become a group the rule owns and removes with it. A change after which the controller (and this server) could no longer reach the internet, in its end state or on the way there, is refused |
273
+ | `net_listGroups` | Address groups (usable in rules) and MAC groups (Wi-Fi allow/deny lists) |
274
+
275
+ On Omada, a network isolation flag (use a block rule instead), a "guest" network type, switching IPv6 on, and WPA2/WPA3
276
+ mixed mode are not available through the API and are refused. Rules are gateway ACLs (the gateway routes between the
277
+ VLANs): LAN to LAN between your networks, LAN to WAN towards the internet. Refused with the reason: the gateway itself as
278
+ a destination (no API option for its own addresses), one device by MAC (give its address), a Wi-Fi network as the
279
+ source, rules that also match replies, schedules (the `omada_` time-range tools do those) and port ranges. Switch
280
+ ports and mDNS arrive in 2.4.8.
274
281
 
275
282
  ### AI Tools (1)
276
283
 
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Omada adapter for the vendor-neutral network model (src/net/model.ts).
3
3
  *
4
- * 2.4.5 covers networks (LAN networks / VLANs) and Wi-Fi (SSIDs). Rules, groups, switch
5
- * ports and mDNS arrive with 2.4.7 and 2.4.8; until then those calls fail with
6
- * NetError UNSUPPORTED.
4
+ * 2.4.5 covers networks (LAN networks / VLANs) and Wi-Fi (SSIDs); 2.4.7 rules (gateway
5
+ * ACLs, see omadaRules.ts) and listing groups. Switch ports and mDNS arrive with 2.4.8;
6
+ * until then those calls fail with NetError UNSUPPORTED.
7
7
  *
8
8
  * Omada specifics handled here:
9
9
  * - networks have no "guest" purpose and no isolation flag in the API (guest is per
@@ -14,7 +14,7 @@
14
14
  * - Omada lists every SSID again under a pseudo WLAN group "gateway" without detail.
15
15
  */
16
16
  import type { OmadaClient } from '../../omadaClient/index.js';
17
- import { type ApplyResult, type Capabilities, type Change, type Client, type Network, type NetworkController, type Plan, type ProtectedResources, type Reservation, type Wifi } from '../model.js';
17
+ import { type ApplyResult, type Capabilities, type Change, type Client, type Group, type Network, type NetworkController, type Plan, type ProtectedResources, type Reservation, type Rule, type Wifi } from '../model.js';
18
18
  export interface OmadaAdapterOptions {
19
19
  siteId?: string;
20
20
  /** The controller's host name or address (host of OMADA_BASE_URL): its network is protected. */
@@ -49,8 +49,8 @@ export declare class OmadaNetworkController implements NetworkController {
49
49
  listReservations(): Promise<Reservation[]>;
50
50
  listPortProfiles(): Promise<never>;
51
51
  listPorts(): Promise<never>;
52
- listRules(): Promise<never>;
53
- listGroups(): Promise<never>;
52
+ listRules(): Promise<Rule[]>;
53
+ listGroups(kind?: Group['kind']): Promise<Group[]>;
54
54
  getMdnsRepeater(): Promise<never>;
55
55
  plan(change: Change): Promise<Plan>;
56
56
  apply(plan: Plan, options?: {
@@ -58,6 +58,60 @@ export declare class OmadaNetworkController implements NetworkController {
58
58
  }): Promise<ApplyResult>;
59
59
  private planWith;
60
60
  private build;
61
+ private ruleWorld;
62
+ /** The rule as the model sees it, with its raw ACL; a rule the model can't express is refused. */
63
+ private editableRule;
64
+ private checkPosition;
65
+ /**
66
+ * Refuses a change if any rule list it passes through (the end state, and the staged
67
+ * one where the rule is switched off) could expose some of the controller's (and this
68
+ * server's) internet traffic to a block that doesn't reach it today (controllerRisk).
69
+ * Waived only when the controller is certainly cut off already.
70
+ */
71
+ private guardController;
72
+ private buildRuleCreate;
73
+ private buildRuleUpdate;
74
+ private buildRuleDelete;
75
+ private buildRuleMove;
76
+ /**
77
+ * Existing ids for an endpoint, or the id of the group created for it. The group is
78
+ * tracked by its (unique) name before it is created, so a create whose answer or
79
+ * read-back got lost can still be found and undone.
80
+ */
81
+ private materialize;
82
+ /**
83
+ * Undoes a create that failed part-way and returns the error to throw. A create that
84
+ * was sent may have happened even if it reported an error: the rule is looked up by
85
+ * its description and removed before its groups. When that can't be confirmed, the
86
+ * groups stay (a live rule must never point at deleted groups) and the error says so.
87
+ */
88
+ private undoCreate;
89
+ /**
90
+ * Undoes an update that failed part-way and returns the error to throw: puts the rule
91
+ * back as it was (if the change may have been written) and removes the groups made
92
+ * for it, unless the rule might still point at them.
93
+ */
94
+ private undoUpdate;
95
+ /** Puts the rule order back after a move that failed (it may have happened anyway); returns the error to throw. */
96
+ private restoreOrder;
97
+ /** Deletes groups made during a failed change (found by name when the id is unknown); returns what it couldn't remove. */
98
+ private dropGroups;
99
+ /**
100
+ * Deletes every group a net_ rule owned that no ACL (gateway, switch or access point)
101
+ * references any more. Run after each successful rule change, so a cleanup that failed
102
+ * once is finished by the next change; a failure here is a warning, not an error (the
103
+ * change itself is done). Writes are serialized per site, so no rule is half-created
104
+ * meanwhile.
105
+ */
106
+ private sweepOwnedGroups;
107
+ private sortedAcls;
108
+ /** Moves one rule to `position` (1 = first); the others keep their order. */
109
+ private reorder;
110
+ /**
111
+ * The result of a change that is done: the rule as it reads back, plus warnings. A
112
+ * failed read-back is a warning, never an error: the change is already applied.
113
+ */
114
+ private done;
61
115
  private buildNetworkCreate;
62
116
  private buildNetworkUpdate;
63
117
  private buildNetworkDelete;