goux-mcp
v0.3.3
Published
MCP server for GoUX platform — browse projects, design tokens, AI sessions, and billing from your IDE.
Maintainers
Readme
goux-mcp
An MCP (Model Context Protocol) server for the GoUX platform. Lets AI assistants (GitHub Copilot, Claude, Cursor, etc.) read GoUX project data — design tokens, components, individual pages and fragments, AI sessions, and billing — directly from your IDE.
Features
- 32 read-only tools covering projects, design system, pages, fragments, versions, members, templates, AI sessions, billing, account — plus
get_design_bundle,get_pages(batch),find_project,list_icons,list_targets(stack metadata + detection signatures) andgenerate_code(deterministic JSON → framework code: tsx, jsx, html, vue, svelte, dart) - Auto-poll device login — single
logincall now waits up to 50 s for the user to approve in the browser; no second call needed in the common case - Format param on chunk/page/fragment reads —
format: "markdown" | "raw" | "json". Use"json"for agents that don't want the markdown wrapper. - ETag-aware reads — pass
if_changed_since: <last_etag>to get anunchangedresponse and skip re-parsing. - Transport size guard — payloads above 80 KB include a warning and a hint to use a narrower tool, instead of being silently truncated by the MCP transport.
- Device authorization flow (RFC 8628) — no copy-pasting API keys
- ETag-aware caching with per-entity TTLs (design tokens & components: 10 min, pages & fragments: 1–5 min, versions: 30 sec)
- Singleflight deduplication — parallel chunk/page requests coalesce into one HTTP call
- Mutex-guarded token refresh — safe when multiple tools run concurrently
- Contract test —
npm run contract-testvalidates every endpoint response against the bundled zod schemas, catching server-side schema drift before it ships.
Quick Start
1. Install (npx — no global install needed)
npx goux-mcp@latest2. Add to your IDE
VS Code (~/Library/Application Support/Code/User/mcp.json):
{
"servers": {
"goux": {
"command": "npx",
"args": ["-y", "goux-mcp@latest"],
"env": {
"API_BASE_URL": "https://api.goux.io"
}
}
}
}Cursor (~/.cursor/mcp.json):
{
"mcpServers": {
"goux": {
"command": "npx",
"args": ["-y", "goux-mcp@latest"],
"env": {
"API_BASE_URL": "https://api.goux.io"
}
}
}
}Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):
{
"mcpServers": {
"goux": {
"command": "npx",
"args": ["-y", "goux-mcp@latest"],
"env": {
"API_BASE_URL": "https://api.goux.io"
}
}
}
}3. Login
Open the MCP tool panel in your IDE and call the login tool. You'll receive a URL and a short code. Open the URL in your browser, enter the code, and approve. Then call login again to complete authentication.
Development
Local server (pointing at local goux-api)
{
"servers": {
"goux-dev": {
"command": "node",
"args": ["/path/to/goux-mcp/dist/index.js"],
"env": {
"API_BASE_URL": "http://localhost:8080",
"LOG_LEVEL": "debug"
}
}
}
}Build
npm install
npm run build # compile TypeScript → dist/
npm run typecheck # type check only
npm run lint # ESLintConfiguration
All configuration is via environment variables:
| Variable | Default | Description |
| ---------------- | --------------------- | ------------------------------------------- |
| API_BASE_URL | https://api.goux.io | GoUX API base URL |
| API_TOKEN_FILE | ~/.goux/token.json | Path to token storage file |
| API_TIMEOUT | 30000 | HTTP request timeout (ms) |
| CACHE_TTL | 300 | Default cache TTL in seconds |
| LOG_LEVEL | info | Log level: debug, info, warn, error |
Token files are stored in ~/.goux/:
| File | Purpose |
| --------------------------- | ------------------------------------ |
| ~/.goux/token.json | Access + refresh token (mode 0600) |
| ~/.goux/pending_auth.json | In-progress device flow state (0600) |
Tools
Authentication (3)
| Tool | Description |
| ------------- | ------------------------------------------------------------------ |
| login | Initiate or complete device auth flow (two-phase: initiate → poll) |
| logout | Revoke device session and clear stored tokens |
| auth_status | Check login status, token expiry, and account email |
Projects — meta (2)
| Tool | Params | Description |
| --------------- | -------------------- | ---------------------------- |
| list_projects | page?, per_page? | List your GoUX projects |
| get_project | project_id | Get project metadata + skills |
Projects — chunks (3 typed + bundle)
All accept optional format: "markdown" | "raw" | "json" and if_changed_since: <etag>.
| Tool | Params | Description |
| -------------------- | ------------ | ------------------------------------------------------------------------------------- |
| get_project_meta | project_id | Project chunk — top-level config |
| get_design_tokens | project_id | Design tokens — colors, typography, spacing, radii, shadows |
| get_components | project_id | Components chunk — buttons, cards, forms, etc. |
| get_design_bundle | project_id | Project + tokens + components + page index + fragment index in one call. Preferred for code generation. |
Projects — pages (3)
| Tool | Params | Description |
| ------------- | ----------------------------------- | -------------------------------------------------------------------- |
| list_pages | project_id | List page keys, labels, and routes |
| get_page | project_id, key | Get a single page's full JSON for code generation (supports format/if_changed_since) |
| get_pages | project_id, keys[] (1-5) | Batch fetch up to 5 pages in one call |
Projects — fragments (2)
| Tool | Params | Description |
| ---------------- | -------------------- | ------------------------------------------------- |
| list_fragments | project_id | List fragment keys (reusable page partials) |
| get_fragment | project_id, key | Get a single fragment's full JSON (supports format/if_changed_since) |
Projects — collaboration & search (4)
| Tool | Params | Description |
| ---------------- | ------------------------------ | ------------------------------------------------------------------------ |
| list_versions | project_id, page?, per_page? | List manual saves and AI auto-snapshots |
| list_members | project_id | List collaborators (name, email, role, billing mode) |
| find_project | query, limit? | Fuzzy-find projects by title — when the user references one by name |
| list_icons | project_id | Audit Lucide icon usage across components + first 20 pages with counts |
Templates (1)
| Tool | Description |
| ---------------- | ------------------------------------------------------------------ |
| list_templates | List public starter templates (public endpoint, no auth required) |
Code generation (2)
| Tool | Params | Description |
| --------------- | ------------------------------------------------------------------ | -------------------------------------------------------------------------- |
| list_targets | — | Returns structured stack metadata for every supported generate_code target — framework, language, router, styling, icons, deps, and a detect signature listing the package names whose presence implies that target. Agents call this first, then read the user's package.json (and pubspec.yaml if present) and match against the signatures themselves. |
| generate_code | project_id, target, scope?, manifest_only?, format? | Turn a project's design data into ready-to-use framework files (a file map of paths → contents). Deterministic — no LLM, no placeholders. |
Targets (v0.3.0)
| Target | Framework | Language | Router | Styling | Icons |
|----------|-------------------------|-------------|----------------------|------------------|----------------------|
| tsx | React 18 | TypeScript | react-router-dom@^6 | Tailwind@^3 | lucide-react |
| jsx | React 18 | JavaScript | react-router-dom@^6 | Tailwind@^3 | lucide-react |
| html | static HTML | HTML | multi-page | Tailwind CDN | lucide UMD |
| vue | Vue 3 | TypeScript | vue-router@^4 | Tailwind@^3 | lucide-vue-next |
| svelte | Svelte 5 | TypeScript | SvelteKit | Tailwind@^3 | lucide-svelte |
| dart | Flutter | Dart | go_router | Tailwind→widget mapper | Material Icons (lucide map) |
Agent integration model
The server ships canonical stack snapshots as data, not as a server-side detector. The agent reads the user's project files itself and matches against each target's detect signature returned by list_targets. This keeps the framework-list ownership on the client (where it belongs — agents have the file system, can see configs and code conventions, and adapt to new frameworks without a server release).
list_targets → discover canonical stacks + each target's `detect` signature
↓
existing project?
└─ yes → read package.json (+ pubspec.yaml if present)
→ match deps to a target's `detect.any_of` / `requires_pubspec` / `requires_typescript`
→ if no exact match (Angular, Lit, Astro, …): pick the closest target,
plan to rewrite client-side after generation
└─ no → AskUserQuestion(framework, TypeScript yes/no)
→ derive target
↓
generate_code(target=…, manifest_only=true) → discover output paths
generate_code(target=…, scope.pages=[…]) → fetch per-page contents
↓
write files; if user uses Next.js / Nuxt / SvelteKit-with-non-default-routes / etc.,
rewrite router/file layout to match their conventionsDetection signatures (each list_targets row carries them as data):
pubspec.yamlpresent → dartsvelte/@sveltejs/kit→ sveltevue/nuxt→ vuereact(+typescript) → tsxreact(no TypeScript) → jsxjquery(or no JS framework) → html- Anything else (Angular, Lit, Astro, Ember, Alpine, htmx, …) → no native emitter; agent picks the closest target and rewrites client-side.
Output flow (handling the 80 KB transport budget)
generate_code is read-only from the server's perspective — it consumes the same GET endpoints used by get_components, get_design_tokens, list_pages, get_page, list_fragments, get_fragment and runs a deterministic local transform. Output exceeds the 80 KB transport budget for medium projects, so the standard flow is:
- Manifest call to discover output paths and ETag:
{ "name": "generate_code", "arguments": { "project_id": "<uuid>", "target": "tsx", "manifest_only": true } } - Per-page call to pull each page's components+fragments+page TSX:
{ "name": "generate_code", "arguments": { "project_id": "<uuid>", "target": "tsx", "scope": { "pages": ["dashboard"] } } } - Per-path call to fetch a specific output file:
{ "name": "generate_code", "arguments": { "project_id": "<uuid>", "target": "tsx", "scope": { "paths": ["src/pages/Dashboard.tsx"] } } }
TSX output drops into npm create vite@latest -- --template react-ts plus npm i lucide-react react-router-dom and builds with zero TypeScript errors. Per-target dep lists are returned by list_targets.
Drop-in CLAUDE.md / agent prompt
If you want the integration to be deterministic in any LLM-based agent (Claude Code, Cursor, Copilot), copy the snippet below into your project's CLAUDE.md (or its equivalent agent-instruction file). It encodes the workflow above so the agent does not have to derive it from tool descriptions alone.
## GoUX code generation
When the user asks to generate UI from their GoUX project:
1. Call `mcp__goux-dev__list_targets` to see supported stacks. Each entry
carries a `detect` signature (`any_of` package names, `requires_pubspec`,
`requires_typescript`).
2. Read `package.json` (and `pubspec.yaml` if it exists) in the project root.
Extract `dependencies` + `devDependencies` and TypeScript presence.
3. Match against each target's `detect` signature. Pick the target that fits.
- If multiple match (e.g. a monorepo with both react and vue), prefer the
framework that owns the directory the user is working in.
- If nothing matches (Angular, Lit, Astro, Ember, Alpine, htmx, etc.):
pick the closest target — `tsx` for component-shaped frameworks, `html`
for template-shaped ones — and plan to rewrite client-side.
4. If there is no project context (greenfield), ask the user which framework
and language they want, then map to the same target list.
5. Call `mcp__goux-dev__generate_code` with `manifest_only: true` to discover
the output file map.
6. For each page the user asked for, call `generate_code` again with
`scope.pages: ["<key>"]` and write the returned files to disk.
7. If the user's router or file layout differs from the target's defaults
(e.g. Next.js App Router vs the emitted `App.tsx` with react-router),
rewrite the App shell and move page files into the correct locations.AI Sessions (4)
| Tool | Params | Description |
| ---------------- | ---------------------------------- | --------------------------------------------- |
| list_sessions | page?, per_page? | List AI sessions |
| get_session | session_id | Get session details and recent messages |
| list_messages | session_id, page?, per_page? | List session messages (max 20/page) |
| get_job_status | job_id | Check AI job progress, plan steps, and usage |
Billing & Account (7)
| Tool | Params | Description |
| ----------------------- | -------------------- | -------------------------------------------------------- |
| get_me | — | Get user profile (email, name, 2FA status) |
| get_subscription | — | Get subscription, payment method, pending changes |
| get_usage | page?, per_page? | Get credit usage breakdown by model |
| list_transactions | page?, per_page? | List billing transactions (subscriptions, purchases) |
| get_purchased_credits | — | Lifetime purchased-credit balance and history |
| list_plans | — | List available billing plans with pricing |
| list_models | — | List available AI models with tiers and credit cost |
Total: 32 read-only tools.
Upgrading
From 0.2.x → 0.3.0 (additive, no breaking changes)
- New
list_targetsandgenerate_codetools — deterministic JSON → framework code. v0.3.0 ships all six targets:tsx,jsx,html,vue,svelte,dart.list_targetsexposes detection signatures (which deps imply each target) so agents can match the user's project natively without a server-side pattern matcher. loginauto-polls — single call waits up to 50 s for browser approval. The two-call pattern still works (call again to keep waiting).- 4 new chunk/page tools:
get_design_bundle,get_pages(batch),find_project,list_icons. - All chunk/page/fragment reads accept optional
formatandif_changed_since. - Payload size warning at 80 KB with hint toward narrower tools.
- Tool count: 26 → 32.
From 0.1.0 → 0.2.0 (breaking)
get_chunkremoved. Use the typed replacements:get_project_meta,get_design_tokens,get_components. Old chunk typesatoms,molecules,organisms,pagesno longer exist on the server.- New tools added for entities the API now exposes per-key:
list_pages,get_page,list_fragments,get_fragment. ProjectSummary.atom_count/molecule_count/organism_countremoved from API. Replaced by singlecomponent_countand existingpage_count.
If your IDE config or scripts hardcoded chunk_type=atoms (etc.), they will return tool-not-found / 404. Switch to the typed tools.
Security
- Tokens are stored at
~/.goux/token.jsonwith0600permissions (owner read/write only). - Access tokens are never logged — only the expiry timestamp and account email are surfaced in logs.
- The server is read-only: it holds
project:read ai:invoke profile:readscopes. No project mutations are possible. - All AI interactions go through the GoUX server — the MCP never invokes AI directly despite holding
ai:invokescope (granted by the server, cannot be excluded).
Troubleshooting
login tool returns "Too many login attempts" — Wait ~60 seconds and try again.
login call seems ignored — Check that LOG_LEVEL=debug is set and look for startup errors in the IDE's MCP server log panel.
Stale data — Call the relevant get_* tool again; the ETag cache will refresh if the server data changed. Versions and pages have shorter TTLs to track active edits.
npx uses a cached old version — Run npx clear-npx-cache then retry with @latest.
License
MIT
