Skip to content
Docs

TypeScript SDK Reference

@vercel/connect is the TypeScript SDK for calling Edgenivo Connect from your app. It authenticates with your Edgenivo deployment's OIDC token and exchanges it for provider tokens through the Edgenivo API. SDK methods that make API requests are subject to rate limits.

For Python, see the Python SDK Reference.

terminal
pnpm add @vercel/connect

The SDK has one runtime dependency, @vercel/oidc, which reads VERCEL_OIDC_TOKEN from the environment.

In a Edgenivo deployment, the SDK reads VERCEL_OIDC_TOKEN automatically. For local development, run vercel link followed by vercel env pull to download a development token into .env.local. The token is short-lived; re-run vercel env pull if you see authentication errors.

To override the token explicitly, pass options.vercelToken:

app/lib/explicit-token.ts
import { getToken } from '@vercel/connect';
 
const token = await getToken(
  'slack/acme-slack',
  { subject: { type: 'app' } },
  { vercelToken: process.env.MY_VERCEL_TOKEN },
);

See Authentication for the full caller-to-Edgenivo-Connect story.

Returns the access token string. Use when you just need the token to put in an Authorization header.

signature
function getToken(
  connector: string,
  params: ConnectTokenParams,
  options?: ConnectOptions,
): Promise<string>;

Minimal example:

app/lib/post-to-slack.ts
import { getToken } from '@vercel/connect';
 
const token = await getToken('slack/acme-slack', {
  subject: { type: 'app' },
  scopes: ['chat:write'],
});
 
await fetch('https://slack.com/api/chat.postMessage', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${token}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ channel: 'C123', text: 'hello' }),
});

This omits installationId and falls back to the connector's default installation, which is the predominant case (a private app installed in a single workspace). Pass installationId explicitly only for multi-tenant connectors where you need to address a specific installation. See Installations.

Returns the full response: the token, its expiry, the connector identity, and provider metadata. Use when your app needs more than the raw string, for example to display the connected workspace name or to decide whether to surface a re-authorize button.

signature
function getTokenResponse(
  connector: string,
  params: ConnectTokenParams,
  options?: ConnectOptions,
): Promise<ConnectTokenResponse>;

Minimal example:

app/lib/inspect-token.ts
import { getTokenResponse } from '@vercel/connect';
 
const response = await getTokenResponse('slack/acme-slack', {
  subject: { type: 'app' },
});
 
console.log(response.connector.uid);
console.log(response.tenantId);
console.log(new Date(response.expiresAt).toISOString());

Returns the connector's stable public metadata and provider-specific configuration. Use it when your app needs connector setup values in addition to a runtime token, such as a Snowflake account identifier.

signature
function getConnectorMetadata(
  connector: string,
  options?: ConnectOptions,
): Promise<ConnectorMetadata>;
app/lib/snowflake.ts
import { getConnectorMetadata } from '@vercel/connect';
 
const connector = await getConnectorMetadata('snowflake/analytics');
const accountIdentifier = connector.vendor.accountIdentifier as string;
 
console.log(connector.name);
console.log(accountIdentifier);

The calling project and environment must be linked to the connector, just as they must be for getToken.

Use @vercel/connect@2.5.2 or later for the experimental MCP event APIs below. The MCP server must support the webhook events extension. See MCP Events for a complete subscription and receiver example, including deployment requirements.

Import the direct APIs and delivery verifier from @vercel/connect/mcp. Import the AI SDK adapter from @vercel/connect/ai-sdk.

Direct API methods take (connector, params, options?). connector is the connector identifier, such as oauth/documents. Build account scope from trusted application state, not model output or an unverified request body.

Parameter typeFields
Experimental_McpEventScopetokenParams: ConnectTokenParams. Selects the authorized account and credential constraints.
Experimental_McpEventSourceInputScope plus optional mcpUrl: string. Defaults to the connector endpoint. Connect must authorize the URL before sending provider credentials.
Experimental_McpSubscriptionLookupInputid: string and optional expectedSubject: ConnectTokenParams['subject']. Account-bound callers should always pass expectedSubject; it asserts the stored creation subject rather than requesting new credentials.

All direct methods accept Experimental_McpEventOptions as their optional third argument:

OptionTypeBehavior
vercelTokenstringOverrides the calling workload's Edgenivo OIDC token.
regionstringSelects the Connect API region; defaults to VERCEL_REGION.
signalAbortSignalCancels the request. It does not cancel an already accepted subscription.
timeoutnumberRequest deadline in milliseconds, including credential resolution.
maxTotalTimeoutnumberOverall deadline in milliseconds. The earlier supplied deadline wins.

Non-success API responses use the Connect error types.

Checks event support for an authorized connection. This does not create a subscription or retrieve event occurrences.

  • Parameters: Experimental_McpEventSourceInput.
  • Returns: Promise<{ status: 'supported' | 'unsupported' | 'unavailable' | 'needs_auth' }>.

unsupported means the server does not support events. unavailable means discovery could not establish support; don't treat it as confirmed lack of support. needs_auth requires account authorization before discovery can complete.

Lists event definitions from the authorized server's catalog.

  • Parameters: Experimental_McpEventSourceInput plus optional cursor: string.
  • Returns: Promise<{ events: Experimental_McpEventDescriptor[]; nextCursor?: string }>.

Each descriptor includes name, optional description, inputSchema, payloadSchema, and delivery modes (webhook, poll, or push). Follow nextCursor until absent. Catalog discovery does not poll for occurrences; Connect subscriptions use webhook delivery.

Creates a subscription and returns Promise<Experimental_McpSubscription>. The input type is Experimental_McpSubscribeInput:

FieldTypeRequiredBehavior
tokenParamsConnectTokenParamsYesAuthorized account and credential constraints.
mcpUrlstringNoOverrides the connector's MCP endpoint, subject to backend validation.
namestringYesEvent name from the catalog.
argumentsRecord<string, unknown>YesArguments matching the event's inputSchema.
destination{ path: string }YesPublic receiver path in the calling project/environment, such as /hooks.
contextRecord<string, unknown>NoApplication context included in forwarded deliveries. This is not an authorization boundary.
idempotencyKeystringYesReuse for retries of the same creation intent. Use a new key for a new subscription.
ttlMsnumber | nullYesApplication monitoring duration in milliseconds. Use an integer from 120000 to 31536000000 (two minutes to 365 days), or null to monitor until stopped.

Pass ttlMs: null for an indefinite watch. Connect manages provider lease renewal separately from this application lifetime. Omitting ttlMs, supplying an invalid duration, or passing expiresAt throws a TypeError before the SDK sends a request. Responses still include the resolved expiresAt deadline.

Creation can return pending while upstream registration finishes. Persist the returned ID and its authorized application binding.

Lists subscriptions for the connector, account, and calling project/environment. The list is not scoped to a conversation or the subscription's context.

  • Parameters: Experimental_McpEventScope plus optional cursor: string, limit: number, and status: Experimental_McpSubscriptionStatus.
  • Returns: Promise<{ subscriptions: Experimental_McpSubscription[]; pagination: { next: string | null } }>.

Pass pagination.next as the next request's cursor. A null value ends pagination. This differs from event catalog and AI SDK adapter pagination, which use nextCursor.

Retrieves a subscription by ID after checking access.

  • Parameters: Experimental_McpSubscriptionLookupInput.
  • Returns: Promise<Experimental_McpSubscription>.

Pass expectedSubject when looking up a subscription on behalf of an account. Knowing a subscription ID does not establish ownership.

Stops local delivery and attempts provider cleanup.

  • Parameters: Experimental_McpSubscriptionLookupInput.
  • Returns: Promise<Experimental_McpSubscription>.

Pass expectedSubject for account-bound calls. A response with status: 'stopped' and cleanupStatus: 'pending' means local delivery has stopped but provider cleanup remains unfinished. Retry unsubscribe to finish cleanup.

Requests a bulk stop for the connector, subject, and calling project/environment.

  • Parameters: Experimental_McpEventScope plus required idempotencyKey: string.
  • Returns: Promise<{ accepted: true }>.

This affects every subscription in that scope, not just one conversation or receiver path. accepted: true acknowledges the request; it does not mean every provider subscription has finished cleanup.

Direct subscribe, get, and unsubscribe calls return this object. Direct list calls return an array of these objects.

FieldsType / meaning
id, connectorId, projectId, environmentStrings identifying the subscription and its saved scope.
subjectExperimental_McpEventSubject: an app or user subject.
name, argumentsEvent name and Record<string, unknown> arguments.
destination{ path: string }.
contextSaved Record<string, unknown> application context.
statuspending, active, needs_auth, stopped, expired, or failed.
expiresAtISO application deadline or null.
createdAt, updatedAtTimestamp strings.
cleanupStatusOptional pending, complete, or exhausted provider cleanup state.
stopReason, lastErrorOptional diagnostic strings.

See subscription lifecycle for status handling and cleanup behavior.

Returns an Experimental_ConnectEventsAdapter for AI SDK's experimental_events.adapter. It is exported from @vercel/connect/ai-sdk. Use @ai-sdk/mcp@2.0.76 or later with @vercel/connect@2.5.2 or later so both packages use the ttlMs creation input.

OptionTypeRequiredBehavior
connectorstringYesConnector identifier.
tokenParamsConnectTokenParamsYesPass the same resolved parameters as connectAuthProvider. Create a separate adapter for each account.
destination{ path: string }YesRegistered receiver path.
mcpUrlstringNoOverrides the MCP client's transport URL. Connect must authorize this endpoint.

The returned adapter implements synchronous createAdapter({ transport }). AI SDK supplies { type: 'http' | 'sse', url: string } or { type: 'custom' }. For custom transports without an explicit mcpUrl, Connect uses the connector's configured endpoint. You don't need to wrap the adapter in another factory.

The bound operations are:

OperationInputResult
subscribename, JSON arguments, idempotencyKey, required ttlMs: number | null, optional JSON context and options.Experimental_ConnectEventsSubscription.
getSubscription{ id, options? }.Experimental_ConnectEventsSubscription.
listSubscriptionsOptional { cursor?, limit?, status?, options? }.{ subscriptions: Experimental_ConnectEventsSubscription[]; nextCursor?: string }.
unsubscribe{ id, options? }.Experimental_ConnectEventsSubscription.

The adapter uses the same subscription lifetime rules as the direct API.

All operations return promises. Experimental_ConnectEventsSubscription contains id, name, JSON arguments, status, expiresAt, and optional cleanupStatus. The adapter binds account scope and automatically supplies expectedSubject for get and unsubscribe. Its request options accept only signal, timeout, and maxTotalTimeout; they cannot override workload identity or API region.

Event catalog discovery remains an MCP request through the AI SDK client. Subscription operations use Connect. See the AI SDK subscription example.

Authenticates a forwarded Connect delivery and validates its envelope:

signature
import type {
  Experimental_McpEventDelivery,
  Experimental_VerifyMcpEventOptions,
} from '@vercel/connect/mcp';
 
declare function experimental_verifyMcpEvent(
  request: Request,
  options: Experimental_VerifyMcpEventOptions,
): Promise<Experimental_McpEventDelivery>;
OptionTypeBehavior
pathstringRequired registered public receiver path, from trusted server configuration.
projectIdstringDefaults to VERCEL_PROJECT_ID. No wildcards.
environmentstringDefaults to VERCEL_TARGET_ENV, then VERCEL_ENV.
customEnvironmentIdstringRequired for a Custom Environment; use its stable env_... ID.
ownerIdstringAdditional restriction; defaults to VERCEL_ORG_ID when set.
audiencestringOptional expected Edgenivo OIDC audience, normally /<team-slug>.
issuerstringOptional expected project OIDC issuer: global or team-specific.
branchstringPreview verification binding; defaults to VERCEL_GIT_COMMIT_REF. Subscription creation currently rejects Preview.

The function consumes the request body. It does not acknowledge delivery, deduplicate it, or run application work. Durably accept by deliveryId before returning success. Use this verifier for Connect-forwarded envelopes, not AI SDK's experimental_createMCPEventWebhook helper for direct provider webhooks.

Experimental_McpEventDelivery includes version: 1, deliveryId, subscriptionId, source: { type: 'mcp', connectorId }, and saved context, plus one of:

  • event: eventId, name, timestamp, JSON data, nullable cursor, and optional _meta.
  • control.type: 'gap': nullable cursor and optional truncated: true.
  • control.type: 'terminated': error with numeric code, message, and optional data.

Verification failures throw Experimental_McpEventVerificationError:

codeMeaning
invalid_deliveryThe delivery cannot be authenticated or its envelope/binding is invalid.
configuration_errorRequired trusted receiver configuration is missing or invalid.
verification_unavailableVerification could not complete, for example because signing keys could not be fetched.

Reject invalid deliveries. Treat configuration and verification availability failures as retryable receiver failures rather than acknowledging or processing the event. See the receiver example.

FieldTypeRequiredDescription
subjectConnectTokenSubject (see below)yesWho the token represents. See Tokens.
installationIdstringnoWhich tenant the token is for. Pass '*' for a cross-installation token where the connector supports it. See Installations.
audiencestring[]noProvider audience claim. Used when the provider requires a specific audience in the issued token.
scopesstring[]noProvider scope strings (chat:write, repo:read, etc.). Pass ['*'] to request the connector's default scopes for the selected subject type.
resourcesstring[]noResource indicators that narrow the token to a specific provider resource (channel, repo, record set). SDK-only.
authorizationDetailsArray<{ type: string } & Record<string, unknown>>noRich authorization requests, when the provider supports them. SDK-only.
validityBufferMsnumbernoRefresh the token if it expires within this many milliseconds. Defaults to 30000 (30 seconds).

A union with four variants:

@vercel/connect
type ConnectTokenSubject =
  | { type: 'app' }
  | { type: 'user'; id: string; issuer?: string }
  | {
      type: 'jwt-bearer';
      sub: string;
      iss?: string;
      aud?: string;
      additionalClaims?: Record<string, unknown>;
    }
  | { type?: 'token'; token: string };
VariantRequired fieldsOptional fields
appnonenone
useridissuer (the OIDC issuer of the user id, when not the default)
jwt-bearersubiss (defaults to the connector's OAuth client id), aud (defaults to the connector's OAuth token endpoint), additionalClaims
tokentoken (a string)type (defaults to 'token' in SDK 2.4.0 and later)

The SDK infers type: 'token' for subject: { token: '...' } before sending the request. Other variants require their explicit type.

FieldTypeDescription
tokenstringThe access token to send to the provider.
tokenIdstring | undefinedPer-issuance identifier (stk_…) for correlating the token with Connect observability and usage data.
expiresAtnumberToken expiration as a Unix timestamp in milliseconds.
connector.idstringOpaque internal identifier for the connector.
connector.uidstringHuman-readable connector identifier (the same string you passed as the first arg).
connector.typestringThe connector type (slack, github, linear, microsoft-entra, oauth, snowflake, salesforce, api-key, custom).
namestring | undefinedHuman-readable connector or installation name, when known.
installationIdstring | undefinedThe installation this token was issued against, when applicable.
tenantIdstring | undefinedProvider's own tenant identifier (Slack team ID, GitHub org ID, Microsoft tenant GUID).
externalSubjectstring | undefinedThe subject identifier at the provider (for example, the Slack user ID for a user-subject token).
metadataRecord<string, unknown> | undefinedDriver-specific metadata stored during OAuth (varies by provider).
claimsRecord<string, unknown> | undefinedAllow-listed claims propagated from the upstream provider token.
FieldTypeDescription
idstringOpaque internal connector identifier.
uidstringHuman-readable connector identifier.
namestringConnector display name.
typestringConnector type, such as snowflake or oauth.
servicestringService the connector integrates with.
clientUrlstring | undefinedFully qualified service URL, when Edgenivo Connect can derive it.
createdAtnumberCreation time as a Unix timestamp in milliseconds.
updatedAtnumberLast update time as a Unix timestamp in milliseconds.
vendorRecord<string, unknown>Provider-specific public configuration stored on the connector.
FieldTypeDescription
vercelTokenstringOverride the OIDC token the SDK reads from the environment. Useful for tests and non-Edgenivo runtimes.
forceRefreshbooleanFor getToken and getTokenResponse, bypass the in-process cache and revalidate the grant with Edgenivo Connect.

Revokes the provider grant for a connector subject and clears the SDK's in-process token cache. Provider support for revocation varies; see Revocation.

Rate limit: 50 requests per minute per team (write operation).

app/lib/disconnect.ts
import { revokeToken } from '@vercel/connect';
 
await revokeToken('oauth/linear', {
  subject: { type: 'user', id: 'user_123' },
});

Removes one cached token without revoking its provider grant. Pass the same connector and complete request parameters that you used for getToken or getTokenResponse. The next request for that cache entry fetches a fresh token.

app/lib/retry-token.ts
import { deleteTokenCacheEntry, getToken } from '@vercel/connect';
 
const params = {
  subject: { type: 'app' as const },
  scopes: ['chat:write'],
};
 
let token = await getToken('slack/acme-slack', params);
 
// If Slack rejects this token with a 401:
deleteTokenCacheEntry('slack/acme-slack', params);
token = await getToken('slack/acme-slack', params);

The SDK maintains an in-process LRU cache with a maximum of 100 entries, keyed by the connector and the full request params. Cached tokens are reused on subsequent calls until they fall inside the validityBufferMs window, at which point the next call fetches a fresh one.

Pass { forceRefresh: true } in ConnectOptions to bypass the cache for a request. Use deleteTokenCacheEntry when you only need to discard one rejected token while preserving normal caching for future calls.

The SDK throws typed error classes you can match on with instanceof:

ErrorCause
NoValidTokenErrorThe connector exists but cannot produce a token for this request. The grant may have been revoked at the provider.
UserAuthorizationRequiredErrorThe request used a { type: 'user' } subject and that user has not authorized the connector. Surface a "connect your account" UI.
ConnectorInstallationRequiredErrorThe connector type requires an installation and none matches the request. Surface an install link.
ConnectorNotFoundErrorThe team has no connector registered under the given uid.
ClientNotLinkedToProjectErrorThe calling project is not linked to this connector. See Project links.
ClientNotEnabledForEnvironmentErrorThe link exists but does not include the environment the OIDC token was issued for.

Most SDK calls have a vercel connect CLI equivalent. The CLI supports --subject, --installation-id, and --scopes. The SDK additionally supports resources and authorizationDetails, which are not exposed through the CLI. The CLI supports --triggers on vercel connect attach, which has no SDK equivalent.

  • Quickstart: Create a connector and request your first token from TypeScript.
  • Python SDK Reference: The same API for Python.
  • Tokens: How a token request is shaped and what each field does.
  • Authentication: What the OIDC token carries and how the API checks it.
Last updated October 8, 2026

Was this helpful?

supported.