MCP v2 Overview
guinness-backend/apps/mcp-v2 is the Model Context Protocol server for the V2
design-to-code workflow. It exposes six project-scoped design, code, and
Des2Code tools to coding assistants.
MCP v2 owns transport, CloudFront token validation, PostgreSQL-backed MCP API
key authentication, project/write permission checks, and request-scoped tool
registration. All domain operations are delegated to
guinness-backend/apps/app internal APIs. MCP v2 does not call SQS,
DocumentDB, AI-v2, or S3 directly.
Target Architecture
flowchart TD
Client["MCP client"] --> CF["CloudFront<br/>X-MCP-Token"]
CF --> MCP["apps/mcp-v2<br/>stateless HTTP /mcp"]
MCP --> Auth["PostgreSQL mcp_api_keys"]
MCP -->|"X-API-Key + X-MCP-Project-ID"| Backend["apps/app internal API"]
Backend --> PG[("PostgreSQL<br/>design/code/project scope")]
Backend -->|"trigger"| Q["SQS des2code"]
Q --> Worker["guinness-ai-v2 apps/des2code"]
Worker --> DocDB[("DocumentDB<br/>design/code/variation/graph/index")]
Worker --> S3[("S3 request artifacts")]
Worker -->|"AI-status webhook"| Backend
Backend -->|"source/index reads"| AIAPI["guinness-ai-v2 internal API"]
AIAPI --> DocDB
Backend -->|"latest result read"| S3
| Area | Owner | Rule |
|---|---|---|
| MCP transport and edge auth | apps/mcp-v2 |
Fresh McpServer/transport per request; CloudFront token required outside local. |
| MCP API-key auth | apps/mcp-v2 + PostgreSQL |
Authenticate active mcp_api_keys, require a valid project scope, enforce write permission for trigger. |
| Domain authorization/orchestration | apps/app |
Revalidate project/org/design scope, design readiness, current AI-v2 index readiness, and SQS dispatch. |
| Source detail/list | AI-v2 DocumentDB through backend | MCP calls backend; backend proxies AI-v2 service-token routes and strips vectors. |
| Des2Code execution | AI-v2 worker | Scoped canonical retrieval/matching, S3 artifact, webhook. |
| Des2Code result | Backend + S3 | Backend authorizes design scope and returns newest contract-valid request artifact; no result row in PostgreSQL. |
MCP Tools
| Tool | Purpose | MCP v2 downstream |
|---|---|---|
trigger-des2code |
Queue matching for an imported design | POST /internal/des2code |
get-des2code |
Read newest success/failure artifact for one design | GET /internal/des2code/{design_id} |
list-designs |
List imported design sources | GET /internal/designs |
list-code |
List imported code sources | GET /internal/code |
get-design-detail |
Read one design source without vectors | GET /internal/designs/{design_id} |
get-code-detail |
Read one code source without vectors | GET /internal/code/{code_id} |
trigger-des2code requires an MCP key with WRITE permission. Every MCP API
key accepted by the server must be project-scoped. Code-index rebuild/status
and codebase-rule CRUD are not MCP v2 tools in the current implementation.
MCP Auth Contract
MCP v2 authenticates API keys with PostgreSQL mcp_api_keys.
flowchart LR
Header["MCP-API-Key<br/>or Authorization: Bearer"] --> Parse["Parse guinness_prefix_secret"]
Parse --> PG["PostgreSQL lookup by key_prefix"]
PG --> Verify["scrypt verify"]
Verify --> State["deleted/revoked/expired checks"]
State --> Scope["positive project_id required"]
Scope --> LastUsed["async last_used_at update"]
| Requirement | Behavior |
|---|---|
| Edge token | X-MCP-Token must match CLOUDFRONT_SECRET_HEADER outside ENVIRONMENT=local; constant-time comparison |
| API-key headers | Prefer MCP-API-Key; accept Authorization: Bearer <api-key> |
| Database | PostgreSQL/Drizzle, table mcp_api_keys |
| Lookup | key_prefix with deleted_at IS NULL |
| Verification | Stored salt/hash using the configured scrypt contract |
| Validity | Reject revoked, expired, deleted, malformed, or unknown keys |
| Scope | Reject keys without a positive project ID; every tool is constrained to it |
| Permission | trigger-des2code requires WRITE; read tools use authenticated project scope |
| Audit | Update last_used_at asynchronously; update failure is logged and non-blocking |
Schema reference: PostgreSQL mcp_api_keys.
Backend Internal API Contract
MCP v2 sends the authenticated project ID to backend. Backend repeats scope validation before PostgreSQL, SQS, AI-v2, or S3 access.
sequenceDiagram
participant Client as MCP client
participant MCP as apps/mcp-v2
participant Backend as apps/app internal API
participant AI as guinness-ai-v2 internal API/worker
participant S3 as S3
Client->>MCP: tools/call
MCP->>MCP: edge + API-key auth, schema, permission/scope
MCP->>Backend: X-API-Key + X-MCP-Project-ID
alt trigger-des2code
Backend->>Backend: authorize design and require completed import
Backend->>AI: read current code_index; require ready
Backend->>AI: SQS flat design/scope/request payload
AI->>S3: write request artifact
AI->>Backend: AI-status webhook
else get-des2code
Backend->>S3: list authorized design prefix
Backend-->>MCP: newest strict artifact projection
else list/detail source
Backend->>AI: service-token scoped read
AI-->>Backend: source without vectors
end
Backend-->>MCP: JSON result
MCP-->>Client: text + structuredContent
Required MCP-to-backend headers:
| Header | Required | Purpose |
|---|---|---|
X-API-Key |
Yes | backend internal service authentication |
X-MCP-Project-ID |
Yes | repeat authenticated project-scope enforcement |
Backend internal routes consumed by MCP v2:
| Route | Backend responsibility |
|---|---|
POST /internal/des2code |
Validate design/project/org and MCP scope, require completed design + ready AI-v2 index, generate request ID, send SQS. |
GET /internal/des2code/{design_id} |
Authorize design, find newest canonical S3 artifact, validate full scope/shape. |
GET /internal/designs |
Validate project scope and proxy paginated AI-v2 design summaries. |
GET /internal/designs/{design_id} |
Validate design/project scope and proxy detail without vectors. |
GET /internal/code |
Validate project scope and proxy paginated AI-v2 code summaries. |
GET /internal/code/{code_id} |
Validate code/project/optional org scope and proxy detail without vectors. |
Backend, SQS, and AI-v2 Contract
Backend sends exactly this worker body after all readiness checks:
{
"design_id": "42_file_node:1",
"project_id": 42,
"organization_id": 1,
"request_id": "0192a3b4-c5d6-7e8f-9a0b-1c2d3e4f5a6b"
}
There is no schema_version, operation, or codebase_index_token. Backend
checks the current AI-v2 DocumentDB code_index through its internal read API,
but the worker independently loads and requires the current scoped index to be
ready before retrieval.
The worker writes
{organization_id}/{project_id}/des2code/{design_id}/{request_id}.json (or
{request_id}-failed.json) and sends the shared AI-status webhook. The webhook
validates design scope and logs operational status; it does not store the
Des2Code result or artifact pointer in PostgreSQL.
Design/code list and detail reads follow this path only:
MCP v2 never receives DocumentDB credentials or embedding vectors.
Backend API Handoff
get-des2code returns implementation and occurrence evidence in
structuredContent: matched_codes, usage_matches, code_index_id,
request_id, retrieval/usage diagnostics, matcher configuration, model summary,
artifact metadata, status, processed time, and error.
For implementation work, the client should:
- use
list-designsto discover a design ID when necessary; - call
trigger-des2codewith exact design/project/organization scope; - poll
get-des2codeuntil an artifact is returned; - inspect
usage_matchesfor Figma-node/state mappings; - call
get-code-detailfor each selectedcode_idto retrieve full source/CSS; - use Figma MCP separately to inspect the referenced node geometry/content.
Environment Variables
| Variable | Required | Purpose |
|---|---|---|
CLOUDFRONT_SECRET_HEADER |
Yes | Expected X-MCP-Token value |
ENVIRONMENT |
No | local skips mandatory edge-token presence |
DATABASE_RDS_PROXY_ENDPOINT or DATABASE_HOST |
Yes outside local | PostgreSQL connection |
DATABASE_PORT |
Deployment-specific | PostgreSQL port |
DATABASE_NAME |
Yes | PostgreSQL database |
DATABASE_USER |
Yes | PostgreSQL user |
DATABASE_PASSWORD |
Yes | PostgreSQL password |
DATABASE_CONNECTION_LIMIT |
No | Pool limit |
BACKEND_INTERNAL_URL |
Yes | Backend internal API base URL |
BACKEND_INTERNAL_API_KEY |
Yes | X-API-Key sent to backend |
BACKEND_INTERNAL_TIMEOUT_MS |
No | Positive timeout, default 10000, max 120000 |
MCP v2 does not need AWS, SQS, S3, DocumentDB, AI provider, Figma, or webhook credentials.
Migration Checklist
- [x] Use PostgreSQL API-key authentication and require a positive project scope.
- [x] Delegate all six domain tools to backend internal APIs.
- [x] Keep SQS, S3, DocumentDB, provider, Figma, and webhook access out of MCP v2.
- [x] Require backend and worker code-index readiness checks before matching.
- [x] Use flat request payloads and immutable request-scoped artifacts.
- [x] Return component and variation evidence through backend-normalized results.