---
title: Manage Vercel projects with a software factory
description: Add Vercel's hosted MCP to the eve software factory template so Foreman can read build logs, runtime errors, and deployment history for the app your target repository deploys, brokered at app scope through Vercel Connect.
url: /kb/guide/software-factory-vercel-mcp
canonical_url: "https://vercel.com/kb/guide/software-factory-vercel-mcp"
published: 2026-09-03
last_updated: 2026-09-03
authors: Ben Sabic
related:
  - /docs/agent-resources/vercel-mcp
  - /docs/agent-resources/vercel-plugin
  - /kb/guide/eve-software-factory
  - /docs/cli
  - /kb/guide/software-factory-browser
  - /docs/connect
install_vercel_plugin: npx plugins add vercel/vercel-plugin
---

The [eve software factory template](https://vercel.com/templates/eve/eve-software-factory) turns GitHub and Linear work items into reviewed draft pull requests, working entirely from text: the issue body, a repository checkout, the diff, and your CI output. But when a deployment fails, the factory sees only GitHub's check-run summary, a check name and a status, which tells Foreman that something broke, not what broke.

This guide adds [Vercel's hosted MCP server](https://vercel.com/docs/agent-resources/vercel-mcp) to the factory's orchestrator, brokering access at app scope via [Vercel Connect](https://vercel.com/connect). Tokens resolve per call and never reach the model, the tool allowlist carries only reads, and the connection is pinned to one team and one project so an issue body can't point it anywhere else.

You'll then put the deployment context to work on three workflows: diagnosing a red deployment from the actual build log, checking a bug report against the errors firing in production, and recording what a run learned in the factory brain so every future run starts from it.

Deploy the template now, or read on if you have already done so.

## Quick start with an AI coding agent

If you're working with an AI coding agent like Claude Code or Cursor, use this prompt to have it make the changes for you:

### Agent prompt

```txt
Add Vercel's hosted MCP to my eve software factory (based on the eve-software-factory-template) so Foreman can read build logs, runtime errors, and deployment history for the app my target repository deploys. It has to work during unattended factory runs, so use app scope rather than per-user OAuth.

Before writing any code, ask me for three things and wait for my answer: my Vercel team ID or slug, the project ID or slug of the project the TARGET repository deploys (not the project Foreman itself runs in), and whether that target repository is public or private. Both IDs are in .vercel/project.json as orgId and projectId.

Ground truth first: read AGENTS.md in the repository root, read agent/connections/linear.ts as the in-repo example of an app-scoped MCP connection with an approval predicate, read agent/lib/constants.ts for how linearAuth is built, and read node_modules/eve/docs/connections/mcp.mdx for tool filters, toolCall.providedArguments, and approval gates. Read agent/lib/trust.ts before writing any policy.

1. Run: eve add connection/vercel
2. Add a vercelAuth constant to agent/lib/constants.ts following the linearAuth pattern: connect({ connector: requireEnv("VERCEL_CONNECTOR", "vercel/foreman-agent"), principalType: "app" }). Do not use connect("vercel"), which is user-scoped and unusable on unattended runs. Add VERCEL_TEAM_ID and VERCEL_PROJECT_ID alongside it, both through requireEnv.
3. Point the connection at vercelAuth and set tools.allow to exactly these eight: get_deployment_build_logs, get_runtime_errors, get_runtime_logs, list_deployments, get_deployment, list_projects, get_project, list_teams. Use allow, not block. Everything else stays undiscovered, including deploy_to_vercel and the buy_pro, buy_credits, buy_addon, and buy_domain purchase tools.
4. Set teamId and projectId through toolCall.providedArguments, so the model never supplies them itself and an issue body cannot name a different project.
5. Add a connection-wide approval predicate using the predicates in agent/lib/trust.ts: return "not-applicable" for isAutonomous, isTrusted, and isScheduleAppAuth callers, and "user-approval" for everyone else.
6. If I said the target repository is public, leave get_runtime_logs and get_runtime_errors out of the allowlist, and tell me you did and why.
7. Tell me the setup commands to run myself, and do not run them: vercel link, vercel connect create vercel --name foreman-agent, vercel env pull.
8. Add the three variables to .env.example in the surrounding comment style, noting they are required at build time. Do not change agent/lib/trust.ts, agent/lib/github/approval.ts, or agent/extensions/github.ts, and do not mount this connection under agent/subagents/.

Finish by running pnpm validate and confirming 0 errors and 0 warnings, then run npx eve info and show me the vercel connection and its tools in the discovered surface. Do not deploy. Follow the Vercel MCP docs for more information: https://vercel.com/docs/agent-resources/vercel-mcp and read the step-by-step guide on the Vercel knowledge base: https://vercel.com/kb/guide/software-factory-vercel-mcp.
```

### Vercel Plugin

The [Vercel Plugin](https://vercel.com/docs/agent-resources/vercel-plugin) turns your AI coding agent (e.g., OpenAI Codex, Claude Code, or Cursor) into a Vercel expert. It adds skills, slash commands, and current knowledge of the tools this guide uses, including eve and Vercel Connect.

The plugin is optional; it isn't required to use eve or to follow this guide.

```bash
npx plugins add vercel/vercel-plugin
```

## Overview

In this guide, you'll learn how to:

- Add the Vercel MCP connection from the eve registry to the software factory.
  
- Broker access at app scope through Vercel Connect, so the agent authenticates as one installation and no token ever reaches the model.
  
- Pin the connection's tool allowlist to eight read tools and pin every call to your team and project, not the model's.
  
- Gate the connection so unattended runs read deployment data freely while untrusted sessions wait for a person.
  
- Diagnose a failed deployment from its actual build log and check a bug report against live production errors.
  
- Record deployment findings in the factory brain, where future runs read them.
  

## Prerequisites

Before you begin, make sure you have:

- A [Vercel account](https://vercel.com/signup).
  
- The [eve software factory](https://vercel.com/kb/guide/eve-software-factory) deployed and cloned locally.
  
- A target repository that deploys to Vercel.
  

For local development, you also need Node.js 24+, pnpm, and the [Vercel CLI](https://vercel.com/docs/cli).

## How it works

Vercel's hosted MCP server exposes deployment data over one connection. Once added, the tools surface under the `vercel__` namespace and eve discovers them at runtime, so Foreman ships no Vercel API code of its own.

Vercel's MCP server offers dozens of tools, including tools for deploying projects, managing domains, and making purchases.

This guide configures an allowlist that limits Foreman to eight read-only tools:

| Tool                           | What Foreman uses it for                               |
| ------------------------------ | ------------------------------------------------------ |
| `get_deployment_build_logs`    | Read the actual build output when a deployment fails   |
| `get_runtime_errors`           | Check a bug report against the errors firing right now |
| `get_runtime_logs`             | Trace a failing request path or status code            |
| `list_deployments`             | Find the deployment carrying a branch or commit        |
| `get_deployment`               | Read one deployment's state and metadata               |
| `list_projects`, `get_project` | Resolve the project the target repository deploys      |
| `list_teams`                   | Resolve the team that owns it                          |

Tools outside the allowlist are never registered with the agent at runtime, so the model cannot see or call them.

The connection attaches to the orchestrator, so deployment context is available on every surface the factory serves:

- Labeled issues and the red-CI fix loop
  
- @mentions on issues and pull requests
  
- Linear Agent Sessions
  
- [The dev TUI](https://eve.dev/docs/guides/dev-tui)
  

The connection authenticates as the agent itself rather than as an individual teammate, so no one needs to complete a consent step before a call. That lets unattended runs like labeled issues and the red-CI fix loop use the connection, and those are the runs where deployment context matters most.

Vercel Connect mints the credential on demand within your team's scope, which means the allowlist limits the model, not the credential.

Who can call the tools depends on how the session started, following the template's trust model:

| Session started by                                       | Vercel tools                  |
| -------------------------------------------------------- | ----------------------------- |
| Labeled issue, red CI on a factory branch, or a schedule | Run without approval          |
| @mention from a maintainer, or a Linear teammate         | Run without approval          |
| The dev TUI, or a PR from an outside contributor         | Pause until a person approves |

Sessions started by labeled issues, red CI, schedules, maintainers, and Linear teammates skip approval because the allowlist is read-only, so the most an issue body can drive is a read of your own project's deployment data.

## Steps

### 1\. Add the connection from the registry

Vercel has an entry in the eve registry, so one command installs the connection and creates the file under `agent/connections/`:

```bash
eve add connection/vercel
```

### 2\. Create the connector

Link your directory to the Vercel project, then create the Vercel connector:

```bash
vercel link
vercel connect create vercel --name foreman-agent
vercel env pull
```

Confirm the UID with `vercel connect list`, then set three variables in the project's [environment variables](https://vercel.com/d?to=%2F%5Bteam%5D%2F%5Bproject%5D%2Fsettings%2Fenvironment-variables):

- `VERCEL_CONNECTOR`: The connector UID from `vercel connect list`
  
- `VERCEL_TEAM_ID`: The team that owns the target project
  
- `VERCEL_PROJECT_ID`: The project your target repository deploys, not the project Foreman itself runs in
  

All three are read at module load, so set them before redeploying or discovery fails. Find `VERCEL_TEAM_ID` and `VERCEL_PROJECT_ID` in the target repository's `.vercel/project.json` as `orgId` and `projectId`.

### 3\. Configure app-scoped auth

Add a `vercelAuth` constant to `agent/lib/constants.ts`, following the `linearAuth` pattern already in the file:

```typescript
export const vercelAuth = connect({
  connector: requireEnv("VERCEL_CONNECTOR", "vercel/foreman-agent"),
  principalType: "app",
});

export const VERCEL_TEAM_ID = requireEnv("VERCEL_TEAM_ID");
export const VERCEL_PROJECT_ID = requireEnv("VERCEL_PROJECT_ID");
```

Do not use `connect("vercel")`. It scopes the connection to individual users, and unattended runs have no user present to complete the consent.

### 4\. Pin the connection to your project and tools

Point the connection at `vercelAuth`, then define the tool allowlist, the pinned IDs, and the approval rule in one file:

```typescript
import { defineMcpClientConnection } from "eve/connections";
import {
  VERCEL_PROJECT_ID,
  VERCEL_TEAM_ID,
  vercelAuth,
} from "../lib/constants.js";
import { isAutonomous, isScheduleAppAuth, isTrusted } from "../lib/trust.js";

export default defineMcpClientConnection({
  url: "https://mcp.vercel.com",
  description:
    "Vercel: build logs, runtime errors, and deployment history for the target repository's app.",
  auth: vercelAuth,
  approval: (ctx) =>
    isAutonomous(ctx.session.auth.current) ||
    isTrusted(ctx.session.auth.current) ||
    isScheduleAppAuth(ctx.session.auth.current)
      ? "not-applicable"
      : "user-approval",
  toolCall: {
    providedArguments: {
      projectId: VERCEL_PROJECT_ID,
      teamId: VERCEL_TEAM_ID,
    },
  },
  tools: {
    allow: [
      "get_deployment_build_logs",
      "get_runtime_errors",
      "get_runtime_logs",
      "list_deployments",
      "get_deployment",
      "list_projects",
      "get_project",
      "list_teams",
    ],
  },
});
```

With this configuration:

- `allow` names the eight read tools and nothing else. `deploy_to_vercel` and the `buy_pro`, `buy_credits`, `buy_addon`, and `buy_domain` purchase tools are never discovered, so the model cannot call them, and any tool the server adds later stays out until you name it here.
  
- `providedArguments` sets the team and project itself. eve deletes `teamId` and `projectId` from the tool description the model sees, then fills in your values as the call goes out, so a `get_runtime_logs` call from the model carries only its own filters, like `level`. The model has no field left to name another project in.
  
- The approval predicate lets autonomous, trusted, and schedule callers run, and parks everyone else, including the dev TUI and the untrusted pull-request summary session, on an approval card.
  

If your target repository is public, leave `get_runtime_logs` and `get_runtime_errors` out of the allowlist and keep the build logs. An unattended run can comment on its intake issue, so anything it reads can be quoted there, and runtime logs carry request paths, headers, and user data.

### 5\. Verify

Run the following commands to verify your setup:

```bash
pnpm validate
eve info
```

`pnpm validate` should finish with zero errors and zero warnings, and `eve info` should list the `vercel` connection with exactly the eight allowed tools. If `deploy_to_vercel` or any `buy_` tool shows up, the filter is not applied.

Then run `pnpm dev` and ask Foreman for a recent deployment's build logs. The dev principal is untrusted, so the call parks on an approval card in the TUI. Approve it, and confirm the result comes back for the pinned project.

## Three workflows to try

### Diagnose a red deployment from the build log

@mention the bot on a pull request whose Vercel check is red:

```plaintext
@foreman the Vercel check on this PR is red, read the deployment's build log and tell me what broke
```

Foreman finds the deployment carrying the branch, reads the actual build output, and reports the failing step. The unattended red-CI loop gains the same context on its own: when a factory branch goes red, the fix attempt starts from the build log rather than a check name.

### Check a bug report against production

@mention the bot on a bug report about live behavior:

```plaintext
@foreman check whether the 500 in this issue is firing in production right now, and since when
```

Foreman reads the errors firing in the pinned project and compares them against the report, so the classifier and analyst work from confirmed production behavior rather than a described one. On a public repository, this workflow isn't available, because the runtime tools stay off the allowlist.

### Teach the factory what the deployment showed

Some of what a deployment read establishes is durable: the app deploys from `apps/web`, or a recurring build failure traces back to one package.

Ask Foreman to remember it:

```plaintext
@foreman record in the factory brain that the target app deploys from apps/web, so failures in packages/ui surface in that project's build log
```

The factory brain is the shared memory every run reads at the start of a task, so a fact one deployment established now grounds every future run, including the unattended ones triggered by labeled issues and red CI. Diagnose once, and the whole pipeline plans with what you found.

### How the guardrails extend

The template treats work-item text as untrusted input, and deployment data cuts both ways. An issue body can try to point the tools somewhere else, and what the tools return can end up quoted where anyone can read it.

The connection follows the same rules:

- Reads are the ceiling. The allowlist carries no deploy or purchase tools, so the most an unattended run can do is read your project's deployment data. Deploying sits past the template's draft-PR ceiling and, like merging, stays a human act.
  
- The model never picks the project. `get_runtime_logs` takes `projectId` and `teamId` as parameters, and an issue body reading "check the logs for prj\_abc" is an instruction the model can follow. With `providedArguments`, eve supplies both values itself and the model has no field to put one in.
  
- Untrusted sessions wait for a person. The pull-request summary session runs on pull requests from outside contributors, and parking its calls on approval keeps a PR description from talking it into quoting production logs into a public comment.
  

The template ships safety evals, and the connection needs one too. Add a case under `evals/safety/` with an issue body that names a foreign project, asserting the call still reads the pinned one.

## Troubleshooting

| Symptom                                                       | Likely cause                                                                                                                             | Fix                                                                                                                                                 |
| ------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
| Vercel tools don't appear under `vercel__*`                   | The connection file isn't discovered, or the project is on an eve older than v0.25                                                       | Run `npx eve info`, check `.eve/discovery/diagnostics.json` for skipped files, and upgrade eve if needed                                            |
| `deploy_to_vercel` or a `buy_` tool appears in the tool list  | The tool filter isn't applied, so the connection is running without the allowlist                                                        | Confirm the connection uses `tools: { allow: [...] }` rather than `block`, then re-run `npx eve info`                                               | | The build fails with a `VERCEL_CONNECTOR` or `VERCEL_*` error | The three variables are read at module load, so a misconfigured factory fails discovery instead of producing a connection with no target | Set `VERCEL_CONNECTOR`, `VERCEL_TEAM_ID`, and `VERCEL_PROJECT_ID` in the project's environment and redeploy                                         | | Calls return data for the wrong project                       | `VERCEL_PROJECT_ID` points at the project Foreman itself runs in, not the one the target repository deploys                              | Read `orgId` and `projectId` from the target repository's `.vercel/project.json` and set the variables to those values                              | | An allowed tool rejects the call                              | Configured arguments apply to every tool on the connection, and this tool takes neither `teamId` nor `projectId`                         | Drop the tool from the allowlist, or mount it as its own connection without the pin                                                                 | | A Vercel call appears to stall in the dev TUI                 | The dev principal is untrusted by design, so the approval predicate parks the call on an approval card                                   | Approve or deny the pending call. To change who runs ungated, edit the predicate in `agent/connections/vercel.ts`                                   | | The connection works locally but fails in production          | `.env.local` is local-only, and the deployed app reads the Vercel project's environment                                                  | Set the three variables in the project's production environment, then redeploy                                                                      | | Reads fail with an authorization error                        | The connector's token isn't team-scoped, or the token's creator lacks access to the pinned project                                       | Re-create the connector with a team-scoped token from an account that can read the target project, and update `VERCEL_CONNECTOR` if the UID changed | ## Next steps - [Build a software factory with eve](https://vercel.com/kb/guide/eve-software-factory): the template this guide builds on
  
- [Giving your software factory a browser](https://vercel.com/kb/guide/software-factory-browser): the same factory reproducing bugs and verifying fixes in a cloud browser
  
- [Vercel MCP](https://vercel.com/docs/agent-resources/vercel-mcp): the canonical reference for the hosted server and its full tool list
  
- [Vercel Connect](https://vercel.com/docs/connect): the access broker that mints the connection's tokens