feat: mcp-paperclip v1.0.0 — 165 tools para Paperclip AI
Triple transport (STDIO + StreamableHTTP + SSE porta 3175). 24 modulos: agents, issues, approvals, routines, goals, projects, costs, activity, skills, secrets, plugins, assets, settings, access. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,781 @@
|
||||
---
|
||||
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<string, string>;
|
||||
|
||||
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<T>(path: string, params?: Record<string, string>): Promise<T>
|
||||
async post<T>(path: string, body?: unknown): Promise<T>
|
||||
async patch<T>(path: string, body?: unknown): Promise<T>
|
||||
async put<T>(path: string, body?: unknown): Promise<T>
|
||||
async delete<T>(path: string): Promise<T>
|
||||
|
||||
// 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*
|
||||
Reference in New Issue
Block a user