Design System MCP Server
by Thaynah
README.md
# MCP Server (HTTP) para Design System
Microsserviço HTTP em NodeJS (Express) que implementa o protocolo MCP via JSON‑RPC para expor recursos de um Design System. A fonte de dados é Markdown (mock local) ou S3.
## Stack
- NodeJS + Express
- `@modelcontextprotocol/sdk` + `zod`
- `@aws-sdk/client-s3`
- `gray-matter`
## Configuração
Copie `.env.example` para `.env` e ajuste:
```
PORT=3000
MOCK_S3=true
AWS_REGION=us-east-1
AWS_ACCESS_KEY_ID=changeme
AWS_SECRET_ACCESS_KEY=changeme
S3_BUCKET=meu-bucket-design-system
S3_PREFIX=components/
```
- `MOCK_S3=true` usa `mock-data/components/*.md`.
- Para S3 real: `MOCK_S3=false` + credenciais e bucket.
## Execução
- Dev: `npm run dev`
- Prod/local: `npm start`
- Base: `http://localhost:3000`
## Endpoints
- `GET /health` → `{ status, service, mock }`
- `POST /mcp` → JSON‑RPC 2.0 (MCP via SDK)
- `GET /mcp` → abre SSE (servidor→cliente) para uma sessão
- `DELETE /mcp` → encerra a sessão atual
Observação: As rotas REST de componentes (`/components`, `/components/:id`) foram removidas. O acesso aos componentes acontece exclusivamente via MCP.
## MCP (SDK oficial)
- Servidor: `McpServer` com `StreamableHTTPServerTransport`.
- Recursos: `ResourceTemplate('component://{id}')` com listagem dinâmica e leitura de markdown.
- Ferramentas (schemas `zod`): `search_components`, `related_components`.
- Prompt: `component_usage`.
### Requisitos de chamada HTTP
- Header `Accept` deve incluir `application/json` e `text/event-stream`.
- `initialize` deve ser enviado com `protocolVersion` (ex.: `2025-03-26`).
- Após `initialize`, inclua `Mcp-Session-Id` e `Mcp-Protocol-Version` em todas as chamadas subsequentes.
### CURLs (SDK)
- Initialize (captura sessão)
```
curl -s -i -X POST http://localhost:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-d '{
"jsonrpc":"2.0",
"id":"init",
"method":"initialize",
"params":{
"clientInfo":{"name":"cli","version":"1.0.0"},
"capabilities":{"jsonResponse":true},
"protocolVersion":"2025-03-26"
}
}'
# Observe o header mcp-session-id na resposta e exporte:
# SID=... (valor do header)
```
- Listar recursos (reutiliza sessão)
```
curl -s -i -X POST http://localhost:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H "Mcp-Session-Id: $SID" \
-H 'Mcp-Protocol-Version: 2025-03-26' \
-d '{"jsonrpc":"2.0","id":"lr","method":"resources/list","params":{}}'
```
- Ler recurso (por URI)
```
curl -s -i -X POST http://localhost:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H "Mcp-Session-Id: $SID" \
-H 'Mcp-Protocol-Version: 2025-03-26' \
-d '{"jsonrpc":"2.0","id":"rr","method":"resources/read","params":{"uri":"component://button"}}'
```
- Listar ferramentas
```
curl -s -i -X POST http://localhost:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H "Mcp-Session-Id: $SID" \
-H 'Mcp-Protocol-Version: 2025-03-26' \
-d '{"jsonrpc":"2.0","id":"lt","method":"tools/list","params":{}}'
```
- Executar ferramenta `search_components`
```
curl -s -i -X POST http://localhost:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H "Mcp-Session-Id: $SID" \
-H 'Mcp-Protocol-Version: 2025-03-26' \
-d '{"jsonrpc":"2.0","id":"ct1","method":"tools/call","params":{"name":"search_components","arguments":{"query":"input"}}}'
```
- Executar ferramenta `related_components`
```
curl -s -i -X POST http://localhost:3000/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H "Mcp-Session-Id: $SID" \
-H 'Mcp-Protocol-Version: 2025-03-26' \
-d '{"jsonrpc":"2.0","id":"ct2","method":"tools/call","params":{"name":"related_components","arguments":{"id":"button"}}}'
```
- SSE dedicado (opcional)
```
curl -s -N -X GET http://localhost:3000/mcp \
-H 'Accept: text/event-stream' \
-H "Mcp-Session-Id: $SID" \
-H 'Mcp-Protocol-Version: 2025-03-26'
```
- Encerrar sessão
```
curl -s -X DELETE http://localhost:3000/mcp \
-H "Mcp-Session-Id: $SID" \
-H 'Mcp-Protocol-Version: 2025-03-26' -i
```
## Estrutura
```
src/
index.js # Express + transporte MCP
mcp-setup.js # Registro de recursos, ferramentas e prompt via SDK
datasource.js # S3 + mock
mock-data/
components/
.env.example
README.md
```
## Debug com MCP Inspector
- Instale e conecte:
```
npx @modelcontextprotocol/inspector
```
- Na UI, conecte usando a URL: `http://localhost:3000/mcp`.
## Conexão com clientes MCP
- Claude Code:
```
claude mcp add --transport http design-system http://localhost:3000/mcp
```
- VS Code (exemplo JSON):
```
code --add-mcp '{"name":"design-system","type":"http","url":"http://localhost:3000/mcp"}'
```
## Coleção Insomnia
- Importação:
- Abra o Insomnia → Application → Import Data → From File.
- Selecione o arquivo `insomnia_mcp_collection.json` na raiz do projeto.
- Ambiente:
- A coleção já define `base_url` (`http://localhost:3000`) e `protocol_version` (`2025-03-26`).
- Encadeamento de sessão:
- A requisição `Initialize (capture session)` captura o header `mcp-session-id`.
- As demais requisições usam esse valor automaticamente com o template `{% response 'req_init', 'header', 'mcp-session-id' %}`.
- Ordem sugerida:
- `Health` → `Initialize (capture session)` → `resources/list` → `resources/read (button)` → `tools/list` → `tools/call search_components` → `tools/call related_components` → `prompts/list` → `prompts/get component_usage (id=button)` → `GET SSE /mcp` (opcional) → `DELETE /mcp`.
- Observações:
- Certifique-se de que o servidor esteja rodando (`PORT=3000 MOCK_S3=true node src/index.js`).
- O SSE é contínuo; interrompa manualmente quando terminar.This server cannot be deployed
Maintenance
ActivityInactive
ResponsivenessNo issues