Skip to content

Commit a6ff194

Browse files
authored
feat(sdk): first-class Vercel Connect integration (#44)
1 parent 58d0158 commit a6ff194

21 files changed

Lines changed: 973 additions & 247 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@github-tools/sdk": minor
3+
---
4+
5+
Add `@github-tools/sdk/connect` and `@github-tools/sdk/connect/eve` helpers for Vercel Connect — preset-derived scopes, `connectGithubToken`, and `connectGithubTools`.

apps/docs/content/docs/3.guide/4.tokens-and-auth.md

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,16 +49,22 @@ Fine-grained personal access tokens let you restrict access per repository and p
4949

5050
| Preset | Repository access | Contents | Pull requests | Issues | Actions | Administration |
5151
|---|---|---|---|---|---|---|
52-
| `repo-explorer` | selected repos | `read` | | | ||
52+
| `repo-explorer` | selected repos | `read` | `read` | `read` | `read` ||
5353
| `code-review` | selected repos | `read` | `read` (or `write` for comments) ||||
5454
| `issue-triage` | selected repos | `read` || `write` |||
5555
| `ci-ops` | selected repos | `read` ||| `write` ||
5656
| `maintainer` | selected repos | `write` | `write` | `write` | `write` | `write` (for repo creation and forking) |
5757

58+
`repo-explorer` and `maintainer` also include gist read (and, for `maintainer`, write) tools. Gists aren't tied to a repository — GitHub only grants gist access to GitHub App *user* access tokens, never installation tokens, so give the PAT the "Gists" account permission separately, and expect gist tools to fail over Vercel Connect (see below).
59+
5860
## Mint tokens with Vercel Connect
5961

6062
For agents deployed on Vercel, [Vercel Connect](https://vercel.com/docs/connect) replaces long-lived PATs entirely. You attach a **GitHub connector** (a Vercel-managed GitHub App) to your project, and your server code requests a **short-lived, scoped token** at runtime — no secret to store, rotate, or leak.
6163

64+
::callout{icon="i-lucide-plug"}
65+
**First-class helper** — use `@github-tools/sdk/connect` to derive scopes from your preset automatically. See the [Vercel Connect guide](/guide/vercel-connect) for `connectGithubTools` and `connectGithubToken`.
66+
::
67+
6268
::steps{level="3"}
6369
### Create a GitHub connector
6470

@@ -70,7 +76,20 @@ Link the connector to the Vercel project that runs your agent. On Vercel, the SD
7076

7177
### Request a token at runtime
7278

73-
Install `@vercel/connect` and call `getToken` with the permissions your preset needs, then pass the result as `token`:
79+
Install `@vercel/connect` and call `getToken` with the permissions your preset needs, then pass the result as `token`. Prefer the [connect subpath](/guide/vercel-connect) when you want preset-derived scopes without maintaining a scope list:
80+
81+
```ts [connect-tools.ts]
82+
import { connectGithubTools } from '@github-tools/sdk/connect'
83+
import { generateText } from 'ai'
84+
85+
const { text } = await generateText({
86+
model: 'anthropic/claude-sonnet-4.6',
87+
tools: connectGithubTools('github/my-connector', { preset: 'code-review' }),
88+
prompt: 'Summarize the open PRs on my-org/my-repo.',
89+
})
90+
```
91+
92+
Manual `getToken` (full control over every parameter):
7493

7594
```ts [connect-token.ts]
7695
import { getToken } from '@vercel/connect'
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
---
2+
title: Vercel Connect
3+
description: Use @github-tools/sdk/connect to mint scoped GitHub tokens from a Vercel Connect connector — preset-derived scopes, zero boilerplate.
4+
navigation:
5+
title: Vercel Connect
6+
path: /guide/vercel-connect
7+
links:
8+
- label: Tokens & Auth
9+
icon: i-lucide-key-round
10+
to: /guide/tokens-and-auth
11+
color: neutral
12+
variant: subtle
13+
- label: Scope with presets
14+
icon: i-lucide-layers
15+
to: /guide/presets
16+
color: neutral
17+
variant: subtle
18+
---
19+
20+
For agents deployed on Vercel, [Vercel Connect](https://vercel.com/docs/connect) replaces long-lived PATs. Attach a **GitHub connector** to your project and mint **short-lived, scoped tokens** at runtime — no secret to store.
21+
22+
The `@github-tools/sdk/connect` subpath wraps Connect with preset-derived scopes so you only think about the connector and preset.
23+
24+
## Quick start (AI SDK)
25+
26+
```ts [connect-tools.ts]
27+
import { connectGithubTools } from '@github-tools/sdk/connect'
28+
import { generateText } from 'ai'
29+
30+
const tools = connectGithubTools('github/my-connector', {
31+
preset: 'code-review',
32+
})
33+
34+
const { text } = await generateText({
35+
model: 'anthropic/claude-sonnet-4.6',
36+
tools,
37+
prompt: 'Summarize open PRs on my-org/my-repo.',
38+
})
39+
```
40+
41+
Scopes are derived automatically from the preset — see the [preset → Connect scope matrix](/guide/tokens-and-auth#map-permissions-to-presets).
42+
43+
## eve agent
44+
45+
```ts [eve-agent.ts]
46+
// agent/agent.ts
47+
import { defineAgent } from 'eve'
48+
49+
export default defineAgent({
50+
model: 'anthropic/claude-sonnet-5',
51+
// TODO(eve-connect-bundle): remove when eve externalizes transitive @vercel/connect
52+
build: {
53+
externalDependencies: ['@vercel/connect'],
54+
},
55+
})
56+
```
57+
58+
```ts [eve-connect.ts]
59+
// agent/tools/github.ts
60+
import { connectGithubTools } from '@github-tools/sdk/connect/eve'
61+
62+
export default connectGithubTools('github/my-connector', {
63+
preset: 'maintainer',
64+
})
65+
```
66+
67+
::note
68+
**eve bundling**`build.externalDependencies` keeps `@vercel/connect` out of the authored-module bundle. Without it, `eve dev` fails when the SDK is workspace-linked. This is temporary until eve handles transitive Connect imports upstream.
69+
::
70+
71+
See [`examples/eve-agent`](https://github.com/vercel-labs/github-tools/tree/main/examples/eve-agent) for a runnable example.
72+
73+
## Token provider only
74+
75+
When you need a lazy token for custom tool factories:
76+
77+
```ts [connect-token.ts]
78+
import { connectGithubToken } from '@github-tools/sdk/connect'
79+
import { createGithubTools } from '@github-tools/sdk'
80+
81+
const tools = createGithubTools({
82+
preset: 'ci-ops',
83+
token: connectGithubToken('github/my-connector', { preset: 'ci-ops' }),
84+
})
85+
```
86+
87+
Pass the same `preset` to both calls — `connectGithubToken` derives Connect scopes from its own `preset` option, independently of the one you give `createGithubTools`. Omitting it mints a token scoped to the union of every preset instead of just `ci-ops`.
88+
89+
## Multi-tenant and repository scoping
90+
91+
Override Connect parameters when you need installation targeting or narrower repository access:
92+
93+
```ts [connect-override.ts]
94+
import { connectGithubTools } from '@github-tools/sdk/connect'
95+
96+
const tools = connectGithubTools('github/my-connector', {
97+
preset: 'issue-triage',
98+
connect: {
99+
installationId: 'inst_abc',
100+
repositories: ['vercel-labs/github-tools'],
101+
scopes: ['issues:write'], // replaces preset-derived scopes when provided
102+
},
103+
})
104+
```
105+
106+
`subject` is always `{ type: 'app' }` — same as `connectGitHubAdapter` from `@vercel/connect`.
107+
108+
## Setup checklist
109+
110+
::steps{level="3"}
111+
### Create a GitHub connector
112+
113+
Create a connector from the [Vercel dashboard](https://vercel.com/docs/connect) (or `vercel connect` in the CLI), then install it on the GitHub org or user account your agent needs.
114+
115+
Or jump straight to the GitHub connector creation form with this [deeplink](https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fconnect%2Fcreate%3Ftype%3Dgithub).
116+
117+
### Link it to your project
118+
119+
Link the connector to the Vercel project that runs your agent. On Vercel, the SDK authenticates automatically with the deployment OIDC token. For local development, run `vercel link` then `vercel env pull`.
120+
121+
### Install the peer dependency
122+
123+
```sh
124+
pnpm add @vercel/connect
125+
```
126+
127+
`@vercel/connect` is an optional peer dependency of `@github-tools/sdk` — install it only when using the `/connect` subpath.
128+
::
129+
130+
## Manual `getToken` (escape hatch)
131+
132+
If you need full control over every `ConnectTokenParams` field, call `getToken` directly and pass the result as `token`. See [Tokens & Auth](/guide/tokens-and-auth#mint-tokens-with-vercel-connect).
133+
134+
## API reference
135+
136+
- [`connectGithubTools`](/api/reference#connectgithubtools) — AI SDK tool set
137+
- [`connectGithubTools` (eve)](/api/reference#connectgithubtools--eve) — eve `defineDynamic` sentinel
138+
- [`connectGithubToken`](/api/reference#connectgithubtoken) — lazy token provider
139+
- [`connectGithubScopesForPreset`](/api/reference#connectgithubscopesforpreset) — scope helper
140+
141+
## External references
142+
143+
- [Vercel Connect documentation](https://vercel.com/docs/connect)
144+
- [Vercel Connect SDK reference](https://vercel.com/docs/connect/ts-sdk-reference)

apps/docs/content/docs/4.api/2.reference.md

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,66 @@ type EveApprovalValue =
262262
263263
Also exports individual eve tool factories (`listPullRequests()`, `createIssue()`, …) for one-tool-per-file layouts. Approval supports `once`, predicates, and eve helper passthrough — unlike the Workflow subpath, approval **is enforced** at runtime.
264264
265+
## `connectGithubTools(connector, options?)`
266+
267+
Import from `@github-tools/sdk/connect`. Returns the same tool record as `createGithubTools`, backed by a Vercel Connect connector. Scopes are derived from `preset` unless overridden in `connect.scopes`:
268+
269+
```ts [connect-tools.ts]
270+
import { connectGithubTools } from '@github-tools/sdk/connect'
271+
272+
const tools = connectGithubTools('github/my-connector', {
273+
preset: 'code-review',
274+
connect: {
275+
installationId: 'inst_abc',
276+
repositories: ['my-org/my-repo'],
277+
},
278+
})
279+
```
280+
281+
```ts [types-connect.ts]
282+
type ConnectGithubToolsOptions = GithubToolsOptions & {
283+
connect?: GithubConnectParams
284+
}
285+
286+
type GithubConnectParams = Omit<ConnectTokenParams, 'subject'> & {
287+
repositories?: string[]
288+
}
289+
```
290+
291+
`subject` is always `{ type: 'app' }`. See [Vercel Connect guide](/guide/vercel-connect).
292+
293+
## `connectGithubTools(connector, options?)` — eve
294+
295+
Import from `@github-tools/sdk/connect/eve`. Same as the AI SDK variant but returns a `defineDynamic` sentinel. Set `build.externalDependencies: ['@vercel/connect']` in `agent.ts` until eve externalizes transitive Connect imports from workspace-linked packages (`TODO(eve-connect-bundle)`).
296+
297+
```ts [connect-eve.ts]
298+
import { connectGithubTools } from '@github-tools/sdk/connect/eve'
299+
300+
export default connectGithubTools('github/my-connector', {
301+
preset: 'maintainer',
302+
})
303+
```
304+
305+
## `connectGithubToken(connector, options?)`
306+
307+
Returns a lazy `GithubTokenInput` backed by `getToken`. Use with `createGithubTools` when you only need the token provider:
308+
309+
```ts [connect-token-provider.ts]
310+
import { connectGithubToken } from '@github-tools/sdk/connect'
311+
import { createGithubTools } from '@github-tools/sdk'
312+
313+
const tools = createGithubTools({
314+
preset: 'ci-ops',
315+
token: connectGithubToken('github/my-connector', { preset: 'ci-ops' }),
316+
})
317+
```
318+
319+
Pass the same `preset` to `connectGithubToken` — it derives Connect scopes independently of the `preset` given to `createGithubTools`.
320+
321+
## `connectGithubScopesForPreset(preset?)`
322+
323+
Returns Vercel Connect scope strings for a preset or combined presets. Without a preset, returns the union of all preset scopes.
324+
265325
## `resolveGithubToken(token?)`
266326

267327
Resolves a `GithubTokenInput` (token string, async provider, or the `process.env.GITHUB_TOKEN` fallback) to a token string. Throws when no token is available.

examples/eve-agent/README.md

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
# GitHub eve Agent
22

3-
Minimal [eve](https://eve.dev) agent using `@github-tools/sdk/eve` with the `maintainer` preset.
4-
5-
> **Temporary:** this example uses [Vercel Connect](https://vercel.com/docs/connect) (`github/test-github-tools`) instead of a `GITHUB_TOKEN` PAT. Revert `agent/tools/github.ts` to drop the `token` provider when you're done testing.
3+
Minimal [eve](https://eve.dev) agent using `@github-tools/sdk/connect/eve` with the `maintainer` preset and a [Vercel Connect](https://vercel.com/docs/connect) connector.
64

75
## Setup
86

@@ -44,27 +42,27 @@ Open the dev TUI and ask it to review a pull request on a repo your connector ca
4442

4543
```
4644
agent/
47-
agent.ts # eve agent config
45+
agent.ts # eve agent config (externalizes @vercel/connect for bundling)
4846
instructions.md # system prompt
49-
tools/github.ts # GitHub tools via createGithubTools() + Vercel Connect
47+
tools/github.ts # GitHub tools via connectGithubTools()
5048
```
5149

50+
`agent.ts` sets `build.externalDependencies: ['@vercel/connect']` so `eve dev` can bundle `connectGithubTools` — a workaround until [eve](https://eve.dev) handles transitive Connect imports from workspace-linked packages without extra config.
51+
5252
## Customize
5353

5454
Swap the preset or configure approval:
5555

5656
```ts
57-
export default createGithubTools({
57+
import { connectGithubTools } from '@github-tools/sdk/connect/eve'
58+
59+
export default connectGithubTools('github/test-github-tools', {
5860
preset: ['code-review', 'issue-triage'],
59-
token: () => getToken('github/test-github-tools', {
60-
subject: { type: 'app' },
61-
scopes: ['contents:read', 'pull_requests:read'],
62-
}),
6361
requireApproval: {
6462
mergePullRequest: true,
6563
addPullRequestComment: 'once',
6664
},
6765
})
6866
```
6967

70-
See the [@github-tools/sdk README](../../packages/github-tools/README.md#eve) for the full eve integration guide.
68+
See the [@github-tools/sdk README](../../packages/github-tools/README.md#vercel-connect) for the full Connect integration guide.

examples/eve-agent/agent/agent.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,10 @@ import { defineAgent } from 'eve'
22

33
export default defineAgent({
44
model: 'anthropic/claude-sonnet-5',
5+
// TODO(eve-connect-bundle): remove when eve externalizes transitive @vercel/connect
6+
// imports from workspace-linked packages without build.externalDependencies.
7+
// See https://github.com/vercel-labs/github-tools/pull/44
8+
build: {
9+
externalDependencies: ['@vercel/connect'],
10+
},
511
})
Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,5 @@
1-
import { getToken } from '@vercel/connect'
2-
import { createGithubTools } from '@github-tools/sdk/eve'
1+
import { connectGithubTools } from '@github-tools/sdk/connect/eve'
32

4-
// TEMP: Vercel Connect instead of GITHUB_TOKEN — connector "test-github-tools" on github-tools-docs
5-
const CONNECTOR_UID = 'github/test-github-tools'
6-
7-
/** Scopes for the maintainer preset — https://github-tools.com/guide/tokens-and-auth */
8-
const MAINTAINER_SCOPES = [
9-
'contents:read',
10-
'contents:write',
11-
'pull_requests:read',
12-
'pull_requests:write',
13-
'issues:read',
14-
'issues:write',
15-
'actions:read',
16-
'actions:write',
17-
'administration:read',
18-
'administration:write',
19-
] as const
20-
21-
export default createGithubTools({
3+
export default connectGithubTools('github/test-github-tools', {
224
preset: 'maintainer',
23-
token: () => getToken(CONNECTOR_UID, {
24-
subject: { type: 'app' },
25-
scopes: [...MAINTAINER_SCOPES],
26-
}),
275
})
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
node_modules
22
.output
33
.env
4+
/.swc

0 commit comments

Comments
 (0)