--- title: "SPEC — MCP Paperclip v1.0" date: 2026-04-07 type: spec status: draft project: mcp-paperclip desk_task: "" tags: [mcp, paperclip, typescript, agentes, orquestração] --- # SPEC — MCP Paperclip v1.0 MCP TypeScript para integração completa com o Paperclip AI (orquestrador autónomo em `clip.descomplicar.pt`). Permite ao Claude Code gerir agentes, issues, rotinas, goals, projectos, aprovações, custos, actividade, skills, segredos e dashboard via API REST. --- ## Contexto | Item | Valor | |------|-------| | **API Base** | `https://clip.descomplicar.pt/api` (produção) | | **Paperclip Version** | `0.3.1` | | **Company ID** | `ebe10308-efd7-453f-86ab-13e6fe84004f` (Descomplicar) | | **User ID** | `v1N5OccPn9DGq6iog7qW9nEvnXYFT3iO` (Emanuel) | | **Auth** | `Authorization: Bearer {PAPERCLIP_API_KEY}` (Board API Key, SHA256 hash em `board_api_keys`) | | **Destino** | `/home/ealmeida/mcp-servers/mcp-paperclip/` | | **Transport** | STDIO (Claude Code) + StreamableHTTP porta `3175` + SSE porta `3175` (legado) | | **Linguagem** | TypeScript (padrão Descomplicar) | | **API Total** | 246 endpoints em 21 módulos — este MCP cobre 159 tools | --- ## Pré-requisito: Criar Board API Key Antes da primeira utilização, gerar e registar uma Board API Key: ```bash # Gerar key KEY=$(node -e "console.log('pcp_mcp_' + require('crypto').randomBytes(24).toString('hex'))") echo "PAPERCLIP_API_KEY=$KEY" # Registar na BD (SHA256 hash) HASH=$(node -e "const c=require('crypto'); process.argv[1] && console.log(c.createHash('sha256').update(process.argv[1]).digest('hex'))" "$KEY") PGPASSWORD=paperclip psql -h 127.0.0.1 -p 54329 -U paperclip -d paperclip -c \ "INSERT INTO board_api_keys (user_id, name, key_hash) VALUES ('v1N5OccPn9DGq6iog7qW9nEvnXYFT3iO', 'claude-code-mcp', '$HASH');" ``` Guardar `KEY` no `.env` do MCP como `PAPERCLIP_API_KEY`. --- ## Arquitectura ``` mcp-paperclip/ ├── src/ │ ├── index.ts # Entry STDIO (Claude Code) │ ├── index-http.ts # Entry StreamableHTTP + SSE porta 3175 │ ├── server.ts # Lógica comum (createServer) │ ├── client.ts # HTTP client para API Paperclip │ ├── tools/ │ │ ├── index.ts # Registar todas as tools │ │ ├── agents.ts # Agentes — CRUD, lifecycle, config, keys, heartbeats │ │ ├── issues.ts # Issues — CRUD, comments, documents, work-products, labels │ │ ├── routines.ts # Rotinas — CRUD, triggers, runs │ │ ├── goals.ts # Goals — CRUD │ │ ├── projects.ts # Projectos — CRUD, workspaces │ │ ├── approvals.ts # Aprovações — governance workflow │ │ ├── costs.ts # Custos e budgets — monitorização financeira │ │ ├── activity.ts # Actividade — audit log │ │ ├── skills.ts # Company skills — gestão de competências │ │ ├── secrets.ts # Segredos — gestão de secrets encriptados │ │ ├── plugins.ts # Plugins — instalar, activar, config, health │ │ ├── assets.ts # Assets — upload imagens e logos │ │ ├── settings.ts # Instance settings — configuração geral │ │ ├── access.ts # Invites, join requests, members │ │ ├── company.ts # Company, org, dashboard, members │ │ └── health.ts # Health check │ └── utils/ │ ├── logger.ts # Logger MCP-compatible (stderr, sem cores) │ └── annotations.ts # inferAnnotations por prefixo ├── tests/ │ └── tools.test.ts ├── docs/ │ └── API_REFERENCE.md # Endpoints mapeados ├── scripts/ │ ├── validate-capabilities.sh │ └── create-api-key.sh # Script criação Board API Key ├── .gitea/workflows/ │ └── ci.yml ├── .env.example ├── .eslintrc / eslint.config.js ├── .prettierrc ├── tsconfig.json ├── package.json ├── CLAUDE.md ├── CHANGELOG.md └── README.md ``` --- ## Tools (159 total) ### 1. Health (1 tool) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `get_health` | GET | `/health` | read | Retorna: `{ status, version, deploymentMode, bootstrapStatus }` --- ### 2. Company / Org (10 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `get_company` | GET | `/companies/:id` | read | | `list_companies` | GET | `/companies` | read | | `get_company_stats` | GET | `/companies/stats` | read | | `update_company` | PATCH | `/companies/:id` | write | | `update_company_branding` | PATCH | `/companies/:id/branding` | write | | `get_org_chart` | GET | `/companies/:id/org` | read | | `get_dashboard` | GET | `/companies/:id/dashboard` | read | | `list_members` | GET | `/companies/:id/members` | read | | `update_member_permissions` | PATCH | `/companies/:id/members/:memberId/permissions` | write | | `get_sidebar_badges` | GET | `/companies/:id/sidebar-badges` | read | **Nota:** `get_org_chart` retorna JSON da hierarquia, não SVG. --- ### 3. Agentes (22 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `list_agents` | GET | `/companies/:id/agents` | read | | `get_agent` | GET | `/agents/:id` | read | | `get_agent_runtime_state` | GET | `/agents/:id/runtime-state` | read | | `get_agent_configuration` | GET | `/agents/:id/configuration` | read | | `get_agent_config_revisions` | GET | `/agents/:id/config-revisions` | read | | `rollback_agent_config` | POST | `/agents/:id/config-revisions/:revisionId/rollback` | write | | `get_agent_skills` | GET | `/agents/:id/skills` | read | | `sync_agent_skills` | POST | `/agents/:id/skills/sync` | write | | `get_agent_task_sessions` | GET | `/agents/:id/task-sessions` | read | | `get_agent_instructions_bundle` | GET | `/agents/:id/instructions-bundle` | read | | `update_agent_instructions_bundle` | PATCH | `/agents/:id/instructions-bundle` | write | | `create_agent` | POST | `/companies/:id/agents` | write | | `create_agent_hire` | POST | `/companies/:id/agent-hires` | write | | `update_agent` | PATCH | `/agents/:id` | write | | `update_agent_permissions` | PATCH | `/agents/:id/permissions` | write | | `update_agent_instructions_path` | PATCH | `/agents/:id/instructions-path` | write | | `pause_agent` | POST | `/agents/:id/pause` | write | | `resume_agent` | POST | `/agents/:id/resume` | write | | `wakeup_agent` | POST | `/agents/:id/wakeup` | write | | `invoke_agent_heartbeat` | POST | `/agents/:id/heartbeat/invoke` | write | | `terminate_agent` | POST | `/agents/:id/terminate` | destrutivo | | `delete_agent` | DELETE | `/agents/:id` | destrutivo | **Parâmetros `create_agent`:** ```typescript { name: string, // nome do agente role: string, // ceo | coo | cto | engineer | analyst | devops | pm | ... title?: string, // descrição do cargo reports_to?: string, // UUID do agente supervisor capabilities?: string, // texto livre model?: string, // claude-sonnet-4-6 | claude-opus-4-6 | ... budget_monthly_cents?: number, instructions_file_path?: string // path absoluto para AGENTS.md } ``` **Parâmetros `create_agent_hire`:** ```typescript { name: string, role: string, title?: string, reports_to?: string, // Passa por governance/approval antes de criar o agente } ``` **Parâmetros `wakeup_agent`:** ```typescript { agent_id: string, issue_id?: string, // acordar em contexto de issue específica message?: string // mensagem de contexto } ``` --- ### 4. Agent Keys (3 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `list_agent_keys` | GET | `/agents/:id/keys` | read | | `create_agent_key` | POST | `/agents/:id/keys` | write | | `delete_agent_key` | DELETE | `/agents/:id/keys/:keyId` | destrutivo | --- ### 5. Heartbeat Runs (6 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `list_heartbeat_runs` | GET | `/companies/:id/heartbeat-runs` | read | | `list_live_runs` | GET | `/companies/:id/live-runs` | read | | `get_heartbeat_run` | GET | `/heartbeat-runs/:runId` | read | | `get_heartbeat_run_events` | GET | `/heartbeat-runs/:runId/events` | read | | `get_heartbeat_run_log` | GET | `/heartbeat-runs/:runId/log` | read | | `cancel_heartbeat_run` | POST | `/heartbeat-runs/:runId/cancel` | write | --- ### 6. Issues (17 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `list_issues` | GET | `/companies/:id/issues` | read | | `get_issue` | GET | `/issues/:id` | read | | `get_issue_heartbeat_context` | GET | `/issues/:id/heartbeat-context` | read | | `create_issue` | POST | `/companies/:id/issues` | write | | `update_issue` | PATCH | `/issues/:id` | write | | `delete_issue` | DELETE | `/issues/:id` | destrutivo | | `checkout_issue` | POST | `/issues/:id/checkout` | write | | `release_issue` | POST | `/issues/:id/release` | write | | `get_issue_comments` | GET | `/issues/:id/comments` | read | | `add_issue_comment` | POST | `/issues/:id/comments` | write | | `list_issue_documents` | GET | `/issues/:id/documents` | read | | `get_issue_document` | GET | `/issues/:id/documents/:key` | read | | `upsert_issue_document` | PUT | `/issues/:id/documents/:key` | write | | `delete_issue_document` | DELETE | `/issues/:id/documents/:key` | destrutivo | | `list_issue_work_products` | GET | `/issues/:id/work-products` | read | | `create_issue_work_product` | POST | `/issues/:id/work-products` | write | | `list_issue_live_runs` | GET | `/issues/:id/live-runs` | read | **Parâmetros `create_issue`:** ```typescript { title: string, description?: string, // markdown assignee_id?: string, // UUID do agente priority?: 'low' | 'medium' | 'high' | 'urgent', labels?: string[] } ``` **Nota:** Issues são a forma principal de dar trabalho aos agentes. `checkout_issue` -> agente bloqueia e começa a trabalhar. `release_issue` -> agente liberta e fica idle. --- ### 7. Labels (3 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `list_labels` | GET | `/companies/:id/labels` | read | | `create_label` | POST | `/companies/:id/labels` | write | | `delete_label` | DELETE | `/labels/:labelId` | destrutivo | --- ### 8. Issue Attachments (4 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `list_issue_attachments` | GET | `/issues/:id/attachments` | read | | `upload_issue_attachment` | POST | `/companies/:id/issues/:issueId/attachments` | write | | `get_attachment_content` | GET | `/attachments/:attachmentId/content` | read | | `delete_attachment` | DELETE | `/attachments/:attachmentId` | destrutivo | --- ### 9. Approvals / Governance (10 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `list_approvals` | GET | `/companies/:id/approvals` | read | | `get_approval` | GET | `/approvals/:id` | read | | `create_approval` | POST | `/companies/:id/approvals` | write | | `list_approval_issues` | GET | `/approvals/:id/issues` | read | | `approve_approval` | POST | `/approvals/:id/approve` | write | | `reject_approval` | POST | `/approvals/:id/reject` | write | | `request_approval_revision` | POST | `/approvals/:id/request-revision` | write | | `resubmit_approval` | POST | `/approvals/:id/resubmit` | write | | `list_approval_comments` | GET | `/approvals/:id/comments` | read | | `add_approval_comment` | POST | `/approvals/:id/comments` | write | --- ### 10. Rotinas (8 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `list_routines` | GET | `/companies/:id/routines` | read | | `get_routine` | GET | `/routines/:id` | read | | `create_routine` | POST | `/companies/:id/routines` | write | | `update_routine` | PATCH | `/routines/:id` | write | | `list_routine_runs` | GET | `/routines/:id/runs` | read | | `run_routine` | POST | `/routines/:id/run` | write | | `create_routine_trigger` | POST | `/routines/:id/triggers` | write | | `delete_routine_trigger` | DELETE | `/routine-triggers/:id` | destrutivo | --- ### 11. Goals (5 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `list_goals` | GET | `/companies/:id/goals` | read | | `get_goal` | GET | `/goals/:id` | read | | `create_goal` | POST | `/companies/:id/goals` | write | | `update_goal` | PATCH | `/goals/:id` | write | | `delete_goal` | DELETE | `/goals/:id` | destrutivo | --- ### 12. Projectos (7 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `list_projects` | GET | `/companies/:id/projects` | read | | `get_project` | GET | `/projects/:id` | read | | `create_project` | POST | `/companies/:id/projects` | write | | `update_project` | PATCH | `/projects/:id` | write | | `delete_project` | DELETE | `/projects/:id` | destrutivo | | `list_project_workspaces` | GET | `/projects/:id/workspaces` | read | | `create_project_workspace` | POST | `/projects/:id/workspaces` | write | --- ### 13. Costs / Budgets (12 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `get_cost_summary` | GET | `/companies/:id/costs/summary` | read | | `get_costs_by_agent` | GET | `/companies/:id/costs/by-agent` | read | | `get_costs_by_agent_model` | GET | `/companies/:id/costs/by-agent-model` | read | | `get_costs_by_provider` | GET | `/companies/:id/costs/by-provider` | read | | `get_costs_by_project` | GET | `/companies/:id/costs/by-project` | read | | `get_finance_summary` | GET | `/companies/:id/costs/finance-summary` | read | | `list_finance_events` | GET | `/companies/:id/costs/finance-events` | read | | `get_window_spend` | GET | `/companies/:id/costs/window-spend` | read | | `get_quota_windows` | GET | `/companies/:id/costs/quota-windows` | read | | `get_budgets_overview` | GET | `/companies/:id/budgets/overview` | read | | `update_company_budget` | PATCH | `/companies/:id/budgets` | write | | `update_agent_budget` | PATCH | `/agents/:agentId/budgets` | write | --- ### 14. Activity / Audit Log (4 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `list_company_activity` | GET | `/companies/:id/activity` | read | | `create_activity_entry` | POST | `/companies/:id/activity` | write | | `list_issue_activity` | GET | `/issues/:id/activity` | read | | `list_issue_runs` | GET | `/issues/:id/runs` | read | --- ### 15. Company Skills (6 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `list_company_skills` | GET | `/companies/:id/skills` | read | | `get_company_skill` | GET | `/companies/:id/skills/:skillId` | read | | `list_skill_files` | GET | `/companies/:id/skills/:skillId/files` | read | | `create_company_skill` | POST | `/companies/:id/skills` | write | | `import_company_skill` | POST | `/companies/:id/skills/import` | write | | `delete_company_skill` | DELETE | `/companies/:id/skills/:skillId` | destrutivo | --- ### 16. Secrets (5 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `list_secrets` | GET | `/companies/:id/secrets` | read | | `list_secret_providers` | GET | `/companies/:id/secret-providers` | read | | `create_secret` | POST | `/companies/:id/secrets` | write | | `rotate_secret` | POST | `/secrets/:id/rotate` | write | | `delete_secret` | DELETE | `/secrets/:id` | destrutivo | --- ### 17. Execution Workspaces (3 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `list_execution_workspaces` | GET | `/companies/:id/execution-workspaces` | read | | `get_execution_workspace` | GET | `/execution-workspaces/:id` | read | | `update_execution_workspace` | PATCH | `/execution-workspaces/:id` | write | --- ### 18. Adapters / Models (2 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `list_adapter_models` | GET | `/companies/:id/adapters/:type/models` | read | | `test_adapter_environment` | POST | `/companies/:id/adapters/:type/test-environment` | write | --- ### 19. Portability / Export-Import (2 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `export_company` | POST | `/companies/:id/exports` | write | | `import_company_preview` | POST | `/companies/:id/imports/preview` | read | --- ### 20. Plugins (17 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `list_plugins` | GET | `/plugins` | read | | `get_plugin` | GET | `/plugins/:pluginId` | read | | `list_plugin_examples` | GET | `/plugins/examples` | read | | `list_plugin_tools` | GET | `/plugins/tools` | read | | `install_plugin` | POST | `/plugins/install` | write | | `delete_plugin` | DELETE | `/plugins/:pluginId` | destrutivo | | `enable_plugin` | POST | `/plugins/:pluginId/enable` | write | | `disable_plugin` | POST | `/plugins/:pluginId/disable` | write | | `upgrade_plugin` | POST | `/plugins/:pluginId/upgrade` | write | | `get_plugin_health` | GET | `/plugins/:pluginId/health` | read | | `get_plugin_logs` | GET | `/plugins/:pluginId/logs` | read | | `get_plugin_config` | GET | `/plugins/:pluginId/config` | read | | `set_plugin_config` | POST | `/plugins/:pluginId/config` | write | | `test_plugin_config` | POST | `/plugins/:pluginId/config/test` | write | | `get_plugin_dashboard` | GET | `/plugins/:pluginId/dashboard` | read | | `list_plugin_jobs` | GET | `/plugins/:pluginId/jobs` | read | | `trigger_plugin_job` | POST | `/plugins/:pluginId/jobs/:jobId/trigger` | write | --- ### 21. Assets (3 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `upload_image_asset` | POST | `/companies/:id/assets/images` | write | | `upload_company_logo` | POST | `/companies/:id/logo` | write | | `get_asset_content` | GET | `/assets/:assetId/content` | read | **Nota:** Uploads usam `multipart/form-data`. --- ### 22. Instance Settings (4 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `get_general_settings` | GET | `/instance/settings/general` | read | | `update_general_settings` | PATCH | `/instance/settings/general` | write | | `get_experimental_settings` | GET | `/instance/settings/experimental` | read | | `update_experimental_settings` | PATCH | `/instance/settings/experimental` | write | --- ### 23. Invites / Onboarding (7 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `create_invite` | POST | `/companies/:id/invites` | write | | `get_invite` | GET | `/invites/:token` | read | | `get_invite_onboarding` | GET | `/invites/:token/onboarding` | read | | `accept_invite` | POST | `/invites/:token/accept` | write | | `revoke_invite` | POST | `/invites/:inviteId/revoke` | write | | `list_join_requests` | GET | `/companies/:id/join-requests` | read | | `approve_join_request` | POST | `/companies/:id/join-requests/:requestId/approve` | write | --- ### 24. Plugin Bridge / Execution (4 tools) | Tool | Método | Endpoint | Tipo | |------|--------|----------|------| | `execute_plugin_tool` | POST | `/plugins/tools/execute` | write | | `plugin_bridge_data` | POST | `/plugins/:pluginId/bridge/data` | read | | `plugin_bridge_action` | POST | `/plugins/:pluginId/bridge/action` | write | | `list_ui_contributions` | GET | `/plugins/ui-contributions` | read | --- ## Endpoints Excluídos (não implementados como tools) | Módulo | Razão | |--------|-------| | **CLI Auth** (challenges, approve, cancel, revoke) | Fluxo interactivo browser-based — não adequado para MCP | | **Board Claims** (get/claim token) | Fluxo de setup inicial — uma vez por instalação | | **LLMs** (`/llms/*.txt`) | Documentação estática — aceder directamente via HTTP | | **Plugin SSE Stream** (`/plugins/:id/bridge/stream/:channel`) | SSE stream contínuo — não compatível com request/response MCP | | **Admin Operations** (promote/demote instance admin, user company access) | Operações privilegiadas de super-admin — proteger de uso acidental | --- ## Variáveis de Ambiente ```bash # .env.example PAPERCLIP_API_URL=https://clip.descomplicar.pt/api PAPERCLIP_API_KEY=pcp_mcp_... # Board API Key gerada pelo script PAPERCLIP_COMPANY_ID=ebe10308-efd7-453f-86ab-13e6fe84004f # HTTP/SSE transport HTTP_PORT=3175 ``` **`PAPERCLIP_COMPANY_ID` injectado automaticamente** nas tools que precisam de `:companyId`, sem obrigar o utilizador a passá-lo em cada chamada. --- ## Cliente HTTP (`src/client.ts`) ```typescript export class PaperclipClient { private baseUrl: string; private companyId: string; private headers: Record; constructor() { this.baseUrl = process.env.PAPERCLIP_API_URL ?? 'https://clip.descomplicar.pt/api'; this.companyId = process.env.PAPERCLIP_COMPANY_ID ?? ''; this.headers = { 'Content-Type': 'application/json', 'Authorization': `Bearer ${process.env.PAPERCLIP_API_KEY}`, }; } async get(path: string, params?: Record): Promise async post(path: string, body?: unknown): Promise async patch(path: string, body?: unknown): Promise async put(path: string, body?: unknown): Promise async delete(path: string): Promise // Helpers com company_id injectado companyPath(suffix: string): string { return `/companies/${this.companyId}${suffix}`; } } ``` --- ## Tool Annotations ```typescript // Aplicar inferAnnotations() a todas as tools: // list_*, get_* → readOnlyHint: true // delete_*, terminate_* → destructiveHint: true // update_*, patch_* → idempotentHint: true // create_*, add_*, checkout_*, release_*, approve_*, reject_* → write normal // run_*, invoke_*, wakeup_*, fire_* → write (side-effects) ``` --- ## Configuração `~/.claude.json` ```json { "mcpServers": { "paperclip": { "command": "node", "args": ["/home/ealmeida/mcp-servers/mcp-paperclip/dist/index.js"], "env": { "PAPERCLIP_API_URL": "https://clip.descomplicar.pt/api", "PAPERCLIP_API_KEY": "pcp_mcp_...", "PAPERCLIP_COMPANY_ID": "ebe10308-efd7-453f-86ab-13e6fe84004f" } } } } ``` --- ## Plano de Implementação (6 sprints) ### Sprint 1 — Fundação + Health + Agentes (read-only) **Objectivo:** MCP operacional com tools de leitura base - [ ] `npm init` + dependências (`@modelcontextprotocol/sdk`, `zod`, `dotenv`, `winston`) - [ ] DevDeps: TypeScript, ESLint, Prettier, Jest, Husky - [ ] `tsconfig.json`, `eslint.config.js`, `.prettierrc`, `.gitignore` - [ ] `src/client.ts` — PaperclipClient com auth Bearer e métodos GET/POST/PATCH/PUT/DELETE - [ ] `src/utils/logger.ts` — logger MCP-compatible (stderr, sem cores) - [ ] `src/utils/annotations.ts` — inferAnnotations - [ ] `src/server.ts` — createServer com capabilities completas - [ ] `src/index.ts` — entry STDIO - [ ] `src/index-http.ts` — entry StreamableHTTP + SSE porta 3175 (stateless) - [ ] `scripts/create-api-key.sh` — script criação Board API Key - [ ] Tools `health.ts`: `get_health` - [ ] Tools `company.ts`: `get_company`, `list_companies`, `get_company_stats`, `get_org_chart`, `get_dashboard`, `get_sidebar_badges` - [ ] Tools `agents.ts` (read): `list_agents`, `get_agent`, `get_agent_runtime_state`, `get_agent_configuration`, `get_agent_config_revisions`, `get_agent_skills`, `get_agent_task_sessions`, `get_agent_instructions_bundle` - [ ] `.env.example`, `CLAUDE.md`, `CHANGELOG.md`, `README.md` - [ ] Testes básicos das tools read - [ ] `npm run quality:check` passa - [ ] Repo Gitea criado, CI verde **Critério de aceitação Sprint 1:** `list_agents` devolve os 64 agentes da Descomplicar via STDIO. --- ### Sprint 2 — Issues + Write Operations Agentes **Objectivo:** CRUD completo de issues e operações write em agentes - [ ] Tools `issues.ts`: list, get, create, update, delete, comments, checkout, release, documents, work-products, heartbeat-context, live-runs (17 tools) - [ ] Tools `labels.ts`: list, create, delete (3 tools) - [ ] Tools `attachments.ts`: list, upload, get_content, delete (4 tools) - [ ] Tools `agents.ts` (write): create, create_hire, update, update_permissions, update_instructions_path, update_instructions_bundle, rollback_config, sync_skills, pause, resume, wakeup, invoke_heartbeat, terminate, delete (14 tools) - [ ] Tools `agent_keys.ts`: list, create, delete (3 tools) - [ ] Validação Zod em inputs de write - [ ] Tratamento de erros HTTP (401, 403, 404, 422) -> mensagens úteis - [ ] Testes issues e write ops - [ ] Actualizar `~/.claude.json` com MCP configurado - [ ] Smoke test: criar issue, atribuir ao Reality Checker, fazer checkout **Critério de aceitação Sprint 2:** Claude Code consegue criar uma issue, assignar a um agente e fazer checkout via MCP. --- ### Sprint 3 — Routines, Goals, Projects, Approvals **Objectivo:** Workflows completos de gestão e governance - [ ] Tools `routines.ts`: list, get, create, update, list_runs, run, create_trigger, delete_trigger (8 tools) - [ ] Tools `goals.ts`: list, get, create, update, delete (5 tools) - [ ] Tools `projects.ts`: list, get, create, update, delete, list_workspaces, create_workspace (7 tools) - [ ] Tools `approvals.ts`: list, get, create, list_issues, approve, reject, request_revision, resubmit, comments (10 tools) - [ ] Testes de workflows: criar goal -> criar issue -> aprovar -> executar **Critério de aceitação Sprint 3:** Workflow completo de governance: criar approval, aprovar, verificar estado. --- ### Sprint 4 — Costs, Activity, Skills, Secrets, Workspaces **Objectivo:** Observabilidade e gestão operacional - [ ] Tools `costs.ts`: summary, by-agent, by-model, by-provider, by-project, finance, budgets (12 tools) - [ ] Tools `activity.ts`: company activity, issue activity, issue runs (4 tools) - [ ] Tools `skills.ts`: list, get, files, create, import, delete (6 tools) - [ ] Tools `secrets.ts`: list, providers, create, rotate, delete (5 tools) - [ ] Tools: execution_workspaces (3 tools), adapters (2 tools), portability (2 tools) - [ ] Tools `company.ts` (write): update, update_branding, members, update_member_permissions - [ ] Heartbeat runs: list, live, get, events, log, cancel (6 tools) - [ ] Testes de observabilidade **Critério de aceitação Sprint 4:** `get_cost_summary` + `get_budgets_overview` retornam dados reais. --- ### Sprint 5 — Plugins, Assets, Settings, Access **Objectivo:** Gestão de plugins, assets, configuração e onboarding - [ ] Tools `plugins.ts`: list, get, examples, tools, install, delete, enable, disable, upgrade, health, logs, config, dashboard, jobs, trigger (17 tools) - [ ] Tools `plugin_bridge.ts`: execute_tool, bridge_data, bridge_action, ui_contributions (4 tools) - [ ] Tools `assets.ts`: upload_image, upload_logo, get_content (3 tools) — suporte multipart/form-data no client - [ ] Tools `settings.ts`: get/update general, get/update experimental (4 tools) - [ ] Tools `access.ts`: create_invite, get_invite, get_onboarding, accept_invite, revoke_invite, list_join_requests, approve_join_request (7 tools) - [ ] Testes de plugins e settings **Critério de aceitação Sprint 5:** `list_plugins` + `install_plugin` + `get_plugin_health` funcionais. --- ### Sprint 6 — Gateway Deploy + CI/CD + Documentação **Objectivo:** Deploy produção + cobertura total - [ ] Deploy no gateway (5.9.90.69) via PM2 - [ ] Registar porta 3175 no `port-map.json` do gateway - [ ] CI/CD workflow Gitea (`.gitea/workflows/deploy.yml`) - [ ] Actualizar `~/.claude/_resources/mcps.json` - [ ] Actualizar `QR-Servidores.md` com novo MCP - [ ] `docs/API_REFERENCE.md` completo - [ ] Testes integração end-to-end (todas as 159 tools) - [ ] Smoke test final: workflow completo via gateway StreamableHTTP **Critério de aceitação Sprint 6:** Todas as 159 tools operacionais via STDIO + StreamableHTTP + SSE. CI verde. --- ## Critérios de Qualidade (pré-entrega) ``` [ ] Zero erros ESLint [ ] Testes passam: npm run test [ ] Build sem erros: npm run build [ ] Capabilities completas (tools + resources + prompts) [ ] Nomenclatura snake_case em todas as tools [ ] Triple transport funcional (STDIO + StreamableHTTP + SSE na porta 3175) [ ] Stateless (sessionIdGenerator: undefined) [ ] Logger para stderr (nunca stdout em STDIO mode) [ ] .env.example sem valores reais [ ] CHANGELOG.md iniciado [ ] CI verde no Gitea [ ] 159 tools operacionais ``` --- ## Dependências ```json { "dependencies": { "@modelcontextprotocol/sdk": "^1.10.0", "dotenv": "^16.4.7", "winston": "^3.17.0", "zod": "^3.24.0" }, "devDependencies": { "@types/node": "^22.0.0", "@typescript-eslint/eslint-plugin": "^7.18.0", "@typescript-eslint/parser": "^7.18.0", "eslint": "^8.57.1", "jest": "^30.0.5", "prettier": "^3.6.2", "ts-jest": "^29.4.0", "typescript": "^5.3.3" } } ``` --- ## Notas de Implementação 1. **`PAPERCLIP_COMPANY_ID` como constante** — injectar em todas as tools que precisam de `:companyId`, nunca expor como parâmetro obrigatório ao utilizador. 2. **Erros da API Paperclip** — mapear para mensagens claras: - `401/403` -> "Sem autorização. Verificar `PAPERCLIP_API_KEY`." - `404` -> "Recurso não encontrado: {id}" - `422` -> incluir erros de validação da resposta 3. **`get_org_chart`** — retorna JSON da hierarquia de agentes, não o SVG. Usar `/companies/:id/org` (JSON) e não `/org.svg`. 4. **`wakeup_agent`** — o Paperclip acorda agentes via heartbeat; útil para forçar execução de uma rotina ou atribuir uma issue urgente. 5. **`checkout_issue`** — permite ao Claude Code "reservar" uma issue enquanto trabalha nela, sinalizando que está em curso. 6. **`create_agent_hire`** — usa governance/approval workflow. Preferível a `create_agent` directo quando há supervisão activa. 7. **Idempotência** — `create_agent` com mesmo `name` pode criar duplicado. Adicionar verificação prévia com `list_agents` se necessário. 8. **Costs** — endpoints de custos aceitam query params `from`, `to` (ISO dates) para filtragem temporal. 9. **Secrets** — valores nunca são retornados em plain text. Apenas metadados (nome, provider, criação). 10. **Attachments e Assets** — uploads usam `multipart/form-data`. O client precisa de suportar este content-type para `upload_issue_attachment`, `upload_image_asset` e `upload_company_logo`. 11. **Plugins** — `install_plugin` aceita URL ou path para o plugin. `execute_plugin_tool` permite invocar tools expostas por plugins instalados. 12. **Instance Settings** — alterações a `experimental` podem activar/desactivar funcionalidades em beta. Usar com cautela. 13. **Invites** — `create_invite` gera token único para onboarding de novos agentes. O fluxo completo: create -> partilhar token -> accept. 14. **Plugin Bridge** — `plugin_bridge_data` e `plugin_bridge_action` permitem comunicação directa com plugins via data/action pattern. --- *SPEC criado em 07-04-2026 | Actualizado em 07-04-2026 (cobertura completa API v0.3.1)* *Baseado no PROC-MCP-Desenvolvimento.md v2.5 + análise directa do código-fonte Paperclip*