@iobroker/mcp-server 1.5.1 → 1.6.0

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
@@ -45,10 +45,13 @@ The adapter can be configured through the ioBroker admin interface using JSONCon
45
45
  endpoint is reachable without credentials — only use that on a trusted network or behind a reverse proxy
46
46
  that provides its own authentication. As a **web extension** the host `web` instance's authentication
47
47
  applies instead, so this switch has no effect there.
48
- - **Default User**: The ioBroker user whose permissions every MCP request runs with (default: `admin`).
49
- All object/state reads and writes performed by the tools are executed in the name of this user, so the
50
- user's ACLs are enforced. A plain name like `operator` is automatically expanded to `system.user.operator`.
51
- When running as a web extension and no user is set here, the host `web` instance's default user is used.
48
+ - **Default User**: The ioBroker user whose permissions MCP requests run with when authentication is
49
+ disabled (default: `admin`). With authentication enabled, every session runs with the permissions of the
50
+ user who logged in, and this setting is not used. All object/state reads and writes performed by the tools
51
+ are executed in the name of that user, so the user's ACLs are enforced. A plain name like `operator` is
52
+ automatically expanded to `system.user.operator`. As a web extension the host `web` instance's default user
53
+ applies. A session is bound to the user that opened it: requests of another user with the same session id
54
+ are answered with `404 Session not found`.
52
55
  - **Enable OAuth**: Offer the browser-based OAuth2 login that MCP clients such as Claude Desktop use when
53
56
  a connector is added. In standalone mode this requires *Enable Authentication*. As a **web extension**
54
57
  it also works, but the login is then provided by the host `web` instance, so OAuth has to be enabled
@@ -307,6 +310,10 @@ client calls it and its result is verified:
307
310
  Placeholder for the next version (at the beginning of the line):
308
311
  ### **WORK IN PROGRESS**
309
312
  -->
313
+ ### 1.6.0 (2026-10-24)
314
+ * (@GermanBluefox) With authentication, the tools run with the permissions of the logged-in user instead of the default user; a session can only be used by the user that opened it
315
+ * (@GermanBluefox) As a web extension, the default user of the `web` instance is used
316
+
310
317
  ### 1.5.1 (2026-10-24)
311
318
  * (@GermanBluefox) Transfer folders left behind by a killed process are removed at startup
312
319
 
@@ -7,7 +7,7 @@
7
7
  * them into an AI-friendly structure of rooms -> devices -> named controls.
8
8
  *
9
9
  * All object reads accept an optional `{ user }` so the detection respects the ACLs of
10
- * the configured default user (see McpServer).
10
+ * the user of the MCP request (see McpServer).
11
11
  */
12
12
  import { type ExternalDetectorState, Types } from '@iobroker/type-detector';
13
13
  /** Read options passed through to `getObjectViewAsync` (currently only the ACL user). */
package/build/devices.js CHANGED
@@ -45,7 +45,7 @@ exports.getAiFriendlyStructure = getAiFriendlyStructure;
45
45
  * them into an AI-friendly structure of rooms -> devices -> named controls.
46
46
  *
47
47
  * All object reads accept an optional `{ user }` so the detection respects the ACLs of
48
- * the configured default user (see McpServer).
48
+ * the user of the MCP request (see McpServer).
49
49
  */
50
50
  const type_detector_1 = __importStar(require("@iobroker/type-detector"));
51
51
  /**
package/build/index.d.ts CHANGED
@@ -17,8 +17,10 @@ export default class McpServer {
17
17
  private config;
18
18
  private readonly extension;
19
19
  private readonly routerPrefix;
20
- /** The ioBroker user whose permissions every MCP request runs with. */
20
+ /** The ioBroker user whose permissions MCP requests run with when no user is logged in. */
21
21
  private readonly defaultUser;
22
+ /** The user of the MCP request being processed, set by {@link runAs} for each HTTP request. */
23
+ private readonly requestUser;
22
24
  /** Default language used to localize device/room/function names. */
23
25
  private readonly language;
24
26
  /**
@@ -149,6 +151,25 @@ export default class McpServer {
149
151
  order: number;
150
152
  pro: boolean;
151
153
  };
154
+ /** Normalize a plain user name or a `system.user.*` id to the full id. */
155
+ private static toUserId;
156
+ /**
157
+ * The ioBroker user a request runs as: the logged-in user when the request was authenticated (by
158
+ * us or, as a web extension, by the host `web` instance), otherwise the default user.
159
+ */
160
+ private getRequestUser;
161
+ /** The user the current tool call runs as. Outside a request (embedded mode) the default user. */
162
+ private get user();
163
+ /**
164
+ * Process a request of a session with the permissions of the session's user. The SDK dispatches the
165
+ * contained messages within this call, so every tool reached from here sees that user in {@link user}.
166
+ */
167
+ private runAs;
168
+ /**
169
+ * Get the session of a request. A session is bound to the user that opened it: requests of another
170
+ * user are answered like an unknown session, so that a leaked session id gives no access.
171
+ */
172
+ private getSession;
152
173
  /** Handle client -> server messages (initialize, tools/call, ...). */
153
174
  private handleMcpPost;
154
175
  /** Handle server -> client SSE stream (GET) and session termination (DELETE). */
@@ -197,12 +218,12 @@ export default class McpServer {
197
218
  private getStates;
198
219
  /**
199
220
  * Write multiple states as one operation: the write permission of every state is verified first, so a
200
- * batch containing a single state the default user may not write fails as a whole and nothing is
221
+ * batch containing a single state the user may not write fails as a whole and nothing is
201
222
  * written. Other failures of single states are reported per item and do not abort the rest.
202
223
  */
203
224
  private setStates;
204
225
  /**
205
- * Verify that the default user may write every given state, mirroring the checks js-controller runs in
226
+ * Verify that the user of the request may write every given state, mirroring the checks js-controller runs in
206
227
  * `setForeignState`: the user must be able to read the object (needed for the type coercion in
207
228
  * {@link setState}) and the state ACL must allow writing — for an alias also on its write target.
208
229
  *
@@ -214,7 +235,7 @@ export default class McpServer {
214
235
  * The state ACL check of js-controller for `setState` on a single object.
215
236
  *
216
237
  * @param obj the state object (objects without ACL are not restricted by js-controller)
217
- * @param permissions the merged group permissions of the default user
238
+ * @param permissions the merged group permissions of the user
218
239
  */
219
240
  private isStateWritable;
220
241
  /**