Grant connector access by label
Aperture connectors are in public alpha. The connectors grant syntax and the connectors configuration section may change. The mcp_tools, mcp_resources, and mcp_templates grant fields are deprecated. Use the connectors field instead.
A label is a flat string you attach to a connector. A grant pattern of label:<name> matches every connector carrying that label, so one grant covers a whole group of connectors and keeps working as you add more. Labels complement the fully qualified name (FQN) patterns described in Grant access to MCP tools: FQN patterns target one connector, and labels target a set.
Every new Aperture instance starts with a label grant already in place. The default configuration grants label:system, which is how the built-in Aperture tools reach users without any setup. That grant is also the working example you can copy: the pattern that carries the built-in tools is the same pattern you use for your own connectors.
Labels do not change how any existing configuration behaves. Grants that name connector IDs continue to work exactly as before, and an unlabeled connector is reachable only through its ID.
Prerequisites
Before you begin, make sure you have the following:
- An Aperture instance with at least one configured connector.
- Admin access to the Aperture dashboard.
- Users who already have a
rolegrant and network access to the Aperture device. If not, complete Grant access to models first.
Step 1: Label your connectors
Decide what the labels represent before you apply them, because a grant is only as clear as the label it names. Aperture reserves no vocabulary other than system and validates only the characters you use, so the scheme is yours to choose. Three schemes cover most instances:
| Purpose | Examples |
|---|---|
| How sensitive the connector's data is | public, private, restricted |
| Which team owns or needs the connector | eng, marketing, sales |
| Where the connector came from | system, applied automatically to built-in connectors |
To label a connector in the dashboard:
Open the Aperture dashboard and go to Administration > Connectors.
- Select the connector you want to label, then edit it.
- In the Labels field, enter a label and press Enter. Repeat for each label. A connector can carry as many labels as you need.
- Save the connector.
The Labels field suggests labels already in use on other connectors. Choosing a suggestion instead of typing a near-duplicate keeps the instance on one vocabulary, which matters because a grant matches a label exactly. The connector list shows a Labels column, so you can review the whole vocabulary at a glance.
You can also set labels directly in the configuration with the labels field:
{
"connectors": {
"servers": {
"salesforce": {
"protocol": "mcp",
"url": "https://api.salesforce.com/platform/mcp/v1/platform/sobject-all",
"labels": ["sales", "restricted"]
},
"analytics": {
"protocol": "mcp",
"url": "http://mcp-analytics.example.ts.net:8080/v1/mcp",
"labels": ["eng", "restricted"]
}
}
}
}
Each label must match [a-zA-Z0-9][a-zA-Z0-9._-]*. A label starts with a letter or digit and contains only letters, digits, dots, underscores, and hyphens. Slashes are rejected because they would be ambiguous with the slash-separated FQN patterns. Dots and hyphens are legal, so you can namespace a label as team.eng when a flat vocabulary would collide, but a namespace convention is never required.
Step 2: Grant access by label
Add label:<name> patterns to the connectors field of a grant. The following example gives the sales team every connector labeled sales, and gives everyone the built-in tools through the default label:system grant:
{
"grants": [
{
"src": ["*"],
"app": {
"tailscale.com/cap/aperture": [
{ "role": "user", "models": "**" },
{ "connectors": ["label:system"] }
]
}
},
{
"src": ["group:sales"],
"app": {
"tailscale.com/cap/aperture": [
{ "connectors": ["label:sales", "docs/tools/*"] }
]
}
}
]
}
Matching group: sources, like group:sales in the example above, requires visible groups enabled for the Aperture device.
Two properties of label patterns determine what a grant actually covers:
- A label match is exact, not a glob. Unlike FQN patterns,
label:patterns do not accept*or**. The patternlabel:team.*matches nothing, and so does any other wildcard form. This mirrors howtag:andgroup:behave in Tailscale grants. - A label match covers the entire connector. When a label matches, the user reaches every category and every resource that connector exposes: tools, resources, templates, and HTTP proxy access. Labels have no per-tool granularity. To grant a single tool or a read-only slice, use an FQN pattern that names the connector ID, such as
"salesforce/tools/get_*".
You can mix both pattern styles in one connectors array, as the group:sales grant above does.
The grant examples on this page use Aperture configuration syntax, where the dst field is not required because the destination is the Aperture device itself. If you define grants in the tailnet policy file instead, you must include a dst key specifying the Aperture device (for example, "dst": ["tag:aperture"]). Omitting dst in a tailnet policy file grant causes the grant to silently have no effect. For a full comparison and conversion steps, refer to Aperture grants vs. tailnet policy file grants.
Step 3: Verify access
Confirm the labels first, then confirm the access they produce.
-
On the Connectors page under Administration, check the Labels column. A label that failed validation never saves, so a label missing from this column was never applied.
-
Sign in to the dashboard as a user the grant matches, then open the Connectors page under My Aperture. The connector appears with its labels listed, rather than showing a No access status.
-
List tools through the MCP endpoint from a device whose tailnet identity matches the grant:
curl http://<aperture-hostname>/v1/mcp \ -H "Content-Type: application/json" \ -d '{"jsonrpc": "2.0", "method": "tools/list", "id": 1}'The response contains the connector's prefixed tools, for example
salesforce_query.
If the tools do not appear, the label in the grant and the label on the connector differ. Because matching is exact, label:Sales does not match a connector labeled sales, and a trailing space or a typo grants nothing rather than reporting an error. Compare the two strings character for character.
Labels widen access, never restrict it
Aperture grants are additive and allow-only, and label grants are no exception. A label grant adds access to the connectors that carry the label. No label subtracts access, and no label acts as a gate.
This matters most for sensitivity vocabularies. Labeling a connector restricted documents the intent, but it does not enforce it. A user holding {"connectors": ["**"]} still reaches that connector, because the broad pattern already grants it. To genuinely limit a sensitive connector, remove the broad wildcard grants that reach it and grant it narrowly by label or by connector ID instead.
For the full model behind additive grants and how Aperture resolves overlapping ones, refer to How Aperture grants work.
The reserved system label
Aperture applies the system label to its built-in connectors automatically, which is what the default label:system grant matches. The label states provenance only. Aperture ships no sensitivity labels, because how sensitive a connector is depends on your deployment rather than on the connector.
Because the shipped default configuration grants label:system to every user, the label is reserved and you cannot apply it to your own connectors:
- The dashboard rejects
systemin the Labels field while you type it, and the API rejects it on save. - A configuration that already carries the label on a connector under
connectors.serversstill loads, with a warning, and Aperture strips the label before it evaluates any grant. A hand-edited or upgraded instance keeps working, and the label never widens access to a connector you did not intend to share.
The label remains valid under connectors.system_labels, which exists to relabel built-in connectors:
{
"connectors": {
"system_labels": {
"aperture": ["system", "public"]
}
}
}
system_labels replaces a built-in connector's labels rather than adding to them. If you omit system from the list, the default label:system grant no longer matches that connector, and its built-in tools become unreachable until you grant them another way.
Next steps
- Grant access to MCP tools to target individual tools, resources, templates, and proxy paths by connector ID.
- Refer to the connectors reference for the
labelsfield, thesystem_labelsfield, and the full grant pattern list. - How connectors work explains the access control model that labels participate in.
- Set up admin access to control who can edit connectors and their labels.