> ## Documentation Index
> Fetch the complete documentation index at: https://pipedream.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Connectors

> Every kind of tool source Conduit can aggregate, how each authenticates upstream, and where credentials live.

A **connector** is a source of tools: an MCP server, an OpenAPI or GraphQL
API, or a Pipedream app. Workspace admins create and manage connectors in
**Settings → Connectors**; who may *use* each one is a separate decision made
by [access policies](/docs/conduit/configure/access-control). Creating and editing connectors is
deliberately a web-UI action rather than one of Conduit's built-in admin
tools, because those requests carry upstream credentials — which don't belong
in an LLM's tool-call transcript.

## Connector kinds

| Kind | What it is | What clients see |
| - | - | - |
| **MCP (remote)** | An MCP server reached over HTTP or SSE | The server's tools, proxied 1:1 |
| **MCP (local, feature-flagged)** | An MCP server defined by launch command, run on each member's machine by the Conduit CLI | The server's tools; results stay on the member's machine, except the error text of a failed call, which is reported to usage |
| **OpenAPI** | An HTTP API described by an OpenAPI spec | One tool per operation |
| **GraphQL** | A GraphQL endpoint | An `execute` tool, plus the schema as an MCP resource |
| **Pipedream apps** | Thousands of SaaS apps via the [Pipedream connector](/docs/conduit/configure/pipedream) | Per-app tools with managed authentication |

Local connectors and CLI setup are hidden behind a browser-level rollout flag.
The flag controls UI visibility, not server access.

Remote MCP connectors can be added three ways: picked from the built-in
catalog (one-click entries such as Linear, Supabase, and Atlassian, with the
right transport and auth mode preselected), by URL, or from a standard MCP
`server.json` manifest. OpenAPI and GraphQL connectors take the API base URL
plus a spec — pasted in or fetched from a URL, with introspection doing the
work for GraphQL; the stored spec's freshness is shown on the connector and
can be refetched on demand.

Tools are namespaced by connector — a connector named `github` contributes
`github__create_issue` — so two connectors can expose same-named tools without
collision. What a client is shown is a shortened form of that name; see
[Connect AI Clients](/docs/conduit/use/mcp-reference#what-a-client-sees).

Details that matter in production:

* **Stateful MCP servers work.** Conduit maintains the upstream's session
  across calls and transparently re-handshakes when the upstream expires it.
* **Live updates.** Adding, changing, or removing a connector updates the tool
  lists of connected AI clients immediately, over the live MCP connection.
* **Deleting a connector** also deletes the credentials stored for it,
  including members' per-user grants.

**Upstreams on private networks** (a VPC-internal MCP server, a vendor API
behind a private endpoint) need their hostname listed in
`CONDUIT_SAFEHTTP_ALLOWED_PRIVATE_HOSTS` — see
[Network Access](/docs/conduit/deploy/network#private-endpoints-and-gateways).

## Authentication to the upstream

Each connector declares how Conduit authenticates to it. Independently of the
method, the *scope* of the credential can be **workspace** (one shared
credential an admin configures) or **per-user** (each member supplies or
connects their own) — and that choice is what determines whose identity the
upstream sees.

| Method | How it works | Credential scope |
| - | - | - |
| **None** | No credential | — |
| **Token / header** | A static bearer token or custom header value | Workspace, per-user, or both |
| **OAuth (authorization code)** | Conduit acts as an OAuth client against the upstream's authorization server; users click through a consent flow | Workspace grant, per-user grants, or both |
| **OAuth (client credentials)** | Conduit exchanges an admin-supplied client ID and secret at the upstream's token endpoint for a workspace-wide machine token — no user interaction, no per-user connect | Workspace only |

### OAuth connectors

For MCP upstreams, Conduit discovers the upstream's authorization server the
standard MCP way and **registers itself dynamically** when the upstream
supports it — zero configuration. When the upstream requires a pre-registered
client instead, the admin supplies a client ID and secret, and registers this
callback URL with the upstream:

```
https://<your-conduit-host>/upstream/callback/<key>
```

Each connector has its **own** callback URL, shown on its form — the form for
a new connector shows it before you save, so it can be registered with the
upstream first. Conduit registers it itself for a client it registers
dynamically.

By default, Conduit requests every OAuth scope the upstream advertises, plus
any scope the upstream's first `401` response asks for that isn't among them.
Discovery refuses an authorization server whose metadata names a different
issuer than the one the upstream points to. A sign-in response is refused
before its code is used when it arrives on another connector's callback URL,
when it names another authorization server, or when it names none although the
server advertised that it would (RFC 9207).

For OpenAPI, GraphQL, and other non-MCP APIs there is no discovery document,
so the admin also supplies the provider's authorization and token endpoints.
The client-credentials variant needs only the token endpoint — it has no
authorization leg.

Per-user OAuth grants (access and refresh tokens) are stored per member and
refreshed automatically; members connect once and don't re-authorize when a
token expires. A member can see and disconnect their connections on the
**Accounts** page.

### Shared credential or their own: `allow user override`

When a workspace credential exists (a stored token, or a workspace OAuth
grant), the connector setting **"Let members use their own credential
instead"** controls whether that's the *only* option:

* **Off** — everyone's calls use the workspace credential. One upstream
  identity, centrally rotated.
* **On** — members may connect their own account or store their own token,
  which then takes precedence for their calls.

The setting exists because some services have no client an admin can register
once on everyone's behalf — each user or tenant instance must create their own
(Salesforce and ServiceNow are the classic shapes). It's meaningless for the
client-credentials grant, which has no per-member form.

With no workspace credential at all, the connector is per-user by definition:
each member connects or supplies a token before the tools work for them. An AI
client whose user hasn't connected yet is guided through it in-band — see
[connecting accounts from the client](/docs/conduit/use/mcp-reference#connecting-your-accounts-from-the-client).

## Config fields: headers and environment variables

Beyond the credential, a connector can declare **config fields** — named
values the connector injects on every use. On a remote connector each field is
sent as an HTTP request header; on a local connector, as an environment
variable for the spawned process. Each field declares:

* a **label and description** for the form that collects it,
* whether it is **required**,
* whether it is **secret** (masked in the UI; values are write-only in the API
  regardless),
* its **scope**: *workspace* (the admin stores one shared value) or *user*
  (each member supplies their own on the connect page, which shows exactly
  which host the value will be sent to before they type it).

Header names that could interfere with the protocol or impersonate the
gateway's own identity headers are rejected — a connector cannot override the
headers Conduit itself sets (see the
[Pipedream identity headers](/docs/conduit/configure/pipedream#how-tool-calls-carry-identity) for
why that matters).

One caveat specific to **local** connectors: a *workspace*-scoped value is, by
design, delivered to the machine of every member who can use the connector —
that is where the process runs. Anything that shouldn't be shared that widely
belongs in a *user*-scoped field. The admin UI states this on the form.

## Where credentials live, and who can see them

* **Encrypted at rest.** Every stored secret — tokens, header values, client
  secrets, OAuth grants — is encrypted (AES-256-GCM) with the instance
  encryption key. There is no external vault dependency.
* **Write-only in the API.** No API response, admin tool, or export ever
  returns a stored secret — responses carry only "a value is set". Editing a
  connector never requires re-entering values that aren't changing.
* **Bound to where they are sent.** A stored secret is kept on an edit only
  while its destination stays the same. Changing a connector's URL needs the
  workspace token or auth headers re-entered, and changing an OAuth client's
  client ID or token endpoint (or the URL, for client credentials) needs its
  client secret re-entered — otherwise the save is refused, so nobody can
  redirect a secret they can't read. Changing the URL of an MCP connector that
  uses OAuth discovers its authorization server again for the new URL.
* **Clients never see upstream credentials.** An AI client holds only its
  Conduit-issued token. Conduit attaches the upstream credential server-side
  on each call and never forwards the client's bearer upstream — so a prompt,
  a transcript, or a compromised client can't exfiltrate an upstream secret it
  never had. The one structural exception is local connectors, whose resolved
  values must reach the member's own machine to start the process there.

You control the [instance encryption key](/docs/conduit/configure/reference#security):
supply your own via `CONDUIT_ENCRYPTION_KEY`, or let Conduit generate one in
the data directory. The database plus your key is the vault.

Credential *use* is observable even though credential *values* are not: every
tool call is recorded in [usage](/docs/conduit/use/usage) and the per-connector
[metrics](/docs/conduit/deploy/monitoring), denied calls land in the audit log, and
upstream failures surface in traces.
