Security
- The MCP endpoint now enforces the same module permissions as the REST API (#823). A member
configured with a module set to "no access" was refused by/api/v1but still served by the
matching MCP tool:list_tasksreturned the household's tasks for an account whose Tasks module
wasnone, and the write tools were open the same way. The reason was structural rather than a
missed check - the curated core tools run in-process against SQLite and never pass through the
Express middleware where the permission rule was spelled out, so nothing was there to apply it.
The rule now lives in one place (moduleAccessVerdictinserver/permissions.js) that both
surfaces call: a module onnonerefuses the read and the write tool, a module onreadrefuses
only the write tool, andtools/listhides what the account may not call, so an AI client is
never offered a tool its next request would deny. Token scopes and member permissions are two
independent limits and both have to agree - handing out a token can no longer widen what the
person behind it is allowed to do. Guest accounts for Shared expenses, which/api/v1confines to
the expense routes, likewise reach no core tool any more. The OpenAPI bridge was never affected:
it loops back through the REST layer and inherited every limit already. Self-hosters who kept the
MCP port away from ordinary accounts for this reason no longer need to.