Uh oh!
There was an error while loading. Please reload this page.
Serve HEY over MCP with hey mcp - #357
Conversation
aa11d9b to
2757539CompareThere was a problem hiding this comment.
Pull request overview
Adds hey mcp, a stdio MCP server exposing authenticated HEY operations.
Changes:
- Adds five catalog-derived MCP gateway tools and dispatch.
- Adds model snapshots, tests, documentation, and dependencies.
- Also includes per-install OAuth identifier changes from #355.
Tip
If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.
Reviewed changes
Copilot reviewed 25 out of 27 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
.surface | Records the MCP command surface. |
README.md | Documents MCP usage. |
go.mod | Adds MCP dependencies. |
go.sum | Records dependency checksums. |
scripts/sync-mcp-model.sh | Synchronizes SDK model snapshots. |
internal/auth/auth.go | Adds install IDs to OAuth requests. |
internal/auth/auth_test.go | Tests OAuth install IDs. |
internal/auth/install_id.go | Persists per-install identifiers. |
internal/auth/install_id_test.go | Tests identifier persistence. |
internal/cmd/auth.go | Displays the install ID. |
internal/cmd/help.go | Categorizes the MCP command. |
internal/cmd/help_test.go | Updates help expectations. |
internal/cmd/mcp.go | Implements hey mcp. |
internal/cmd/mcp_test.go | Tests command integration. |
internal/cmd/root.go | Registers the command. |
internal/mcpserver/catalog.go | Loads the embedded catalog. |
internal/mcpserver/catalog_test.go | Tests catalog derivation. |
internal/mcpserver/dispatch.go | Dispatches actions to the SDK. |
internal/mcpserver/dispatch_test.go | Tests request construction. |
internal/mcpserver/domains.go | Defines exposed domains. |
internal/mcpserver/server.go | Configures the MCP gateway. |
internal/mcpserver/server_test.go | Tests gateway behavior. |
internal/mcpserver/model/PROVENANCE.json | Records snapshot provenance. |
internal/mcpserver/model/behavior-model.json | Vendors operation traits. |
internal/mcpserver/model/openapi.json | Vendors API schemas. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:aa11d9b30d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
2757539 to
adba328Compareda2eea2 to
ec33a59CompareThere was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:ec33a59c10
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
ec33a59 to
24a146fCompareThere was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:24a146f378
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Uh oh!
There was an error while loading. Please reload this page.
24a146f to
e38a672CompareThere was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:e38a672cd4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Uh oh!
There was an error while loading. Please reload this page.
hey mcp runs an MCP server on stdin/stdout: seven domain gateway tools
(boxes, search, threads, contacts, todos, calendar, identity) derived
from hey-sdk's model exports via the shared toolkit at
github.com/basecamp/mcp, dispatching real API calls through the CLI's
authenticated, account-scoped SDK client — the same keychain-stored
credentials every other command uses.
The catalog vendors a hey-sdk model snapshot (behavior-model.json +
openapi.json at go/v0.28.0, the version go.mod pins — kept in lockstep
by test), synced by scripts/sync-mcp-model.sh with provenance recorded,
and the dispatcher maps catalog operations onto the SDK's generic
verbs: path and required query params enforced, substituted, and
escaped, remaining params gathered into the request body with property
names checked against the body schema as a typo guard. Listings with
more pages surface their geared_pagination cursor as
{"next_page": cursor, "results": ...} — HEY pages by cursor, and a
numeric page is answered with the first page forever. Failures are
in-band isError results; stdout belongs to the MCP wire, logs go to
stderr.
--read-only serves only read-only actions and refuses write dispatch;
--domains narrows the served surface, failing closed on unknown keys.e38a672 to
c0cfa54CompareUh oh!
There was an error while loading. Please reload this page.
What
hey mcpruns an MCP (Model Context Protocol) server on stdin/stdout, serving HEY as tools backed by the signed-in account. Seven domain gateway tools —hey_boxes,hey_search,hey_threads,hey_contacts,hey_todos,hey_calendar,hey_identity— derived from hey-sdk's model exports via the shared toolkit at github.com/basecamp/mcp, dispatching real API calls through the CLI's authenticated, account-scoped SDK client. One install, no separate binary:Design
Why not import hey-mcp-server? This repo is public;
basecamp/hey-mcp-serveris private, so a module dependency is a broken build for everyone outside the org, and vendoring it would publish it wholesale. Everything the server actually needs is already public — thebasecamp/mcptoolkit (catalog, gateway, mcptest) and hey-sdk's model exports — so the CLI assembles the same shape from those parts, per the toolkit's own two-instance-by-duplication convention. hey-mcp-server remains the home of the hosted/HTTP story; when its catalog curation finds a shared public home (hey-sdk being the natural candidate), both consumers converge on it.Real dispatch, not the stub. hey-mcp-server's handler is still the spike boundary (dispatch names the operation it would call). Here the CLI's
*hey.Client— auth, token refresh, retry, account scoping, body limits — is already in hand, so the dispatcher maps catalog operations onto the SDK's generic verbs: path params substituted and escaped, query params encoded, remaining params gathered into the request body with property names checked against the body schema (a typo guard — types and required properties stay the server's to enforce, with its errors surfaced in-band). Calling convention (path/query/body all flat inparams,describeserves the schema, paginated listings surface their geared_pagination cursor asnext_pageto pass back aspage) lives ininternal/mcpserver/dispatch.go; it should migrate to the toolkit once a second instance proves it.Catalog snapshot.
internal/mcpserver/model/vendors hey-sdk'sbehavior-model.json+openapi.jsonatgo/v0.28.0— the same version go.mod pins — synced byscripts/sync-mcp-model.shwith provenance recorded. Unmapped SDK tags are pinned by test, so growing the surface is a deliberate one-line change plus a snapshot refresh.Auth composition with #355/#356.
hey mcpnever touches the login flow: it reads stored credentials through the sameauth.Manager→ SDK bridge as every other command (requireAuth()+ the packagesdkclient), and the Manager's proactive refresh keeps a long-running server alive across token expiry. The ephemeral-port listener (#356) and per-install id (#355) change how tokens are acquired, not how they're read, so this composes with both unchanged — based on main; a rebase after they land is a no-op for this diff.Tests
internal/mcpserver: catalog derivation pinned (seven tools, unmapped tags accounted, snapshot ref asserted against go.mod's hey-sdk version);buildRequesttable (path substitution/escaping, scalar formatting, query encoding, body gathering, schema-checked strays, missing/malformed params); wire-level tests via the toolkit'smcptestharness (tools/list, describe, dispatch-through-API, read-only refusal, domain narrowing).internal/cmd: command registration, account-scope policy, auth requirement, and an end-to-end test running the actualhey mcpcommand against an httptest HEY server through the transport seam — MCP initialize + tools/list + a tool call, asserting the CLI's bearer token rides on the dispatched request.--read-only/--domainspassthrough proven over the wire.make checkgreen exceptinternal/tui's pre-existing unix-socket-path failures on this macOS sandbox (fail on main too, as Bind the OAuth callback listener to an ephemeral loopback port (RFC 8252 §7.3) #356 also notes).go test -raceclean on the new packages. Size budget: 34.3 MiB of 37 (the embedded 425 KB model is noise).