Claude Tag gives a Slack channel an agent, and an access bundle gives that agent credentials. The idea is right: name a set of connections, attach it to a scope, and everyone in that channel acts through it.
The granularity is the problem. A bundle can say which tools Claude reaches. It cannot say how far into any one of them.
Anthropic's own docs are direct about it:
A connection has no setting for which pages, folders, or projects Claude can reach inside a tool. The connection's reach is whatever the connected account can access in that tool. To narrow Claude to a subset, narrow the account.
So scope is not a setting. It is a second service account created in the vendor, a second credential, and its own bundle to keep it out of every other channel.
Do that for four channels and three tools and you are maintaining twelve identities to express twelve lines of policy. Most people do not. They connect one account with broad reach and over-provision every channel that touches it.
How Lanes Link does it
- One row per connection, with its own rules. A profile's
grants:names each connection as<provider>.<id>and carries its ownallowanddenyglobs. Read one mailbox and write the other is a thing you can actually write down, on the same profile, without a second account anywhere. - A connection with no row is absent, not denied. An agent asking that profile never learns the connection exists. An unused connector is not something to hope nobody talks their way into, because it is not in the tool list.
- Narrowing is a line in a file.
lanes link policy deny gmail.send --profile supporttakes effect at once. A deny always beats an allow whatever the order, an absent rule grants nothing, and a rule can carryexpires_atfor access you want to hand out for an afternoon. - One connection in the bundle, however many accounts behind it. The bundle holds a single Bearer credential and a single allowed host. Everything past that host is your profile's business, so connecting a twelfth account changes nothing in the admin console.
- The token is the profile.
auth.token_reflives inside the profile file, so the credential a channel holds resolves to exactly one profile's grants. Two channels, two tokens, two profiles, and no shared ceiling between them. - One audit log across every provider. Append-only, one record per invocation with refusals included, hash-chained, and
lanes link audit verifywalks the chains. A bundle leaves you reading each vendor's own log, where every call is attributed to the same service account. - The same grants serve every other client. Claude Code, Codex, claude.ai, ChatGPT, a phone, and a Slack channel read one profile. An access bundle only ever applies in Slack, and personal claude.ai connectors only ever apply in DMs.
The workflow
One profile per channel scope, named after the work rather than the team: support, data-readonly, deploys. Grant narrowly, then let refusals tell you what the channel actually needs.
lanes link audit tail --denied-only is a better specification than any guess you make up front. A refused call is the boundary working, not an obstacle to route around.
After that the operations are small. Adding an account is connect. Widening is one policy line. Revoking is lanes link token rotate, which invalidates what that channel holds without touching another channel.
None of it is a trip through the admin console, and none of it is a new identity in someone else's product.
Set it up
Claude Tag runs its sessions in a cloud sandbox Anthropic hosts, and it can only attach an MCP server it can reach at a URL. A loopback endpoint on your laptop is not reachable, so this is the deployed path:
$ bun install -g @lanes-sh/link
$ lanes link profile add support
$ lanes link deploy --workspace cloud
$ lanes link connect zendesk --id helpdesk --workspace cloud
$ lanes link grant add zendesk.helpdesk --profile support --workspace cloud
$ lanes link outputs --workspace cloudThen:
-
Answer
public, and yes to a remote connector. Two of the deploy questions decide whether an agent can reach the endpoint at all. Theiamdefault has Cloud Run demand a Google-signed token no MCP client can mint, and the second answer is what lets the endpoint issue its own. -
Grant only what the channel does.
lanes link grant addper connection, thenpolicy denyfor the verbs it should not have. Everything you do not name stays denied. -
Add it to the bundle. In Claude Tag's admin settings, the Plugins tab takes a plugin whose
.mcp.jsonpoints at the endpoint URL. The Credentials tab takes Custom tool, credential type Bearer, the token fromoutputs, and Allowed websites set to the endpoint host.That pair is the documented way to attach a remote MCP server. An
.mcp.jsonin a repository Claude clones is not loaded. -
Attach the bundle to the channel, then read the log. Ask Claude in a new thread for a small read to confirm the credential is live, and watch
audit tail --denied-onlyfor the first week to find a scope that is too tight.
members: gates who may mint a token, not who may type @Claude in a channel whose bundle already holds one. What changes is the shape of the thing in the bundle: a credential you can narrow per connection and per capability, rather than an account whose reach you can only reduce by making a different account.Further reading
- Lanes Link vs Claude Tag: where the two access models overlap, and the one place they diverge.
- Give agents scoped access, with an audit trail: deny-by-default and the audit record, in full.
- Keep work and personal accounts apart: the profile boundary this leans on.
- Lanes Link: one endpoint for everything an agent needs: the permission model and the design behind it.
Browse the source at lanes-sh/link, Apache-2.0, or read the announcement.