Connections Overview

Purpose and Scope

Connections are eve's integration layer for external systems that an agent does not implement itself. A connection can point to a remote MCP server, such as a Linear, GitHub, or warehouse MCP endpoint, or to an HTTP API described by an OpenAPI or Swagger document. The important distinction is ownership: the external service owns the server, schema, and credentials, while eve owns the agent-facing discovery, tool surfacing, and authorization brokerage. This page explains how to choose connections, how they differ from channels and local tools, and where they fit in the filesystem-first project model.

Sources: docs/connections/overview.mdx, docs/connections/mcp.mdx, docs/connections/openapi.mdx

The core reader problem is avoiding custom glue for every third-party service. Without a connection abstraction, an agent author would need to fetch remote schemas, decide how to describe available operations to the model, inject or hide credentials, qualify tool names, and refresh tokens safely. eve treats those concerns as runtime infrastructure. The model discovers external capabilities through the built-in connection_search mechanism, then calls matched remote tools with a qualified name such as <connection>__<tool>. That gives the model a stable calling convention without exposing URLs, access tokens, or provider-specific setup details in conversation history.

Connections live in the conventional directory agent/connections/. The file stem becomes the runtime connection name, so agent/connections/linear.ts registers as linear, and remote tools under that integration are addressed with the linear__... prefix. This mirrors eve's broader filesystem-first approach: agent/agent.ts controls runtime configuration, agent/channels/ declares message surfaces, and agent/connections/ declares external systems that can become model-callable capabilities. Naming therefore becomes part of the public behavior of the agent, not just a local implementation detail.

Relevant Source Files

  • docs/connections/overview.mdx defines the connection concept, agent/connections/ convention, connection_search, qualified tool names, token behavior, and app-versus-user credential model.
  • docs/connections/mcp.mdx documents MCP connection authoring with defineMcpClientConnection, remote transport requirements, Vercel Connect OAuth, static tokens, and MCP-specific selection guidance.
  • docs/connections/openapi.mdx documents OpenAPI connection authoring with defineOpenAPIConnection, operation-derived tools, spec, baseUrl, OAuth, and generated operation naming.
  • docs/connections/meta.json establishes the public documentation grouping for the Connections section: overview, MCP, and OpenAPI.
  • docs/agent-config.md places connections in the larger agent runtime model by documenting agent.ts, defineAgent, model selection, compaction, limits, and workflow-world configuration.
  • docs/channels/custom.mdx provides the contrast point for channels: custom channels own HTTP or WebSocket routes, inbound messages, sessions, event delivery, CORS, and continuation handling rather than remote tool discovery.

Core Primitives

The first primitive is the connection definition file. Create one file under agent/connections/ and export a connection definition from it. For MCP servers, the public helper is defineMcpClientConnection; for HTTP APIs with OpenAPI or Swagger contracts, the public helper is defineOpenAPIConnection. In both cases, the filename determines the connection's identity at runtime. A linear.ts file produces the connection name linear; a petstore.ts file produces petstore. Tool names are then qualified by that name so external capabilities do not collide with local tools or with other providers.

Sources: docs/connections/mcp.mdx, docs/connections/openapi.mdx

The second primitive is the model-facing description. Connection descriptions are not just comments for maintainers. In the MCP documentation, the description is explicitly written for the model because it is a main signal used when connection_search decides which connection to query. In OpenAPI connections, the description similarly explains the provider domain, such as pet inventory, GitHub repositories, or CRM accounts. Good descriptions should name the system, the resource families, and the kinds of work the agent should attempt there. They should not include secrets, internal URLs, or implementation notes that do not help tool selection.

The third primitive is authorization. eve supports static-token authorization through auth.getToken, which returns a TokenResult shaped like { token, expiresAt? }. eve sends the token as Authorization: Bearer <token> on requests and can refresh ahead of a known expiry. The token can come from an environment variable, secrets manager, vault, service account flow, or custom OAuth exchange. The overview documentation emphasizes that tokens are resolved and cached per step, never placed in conversation history, and never shown to the model.

The fourth primitive is credential ownership. A connection can act as the app or as the user. App-scoped credentials are appropriate when the agent should use one shared bot, installation, service account, or application credential. User-scoped credentials are appropriate when each end user should use their own third-party account. User-scoped connection auth depends on session auth: eve can only resolve a user token when the active session already has a user principal from route auth or a platform channel. principalType: "user" therefore means the credential is keyed to an authenticated user already attached to the session, not that eve can ask an arbitrary human for credentials later.

Connections, Channels, and Tools

Connections are not channels. A channel is an ingress and delivery surface: it exposes HTTP or WebSocket routes, parses inbound platform events, starts or resumes sessions, streams session events, and delivers completed messages back to the platform. The custom channel documentation shows routes declared with helpers such as POST(), GET(), and WS(), plus event handlers like message.completed. A connection, by contrast, is not primarily a user-facing surface. It is an external system adapter whose remote capabilities can be discovered and invoked by the agent during a turn.

Sources: docs/channels/custom.mdx, docs/connections/overview.mdx

Connections are also different from local tools. Local tools are functions the agent project authors and owns. A connection exposes capabilities owned by a remote MCP server or generated from an external OpenAPI document. That means the remote service may define schemas dynamically, require provider-specific authorization, or update its API contract outside the agent repository. eve's connection layer gives those external operations a model-facing tool shape while keeping provider credentials out of model context. Use a local tool when the project owns the implementation; use a connection when the agent needs to operate against a third-party or separately owned service contract.

This distinction matters when designing an agent architecture. A Slack or custom webhook channel may authenticate an end user and start a session. That same session may later use a user-scoped GitHub or Linear connection because the channel or route auth attached the user principal. The channel owns the conversation transport and the session lifecycle entry point; the connection owns access to the external service; the model call chooses relevant capabilities through discovery and qualified invocation. Separating these responsibilities makes it easier to audit which code accepts requests, which code reaches external APIs, and which credentials are scoped to the app or user.

MCP Connections

Use an MCP connection when the external service already exposes a Model Context Protocol server, when that server owns tool schemas dynamically, or when one connection should expose a family of related remote tools. The MCP documentation describes the remote server as the owner of its tools and schemas, with eve exposing matching tools to the model through connection_search. The connection definition includes a url, a model-facing description, and an auth configuration. The URL must speak Streamable HTTP or SSE, which is the transport constraint called out for remote MCP connections.

Sources: docs/connections/mcp.mdx

A minimal MCP connection follows this pattern:

import { connect } from "@vercel/connect/eve";
import { defineMcpClientConnection } from "eve/connections";
 
export default defineMcpClientConnection({
  url: "https://mcp.linear.app/mcp",
  description: "Linear workspace: issues, projects, cycles, and comments.",
  auth: connect("mcp.linear.app/linear"),
});

For OAuth-backed MCP servers, the docs recommend Vercel Connect. Connect owns the browser consent flow, encrypted token storage, refresh, and project access, while the connect() helper plugs that lifecycle into eve's connection auth. By default, connect("...") is user-scoped. The first tool call for a new user can emit an authorization.required event with a URL to visit, park the turn, and resume after the callback completes. If the session has no authenticated user principal, user-scoped connection resolution fails with principal_required, which is a design signal to wire route or channel auth before invoking user-owned external accounts.

App-scoped MCP auth is the alternative for non-interactive service behavior. The connection can call connect({ connector: "mcp.linear.app/linear", principalType: "app" }), asking Connect for one shared app token. If the connector is missing or cannot issue that token, the tool call fails terminally so an operator can fix setup. Static token auth is also available with auth.getToken, which is useful for bearer tokens, API keys, service accounts, or OAuth flows managed outside Vercel Connect. In both approaches, the model sees neither the URL credential nor the token material.

OpenAPI Connections

Use an OpenAPI connection when a service publishes an OpenAPI 3.x or Swagger 2.0 document and you want eve to derive tools from the contract. The OpenAPI documentation states that eve turns operations in the document into connection tools, one per operation. The generated tool name normally uses <connection>__<operationId>, such as petstore__getInventory. When an operation lacks an operationId, eve derives a deterministic name from the HTTP method and sanitized path, which keeps the model-facing tool set stable enough to call without hand-writing every operation as a local tool.

Sources: docs/connections/openapi.mdx

A minimal OpenAPI connection follows this pattern:

import { defineOpenAPIConnection } from "eve/connections";
 
export default defineOpenAPIConnection({
  spec: "https://petstore3.swagger.io/api/v3/openapi.json",
  description: "Pet store inventory and orders.",
  auth: { getToken: async () => ({ token: process.env.PETSTORE_TOKEN! }) },
});

The spec can be an HTTPS URL fetched at runtime or an inline parsed OpenAPI object. Prefer a URL when the provider owns the contract and updates it. Prefer an inline object when the API is private, generated and pinned in source control, or small enough to hand-author safely. Operation paths resolve against an explicit baseUrl when provided. Otherwise, eve derives a base URL from the spec: OpenAPI 3.x uses the first usable servers entry, while Swagger 2.0 uses schemes, host, and basePath. Set baseUrl when the provider spec points at the wrong environment or lacks usable server data.

OAuth-backed OpenAPI APIs can also use Vercel Connect. The docs show installing @vercel/connect, linking the Vercel project, creating and attaching a connector, pulling environment, and then using connect("github/github") or an app-scoped connect({ connector: "github/github", principalType: "app" }). This makes OpenAPI connections suitable for user-owned APIs such as GitHub as well as app-owned integrations. The same security boundary applies: Connect and eve handle token storage and refresh without putting credentials into model-visible context.

System-to-Code Mapping

The Connections documentation is organized as a small, explicit docs section. docs/connections/meta.json lists the pages as overview, mcp, and openapi, which matches the conceptual split: first understand the abstraction, then choose the transport and schema source. The overview page defines the common contract: filesystem location, runtime naming, discovery with connection_search, qualified tool invocation, static-token auth, and credential ownership. The MCP and OpenAPI pages specialize that contract for remote MCP servers and OpenAPI-derived HTTP operation tools.

Sources: docs/connections/meta.json, docs/connections/overview.mdx

The agent runtime configuration page is relevant because it describes the root agent/agent.ts file and defineAgent as the place to choose model and runtime behavior. Connections are not configured there in the supplied docs; they are discovered by filesystem convention under agent/connections/. That separation keeps model/runtime policy in agent.ts and external service integration declarations in their own directory. When onboarding a new project, read agent.ts for global behavior such as model, reasoning, compaction, limits, and workflow world, then inspect agent/connections/ to understand what remote systems the agent can reach.

Sources: docs/agent-config.md, docs/connections/overview.mdx

A compact decision reference is:

NeedUseAuthoring locationPublic helper or APIModel-facing result
External server with MCP tools and schemasMCP connectionagent/connections/<name>.tsdefineMcpClientConnectionMatched tools called as <connection>__<tool>
HTTP API with OpenAPI or Swagger contractOpenAPI connectionagent/connections/<name>.tsdefineOpenAPIConnectionOne generated tool per operation
User or platform ingressChannelagent/channels/<id>.tsdefineChannel, GET, POST, WSSessions, route handlers, streams, events
Project-owned callable functionLocal toolAgent tool filesTool APIs outside this pageDirect model-callable local capability

Implementation and Security Notes

The most important security property is that connection credentials are not model context. The overview states that the model never sees a connection's URL or credentials, and both MCP and OpenAPI pages repeat that Vercel Connect and eve keep tokens out of conversation history. This is stronger than merely telling the model not to reveal secrets. The runtime resolves tokens at the connection boundary, sends bearer tokens on requests when appropriate, and caches per step. Developers should preserve that boundary by keeping descriptions concise and non-secret, avoiding hard-coded credentials in source, and using environment variables, Connect, or secret managers for token material.

Static-token auth defaults to app-scoped ownership when it is the only auth shape. That is a safe default for service accounts and bot tokens, but it is not always the correct product behavior. If a user asks an agent to file an issue in their own account, the connection should be user-scoped and the session must already carry that user's principal. If a nightly job syncs warehouse data using one service account, app scope is simpler and more auditable. Choosing scope is therefore both a security decision and a product decision about whose authority the agent is exercising.

A useful build sequence is to start with the external system's contract. If it publishes an MCP server with rich tool semantics, define an MCP connection and write a description that helps connection_search select it. If it publishes a stable HTTP API contract, define an OpenAPI connection, decide whether spec should be remote or inline, and pin baseUrl when environment selection matters. Then choose auth: Vercel Connect for OAuth-backed providers, getToken for existing bearer-token or service-account flows, and explicit principalType when the default ownership does not match your authorization model.

Next Steps

After this overview, read the MCP and OpenAPI pages according to the provider you need to connect. If the provider already has an MCP endpoint, continue with MCP connection setup, transport requirements, Vercel Connect OAuth, and tool filtering. If the provider exposes an OpenAPI or Swagger document, continue with OpenAPI connection setup, spec, baseUrl, operation naming, OAuth, and operation filters. If you are deciding how users reach the agent in the first place, read the channels documentation next, especially custom channels, because channels provide routes, streams, event delivery, and the session auth context that user-scoped connections depend on.