✨ Features
- A drifted MCP-proxy catalogue now opens a maintenance issue instead of only logging.
- Access levels can be set for staff, and defaulted per group.
- Saving an access level sends only the cell that changed.
- The access table tells a lapsed connection apart from one that never existed.
- The access table separates a tool call from a browser visit.
- The Organization page is now one access table.
- Removing a person now works from the access table too.
- A grant can be read-only.
- MCP-proxy connectors now notice when their upstream tool catalogue moves.
- Removing a person from the gateway is now available on the Organization page.
- The DNS connector can tell that a subscription ENDED, not only that one is running.
- A configuration failure now tells the person who can fix it.
- Notification suppression holds under load and when the store is unavailable.
- An automation failing for a reason retrying cannot fix now reaches a person.
- A service account's set of permitted services can be changed after it is created.
- A generated spreadsheet can be made readable, and a missing action is no longer a dead end.
🔧 Improvements
- Every registered service now has a column on the access table, so a group or member access level can be set for any of them.
- The access table uses the full width of the pane.
- Guest access has no expiry date.
- The read / write / high-risk badge has one set of colours.
- A plain grant is read and write, and the Access legend fits on one line.
- A refused call now records the sentence that says what to do instead.
- A failure that is not a short code no longer breaks the record of it.
- A scope change records what it replaced.
- A connector capability can only disappear by a decision that is written down.
- A user search without a selector fails immediately.
- A change to advertising spend now reaches the maintainer.
- Actions that quietly called the wrong version of an API are now visible.
- Two actions whose names pointed the wrong way now say what to use instead.
- The weekly connector-spec refresh now reports what it cannot reach.
- An internal check that watches for credentials being handed back no longer trips over a variable name.
🐛 Fixes
- A locked access column now states a reason that is true.
- A column is no longer offered for a service the tool gate withholds.
- A service that delegates its OAuth scopes to sub-services inherits their sign-in restriction.
- The sign-in restriction now follows the connector's declared type rather than its name.
- A locked column names the missing credential before the restriction.
- A cell that cannot be used says why on hover, not only to a screen reader.
- Windmill catalogue drift now ignores a user's own scripts and flows in every spelling.
- The Notion tool catalogue on the services page matches the current upstream again.
- Transifex translated-file downloads now complete for large resources.
- The pinned name column no longer lets the table show through it.
- A group-wide access change now says on the page what it reached, and what to do when it reaches nobody.
- A group-wide access change explains itself differently per group, because the reason differs.
- A GitLab reference an agent adds on its own no longer creates activity in your name.
- The dead-test check no longer flags a test that guards on submodule content.
- The access table's Save row now actually docks.
- What a bulk change reaches is now shown, not only announced.
- A group heading's reported reach no longer outlives the state it describes.
- Internal: a regression guard for the access table no longer depends on which services an install happens to have.
- Internal: a premise check for the access table's footer rule no longer depends on the design-system submodule being checked out.
- A missing-permission notice no longer talks you out of the fix that works.
- A bulk change says which rows it reaches, and which it does not.
- The commit row on the access table stays reachable on a long page.
- Looking up a Slack user by email address works.
- The band headings on the team table read as the bulk controls they are.
- A guest's cell says whether its access level is its own.
- A level changed from a group default to the same value explicitly is recognised as a change and saved.
- The group heading reads as the control it is.
- A cell shows the access level that will apply without claiming it as the row's own.
- The band headings line up with the switches they carry.
- The startup storage report answers from the same policy the encryption sweep enforces.
- Setting an access level works for every service the table shows.
- Self-healing survives an over-long agent output line.
- Tool calls now reach the activity signal.
- Deleting a user removes every trace the access table reads.
- Importing a guest snapshot rejects a record whose address does not match its own key.
- The access table is the only roster.
- Every row in the access table reports the same status the same way.
- The group a row belongs to stays readable when the table is scrolled sideways.
- Access table: the invite, the cell saves and the removal entry now work.
- Granting and withdrawing admin works on every install.
- A guard for inline JavaScript that queries controls a page no longer renders.
- Withdrawing admin access also ends the sessions that carry it.
- Guest access is no longer lost when a row is saved.
- Withdrawing admin access now reaches every record the person holds.
- Session cleanup on user deletion now reaches unencrypted session records too.
- Access table edits register every change.
- Admin access set by the deployment is no longer withdrawable from the page.
- The access table's Save control keeps its place.
- Bulk-granting a service keeps each person's existing access level.
- Withdrawing admin access is only declined for addresses the deployment itself lists.
- A cleared access cell no longer explains a grant it no longer holds.
- Slack sending actions now state who the message went out as, instead of leaving it to be inferred from a bot profile.
post_messagenow documents what its legacyas_userparameter actually does.- Refreshed the bundled tool catalogues for five MCP-proxy connectors, and discovery calls now verify them.
- Windmill connector: refreshed tool catalogue and corrected guidance on preview runs.
- MCP-proxy tool catalogues are now cached as intended, cutting one upstream round-trip per proxied call.
- MCP-proxy tool catalogues are cached per user, and dropped on a hot reload.
- The SSE health endpoint now reports an unavailable MCP server as unavailable.
- A logged upstream failure now names the class that failed.
- A test fixture no longer leaves later tests reading a deleted directory.
- A value passed to a saved analytics question now binds to exactly one parameter, or to none.
- A Slack lookup by email now tries every domain the deployment treats as its own.
- An unattended caller is now recognised by what it is, not by whether its registration happens to be readable.
- A notice now names the change its condition actually needs.
- Creating and editing a service account agree about a service name.
- Two connectors announced a default app without naming one.
- A value passed to a saved Metabase question now actually reaches the query.
- Looking someone up by email tries every domain the deployment uses.
- Registering an automation accepts a script as well as a flow.
- Parameter values reach a saved question.
- Looking someone up by email tries every domain the deployment uses.
- Registering an automation accepts a script as well as a flow.
- Parameter values reach a saved question.
- Asking a proxied connector what it can do now has an answer.
- One upstream failure now reads the same way in the audit log whatever channel it arrived over.
- A saved analytics question that expects parameters can now be run, and says what it needs when it cannot.
- Figma webhook actions work, and an API version can no longer hide in a connector's base address.
- Failed audit rows name the upstream cause.
- Recorded failure reasons no longer carry identifiers.
- A row's severity is decided by its own fields, not by its wording.
- Connector coverage is checked against the route an action actually calls.
- Debug endpoints no longer take a subject from the query string.
- App Store Connect actions now reach the API version they name.
- You now hear when the bug you reported is fixed.
- A merge that did not schedule itself no longer reports that it did.
- An automation allowed to read a calendar can now read the calendar.
- A permission for one Google service no longer leaks into another through a helper step.
- A failure in the gateway is no longer excused by the words it happens to contain.
- A service that stops answering is no longer reported to the rest of the gateway as a mistake on our side.
- Our own connection pool running dry is no longer mistaken for another service being slow.
- A failure caused by another system is no longer reported as a bug in the gateway — and a real bug is no longer mistaken for one.
- Failures that time out are now reported under their own name.
- An outage at another service no longer files a bug report against the gateway.
- Whether a problem at another service counts as recurring is now measured by time, not by attempts.
- A connection that dies mid-request is no longer reported as a fault in the gateway.
- A failure report is judged by what the code wrote, not by words that happen to appear in it.
- Disconnecting Metabase now ends the session inside Metabase too, not only in the gateway.
- A disconnect no longer depends on the other service answering.
- Disconnecting a credential-login service now also drops the session it had cached.
- Disconnecting a service now clears every session cached from that credential, not only one kind.
- A disconnect can no longer be overtaken by a request that was already in flight.
- Disconnecting a service now finds every session it cached, including ones minted before a setting changed.
- A disconnect that cannot fully clear a session now says so, and survives interruption and concurrency.
- Disconnecting the OTOBO connector now clears its session on every worker, not just one.
- A session being created at the moment of a disconnect is much less likely to slip past it.
- A session created just before a disconnect can no longer be handed out after it.
- A disconnect no longer trusts a session record it cannot verify.
- Refusing a stored session no longer risks deleting a newer one.
Full changelog: https://mcpgate.de/changelog/
Docker: docker pull mcpgate/mcpgate:2.0.2572