Aperture connectors reference

Last validated:

The connectors section of the Aperture configuration configures outbound integrations with external services. Connectors support two protocols:

  • MCP ("protocol": "mcp"): Aperture connects to remote Model Context Protocol servers, aggregates their tools and resources, and exposes them through the /v1/mcp endpoint.
  • HTTP ("protocol": "http"): Aperture acts as an authenticated reverse proxy, forwarding requests to upstream HTTP APIs with credentials injected automatically.

Connectors replace the deprecated mcp.servers syntax and add support for authenticated connections and multiple protocols.

For setup and verification steps, refer to Get started with connectors. For provider selection, refer to the Connectors catalog. For upstream credentials and authorization, refer to Connector authentication. The aperture system connector and its tools are documented in System connectors.

connectors fields

The connectors section accepts the following top-level fields:

FieldTypeDefaultDescription
serversmap{}Map of connector ID to server configuration. The map key is the connector ID, which becomes the name prefix for tools (connectorID_toolname), resources (connectorID-uri), and resource templates (connectorID-uriTemplate).

servers fields

Each entry in the servers map accepts the following fields:

FieldTypeRequiredDefaultDescription
protocolstringYesN/AHow Aperture communicates with the upstream. One of "mcp" or "http".
urlstringNoN/AEndpoint URL of the upstream server. A missing url produces a load-time warning rather than a fatal error, so Aperture still loads the configuration. The dashboard's connector save path, however, rejects it as an error.
providerstringNo"Custom"Case-sensitive provider identifier. Use a verified provider ID from the registry, a reserved built-in provider ("Tailnet" or "TailnetSSH"), or "Custom" (the default). Any other value is a load-time error. For example, use "Salesforce", not "salesforce".
descriptionstringNounset ("")Human-readable label displayed in the Aperture UI. For granted HTTP connectors, aperture_list_connectors also returns it to permitted users. When empty, the field is omitted from the stored configuration.
contextstring or JSONNoN/APrompt or context information for a connector. Accepts a plain string or arbitrary JSON object. For granted HTTP connectors, aperture_list_connectors returns it to permitted users.
labelsarray of stringsNo[]Flat labels that group the connector for access control. A grant pattern of label:<name> matches every connector carrying that label. Each label must match [a-zA-Z0-9][a-zA-Z0-9._-]*. The label system is reserved. Refer to connector labels.
authobjectNoN/AUpstream authentication configuration, selected by the type field. Refer to the authentication-type catalog.

Example with both protocols:

{
  "connectors": {
    "servers": {
      "tailnetMCP": {
        "protocol": "mcp",
        "url": "http://mcp-server.example.ts.net:8080/v1/mcp"
      },
      "github": {
        "protocol": "http",
        "url": "https://api.github.com",
        "description": "GitHub REST API (read-only)",
        "auth": {
          "type": "bearer_token",
          "secret": "github_pat_example"
        }
      }
    }
  }
}

In this example, github is a custom HTTP connector (its provider is unset, so it defaults to "Custom"). It is distinct from the verified GitHub MCP connector in the registry, which uses the case-sensitive provider ID "GitHub".

Connector ID rules

Connector IDs must match the pattern [a-zA-Z][a-zA-Z0-9]* (letters and digits only, starting with a letter). Connector IDs cannot contain underscores or hyphens because the MCP wire format reserves these as separators: underscores separate the connector ID from the tool name (snowflake_query), and hyphens separate the connector ID from resource URIs (snowflake-resource://...).

Valid IDs: github, snowflake, analyticsV2. Invalid IDs: my-mcp (hyphen), github_api (underscore), 2fast (starts with digit).

The IDs tailscale, internal, and aperture are reserved and cannot be used as connector IDs. The aperture ID is used by the aperture system connector and produces a distinct error message from tailscale and internal (refer to validation errors).

Connector labels

Labels are flat strings that group connectors for access control. Set the labels field on any connector, then grant access to the group with a label:<name> pattern in the connectors field of a grant:

{
  "connectors": {
    "servers": {
      "salesforce": {
        "protocol": "mcp",
        "url": "https://api.salesforce.com/platform/mcp/v1/platform/sobject-all",
        "labels": ["sales", "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 to avoid ambiguity with slash-separated FQN patterns. Because dots and hyphens are legal, labels can be namespaced (team.eng), but Aperture neither requires nor interprets that convention.

Beyond that grammar, labels are free text. Aperture defines no vocabulary and attaches no meaning to a label's value. The dashboard suggests labels already in use on other connectors so an Aperture gateway converges on one vocabulary rather than accumulating near-duplicates. Common schemes classify a connector by data sensitivity (public, private, restricted) or by team ownership (eng, sales).

Label matching has two characteristics that differ from FQN patterns:

  • Exact match, no globs. A label:<name> pattern is compared literally against a connector's labels, the same way tag: and group: behave in Tailscale grants. Wildcard forms such as label:team.* match nothing.
  • Whole-connector access. A matching label grants every category and resource the connector exposes, including HTTP proxy access. Labels have no per-tool granularity. For tool-level or resource-level access, use an FQN pattern that names the connector ID.

Labels widen access and never restrict it. Grants are additive and allow-only, so labeling a connector restricted documents intent without enforcing it: a user holding {"connectors": ["**"]} still reaches that connector. To limit a sensitive connector, remove the broad wildcard grants that reach it and grant it narrowly by label or by connector ID.

The reserved system label

Aperture applies the system label to the aperture system connector automatically. The shipped default configuration grants label:system, providing access to this connector on a new Aperture gateway. Individual tools still depend on their availability conditions. Only system connectors can have the label. The Tailnet and TailnetSSH built-in connectors are not system connectors and never receive it. Because the default grant reaches every user, system is reserved under connectors.servers:

  • A configuration that already includes the label loads with a warning. Aperture strips the label from that connector before evaluating grants.
  • Aperture treats this warning as an error when you save configuration, so you can't add or keep the label on a connector.

For step-by-step instructions, refer to Grant connector access by label.

Connector statuses

Use the Connectors page in Aperture Chat to check a connector's status.

The following table lists each API status, how Aperture Chat displays it, and how to resolve it:

API statusChat displayMeaningResolution
readyReady, under Ready to useThe caller has access and is authorized. This does not confirm that the upstream is reachable, that the tool list is current, or that a live tool call succeeds.If the tool list is missing or outdated, select Refresh tools. To confirm that the connector works, call a permitted tool or proxy path.
needs_authConnect, under Connect to use, with no status badgeThe caller has a grant but has not authorized this per-user OAuth connector.Select Connect.
misconfiguredNeeds reconnect with ReconnectAuthorization needs renewal. The access token expired without a refresh token, or the provider rejected a token refresh and requires new consent.Select Reconnect. If the problem recurs after token expiry, check the provider's offline-access configuration.
unavailableTemporarily unavailableAperture could not read the caller's credential state.Reload or retry later. Reconnecting is not necessary.
no_accessHiddenThe caller has no matching connectors grant.An admin adds a matching grant.
not_configuredAvailable to add for admins, Requires admin setup for other usersA built-in connector has no configured instance. The API returns it as a setup placeholder.An admin selects Configure.

If the provider does not issue a refresh token, a new authorization reports ready until its access token expires.

The no_access status follows these rules:

  • For non-admin callers, the list omits configured connectors that have no matching grant.
  • Admins receive those configured connectors as no_access.
  • Built-in system connectors appear in the list for every caller, with no_access if the caller has no grant.
  • Aperture Chat hides no_access entries, including for admins. The exception is the built-in aperture system connector: Chat still lists it when Web or Code Sandbox is available.
  • If a non-admin opens a configured connector in Aperture Chat without a grant, Aperture returns 404 Not Found and does not reveal that the connector exists.

If a configured connector is missing from a user's list, check that user's connector grants.

Status describes caller access and authorization, not upstream health. The connector detail page shows cached capabilities and does not contact the upstream. A ready per-user connector can show an empty tool list if the first capability discovery did not complete. A later request or Refresh tools can discover the tools. Refresh tools contacts the upstream and can return a connection error. A populated tool list does not prove that a live tool call succeeds.

Authentication

The auth object configures how Aperture authenticates requests to an upstream server. For the complete authentication-type catalog, configuration fields, and per-user OAuth behavior, refer to Connector authentication.

MCP connectors

When protocol is "mcp", Aperture connects to remote MCP servers, aggregates their tools and resources, and exposes them through the /v1/mcp endpoint.

Name prefixing

Each key in the servers map is a connector ID that Aperture uses as a name prefix:

  • Aperture prefixes tools with the connector ID and an underscore. For example, a tool named search on the docs connector becomes docs_search.
  • Resources use a hyphen instead of an underscore. For example, docs-files://readme.md.

Name prefixing prevents collisions when multiple servers expose tools with the same name. Clients receive the prefixed names and Aperture automatically strips the prefix when forwarding calls to the remote server.

Transport auto-detection

Aperture automatically detects whether each remote MCP server supports Streamable HTTP (the current protocol) or legacy SSE. When connecting to a remote server, Aperture tries Streamable HTTP first and falls back to SSE if the server does not support it. You can upgrade remote servers to a later protocol version without restarting Aperture.

The same auto-detection applies to clients connecting to Aperture's /v1/mcp endpoint. Aperture serves both Streamable HTTP and legacy SSE clients.

Capability updates

Aperture polls each MCP connector that does not use per-user credentials every few seconds. When a server adds or removes tools or resources, Aperture updates the capabilities available to connected clients.

If Aperture cannot connect to a remote server, it removes that server's tools from /v1/mcp until the server recovers. If Aperture connects but cannot list the server's capabilities, it keeps the capabilities from the last successful check. In both cases, Aperture Chat can still show the last cached tool list, so a listed tool does not guarantee that a live call succeeds.

Per-user OAuth connectors do not use this periodic check. They load capabilities with each user's credentials after consent or on a later request. To request current capabilities, select Refresh tools in Aperture Chat. Refresh contacts the upstream server. It can return a connection error while the status stays Ready.

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

HTTP connectors

When protocol is "http", Aperture acts as an authenticated reverse proxy. Aperture forwards requests sent to /v1/connectors/<id>/<path> to the connector's upstream URL and injects credentials automatically. Agents discover HTTP connectors through the aperture_list_connectors system tool.

The authentication credentials configured on an HTTP connector are shared by all users with a matching connectors grant. Users must have a grant matching "connectorID/proxy" or a broader pattern like "connectorID/**" to access the proxy endpoint. Use the narrowest possible credential scope, preferably read-only. Do not put sensitive information in description or context. The aperture_list_connectors tool returns these fields only for HTTP connectors the user has permission to access.

Allowed HTTP methods

HTTP connectors accept the following request methods: GET, HEAD, POST, PUT, PATCH, DELETE, and OPTIONS. Aperture rejects all other methods, including TRACE and CONNECT, with 405 Method Not Allowed. Aperture blocks TRACE because it reflects request headers, which would expose injected authentication credentials.

Request and response handling

Aperture modifies requests and responses passing through the HTTP connector proxy:

  • Request headers: Aperture removes Authorization, Cookie, and all Tailscale-* headers from client requests before forwarding to the upstream. This prevents clients from injecting credentials or identity headers that could leak to the upstream server. Aperture adds credentials separately, based on the connector's auth configuration.
  • Response headers: Aperture strips Set-Cookie headers from upstream responses, preventing the upstream from setting cookies on Aperture's origin.
  • Hop-by-hop headers: Standard hop-by-hop headers (Connection, Keep-Alive, Proxy-Authenticate, Proxy-Authorization, Te, Trailer, Transfer-Encoding, Upgrade) are stripped in both directions per HTTP specification.
  • Request body: Forwarded as-is with no size limit.
  • Response body: Limited to 50 MB. Responses exceeding this limit are truncated.

Security behavior

HTTP connectors enforce the following security restrictions:

  • URL restrictions: Connector URLs are validated against a safe dialer that blocks internal and reserved address ranges. RFC 1918 (private), ULA, and Tailscale CGNAT addresses are permitted.
  • Redirect blocking: HTTP connectors block all redirects from upstream servers to prevent credential exfiltration through redirect chains.
  • Credential injection: Aperture always removes client-supplied Authorization headers. It adds credentials to each proxied request only when the connector has an auth configuration.

Legacy MCP server registration

Runtime MCP server registration is configured only through the legacy mcp section and has no connectors equivalent. It is separate from OAuth dynamic client registration (oauth2_dcr), which registers an OAuth client with an upstream authorization server.

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 of your configuration. This field requires the mcp section and has no equivalent in connectors.

{
  "mcp": {
    "accept_registrations": true,
    "servers": {}
  }
}

Remote servers register by sending a POST request to /v1/mcp/register with a JSON body containing their URL:

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

Aperture checks that the URL uses http or https and includes a host, then tries to fetch the server's tools. It responds with HTTP 200 even if the fetch fails, logging a warning rather than rejecting the registration. If accept_registrations is false, Aperture responds with HTTP 403. Each dynamically registered server receives a sequential ID such as auto1 or auto2, and Aperture prefixes its tools accordingly, for example auto1_search.

The registration endpoint requires Tailscale authentication, the same as all other Aperture endpoints. The registering server must be accessible through the tailnet.

The registering server must keep the HTTP connection to /v1/mcp/register open. When the server closes the connection, Aperture automatically unregisters all of its tools and resources.

You can combine static connectors and dynamic registration in the same configuration. Static connectors are always available, while dynamically registered servers come and go as they connect and disconnect.

mcp fields

FieldTypeDefaultDescription
accept_registrationsbooleanfalseAllow backends to register dynamically through POST /v1/mcp/register. Backends send {"url": "http://..."} in a POST request and keep the connection open. Aperture unregisters their tools when the connection closes. This field has no connectors equivalent.
serversmap{}Map of server ID to server configuration. Deprecated: use connectors.servers instead. The map key is the server ID, which becomes the name prefix for tools (serverID_toolname), resources (serverID-uri), and resource templates (serverID-uriTemplate) from that backend.

Grants for connector resources

Aperture is deny-by-default. Without grants, users cannot access any connector capabilities. This applies to both MCP and HTTP connectors. Add grants in the grants section of the Aperture configuration.

Connector grants use the connectors field with "connectorID/category/resource" FQN glob patterns, or with label:<name> patterns that match by label. The following example grants all users access to the aperture system connector's tools through the system label, all tools from the docs connector, and proxy access to the github HTTP connector:

{
  "grants": [
    {
      "src": ["*"],
      "app": {
        "tailscale.com/cap/aperture": [
          {"role": "user"},
          {"connectors": ["label:system"]},
          {"connectors": ["docs/tools/*"]},
          {"connectors": ["github/proxy"]}
        ]
      }
    }
  ]
}

The connectors field accepts an array of FQN glob strings and label:<name> strings. Each FQN pattern has up to three segments: connectorID/category/resource.

Grant categories

CategoryApplies toDescriptionExample
toolsMCP connectorsMCP tools exposed by the connector"docs/tools/search"
resourcesMCP connectorsMCP resources exposed by the connector"docs/resources/*"
templatesMCP connectorsMCP resource templates exposed by the connector"docs/templates/*"
proxyHTTP connectorsProxy access to the HTTP connector endpoint"github/proxy"

Grant patterns

You can use * to match any characters within a segment and ** to match across segments:

  • "docs/tools/search": the search tool from the docs connector.
  • "docs/tools/*": all tools from the docs connector.
  • "docs/**": all capabilities from the docs connector (tools, resources, templates).
  • "github/proxy": proxy access to the github HTTP connector.
  • "github/**": every category and resource under github, including proxy access and any future categories. Use "github/proxy" when only HTTP proxy access is needed.
  • "**": all capabilities from all connectors.
  • "label:system": every connector labeled system. By default, this is the aperture system connector. This pattern is in the shipped default configuration.
  • "label:team.eng": every connector labeled team.eng, at every category and resource.

A top-level pattern like "connectorID/*" is automatically expanded to "connectorID/**", so it covers all categories and sub-resources.

A label:<name> pattern is matched exactly rather than expanded as a glob, and a match grants the whole connector. Refer to connector labels for the label grammar and matching rules.

Aperture checks grants when clients list available tools and resources. Users can access only the items their grants permit. Aperture also enforces grants at invocation time: when a client calls a tool, reads a resource, or sends a proxy request, Aperture checks the session's grants before dispatching the request. If no grant matches, Aperture rejects the call with a "forbidden" or "unknown tool" error.

The deprecated mcp_tools, mcp_resources, and mcp_templates grant fields continue to work for backward compatibility with the "server/item" pattern syntax. New configurations should use the connectors field, which supports all connector types including HTTP proxy access.

Resource grants are now matched against the resource's name, not its URI. Legacy mcp_resources patterns written against resource URIs no longer match. Rewrite them against the resource name using connectors with the resources category.

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

Migration from mcp.servers

The connectors section replaces the deprecated mcp.servers syntax. At load time, Aperture automatically folds legacy mcp.servers entries into connectors.servers with protocol: "mcp" and no authentication. Both sections can coexist during migration, but connector IDs must be unique across both. Aperture rejects duplicate IDs at load time.

Legacy mcp.servers entries that use connector IDs not conforming to the [a-zA-Z][a-zA-Z0-9]* pattern generate a warning but are still accepted for backward compatibility. New entries in the connectors section must conform to the ID rules.

Consider the following mcp.servers entry:

"mcp": { "servers": { "docs": { "url": "http://mcp-server.example.ts.net:8185/v1/mcp" } } }

The equivalent connectors entry is:

"connectors": { "servers": { "docs": { "protocol": "mcp", "url": "http://mcp-server.example.ts.net:8185/v1/mcp" } } }

The mcp section is retained for backward compatibility and for the accept_registrations field, which has no connectors equivalent.

Validation errors

Aperture validates connector configuration at load time. The following table describes connector-specific validation messages:

ConditionMessageSeverity
Connector missing protocolconnectors.servers.{id}: protocol is required (e.g. "mcp" or "http")Error
Unsupported connector protocolconnectors.servers.{id}: unsupported protocol "{value}" (supported: "mcp", "http")Error
Invalid connector IDconnectors.servers.{id}: invalid ID "{id}"; connector IDs must match [a-zA-Z][a-zA-Z0-9]* (letters and digits only, starting with a letter; no hyphens or underscores)Error
Reserved connector ID (tailscale, internal)connectors.servers.{id}: "{id}" is a reserved identifierError
Reserved system connector ID (aperture)connectors.servers.{id}: "{id}" is a reserved system connector identifierError
Connector sets an unknown providerconnectors.servers.{id}: unknown provider "{value}"; use a verified ID or omit for custom connectorsError
Connector missing URLconnectors.servers.{id}: URL is requiredWarning
Connector URL uses restricted addressconnectors.servers.{id}: URL {details}Warning
Connector auth validation failureconnectors.servers.{id}.auth: {details}Error
Invalid connector labelconnectors.servers.{id}.labels: invalid label "{label}"; labels must match [a-zA-Z0-9][a-zA-Z0-9._-]* (no slashes)Error
Reserved label on a user connectorconnectors.servers.{id}.labels: removed reserved label "system"Warning
Duplicate connector ID across mcp and connectorsconfig: server ID "{id}" is defined in both 'mcp.servers' and 'connectors.servers'; IDs must be unique across both sectionsError

Refer to the Aperture configuration reference for the full validation table.

HTTP connector proxy endpoint

Use the following endpoint to send requests through an HTTP connector:

MethodPathDescriptionAccess
Any supported/v1/connectors/<id>/<path>Reverse proxy to an HTTP connector's upstream URL.Requires connectorID/proxy grant

Full annotated example

The following example shows a complete connector configuration with both MCP and HTTP protocols, authentication, grants, and legacy MCP server registration:

{
  // Outbound integrations (MCP servers and HTTP APIs)
  "connectors": {
    "servers": {
      // Unauthenticated MCP server in your tailnet
      "tailnetMCP": {
        "protocol": "mcp",
        "url": "http://mcp-server.example.ts.net:8080/v1/mcp"
      },
      // MCP server with bearer token auth, grouped by label
      "snowflake": {
        "protocol": "mcp",
        "url": "https://mcp.example.com/v1/mcp",
        "labels": ["analytics", "restricted"],
        "auth": {
          "type": "bearer_token",
          "secret": "sk-example-token"
        }
      },
      // HTTP API proxy with OAuth 2.0 client credentials
      "analytics": {
        "protocol": "http",
        "url": "https://analytics.example.com/api",
        "description": "Analytics API (read-only)",
        "auth": {
          "type": "oauth2_client_credentials",
          "client_id": "aperture-analytics",
          "client_secret": "secret-example",
          "token_url": "https://auth.example.com/oauth2/token",
          "scopes": ["read:data"]
        }
      }
    }
  },

  // Dynamic MCP registration (accept_registrations has no connectors equivalent)
  "mcp": {
    "accept_registrations": true
  },

  // Grant all users the `aperture` system connector's tools (the shipped default) and,
  // separately, everything the analytics team needs by label
  "grants": [
    {
      "src": ["*"],
      "app": {
        "tailscale.com/cap/aperture": [
          {"role": "user"},
          {"connectors": ["label:system"]}
        ]
      }
    },
    {
      "src": ["group:analytics"],
      "app": {
        "tailscale.com/cap/aperture": [
          {"connectors": ["label:analytics"]}
        ]
      }
    }
  ]
}

Troubleshooting

Connector problems fall into two flows with different causes and fixes: an admin setting up and configuring a connector, and a user authorizing and using a connector's tools. Use the section that matches your role.

The connector list and Ready status do not probe upstream health. Refresh tools is the explicit upstream capability check.

For admins setting up connectors

These issues affect connector configuration and reachability. Admins manage connector configuration under Administration > Connectors and grants under Administration > Grants.

Missing Chat connectors or tools

If a configured connector does not appear in Chat, the user may have no matching grant, and Chat hides the connector. Admins check the user's grants under Administration > Grants.

For missing MCP tools, the admin verifies the upstream URL, authentication configuration, and capability filters. A granted user then opens the connector detail page in Chat and selects Refresh tools. If refresh returns an error, verify reachability from the Aperture gateway and confirm credential validity.

Connection refused or host not found

These errors indicate the connector URL is unreachable from the Aperture gateway.

  • Connection refused: The 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.

Auth configuration rejected with unknown field error

The auth block uses strict field validation. If a field name is misspelled (for example, "secert" instead of "secret"), the configuration fails to load with a JSON decoder error. Double-check field names against the authentication-type catalog.

Legacy MCP server registration fails

If remote servers cannot register dynamically:

  1. Verify accept_registrations is set to true in the mcp section of your configuration (this field is not available in the connectors section).
  2. Make sure the remote server sends a valid POST request to /v1/mcp/register with a JSON body containing {"url": "<mcp-server-url>"}.
  3. The remote server must keep the HTTP connection open after registration. If the connection closes, Aperture unregisters the server's tools immediately.

For users authorizing and using connectors

These issues affect authorizing a connector and calling its tools. Users can check status, refresh tools, and reconnect in Aperture Chat. If a refresh or tool call still fails after authorization, an admin might need to check the upstream service or the connector configuration.

Authorizing and reconnecting

  • Connect: Each user must authorize a per-user OAuth connector individually. Select Connect and complete the provider's consent flow. If tools are still missing after the connector is Ready, select Refresh tools. Discovery can fail while the upstream is unreachable.
  • Needs reconnect: The access token expired without a refresh token, or a token-refresh failure requires new consent. Select Reconnect. If the problem recurs after token expiry, ask your admin to check the provider's offline-access configuration.
  • Temporarily unavailable: Aperture could not read the credential state. Reload the page. Reconnecting is not necessary.
  • Reset authorization: To clear your per-user authorization, select Disconnect. Then select Connect to authorize again.

Tools stop working after previously working

If a connector is Ready but its tools fail, check for temporary provider downtime, timeouts, or rate limits. Do not disconnect a valid authorization only because a tool call fails.

Tool calls time out

If tool calls fail with timeout errors, the remote MCP server is not responding quickly enough. After a connection error, Aperture reconnects to the remote server and retries the tool call one time. If timeouts continue, ask your admin to check the remote server's performance and logs.