docs: split connections pages (#273)

Signed-off-by: Allen Zhou <46854522+allenzhou101@users.noreply.github.com>
This commit is contained in:
Allen Zhou
2026-06-24 19:58:06 -07:00
committed by GitHub
parent 55af52ed1b
commit 60802a8e69
13 changed files with 194 additions and 95 deletions
+1 -1
View File
@@ -5,7 +5,7 @@ import { Gallery } from "./components/gallery";
const title = "Integrations";
const description =
"Browse every third-party service eve connects to: messaging channels and MCP connections, each with install, quick start, and configuration steps.";
"Browse every third-party service eve connects to: messaging channels, MCP connections, and OpenAPI connections, each with install, quick start, and configuration steps.";
export const metadata: Metadata = {
title,
@@ -175,7 +175,7 @@ export const buildConnectionConfigure = (integration: Integration): string => {
}
sections.push(
"See the [Connections docs](/docs/connections) for principal types, headers, approval, and tool filters.",
"See the [Connections docs](/docs/connections) for principal types, headers, approval, and protocol-specific filters.",
);
return sections.join("\n\n");
};
+3 -3
View File
@@ -310,7 +310,7 @@ Point your frontend at the session routes eve serves (\`/eve/v1/session\`) and s
const connectionPresentations: Record<string, ConnectionPresentation> = {
linear: {
logo: "linear",
docsHref: "/docs/connections",
docsHref: "/docs/connections/mcp",
keywords: ["mcp", "issues", "project management", "oauth", "connect"],
authModes: ["user", "app"],
},
@@ -324,7 +324,7 @@ const connectionPresentations: Record<string, ConnectionPresentation> = {
},
datadog: {
logo: "datadog",
docsHref: "/docs/connections",
docsHref: "/docs/connections/mcp",
keywords: ["mcp", "observability", "metrics", "monitoring", "logs"],
authModes: ["jwtBearer"],
configureNote:
@@ -332,7 +332,7 @@ const connectionPresentations: Record<string, ConnectionPresentation> = {
},
honeycomb: {
logo: "honeycomb",
docsHref: "/docs/connections",
docsHref: "/docs/connections/mcp",
keywords: ["mcp", "observability", "traces", "queries"],
authModes: ["jwtBearer"],
},
+1 -1
View File
@@ -41,7 +41,7 @@ Read in this order:
6. [Context Control](./concepts/context-control.md)
7. [Skills](./skills.mdx)
8. [Tools](./tools/overview.mdx)
9. [Connections](./connections.mdx)
9. [Connections](./connections/overview.mdx)
10. [Sandboxes](./sandbox.mdx)
11. [Channels](./channels/overview.mdx)
12. [Session Context](./reference/typescript-api.md)
+1 -1
View File
@@ -158,4 +158,4 @@ For issue or comment targets, the channel calls Linear's proactive Agent Session
## What to read next
- [Channels overview](./overview): the channel contract and every built-in channel
- [Connections](../connections): use the Linear MCP connection when the agent needs to inspect or edit Linear data from another channel
- [MCP connections](../connections/mcp): use the Linear MCP connection when the agent needs to inspect or edit Linear data from another channel
+61
View File
@@ -0,0 +1,61 @@
---
title: "MCP Connections"
description: "Connect an eve agent to a remote MCP server and control which tools the model can discover."
---
MCP connections point eve at an MCP server you do not author. The server publishes its tools and schemas, and eve exposes matched tools to the model through `connection_search`.
Use MCP when the service already has an MCP server, when the server needs to own tool schemas dynamically, or when one connection should expose a family of related remote tools.
## Define an MCP connection
`defineMcpClientConnection` needs a `url` and a `description`:
```ts title="agent/connections/linear.ts"
import { defineMcpClientConnection } from "eve/connections";
export default defineMcpClientConnection({
url: "https://mcp.linear.app/sse",
description: "Linear workspace: issues, projects, cycles, and comments.",
auth: {
getToken: async () => ({ token: process.env.LINEAR_API_TOKEN! }),
},
});
```
The `url` must speak Streamable HTTP or SSE. Write the `description` for the model, not for yourself. It shows up in `connection_search`, and the model uses it to decide which connection to query.
The file path provides the connection name. `agent/connections/linear.ts` registers as `linear`, and remote tools appear as `linear__<tool>` after discovery.
## Tool filters
To narrow which remote tools the model sees, set exactly one of `tools.allow` or `tools.block`. Filtered-out tools do not appear in `connection_search`:
```ts title="agent/connections/linear.ts"
import { defineMcpClientConnection } from "eve/connections";
export default defineMcpClientConnection({
url: "https://mcp.linear.app/sse",
description: "Linear: read-only.",
auth: { getToken: async () => ({ token: process.env.LINEAR_API_TOKEN! }) },
tools: { allow: ["search_issues", "get_issue"] },
});
```
Use `allow` for the smallest safe surface, especially on MCP servers that expose write tools alongside read tools. Use `block` only when the server has a broad stable surface and you need to hide a few tools.
## Auth, headers, and approval
MCP connections support the shared connection options:
- `auth` for static tokens, Vercel Connect, or self-hosted interactive OAuth.
- `headers` for API-key schemes or extra server configuration.
- `approval` for human-in-the-loop gates before connection tools run.
See [Connections](/docs/connections) for the shared auth, headers, and approval shapes.
## What to read next
- [OpenAPI connections](./openapi): generate tools from OpenAPI operations.
- [Auth & route protection](../guides/auth-and-route-protection): the full interactive-OAuth flow with Vercel Connect.
- [Security model](../concepts/security-model): how connection credentials stay out of the model's reach.
+4
View File
@@ -0,0 +1,4 @@
{
"title": "Connections",
"pages": ["overview", "mcp", "openapi"]
}
+68
View File
@@ -0,0 +1,68 @@
---
title: "OpenAPI Connections"
description: "Turn an OpenAPI 3.x document into eve connection tools, one tool per operation."
---
OpenAPI connections turn any OpenAPI 3.x document into connection tools, one per operation. Use OpenAPI when a service already publishes an HTTP API contract and you want eve to derive the model-facing tools from that contract.
## Define an OpenAPI connection
`defineOpenAPIConnection` takes an HTTPS URL that eve fetches at runtime, or an inline parsed object:
```ts title="agent/connections/petstore.ts"
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! }) },
});
```
Each operation becomes `<connection>__<operationId>` (e.g. `petstore__getInventory`). When an operation has no `operationId`, eve derives a deterministic `<method>_<sanitized-path>` name instead.
The file path provides the connection name. `agent/connections/petstore.ts` registers as `petstore`, so operation tools are qualified under `petstore__`.
## OpenAPI fields
OpenAPI connections use the shared connection fields from [Connections](/docs/connections), plus two OpenAPI-specific fields:
| Field | Purpose |
| ------------ | ------------------------------------------------------------------------------------------------------------- |
| `baseUrl` | Base URL operation paths resolve against. Optional; defaults to the document's first usable `servers` entry. |
| `operations` | Filter keyed on `operationId` (`allow` or `block`). Mirrors `tools` on MCP connections, but names operations. |
Use `baseUrl` when the spec's `servers` list is absent, points at the wrong environment, or needs to be pinned for this agent.
## Operation filters
To narrow which generated tools the model sees, set exactly one of `operations.allow` or `operations.block`:
```ts title="agent/connections/petstore.ts"
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! }) },
operations: { allow: ["getInventory", "placeOrder"] },
});
```
Filters match `operationId`. If an operation does not declare one, use the deterministic name eve derives from the method and path.
## Auth, headers, and approval
OpenAPI connections support the shared connection options:
- `auth` for static tokens, Vercel Connect, or self-hosted interactive OAuth.
- `headers` for API-key schemes or extra server configuration.
- `approval` for human-in-the-loop gates before generated operation tools run.
See [Connections](/docs/connections) for the shared auth, headers, and approval shapes.
## What to read next
- [MCP connections](./mcp): connect to remote MCP servers.
- [Auth & route protection](../guides/auth-and-route-protection): the full interactive-OAuth flow with Vercel Connect.
- [Security model](../concepts/security-model): how connection credentials stay out of the model's reach.
@@ -1,6 +1,7 @@
---
title: "Connections"
description: "Expose external MCP and OpenAPI servers to the model, with connection tokens the model never sees."
url: /connections
---
A connection wires an agent into an external server you don't author, either an MCP server (Linear, GitHub, a warehouse) or any HTTP API with an OpenAPI document. eve handles the parts you'd otherwise hand-roll, discovering the remote tools, surfacing them to the model, and brokering auth.
@@ -9,23 +10,17 @@ Connections live under `agent/connections/`. The runtime name comes from the fil
## MCP connections
`defineMcpClientConnection` points at an MCP server. Supply a `url` and a `description`:
Use an MCP connection when the external service already exposes an MCP server. The server publishes its tools and schemas, and eve makes the matched tools callable by the model.
```ts title="agent/connections/linear.ts"
import { defineMcpClientConnection } from "eve/connections";
Read [MCP connections](/docs/connections/mcp) for `defineMcpClientConnection`, transport requirements, and MCP tool filters.
export default defineMcpClientConnection({
url: "https://mcp.linear.app/sse",
description: "Linear workspace: issues, projects, cycles, and comments.",
auth: {
getToken: async () => ({ token: process.env.LINEAR_API_TOKEN! }),
},
});
```
## OpenAPI connections
The `url` must speak Streamable HTTP or SSE. Write the `description` for the model, not for yourself. It shows up in `connection_search`, and the model uses it to decide which connection to query.
Use an OpenAPI connection when the service exposes an OpenAPI 3.x document. eve turns operations in the document into connection tools, one per operation.
### Static-token auth
Read [OpenAPI connections](/docs/connections/openapi) for `defineOpenAPIConnection`, `baseUrl`, and operation filters.
## Static-token auth
`getToken` returns a `TokenResult` (`{ token, expiresAt? }`), and eve sends it as `Authorization: Bearer <token>` on every request. Because it runs on each connection attempt, you can mint a fresh token from wherever you keep secrets, including an env var, a secrets manager, an internal vault, or your own OAuth exchange. If the token has a known TTL, set `expiresAt` (milliseconds since epoch) and eve refreshes ahead of time rather than waiting for a `401`.
@@ -33,24 +28,28 @@ When `getToken` is the only auth, `principalType` defaults to `"app"`: one share
eve resolves and caches connection tokens per step; they never land in conversation history or reach the model.
### No auth
## No auth
Drop `auth` entirely for servers that need no token, such as a localhost server during development or a public one:
```ts
```ts title="agent/connections/local.ts"
import { defineMcpClientConnection } from "eve/connections";
export default defineMcpClientConnection({
url: "http://localhost:3001/mcp",
description: "Local dev server.",
});
```
We recommend using no-auth connections only for services that are intentionally public, local-only, or otherwise protected outside eve. Do not use no-auth connections for sensitive third-party services.
Use no-auth connections only for services that are intentionally public, local-only, or otherwise protected outside eve. Do not use no-auth connections for sensitive third-party services.
### Headers
## Headers
Use `headers` when the server wants a non-Bearer scheme (an API-key header) or extra configuration. Headers stack on top of `auth`:
Use `headers` when the server wants a non-Bearer scheme (an API-key header) or extra configuration. Headers stack on top of `auth` and work for both MCP and OpenAPI connections:
```ts title="agent/connections/example.ts"
import { defineMcpClientConnection } from "eve/connections";
```ts
export default defineMcpClientConnection({
url: "https://example.com/mcp",
description: "Example service.",
@@ -58,24 +57,12 @@ export default defineMcpClientConnection({
});
```
### Tool filters
To narrow which remote tools the model sees, set exactly one of `tools.allow` or `tools.block`. Filtered-out tools do not appear in `connection_search`:
```ts
export default defineMcpClientConnection({
url: "https://mcp.linear.app/sse",
description: "Linear: read-only.",
auth: { getToken: async () => ({ token: process.env.LINEAR_API_TOKEN! }) },
tools: { allow: ["search_issues", "get_issue"] },
});
```
### Per-connection approval
## Per-connection approval
To put every tool a connection serves behind a human, use the helpers from `eve/tools/approval`:
```ts
```ts title="agent/connections/linear.ts"
import { defineMcpClientConnection } from "eve/connections";
import { once } from "eve/tools/approval";
export default defineMcpClientConnection({
@@ -86,32 +73,9 @@ export default defineMcpClientConnection({
});
```
`never()` lets every call through, `once()` asks for approval the first time in a session, and `always()` asks every time. The pause and resume is the same human-in-the-loop flow covered in [Tools](./tools).
`never()` lets every call through, `once()` asks for approval the first time in a session, and `always()` asks every time. The pause and resume is the same human-in-the-loop flow covered in [Tools](/docs/tools).
For connection tools that can create, modify, delete, transmit, purchase, message, or access sensitive data, use approval, tool allow-lists, or other safeguards appropriate to the action.
## OpenAPI connections
`defineOpenAPIConnection` turns any OpenAPI 3.x document into connection tools, one per operation. Pass an HTTPS URL eve fetches at runtime, or an inline parsed object:
```ts title="agent/connections/petstore.ts"
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! }) },
});
```
Each operation becomes `<connection>__<operationId>` (e.g. `petstore__getInventory`). When an operation has no `operationId`, eve derives a deterministic `<method>_<sanitized-path>` name instead.
`auth`, `headers`, and `approval` work exactly as they do for MCP. There are two fields specific to OpenAPI:
| Field | Purpose |
| ------------ | ----------------------------------------------------------------------------------------------------------------------- |
| `baseUrl` | Base URL operation paths resolve against. Optional; defaults to the document's first usable `servers` entry. |
| `operations` | Filter keyed on `operationId` (`allow` or `block`). Mirrors `tools` on MCP connections, but names operations not tools. |
For connection tools that can create, modify, delete, transmit, purchase, message, or access sensitive data, use approval, allow-lists, or other safeguards appropriate to the action.
## Interactive OAuth via Vercel Connect
@@ -128,7 +92,7 @@ export default defineMcpClientConnection({
});
```
`"linear/myagent"` is the UID you chose when registering the Connect client. Connect-managed OAuth is user-scoped by default, so the runtime resolves the per-user token before each tool call. The full setup (Connect client provisioning, project linking, the runtime consent flow) lives in [Auth & route protection](./guides/auth-and-route-protection).
`"linear/myagent"` is the UID you chose when registering the Connect client. Connect-managed OAuth is user-scoped by default, so the runtime resolves the per-user token before each tool call. The full setup (Connect client provisioning, project linking, the runtime consent flow) lives in [Auth & route protection](/docs/guides/auth-and-route-protection).
## Self-hosted interactive OAuth
@@ -236,7 +200,8 @@ A tool can require both sign-in (`auth`) and a human approval. The model's appro
## What to read next
- [MCP connections](/docs/connections/mcp): connect to remote MCP servers.
- [OpenAPI connections](/docs/connections/openapi): generate tools from OpenAPI operations.
- [Integrations](/integrations): browse every channel and connection eve ships, in one gallery.
- [Tools](./tools): authored tools live alongside connection-provided tools; the same approval helpers apply.
- [Auth & route protection](./guides/auth-and-route-protection): the full interactive-OAuth flow with Vercel Connect.
- [Security model](./concepts/security-model): how connection credentials stay out of the model's reach.
- [Tools](/docs/tools): authored tools live alongside connection-provided tools; the same approval helpers apply.
- [Security model](/docs/concepts/security-model): how connection credentials stay out of the model's reach.
+2 -2
View File
@@ -84,7 +84,7 @@ As the agent grows, each concern still has a predictable home:
| Path | Add it when you need... |
| ------------------------------- | ------------------------------------------------ |
| [`connections/`](./connections) | Tools from external MCP servers |
| [`connections/`](./connections) | Tools from external MCP or OpenAPI services |
| [`hooks/`](./guides/hooks) | Code that reacts to lifecycle and stream events |
| [`sandbox/`](./sandbox) | A controlled workspace for files and commands |
| [`subagents/`](./subagents) | Specialist agents the root agent can delegate to |
@@ -99,5 +99,5 @@ The result stays readable before it runs. The directory tells you what the agent
- [Tools](./tools): the typed actions your agent calls
- [Instructions](./instructions): the always-on system prompt that shapes behavior
- [Channels](./channels/overview): reach the agent from Slack, Discord, or a web UI
- [Connections](./connections): pull in tools from external MCP servers
- [Connections](./connections): pull in tools from external services
- [Project layout](./reference/project-layout): every authored slot under `agent/`
+20 -19
View File
@@ -30,25 +30,26 @@ export default defineTool({
## The define\* helpers
| Helper | Import from | Authored at | Guide |
| ------------------------------------------------------ | --------------------------------------------- | ------------------------------------ | ------------------------------------------------------ |
| `defineAgent` | `eve` | `agent/agent.ts` | [agent.ts](../agent-config) |
| `defineTool` | `eve/tools` | `agent/tools/<name>.ts` | [Tools](../tools) |
| `defineDynamic` | `eve/tools`, `eve/skills`, `eve/instructions` | `agent/{tools,skills,instructions}/` | [Dynamic capabilities](../guides/dynamic-capabilities) |
| `defineMcpClientConnection`, `defineOpenAPIConnection` | `eve/connections` | `agent/connections/<name>.ts` | [Connections](../connections) |
| `defineChannel` | `eve/channels` | `agent/channels/<name>.ts` | [Custom channels](../channels/custom) |
| `eveChannel`, `slackChannel`, and the other platforms | `eve/channels/<platform>` | `agent/channels/<platform>.ts` | [Channels](../channels/overview) |
| `defineSkill` | `eve/skills` | `agent/skills/<name>.ts` | [Skills](../skills) |
| `defineInstructions` | `eve/instructions` | `agent/instructions.ts` | [Instructions](../instructions) |
| `defineHook` | `eve/hooks` | `agent/hooks/<slug>.ts` | [Hooks](../guides/hooks) |
| `defineSchedule` | `eve/schedules` | `agent/schedules/<name>.ts` | [Schedules](../schedules) |
| `defineState` | `eve/context` | tools, hooks, lifecycle | [Session context](../guides/session-context) |
| `defineSandbox` | `eve/sandbox` | `agent/sandbox.ts` | [Sandbox](../sandbox) |
| `defineInstrumentation` | `eve/instrumentation` | `agent/instrumentation.ts` | [instrumentation.ts](../guides/instrumentation) |
| `defineRemoteAgent` | `eve` | `agent/subagents/<id>/agent.ts` | [Remote agents](../guides/remote-agents) |
| `defineEval` | `eve/evals` | `evals/*.eval.ts` | [Evals](../evals/overview) |
| `defineEvalConfig` | `eve/evals` | `evals/evals.config.ts` | [Evals](../evals/overview) |
| `useEveAgent` | `eve/react`, `eve/vue`, `eve/svelte` | frontend | [Frontend](../guides/frontend/overview) |
| Helper | Import from | Authored at | Guide |
| ----------------------------------------------------- | --------------------------------------------- | ------------------------------------ | ------------------------------------------------------ |
| `defineAgent` | `eve` | `agent/agent.ts` | [agent.ts](../agent-config) |
| `defineTool` | `eve/tools` | `agent/tools/<name>.ts` | [Tools](../tools) |
| `defineDynamic` | `eve/tools`, `eve/skills`, `eve/instructions` | `agent/{tools,skills,instructions}/` | [Dynamic capabilities](../guides/dynamic-capabilities) |
| `defineMcpClientConnection` | `eve/connections` | `agent/connections/<name>.ts` | [MCP connections](../connections/mcp) |
| `defineOpenAPIConnection` | `eve/connections` | `agent/connections/<name>.ts` | [OpenAPI connections](../connections/openapi) |
| `defineChannel` | `eve/channels` | `agent/channels/<name>.ts` | [Custom channels](../channels/custom) |
| `eveChannel`, `slackChannel`, and the other platforms | `eve/channels/<platform>` | `agent/channels/<platform>.ts` | [Channels](../channels/overview) |
| `defineSkill` | `eve/skills` | `agent/skills/<name>.ts` | [Skills](../skills) |
| `defineInstructions` | `eve/instructions` | `agent/instructions.ts` | [Instructions](../instructions) |
| `defineHook` | `eve/hooks` | `agent/hooks/<slug>.ts` | [Hooks](../guides/hooks) |
| `defineSchedule` | `eve/schedules` | `agent/schedules/<name>.ts` | [Schedules](../schedules) |
| `defineState` | `eve/context` | tools, hooks, lifecycle | [Session context](../guides/session-context) |
| `defineSandbox` | `eve/sandbox` | `agent/sandbox.ts` | [Sandbox](../sandbox) |
| `defineInstrumentation` | `eve/instrumentation` | `agent/instrumentation.ts` | [instrumentation.ts](../guides/instrumentation) |
| `defineRemoteAgent` | `eve` | `agent/subagents/<id>/agent.ts` | [Remote agents](../guides/remote-agents) |
| `defineEval` | `eve/evals` | `evals/*.eval.ts` | [Evals](../evals/overview) |
| `defineEvalConfig` | `eve/evals` | `evals/evals.config.ts` | [Evals](../evals/overview) |
| `useEveAgent` | `eve/react`, `eve/vue`, `eve/svelte` | frontend | [Frontend](../guides/frontend/overview) |
A few non-`define*` helpers round out the set: `disableTool` and `ExperimentalWorkflow` from `eve/tools` (see [Default harness](../concepts/default-harness)), the route verbs `GET`/`POST`/`PUT`/`PATCH`/`DELETE`/`WS` from `eve/channels`, the approval predicates `always`/`once`/`never` from `eve/tools/approval`, and the channel auth helpers `localDev`/`vercelOidc`/`placeholderAuth` from `eve/channels/auth`. To wrap a built-in tool, import its default value from `eve/tools/defaults` (`bash`, `readFile`, `writeFile`, `glob`, `grep`, `webFetch`, `webSearch`, `todo`, `loadSkill`). `AgentWorkflowDefinition` and `AgentWorkflowWorldDefinition` are exported from `eve` for the `defineAgent({ experimental: { workflow } })` config shape.
+3 -3
View File
@@ -33,7 +33,7 @@ Once Connect is enabled on your account, wire it up:
3. Link the client to your project.
4. Run `vercel link` and `vercel env pull` so `VERCEL_OIDC_TOKEN` is available locally.
For the full reference, see [Connections](../connections).
For the full reference, see [MCP connections](../connections/mcp).
## What the user sees
@@ -49,8 +49,8 @@ The first time, the model picks a warehouse tool but there's no token yet, so th
Right before each request to the MCP server, eve resolves the bearer and sends it as `Authorization: Bearer <token>`. The model only ever sees tool names, descriptions, and results. The credential stays out of its reach.
If you want more control, gate the connection behind approval (`approval: once()`) or narrow which tools the model sees (`tools.allow`). See [Connections](../connections).
If you want more control, gate the connection behind approval (`approval: once()`) or narrow which tools the model sees (`tools.allow`). See [MCP connections](../connections/mcp).
→ Next: [Run analysis](./run-analysis)
Learn more: [Connections](../connections) · [Auth and route protection](../guides/auth-and-route-protection)
Learn more: [MCP connections](../connections/mcp) · [Auth and route protection](../guides/auth-and-route-protection)
+1 -1
View File
@@ -148,7 +148,7 @@ Across the nine steps you built and shipped one agent, and along the way you use
## Next steps
- [Connections](../connections) for tool allowlists and per-connection approval.
- [MCP connections](../connections/mcp) for tool allowlists and per-connection approval.
- [Sandbox](../sandbox) for backends, lifecycle, and network policy.
- [Dynamic capabilities](../guides/dynamic-capabilities) for schema-derived dynamic tools, a read-only analyst subagent, and model-authored report workflows on this same example.
- [Auth and route protection](../guides/auth-and-route-protection) for production auth patterns.