Documentation
¶
Overview ¶
Package mcpserver assembles the MCP server behind `basecamp mcp`: Basecamp's tool catalog derived from basecamp-sdk's model exports, dispatched through the CLI's authenticated, account-scoped SDK client.
The generic machinery — joining behavior-model.json with openapi.json, rendering domain gateway tools, action dispatch, read-only filtering, the in-band describe action — lives in the shared toolkit at github.com/basecamp/mcp. This package supplies the product half: the curated DomainSpecs mapping basecamp-sdk tags to domains, the vendored model snapshot under model/ (synced by scripts/sync-mcp-model.sh, provenance recorded), and the dispatcher that turns catalog operations into basecamp-sdk requests.
Index ¶
Constants ¶
const Name = "basecamp-cli"
Name identifies the server in the MCP initialize handshake. The version is the CLI's own: `basecamp mcp` is the CLI serving MCP, not a separate product.
Variables ¶
var DomainSpecs = []catalog.DomainSpec{ { Key: "projects", Tags: []string{"Projects"}, Blurb: "Basecamp projects: list, get, create, update, archive, unarchive, and trash.", }, { Key: "todos", Tags: []string{"Todos", "Subtasks"}, Blurb: "Todos, todolists, todolist groups, and todosets — plus each todolist's hill chart, and the subtasks on to-dos and cards.", }, { Key: "cards", Tags: []string{"Card Tables"}, Blurb: "Card tables (kanban): cards, columns, steps, and wormholes, with moves, repositioning, and on-hold state.", }, { Key: "messages", Tags: []string{"Messages"}, Blurb: "Message boards: messages, comments, message types (categories), and pinning.", }, { Key: "campfires", Tags: []string{"Campfire"}, Blurb: "Campfire chat: rooms, chat lines, uploads, and chatbots.", }, { Key: "boosts", Tags: []string{"Boosts"}, Blurb: "Boosts (emoji reactions) on recordings and their events: list, get, create, and delete.", }, { Key: "schedules", Tags: []string{"Schedule", "Calendars"}, Blurb: "Schedules and schedule entries (calendar events), timesheets and time tracking, and per-account calendars.", }, { Key: "files", Tags: []string{"Files", "Folders"}, Blurb: "Docs & Files: vaults (folders), documents, uploads, attachments, cloud file links, Google documents, and home-screen project folders.", }, { Key: "people", Tags: []string{"People"}, Blurb: "People and access: profiles, pingable and assignable people, project access, out-of-office, preferences, and notification subscriptions.", }, { Key: "automation", Tags: []string{"Checkins", "Templates", "Webhooks", "Lineup", "Dock", "Recordings", "Search"}, Blurb: "Automatic check-ins (questionnaires, questions, answers, reminders), project templates and the template library, webhooks, lineup markers, dock tools, recording lifecycle (archive/trash), change events, and search.", }, { Key: "reports", Tags: []string{"Reports", "Timeline"}, Blurb: "Reports and timelines: progress, assigned and overdue todos, upcoming schedule, per-person progress, and project timelines.", }, { Key: "everything", Tags: []string{"Everything"}, Blurb: "Account-wide feeds: every checkin, comment, file, forward, and message, and cards and todos filtered by state (open, completed, overdue, unassigned, no due date, not now).", }, { Key: "eventfeed", Tags: []string{"EventFeed"}, Blurb: "The account event feed: poll events from a resumable position, and poll the agent inbox of addressed items. Pages carry a position and a continuation URL rather than page numbers; deduplicate events by id and inbox items by addressing_id, and refetch the referenced recording before acting on it. Minting a live-stream ticket is not served here — the ticket is a bearer this surface cannot use, and 'basecamp events ticket' is where it lives.", }, { Key: "clientside", Tags: []string{"ClientFeatures"}, Blurb: "The Clientside: client approvals, correspondences, replies, and client visibility of recordings.", }, { Key: "forwards", Tags: []string{"Forwards"}, Blurb: "Email forwards: project inboxes, forwarded emails, and their replies.", }, { Key: "account", Tags: []string{"Account", "Gauges", "MyAssignments", "MyNotes", "MyNotifications", "Bookmarks", "BubbleUps", "Drafts"}, Blurb: "Account info and your personal surface: gauges and needles, my assignments and priorities, notifications and bubble-ups, bookmarks, bubbling recordings up, personal note, and drafts.", }, }
DomainSpecs curates which slice of the basecamp-sdk surface each domain gateway tool exposes, in tool display order. Tags are basecamp-sdk's OpenAPI tags (each operation carries exactly one); a spec may merge several tags into one tool. This mapping is the only hand-maintained part of the catalog — everything else derives from the SDK model via the toolkit.
The grouping mirrors basecamp-mcp-server's domain curation (projects, todos, cards, messages, campfires, schedules, files, people, account) where the SDK's tags allow, and follows the tags where they don't: the server's checkins domain lives inside the SDK's Automation tag alongside templates, webhooks, lineup, dock tools, and search, so it is served as the automation domain; the server's admin grab-bag lands across reports, everything, and automation. Every tag is claimed — Catalog.Unmapped is pinned empty by tests, so an SDK tag nobody has decided about fails the build.
Functions ¶
This section is empty.
Types ¶
type API ¶
type API interface {
Get(ctx context.Context, path string) (*basecamp.Response, error)
Post(ctx context.Context, path string, body any) (*basecamp.Response, error)
Put(ctx context.Context, path string, body any) (*basecamp.Response, error)
Delete(ctx context.Context, path string) (*basecamp.Response, error)
Recordings() *basecamp.RecordingsService
Comments() *basecamp.CommentsService
EventFeed() *basecamp.EventFeedService
}
API is the slice of the basecamp-sdk client the dispatcher drives. The CLI's *basecamp.AccountClient satisfies it; the client carries auth, token refresh, retry, account scoping, and base URL resolution, so the dispatcher only assembles paths and bodies.
The four verbs serve every model operation but the feed's two poll lanes. The recordings and comments services serve the composite actions (see composite.go), which are SDK compositions rather than single requests and so cannot be assembled from a method and a path. The event feed service serves poll_events and poll_inbox, whose refusals carry the data a consumer resumes from and whose bodies the verbs above throw away (see feed.go).
Every one of them is required rather than probed for. The catalog derives from the model and always carries these actions, so a client that satisfied only the verbs would advertise actions it then failed as internal errors — a promise nothing keeps. Required here, that mismatch cannot exist, and the compiler is what says so.
type Config ¶
type Config struct {
// ReadOnly drops every write action from the catalog and refuses write
// dispatch outright.
ReadOnly bool
// Domains narrows the served domains by key ("projects", "todos", ...).
// Empty means all. Unknown keys are a startup error — fail closed.
Domains []string
}
Config selects the served tool surface.
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server wraps the toolkit gateway serving Basecamp's derived catalog, dispatching through the CLI's authenticated, account-scoped SDK client.
func New ¶
New derives the catalog and hands it to the gateway, which applies the config's domain and read-only filters. Tool calls dispatch through api.
func (*Server) BuildMCPServer ¶
BuildMCPServer constructs the SDK MCP server with one gateway tool per served domain.