Connectors

External MCP Providers

Import a remote MCP server's tools as governed Ductor connector actions, with metadata and executable imports kept separate and every call re-gated.

An external MCP (Model Context Protocol) server exposes a tools/list — a set of callable tools. External MCP providers let Ductor import those tools into the action inventory as governed connector actions, so an MCP server's capabilities become first-class actions that flow through the same executor, policy, and audit machinery as any other connector. Once imported, a tool from someone else's MCP server is just another governed action a workflow step or a worker — human or agent — can execute, with the same semantics, quotas, and audit trail.

This is the outbound MCP capability: Ductor as a client of someone else's MCP server. For the inbound side — Ductor exposing its own tools as an MCP server — see Ductor's MCP Server.

The provider stays external

The remote provider is never absorbed. Ductor stores only redacted provider specs, immutable tool snapshots (artifact kind external_mcp_tool_snapshot), discovery/import receipts, and action descriptors that can pass normal connector governance (docs/connectors/external-mcp-providers.md).

Before a tool snapshot can be promoted, the provider spec must declare four governance refs:

  • permission_manifest_refs
  • egress_policy_ref
  • entitlement_key
  • certification_requirements

Promotion preflight resolves the snapshot and fails closed unless all hold: the snapshot is available, the spec still carries all four refs, a successful import receipt covers both the snapshot id and the action key, and artifact pins match the immutable schema and tool hashes.

Metadata import vs. executable import

Importing a tool's description and making it executable are deliberately separate steps.

  • Metadata import (PrepareToolImport) records a manifest hash and, when receipt recording is on, an immutable import receipt. The metadata becomes available for permission and egress-policy previews.
  • Executable import additionally requires an explicitly redacted recorded transcript with exactly one server/discover, one tools/list, and one tools/call exchange per imported action. HTTP headers and credential material are forbidden in the transcript. Ductor replays it through the real bounded outbound MCP client against an ephemeral local replay server and publishes an executed-v1 recorded-replay scorecard.

Missing evidence leaves metadata, not an action

If the transcript, tool, schema, semantics, runner, scorecard, or implementation evidence is missing, expired, or mismatched, the metadata stays available but no executable action is registered. You cannot get an executable external MCP action without a clean recorded-replay scorecard.

Stateless provider contract

Ductor's outbound client speaks MCP 2026-07-28. It does not initialize a connection or retain an MCP session. Every discovery, listing, and call request includes the protocol version, client capabilities, method, optional tool name, and trace context needed to process that request independently.

The provider must return a complete discovery result that advertises 2026-07-28, its capabilities, server identity, and valid cache hints. Tool catalog results must also include complete result and cache fields. Ductor excludes a tool if its input schema does not have an object root or contains an unsafe x-mcp-header annotation.

When a schema marks an input with x-mcp-header, Ductor copies that argument to the matching Mcp-Param-* header and preserves the value in the JSON body. This lets providers route on selected parameters without making headers a second source of truth.

A provider can return input_required with typed inputRequests and opaque requestState. Ductor exposes those fields in the connector result. The caller can then retry the original action with a reserved _ductor_mcp control object:

{
  "id": "provider-argument",
  "_ductor_mcp": {
    "client_capabilities": {
      "elicitation": {}
    },
    "input_responses": {
      "approval": {
        "action": "accept"
      }
    },
    "request_state": "opaque-provider-state"
  }
}

Ductor strips _ductor_mcp before validating or sending the provider's tool arguments. The control fields become MCP request metadata and continuation fields instead. No replica affinity or hidden continuation state is required.

Every call is re-gated

Certified registrations are durable: each Ductor process opens its own registration epoch, seeds an outbox from active registrations, and claims pages with FOR UPDATE SKIP LOCKED; registration is idempotent for exact hashes and rejects drift, reporting registration_pending before a tenant-scoped registration is available. The durable worker is connector.external_mcp_registration_worker (bounded interval, batch, lease, retry, and max-attempt settings). The whole feature is gated behind connector.external_mcp.enabled — an enterprise activation.

Importing a provider registers metadata; it never opens a side door. Both paths below converge on the same executor, so an imported MCP tool clears exactly the gates a first-party action does:

no shortcut import: register metadata exec tool call scope, semantics, entitlement, egress, admission shared HTTP client external MCP server

No trust is inherited from import

Every outbound call still enters the normal connector action executor. That single boundary re-checks tenant/provider-config scope, action semantics, entitlement/readiness facts, egress placement and dispatch policy, and active fair-admission capacity before the shared connector HTTP client issues the request. And external providers never import or recursively expose Ductor's own inbound MCP server.

Already shipping

Many *_mcp connectors already ship as external MCP providers — including hubspot_mcp, linear_mcp, notion_mcp, slack_mcp, and vercel_mcp — visible in the catalog like any other provider. Their promotion evidence emits redacted metadata only (provider config identity, remote tool name, Ductor action key, schema/tool hashes, import receipt id, governance refs, and a single connector operation), which feeds the existing permission preview and egress placement policy preview.

Where to go next