SuperAPI AI Directory

configure-private-mcp-access

Deployment & operations

View repository

Updated 11-02 22:48

About this skill

Configure private access for an existing MCP

If this connection lists call_platform_tool instead of the tools this workflow names, find each named tool with search_platform_tools, describe it with describe_platform_tool, then run it with call_platform_tool and the same arguments. Whether a tool exists for you is decided by describe_platform_tool with its exact name, not by tools/list or one page of search results: a name returned in not_found is unavailable to you, so say so rather than guess. The call itself still checks your access. When execute is also listed, a multi-step read may run in execute with tools.search, tools.describe and tools.call on platform--<tool name> paths. End each execute run at a confirmation point and ask the user before any write.

Use the authenticated Speakeasy AI Control Plane (AICP) Platform MCP. Installing a plugin does not grant organization access, network access, or authorization to change an MCP. This workflow changes the address or network mode of an existing MCP server (including a hosted toolset) or gateway, not its upstream URL, its plugin membership, or its users' permissions. A hosted toolset's address and network mode belong to its canonical MCP server target, not the toolset. Change its address and network mode through that target. A hosted server can have several endpoints: set_mcp_address adds one or changes one in place. Removing an endpoint is done in the dashboard, which keeps an enabled hosted server from losing its last working address: disable the server before removing its last endpoint that can serve. Endpoints on deleted or unverified domains can always be removed.

  1. Call list_projects and ask the administrator to select an exact project. The list caps at 100; if truncated, use the AICP dashboard to select the project rather than assuming the first page is complete.
  2. Call list_plugins for that project and ask which existing plugin is affected. Call get_plugin for that exact plugin. Follow membership_next_cursor until all its members are listed. If a membership changes mid-pagination, restart. Preserve each typed target ID; do not guess an MCP from a display name or substitute a different server for a hosted toolset's canonical MCP server.
  3. Ask the administrator to choose the exact MCP server or gateway. Call get_mcp_connection_settings with its project_id, target_kind, and target_id. Explain the current endpoints, network mode, configured ingress and plugin memberships. These are settings and observations, not evidence that a tailnet or client can connect. Stop if the target is ambiguous, unproxied, hidden, or the private address cannot be resolved safely.
  4. If changing an address, ask which existing endpoint should change or whether to add a new endpoint, and which slug and existing custom domain to use. A hosted server's custom domain must be the organization's verified, active domain, and a hosted server cannot leave a live custom domain. Present the exact before and after address. Moving an endpoint that is its custom domain's root to another domain is done in the dashboard; set_mcp_address refuses it. Never silently take another root alias, create a custom domain, alter backend IDs, or add the target to a plugin.
  5. If changing network access, call get_mcp_network_traffic for the selected project_id and target_id with window: "7d". For its target_kind, use mcp for an MCP server or gateway for a gateway (connection settings instead uses mcp_server or gateway). Report observed public and private request counts and last-seen times before proposing the exact transition among public_only, dual, and private_only. Counts cover only observed requests while telemetry was enabled: zero does not prove a route is unused or that every client has migrated. If traffic reporting is unavailable, say so and require an independent client inventory before cutting off either route. Explain that private_only can break public clients, while dual retains public access. A private mode requires the server's admission and ingress readiness checks; do not infer readiness from a configured DNS name alone.
  6. Immediately before each change, refresh get_mcp_connection_settings for the same exact target. Call set_mcp_address or set_mcp_network_access without confirmed: true, with the fresh version as expected_version and a stable idempotency_key for that exact request: nothing is written, and the confirmation_required refusal returns a preview of the current settings and the exact change. Show that preview and ask for explicit confirmation, then repeat the same call with the same key and confirmed: true. If the server instead answers invalid_request saying the change was not confirmed, it predates the preview: ask for confirmation of the exact change and then send it with confirmed: true. The preview runs the same checks as the confirmed call, so a refusal at either step means the change cannot be made as requested: report the specific reason, and once the user corrects the value or the readiness condition, start a new preview with a fresh idempotency_key. On conflict, re-read the settings and request confirmation again. Never silently retry with a different target or value.
  7. Treat the mutation receipt as evidence of the historical committed change, not of publication. Read get_mcp_connection_settings again to check current settings. Call get_plugin for every affected plugin and compare its publication evidence and desired package addresses. An enqueued request is not a published package; fresh: null is unknown, and fresh: false means the package needs a refresh. Read fresh together with last_publish: queued, running, or retrying means an update is already on its way, so read get_plugin again later instead of republishing; failed with failure_category: repository_conflict cannot be fixed by republishing, so do not retry it and send the administrator to Speakeasy support; last_publish.unavailable: true means the attempt could not be read, so do not infer a failure; if the publication evidence reports not_configured: true, no publish has ever been recorded and republish_plugin would refuse it, so send the administrator to the dashboard or Speakeasy support instead of offering it. If the publication evidence reports awaiting_manual_sync: true, the plugin's auto sync is off and its own package has changes waiting, so no automatic publish will deliver the new address: only a manual sync does. That flag stays true until a manual sync finishes, so it does not override last_publish: while last_publish is queued, running, or retrying, a sync may already be on its way, so read get_plugin again later instead of offering another one. Only when nothing is in flight, say that the address waits for a manual sync and offer one. If the package still reports fresh: false without an update on its way or a repository conflict, and the administrator wants it refreshed now, explain that republishing regenerates every plugin in the project and also publishes changes waiting on plugins whose auto sync is off, ask for explicit confirmation, then call republish_plugin with the exact project_id selected in step 1, that exact plugin, confirmed: true, and a stable idempotency_key. If the outcome is already_current, report that the package is already current and that no publish was requested. If it is enqueued, it is only a request that can be accepted before its run starts: treat it as pending until last_publish.requested_at is later than the republish or the publication evidence reports fresh: true (a republish can fold into a run already in flight without moving requested_at), read get_plugin again later before reporting the package as current, and never treat an older failed or succeeded attempt as the new request failing or being missed, or republish again because of it. If republish_plugin refuses: for not_configured, report that no package repository is connected and present the returned Plugins link; for not_found or ambiguous_target, ask the user for the exact plugin and do not hand off to the dashboard; for rate_limited, say nothing changed and do not retry automatically. If emission is disabled, the best-effort signal fails, the tool is unavailable, or the package cannot be verified, say so plainly and use the dashboard. Do not claim installed clients have refreshed or OAuth sessions have reconnected.
  8. Report the exact MCP and plugin, the current configured address and mode, whether the generated package would use the private address, whether stored published fingerprints are current, and what the administrator must do to test tailnet connectivity and refresh clients. Keep operational selectors, version hashes, idempotency keys, and receipts out of the user-facing summary.

Never request or transmit API keys, OAuth codes, client secrets, access tokens, network credentials, or upstream authentication headers in chat. A public gateway does not become private because a member MCP is private; configure each selected endpoint independently.