Connectors

Last validated:

Aperture connectors are currently in alpha.

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.

Connectors let Aperture reach external MCP servers and HTTP APIs through a single authenticated gateway. Aperture handles credential injection, request proxying, and access control, so agents interact with one proxy instead of managing individual service connections. Connectors complement providers: providers route model requests, and connectors route tool calls and API requests.

Connectors require the connectors feature flag. The get started guide covers enabling it.

Set up connectors

Configure connectors, credentials, and access. These tasks require admin access to the Aperture configuration.

Use connectors

Authorize and call connectors that an admin has configured. These tasks need only access to the Aperture dashboard.

  • Use a connector - Authorize a connector, discover and call its tools, and reconnect when access expires.

Understand connectors

Learn the model behind connectors before you configure one.

  • How connectors work - Understand the connector model, the MCP and HTTP protocols, authentication, and access control.

Look up exact field definitions and related setup tasks.

To set up connectors in Aperture, enable the feature flag, add connector entries, grant users access, and verify the connection.

Step 1: Enable the feature flag

Open the Settings page of the Aperture dashboard and add the connectors feature flag to your configuration:

{
  "flags": {
    "connectors": {"value": true}
  }
}

Step 2: Add connectors

For connectors that authenticate (especially oauth2_authorization_code and oauth2_client_credentials), complete the upstream setup first. Create the OAuth application or API credentials on the MCP server or API provider, then register Aperture's callback URL (https://<aperture-hostname>/aperture/auth/<connector-id>/callback) and note the client ID, client secret, scopes, and token URLs. Provider setup is often the most error-prone part of configuring a connector, and provider documentation varies in quality. You supply these values when you add the connector below.

You can add connectors in two ways:

  • From the verified registry: The Aperture dashboard includes a connector picker with pre-configured defaults for Salesforce, Atlassian, and Slack. Select a provider, and Aperture pre-fills the URL, auth URLs, token URLs, and scopes. You only need to supply your OAuth client credentials.
  • Custom configuration: Add a connectors section with one or more server entries. Each entry needs a protocol ("mcp" or "http") and a url.

The following example adds an unauthenticated MCP server and an authenticated HTTP API:

{
  "connectors": {
    "servers": {
      "local": {
        "protocol": "mcp",
        "url": "http://localhost:8185/v1/mcp"
      },
      "github": {
        "protocol": "http",
        "url": "https://api.github.com",
        "description": "GitHub REST API (read-only)",
        "auth": {
          "type": "bearer_token",
          "secret": "github_pat_example"
        }
      }
    }
  }
}

Each key in the servers map is a connector ID that Aperture uses as a name prefix. For the configuration above, tools from the local MCP server appear as local_search, local_query, and similar. Connector IDs must contain only letters and digits, starting with a letter. The IDs tailscale, internal, and aperture are reserved and cannot be used.

The Aperture host uses its tailnet HTTP client for connections, so you can use MagicDNS hostnames (for example, http://mcp-server.example.ts.net:8080/v1/mcp) without additional network configuration.

Step 3: Grant access

Aperture is deny-by-default. Without grants, users cannot access any connector capabilities. Add grants in the grants section of your configuration.

The following example grants all users access to the built-in Aperture tools and all capabilities from every configured connector:

{
  "grants": [
    {
      "src": ["*"],
      "app": {
        "tailscale.com/cap/aperture": [
          {"connectors": ["aperture/**"]},
          {"connectors": ["**"]}
        ]
      }
    }
  ]
}

Connector grants use the connectors field with "connectorID/category/resource" FQN glob patterns. The valid categories are tools, resources, templates, and proxy:

  • "local/tools/*": all MCP tools from the local connector.
  • "local/**": all capabilities (tools, resources, templates) from the local connector.
  • "github/proxy": proxy access to the github HTTP connector.
  • "github/**": all access to the github connector (proxy and any future categories).
  • "**": all capabilities from all connectors.

Both MCP and HTTP connectors require grants. Without a matching connectors grant, users cannot access any connector capabilities.

Refer to the grants configuration reference for the full grants syntax.

Step 4: Verify the connection

First, verify the connector in Aperture before you point an MCP client or agent at it. Open the Connectors page in the dashboard, select the connector, and confirm its status shows Ready and that the capability list contains the tools, resources, and templates you expect. The Connectors page probes the upstream URL, so a connector that cannot reach its server or list its capabilities surfaces the error here. Confirming the connector works in Aperture first removes most of the confusion that occurs when a tool fails from the agent side.

Once the connector shows Ready, verify access from a client. For MCP connectors, configure your MCP client to use the Aperture URL and list available tools:

curl http://<aperture-hostname>/v1/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc": "2.0", "method": "tools/list", "id": 1}'

The response should contain a tools array with prefixed entries from your configured connectors (for example, local_search).

For HTTP connectors, send a request through the Aperture proxy path:

curl http://<aperture-hostname>/v1/connectors/github/user

Aperture forwards the request to https://api.github.com/user and injects the configured bearer token automatically.

Common scenarios

The following sections describe common tasks related to connectors.

Connect to an authenticated MCP server

Use the auth field to configure credentials for MCP servers that require authentication. The following example uses OAuth 2.0 client credentials for a machine-to-machine connection:

{
  "connectors": {
    "servers": {
      "analytics": {
        "protocol": "mcp",
        "url": "https://analytics.example.com/v1/mcp",
        "auth": {
          "type": "oauth2_client_credentials",
          "client_id": "aperture-analytics",
          "client_secret": "secret-example",
          "token_url": "https://auth.example.com/oauth2/token",
          "scopes": ["read:data"]
        }
      }
    }
  }
}

Aperture supports five auth types: bearer_token, api_key, basic, oauth2_client_credentials, and oauth2_authorization_code. Refer to the connectors reference for full details on each auth type, including required fields and provider-specific auth_params configuration.

Set up per-user OAuth 2.0 authentication

For connectors where each user needs their own credentials (for example, Google Workspace or Atlassian), use oauth2_authorization_code. Aperture always uses PKCE (S256) and gives each user an isolated MCP session.

{
  "connectors": {
    "servers": {
      "google": {
        "protocol": "mcp",
        "url": "https://mcp.google.example.com/v1/mcp",
        "auth": {
          "type": "oauth2_authorization_code",
          "client_id": "example-client-id",
          "client_secret": "example-client-secret",
          "auth_url": "https://accounts.google.com/o/oauth2/v2/auth",
          "token_url": "https://oauth2.googleapis.com/token",
          "scopes": ["https://www.googleapis.com/auth/spreadsheets.readonly"],
          "auth_params": {"access_type": "offline", "prompt": "consent"}
        }
      }
    }
  }
}

The auth_params field is required for some providers. Google requires {"access_type": "offline", "prompt": "consent"} to issue a refresh token. Without it, the connector silently breaks after the initial access token expires. Refer to the connectors reference for provider-specific examples.

When setting up the OAuth application at the provider, register https://<aperture-hostname>/aperture/auth/<connector-id>/callback as the redirect URI.

Each user starts authorization through the Aperture UI Connectors page or by sending POST /api/connectors/<id>/connect, which returns a JSON response with the authorization URL:

{"auth_url": "https://accounts.google.com/o/oauth2/v2/auth?client_id=..."}

The user opens this URL in a browser, grants consent, and is redirected back to Aperture. A success page confirms authorization. Tools from the connector then appear in tools/list for that user. Authorization flows expire after 15 minutes if not completed.

Tools from per-user connectors do not appear until at least one user has authorized. Aperture fetches the tool catalog lazily on first authenticated request.

Set up an HTTP API proxy

HTTP connectors let agents access REST APIs through Aperture. Aperture forwards requests sent to /v1/connectors/<id>/<path> to the upstream URL and injects credentials automatically. When at least one HTTP connector is configured, Aperture registers an aperture_list_connectors MCP tool so that AI models can discover available HTTP connectors.

{
  "connectors": {
    "servers": {
      "github": {
        "protocol": "http",
        "url": "https://api.github.com",
        "description": "GitHub REST API (read-only)",
        "context": "Use this connector to look up repository metadata and pull request status.",
        "auth": {
          "type": "bearer_token",
          "secret": "github_pat_example"
        }
      }
    }
  }
}

The authentication credentials configured on an HTTP connector are shared by all authenticated tailnet users. Use the narrowest possible scope (ideally read-only) and do not put sensitive information in the description or context fields, which are visible to all users.

HTTP connectors enforce the following security behavior:

  • Allowed methods: GET, HEAD, POST, PUT, PATCH, DELETE, and OPTIONS. Other methods (TRACE, CONNECT) are rejected with 405 Method Not Allowed.
  • Stripped request headers: Authorization and Cookie headers from the client are removed before forwarding. Aperture injects the correct credentials from the connector's auth configuration.
  • Stripped response headers: Set-Cookie headers from the upstream are removed.
  • Redirect blocking: All redirects from the upstream are blocked.
  • Response size limit: 50 MB.

Enable dynamic registration

Dynamic registration is not available for connectors. It is configured only through the legacy mcp section. The following describes the mcp-section behavior.

Dynamic registration lets MCP servers register themselves with Aperture at runtime instead of through static configuration. Set accept_registrations to true in the mcp section. This field requires the mcp section and has no equivalent in connectors.

{
  "mcp": {
    "accept_registrations": true
  }
}

Remote servers register by sending a POST request to /v1/mcp/register:

curl -X POST http://<aperture-hostname>/v1/mcp/register \
  -H "Content-Type: application/json" \
  -d '{"url": "http://my-mcp-server:8080/v1/mcp"}'

Each dynamically registered server receives a sequential ID (auto1, auto2, and more). The registering server must keep the HTTP connection open. Aperture unregisters its tools when the connection closes.

You can combine static connectors and dynamic registration in the same configuration.

Use the context field for model guidance

The context field lets you provide instructions or metadata that help AI models understand what a connector does and when to use it. The field accepts a plain string or a JSON object and is visible to all authenticated users through MCP tool discovery.

{
  "connectors": {
    "servers": {
      "jira": {
        "protocol": "http",
        "url": "https://your-org.atlassian.net/rest/api/3",
        "description": "Jira Cloud API",
        "context": "Use this connector to look up issue status and sprint progress. Do not create or modify issues without explicit user approval.",
        "auth": {
          "type": "basic",
          "username": "api-user@example.com",
          "password": "api-token-example"
        }
      }
    }
  }
}

Use API key authentication

The api_key auth type injects a credential as a named header or query parameter. Specify in as "header" or "query", and name as the header or parameter name:

{
  "connectors": {
    "servers": {
      "weather": {
        "protocol": "http",
        "url": "https://api.weather.example.com",
        "auth": {
          "type": "api_key",
          "secret": "wk-example-key",
          "name": "X-API-Key",
          "in": "header"
        }
      }
    }
  }
}

Migrate from mcp.servers

If you have existing MCP servers configured in the legacy mcp.servers section, Aperture automatically folds them into connectors.servers at load time with protocol: "mcp" and no authentication. Both sections can coexist during migration, but connector IDs must be unique across both.

To migrate, move each entry from mcp.servers to connectors.servers and add the protocol field:

  • Before: "mcp": { "servers": { "local": { "url": "http://localhost:8185/v1/mcp" } } }
  • After: "connectors": { "servers": { "local": { "protocol": "mcp", "url": "http://localhost:8185/v1/mcp" } } }

Legacy entries cannot specify authentication. To add auth to an existing MCP server, move it to the connectors section.

Manage connectors in the dashboard

The Aperture dashboard provides two views for working with connectors: a browsing page for all users and an admin settings page for managing connector configuration.

Connectors page

The Connectors page (accessible from the top navigation when the connectors feature flag is enabled) shows all available connectors in a primary-detail layout. Connectors are grouped into three categories:

  • System: Built-in connectors provided by Aperture (for example, the aperture connector with the list_connectors tool).
  • Custom: Connectors configured by an admin in connectors.servers with a custom provider.
  • Verified: Connectors from the verified registry (Salesforce, Atlassian, Slack). Verified connectors that are not yet configured appear with a "not configured" status and a prompt to set them up.

Each connector shows a status indicator:

StatusIconMeaning
ReadyGreen check markAccessible and authorized.
Needs authAmber alertAccessible but the user has not completed the OAuth authorization flow.
MisconfiguredOrange alertOAuth token exists but lacks a refresh token. The OAuth application may not be configured for offline access.
No accessBan iconThe user does not have a matching connectors grant.
Not configuredSettings iconA verified provider that has not been configured by an admin. UI only. The API does not return this status.

Selecting a connector shows its details in the right panel. For MCP connectors, the detail view shows the connector's capabilities (tools, resources, and resource templates) with an indication of which items the user can access based on their grants. For connectors using oauth2_authorization_code, the detail view includes Connect and Disconnect buttons to manage the per-user OAuth flow.

Settings page

The Connectors tab on the Settings page (admin only) provides a visual editor for managing connector configuration. Admins can:

  • Add connectors using the connector picker, which offers pre-configured defaults from the verified registry (Salesforce, Atlassian, Slack) or a custom connector option.
  • Edit connectors by modifying fields, auth configuration, and context through a form UI. A live JSON preview shows the resulting configuration.
  • Delete connectors with a confirmation dialog.

Limitations

Connectors have the following limitations:

  • Feature flag required: The connectors section requires the connectors feature flag. Without it, Aperture rejects new connector entries with an error when you save through the API or dashboard. Connectors that were saved before the flag was disabled continue to function.
  • HTTP connector credentials are shared: Authentication credentials configured on an HTTP connector are shared by all users who have a matching connectors grant. There is no per-user credential isolation for HTTP connectors. Users must have a grant matching "connectorID/proxy" or a broader pattern like "connectorID/**" to access the HTTP proxy endpoint.
  • Dynamic registration requires the mcp section: The accept_registrations field has no equivalent in the connectors section. You must use the mcp section for dynamic registration.
  • Polling-based discovery: Aperture detects remote MCP server capability changes through polling (every 5 seconds), not push notifications. There is a brief delay between a remote server adding a tool and that tool becoming available to clients. Connectors using oauth2_authorization_code are an exception: they have no background poller and instead load capabilities lazily when a user starts a session or calls the capability refresh endpoint.

Troubleshooting

Use the following sections to diagnose and resolve common issues with connectors.

Connector validation errors

If your configuration fails to load, check the error message against the following common causes:

  • protocol is required (e.g. "mcp" or "http"). The entry is missing the protocol field. Add "protocol": "mcp" or "protocol": "http".
  • invalid ID "..."; connector IDs must match [a-zA-Z][a-zA-Z0-9]*. The connector ID contains hyphens, underscores, or starts with a digit. Use only letters and digits, starting with a letter.
  • "tailscale" is a reserved identifier. The connector ID tailscale is reserved. Choose a different ID.
  • server ID "..." is defined in both 'mcp.servers' and 'connectors.servers'. The same ID appears in both sections. Remove the duplicate from one section.

MCP tools do not appear

If tools from a configured MCP connector are not visible:

  1. Open the Connectors page in the dashboard and check the connector's status and capability list. The page probes the upstream URL, so it reports whether Aperture can reach the server and list its capabilities. You do not need access to the Aperture host to do this.
  2. Verify the URL in your configuration is correct and the MCP server is running.
  3. Verify your grants include connectors patterns that match the connector and tool names (for example, "local/tools/*"). Without grants, users cannot access any connector tools.

Connection refused or host not found

  • Connection refused: The upstream server is not running or is not listening on the configured port.
  • Host not found: DNS cannot resolve the hostname. For tailnet hostnames, verify the device is connected to the tailnet and check with tailscale status.

Tools stop working after previously working (OAuth connectors)

If tools from a per-user OAuth connector stop working after a period of inactivity, the refresh token has likely expired or been revoked. To recover, open the Connectors page, select the connector, and choose Disconnect and then Connect to re-authorize. Disconnecting and reconnecting is safe and forces Aperture to generate fresh tokens, which also clears a token that is stuck or broken but still present.

Tool calls time out

If tool calls fail with timeout errors, the remote MCP server is not responding quickly enough. Aperture retries tool calls once on connection errors. Check the remote server's performance and logs to identify the delay.

Auth configuration rejected with unknown field error

The auth block uses strict field validation. Misspelled field names (for example, "secert" instead of "secret") cause the configuration to fail with a JSON decoder error. Double-check field names against the connectors reference.

For step-by-step setup instructions, refer to the following topics: