biaws-mcp 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -27
- package/package.json +1 -1
- package/src/domains/catalog/service.js +10 -0
- package/src/domains/catalog/tools.js +23 -9
- package/src/domains/knowledge/documentTypeCatalog.js +7 -0
- package/src/domains/knowledge/documentTypeCatalogData.js +104 -0
- package/src/domains/knowledge/service.js +24 -0
- package/src/domains/knowledge/tools.js +237 -36
- package/src/tools.js +100 -1
- package/src/version.js +1 -1
package/README.md
CHANGED
|
@@ -9,19 +9,18 @@ O servidor separa os domínios:
|
|
|
9
9
|
topologia operacional.
|
|
10
10
|
- `issues_*`: chamados, incidentes, requisições operacionais, taxonomia e classificação.
|
|
11
11
|
- `demands_*`: melhorias, especificações, jornadas, prazos e contexto para desenvolvimento.
|
|
12
|
-
- `
|
|
13
|
-
|
|
14
|
-
relacionado a aplicações e componentes.
|
|
12
|
+
- `documents_*`: regras, decisões, guidelines, features, referências técnicas e
|
|
13
|
+
procedimentos relacionados ao workspace, a aplicações e a componentes.
|
|
15
14
|
- `knowledge_context_load`: regras ativas e decisões aceitas para o contexto
|
|
16
15
|
solicitado.
|
|
17
16
|
- `attachments_*`: envio, download, classificação e exclusão de arquivos de
|
|
18
|
-
chamados, melhorias, tarefas e
|
|
17
|
+
chamados, melhorias, tarefas e documentos.
|
|
19
18
|
- `secrets_*`: consulta e registro de metadados de segredos, sem acesso aos valores.
|
|
20
19
|
- `monitoring_templates_*`, `runtime_active_monitors_*` e
|
|
21
20
|
`runtime_monitoring_results_list`: administração versionada de templates,
|
|
22
21
|
configuração de monitores e consulta do histórico dos runtimes.
|
|
23
22
|
- `resource_collections_*` e `*_move_to_collection`: organização hierárquica
|
|
24
|
-
de aplicações,
|
|
23
|
+
de aplicações, documentos, melhorias, segredos, skills e servidores.
|
|
25
24
|
|
|
26
25
|
O carregamento de ambiente é autocontido no pacote. Em um checkout, ele preserva
|
|
27
26
|
o fallback para o `.env` da raiz; no pacote publicado, usa o `.env` local ou o
|
|
@@ -66,13 +65,13 @@ O pacote público expõe o executável `biaws-mcp`. Clientes configurados pelo C
|
|
|
66
65
|
usam uma versão fixada por meio do cache local do npm:
|
|
67
66
|
|
|
68
67
|
```bash
|
|
69
|
-
npx --yes biaws-mcp@0.
|
|
68
|
+
npx --yes biaws-mcp@0.6.0
|
|
70
69
|
```
|
|
71
70
|
|
|
72
71
|
Também é possível instalá-lo explicitamente:
|
|
73
72
|
|
|
74
73
|
```bash
|
|
75
|
-
npm install --global biaws-mcp@0.
|
|
74
|
+
npm install --global biaws-mcp@0.6.0
|
|
76
75
|
biaws-mcp
|
|
77
76
|
```
|
|
78
77
|
|
|
@@ -91,7 +90,7 @@ npm start
|
|
|
91
90
|
Em um cliente MCP, configure o comando:
|
|
92
91
|
|
|
93
92
|
```bash
|
|
94
|
-
npx --yes biaws-mcp@0.
|
|
93
|
+
npx --yes biaws-mcp@0.6.0
|
|
95
94
|
```
|
|
96
95
|
|
|
97
96
|
O fluxo recomendado é gerar a configuração completa com:
|
|
@@ -158,7 +157,8 @@ As escritas estruturadas são:
|
|
|
158
157
|
- `integrations_create` e `integrations_update`;
|
|
159
158
|
- `repositories_create` e `repositories_update`;
|
|
160
159
|
- `servers_create` e `servers_update`;
|
|
161
|
-
- `deployments_create` e
|
|
160
|
+
- `deployments_create`, `deployments_update` e
|
|
161
|
+
`deployments_record_publication`;
|
|
162
162
|
- `runtimes_create` e `runtimes_update`.
|
|
163
163
|
|
|
164
164
|
As ferramentas de escrita usam `POST` ou `PATCH` da API e, portanto, herdam
|
|
@@ -220,19 +220,19 @@ monitor antes de provisionar o executor, crie-o com `enabled: false`.
|
|
|
220
220
|
- `resource_collections_delete`: exclui somente uma coleção vazia, sem
|
|
221
221
|
subcoleções nem itens vinculados;
|
|
222
222
|
- `applications_move_to_collection`, `servers_move_to_collection`,
|
|
223
|
-
`secrets_move_to_collection`, `skills_move_to_collection
|
|
224
|
-
`
|
|
223
|
+
`secrets_move_to_collection`, `skills_move_to_collection`,
|
|
224
|
+
`demands_move_to_collection` e `documents_move_to_collection`: movem um item
|
|
225
|
+
para uma coleção validada ou
|
|
225
226
|
para a raiz quando `collectionId` é vazio.
|
|
226
227
|
|
|
227
228
|
As quatro ferramentas `resource_collections_*` aceitam `resourceType` com os
|
|
228
|
-
valores `applications`, `
|
|
229
|
-
|
|
230
|
-
compartilhada por tipo. Todas as mutações mantêm as validações contra ciclos,
|
|
229
|
+
valores `applications`, `demands`, `documents`, `secrets`, `skills` ou
|
|
230
|
+
`servers`. Todas as mutações mantêm as validações contra ciclos,
|
|
231
231
|
escopo do workspace, permissões e auditoria da API.
|
|
232
232
|
|
|
233
233
|
`applications_get_context` entrega, em uma única consulta, a aplicação,
|
|
234
234
|
integrações, componentes, repositórios, deployments, runtimes, servidores referenciados e
|
|
235
|
-
resumos de issues, melhorias e
|
|
235
|
+
resumos de issues, melhorias e documentos associados. O argumento `limit`
|
|
236
236
|
vale separadamente para cada grupo, tem teto de 100 e padrão 25. O resultado
|
|
237
237
|
informa totais e truncamentos e não contém credenciais, endereços dos
|
|
238
238
|
servidores, metadata dos runtimes, anexos nem os textos extensos da base de
|
|
@@ -294,7 +294,7 @@ conhecimento.
|
|
|
294
294
|
conteúdo armazenado.
|
|
295
295
|
|
|
296
296
|
As quatro ferramentas aceitam `entityType` com `issue`, `demand`, `task` ou
|
|
297
|
-
`
|
|
297
|
+
`document`. `entityId` identifica o chamado, melhoria ou documento. Para
|
|
298
298
|
`task`, `entityId` deve ser o ID da melhoria pai e `taskId` deve identificar a
|
|
299
299
|
tarefa por ID ou código.
|
|
300
300
|
|
|
@@ -315,15 +315,25 @@ quando essas permissões tiverem sido removidas ou ainda não existirem, um
|
|
|
315
315
|
administrador deverá concedê-las. Operações no contexto de tarefa usam as
|
|
316
316
|
permissões de anexos da melhoria pai.
|
|
317
317
|
|
|
318
|
-
###
|
|
319
|
-
|
|
320
|
-
- `
|
|
321
|
-
|
|
322
|
-
- `
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
318
|
+
### Documentos
|
|
319
|
+
|
|
320
|
+
- `document_types_list`: consulta o contrato oficial de cada tipo, incluindo
|
|
321
|
+
estados, contexto obrigatório e campos específicos de `details`;
|
|
322
|
+
- `documents_search` e `documents_get`: localizam documentos e carregam seu
|
|
323
|
+
conteúdo completo sob demanda;
|
|
324
|
+
- `documents_create`: cria regras, decisões, guidelines, features, referências
|
|
325
|
+
técnicas e procedimentos usando um schema discriminado por `documentType`;
|
|
326
|
+
- `documents_update`: atualiza conteúdo, contexto e metadados, preservando o
|
|
327
|
+
tipo imutável;
|
|
328
|
+
- `documents_add_observation`: acrescenta uma observação imutável.
|
|
329
|
+
|
|
330
|
+
Regras de negócio, decisões arquiteturais e features exigem `applicationId`.
|
|
331
|
+
Referências técnicas podem pertencer ao workspace ou a uma aplicação.
|
|
332
|
+
Procedimentos também podem pertencer ao workspace ou ser vinculados a uma
|
|
333
|
+
aplicação e seus componentes; são documentos com `documentType=procedure`.
|
|
334
|
+
Guidelines usam `details.scope`: `workspace` proíbe `applicationId`,
|
|
335
|
+
`application` o exige e `component` exige também `affectedComponentIds`.
|
|
336
|
+
Componentes sempre devem estar ativos e pertencer à aplicação informada.
|
|
327
337
|
|
|
328
338
|
### Metadados de segredos
|
|
329
339
|
|
|
@@ -343,8 +353,8 @@ O grupo padrão `agent-operator` recebe `secrets.metadata.read` e
|
|
|
343
353
|
`secrets.value.reveal`.
|
|
344
354
|
|
|
345
355
|
Issues e melhorias criadas pelo MCP sempre pertencem a uma aplicação e podem
|
|
346
|
-
informar `affectedComponentIds`.
|
|
347
|
-
|
|
356
|
+
informar `affectedComponentIds`. Documentos seguem as regras de contexto
|
|
357
|
+
declaradas por `document_types_list`.
|
|
348
358
|
Nas ferramentas de consulta, os filtros comuns são `workspaceId`,
|
|
349
359
|
`applicationId` e `componentId`.
|
|
350
360
|
|
package/package.json
CHANGED
|
@@ -256,6 +256,16 @@ export async function updateDeployment(args = {}) {
|
|
|
256
256
|
);
|
|
257
257
|
}
|
|
258
258
|
|
|
259
|
+
export async function recordDeploymentPublication(args = {}) {
|
|
260
|
+
const deploymentId = requiredId(args, "deploymentId");
|
|
261
|
+
return sendJson(
|
|
262
|
+
`${entityPath("deployments", deploymentId)}/publications`,
|
|
263
|
+
mutationPayload(args, ["deploymentId"]),
|
|
264
|
+
{},
|
|
265
|
+
"POST",
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
|
|
259
269
|
export async function listRuntimes(args = {}) {
|
|
260
270
|
const deploymentId = requiredId(args, "deploymentId");
|
|
261
271
|
return fetchJson(
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
listRuntimes,
|
|
24
24
|
listServers,
|
|
25
25
|
listWorkspaces,
|
|
26
|
+
recordDeploymentPublication,
|
|
26
27
|
updateApplication,
|
|
27
28
|
updateComponent,
|
|
28
29
|
updateDeployment,
|
|
@@ -165,6 +166,18 @@ const SERVER_PROPERTIES = {
|
|
|
165
166
|
tags: TAGS,
|
|
166
167
|
};
|
|
167
168
|
|
|
169
|
+
const PUBLICATION_PROPERTIES = {
|
|
170
|
+
version: STRING,
|
|
171
|
+
revision: STRING,
|
|
172
|
+
repositoryId: { type: ["string", "null"] },
|
|
173
|
+
status: {
|
|
174
|
+
type: "string",
|
|
175
|
+
enum: ["planned", "canceled", "deployed"],
|
|
176
|
+
},
|
|
177
|
+
publishedAt: { type: ["string", "null"] },
|
|
178
|
+
description: STRING,
|
|
179
|
+
};
|
|
180
|
+
|
|
168
181
|
const DEPLOYMENT_PROPERTIES = {
|
|
169
182
|
key: APPLICATION_PROPERTIES.key,
|
|
170
183
|
name: STRING,
|
|
@@ -183,15 +196,7 @@ const DEPLOYMENT_PROPERTIES = {
|
|
|
183
196
|
required: ["version"],
|
|
184
197
|
properties: {
|
|
185
198
|
id: ID,
|
|
186
|
-
|
|
187
|
-
revision: STRING,
|
|
188
|
-
repositoryId: { type: ["string", "null"] },
|
|
189
|
-
status: {
|
|
190
|
-
type: "string",
|
|
191
|
-
enum: ["planned", "canceled", "deployed"],
|
|
192
|
-
},
|
|
193
|
-
publishedAt: { type: ["string", "null"] },
|
|
194
|
-
description: STRING,
|
|
199
|
+
...PUBLICATION_PROPERTIES,
|
|
195
200
|
recordedAt: { type: ["string", "null"] },
|
|
196
201
|
recordedBy: STRING,
|
|
197
202
|
},
|
|
@@ -553,6 +558,15 @@ export const catalogTools = [
|
|
|
553
558
|
["deploymentId"],
|
|
554
559
|
),
|
|
555
560
|
),
|
|
561
|
+
definition(
|
|
562
|
+
"deployments_record_publication",
|
|
563
|
+
"Registra uma publicação no histórico append-only de um deployment sem reenviar as entradas existentes.",
|
|
564
|
+
recordDeploymentPublication,
|
|
565
|
+
schema({ deploymentId: ID, ...PUBLICATION_PROPERTIES }, [
|
|
566
|
+
"deploymentId",
|
|
567
|
+
"version",
|
|
568
|
+
]),
|
|
569
|
+
),
|
|
556
570
|
definition(
|
|
557
571
|
"runtimes_create",
|
|
558
572
|
"Cria um runtime de deployment com metadata limitada e sem segredos.",
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// Keep this published copy synchronized with shared/documentTypes.js. The MCP
|
|
2
|
+
// package cannot import files outside its package root; the parity test prevents
|
|
3
|
+
// the API and MCP contracts from drifting.
|
|
4
|
+
export {
|
|
5
|
+
DOCUMENT_TYPE_CATALOG,
|
|
6
|
+
DOCUMENT_TYPES,
|
|
7
|
+
} from "./documentTypeCatalogData.js";
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
export const DOCUMENT_TYPE_CATALOG = Object.freeze({
|
|
2
|
+
"business-rule": Object.freeze({
|
|
3
|
+
type: "business-rule",
|
|
4
|
+
label: "Regra de negócio",
|
|
5
|
+
description: "Condições e comportamentos esperados do domínio.",
|
|
6
|
+
defaultStatus: "draft",
|
|
7
|
+
statuses: Object.freeze(["draft", "active", "retired", "archived"]),
|
|
8
|
+
currentStatuses: Object.freeze(["active"]),
|
|
9
|
+
applicationRequired: true,
|
|
10
|
+
details: Object.freeze({
|
|
11
|
+
ruleCode: Object.freeze({ type: "string", maxLength: 80 }),
|
|
12
|
+
effectiveFrom: Object.freeze({ type: "date" }),
|
|
13
|
+
}),
|
|
14
|
+
}),
|
|
15
|
+
"architecture-decision": Object.freeze({
|
|
16
|
+
type: "architecture-decision",
|
|
17
|
+
label: "Decisão arquitetural",
|
|
18
|
+
description: "Escolhas técnicas, contexto, alternativas e consequências.",
|
|
19
|
+
defaultStatus: "proposed",
|
|
20
|
+
statuses: Object.freeze([
|
|
21
|
+
"proposed",
|
|
22
|
+
"accepted",
|
|
23
|
+
"rejected",
|
|
24
|
+
"superseded",
|
|
25
|
+
"archived",
|
|
26
|
+
]),
|
|
27
|
+
currentStatuses: Object.freeze(["accepted"]),
|
|
28
|
+
applicationRequired: true,
|
|
29
|
+
details: Object.freeze({
|
|
30
|
+
decidedAt: Object.freeze({ type: "date" }),
|
|
31
|
+
}),
|
|
32
|
+
}),
|
|
33
|
+
guideline: Object.freeze({
|
|
34
|
+
type: "guideline",
|
|
35
|
+
label: "Guideline",
|
|
36
|
+
description: "Diretrizes e padrões de desenvolvimento.",
|
|
37
|
+
defaultStatus: "draft",
|
|
38
|
+
statuses: Object.freeze(["draft", "published", "deprecated", "archived"]),
|
|
39
|
+
currentStatuses: Object.freeze(["published"]),
|
|
40
|
+
applicationRequired: false,
|
|
41
|
+
details: Object.freeze({
|
|
42
|
+
scope: Object.freeze({
|
|
43
|
+
type: "string",
|
|
44
|
+
enum: Object.freeze(["workspace", "application", "component"]),
|
|
45
|
+
default: "workspace",
|
|
46
|
+
}),
|
|
47
|
+
enforcement: Object.freeze({
|
|
48
|
+
type: "string",
|
|
49
|
+
enum: Object.freeze(["required", "recommended", "informative"]),
|
|
50
|
+
default: "recommended",
|
|
51
|
+
}),
|
|
52
|
+
}),
|
|
53
|
+
}),
|
|
54
|
+
feature: Object.freeze({
|
|
55
|
+
type: "feature",
|
|
56
|
+
label: "Feature",
|
|
57
|
+
description: "Descrição funcional e técnica aprofundada de uma capacidade.",
|
|
58
|
+
defaultStatus: "draft",
|
|
59
|
+
statuses: Object.freeze(["draft", "published", "deprecated", "archived"]),
|
|
60
|
+
currentStatuses: Object.freeze(["published"]),
|
|
61
|
+
applicationRequired: true,
|
|
62
|
+
details: Object.freeze({
|
|
63
|
+
maturity: Object.freeze({
|
|
64
|
+
type: "string",
|
|
65
|
+
enum: Object.freeze(["planned", "beta", "stable", "retired"]),
|
|
66
|
+
default: "stable",
|
|
67
|
+
}),
|
|
68
|
+
}),
|
|
69
|
+
}),
|
|
70
|
+
"technical-reference": Object.freeze({
|
|
71
|
+
type: "technical-reference",
|
|
72
|
+
label: "Referência técnica",
|
|
73
|
+
description: "Arquitetura atual, contratos, schemas e mecanismos.",
|
|
74
|
+
defaultStatus: "draft",
|
|
75
|
+
statuses: Object.freeze(["draft", "published", "deprecated", "archived"]),
|
|
76
|
+
currentStatuses: Object.freeze(["published"]),
|
|
77
|
+
applicationRequired: false,
|
|
78
|
+
details: Object.freeze({
|
|
79
|
+
referenceKind: Object.freeze({
|
|
80
|
+
type: "string",
|
|
81
|
+
enum: Object.freeze([
|
|
82
|
+
"architecture",
|
|
83
|
+
"contract",
|
|
84
|
+
"schema",
|
|
85
|
+
"protocol",
|
|
86
|
+
"mechanism",
|
|
87
|
+
]),
|
|
88
|
+
default: "architecture",
|
|
89
|
+
}),
|
|
90
|
+
}),
|
|
91
|
+
}),
|
|
92
|
+
procedure: Object.freeze({
|
|
93
|
+
type: "procedure",
|
|
94
|
+
label: "Procedimento",
|
|
95
|
+
description: "Instruções operacionais reutilizáveis.",
|
|
96
|
+
defaultStatus: "draft",
|
|
97
|
+
statuses: Object.freeze(["draft", "published", "deprecated", "archived"]),
|
|
98
|
+
currentStatuses: Object.freeze(["published"]),
|
|
99
|
+
applicationRequired: false,
|
|
100
|
+
details: Object.freeze({}),
|
|
101
|
+
}),
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
export const DOCUMENT_TYPES = Object.freeze(Object.keys(DOCUMENT_TYPE_CATALOG));
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { cleanParams, fetchJson, sendJson } from "../../httpClient.js";
|
|
2
|
+
import { DOCUMENT_TYPE_CATALOG } from "./documentTypeCatalog.js";
|
|
2
3
|
|
|
3
4
|
const BASE_PATH = "/api/knowledge/documents";
|
|
4
5
|
|
|
5
6
|
function documentPayload(args = {}, current = {}) {
|
|
6
7
|
return {
|
|
8
|
+
identifier: args.identifier ?? current.identifier,
|
|
7
9
|
documentType: args.documentType ?? current.documentType,
|
|
8
10
|
title: args.title ?? current.title,
|
|
9
11
|
summary: args.summary ?? current.summary,
|
|
@@ -29,6 +31,28 @@ function documentPayload(args = {}, current = {}) {
|
|
|
29
31
|
};
|
|
30
32
|
}
|
|
31
33
|
|
|
34
|
+
export function listDocumentTypes() {
|
|
35
|
+
return {
|
|
36
|
+
documentTypes: Object.values(DOCUMENT_TYPE_CATALOG).map((config) => ({
|
|
37
|
+
...config,
|
|
38
|
+
context: config.applicationRequired
|
|
39
|
+
? { applicationId: "required", affectedComponentIds: "optional" }
|
|
40
|
+
: config.type === "guideline"
|
|
41
|
+
? {
|
|
42
|
+
applicationId: "depends-on-details.scope",
|
|
43
|
+
affectedComponentIds: "required-when-scope-is-component",
|
|
44
|
+
}
|
|
45
|
+
: { applicationId: "optional", affectedComponentIds: "optional" },
|
|
46
|
+
})),
|
|
47
|
+
commonRules: {
|
|
48
|
+
workspaceId: "implicit-from-mcp-configuration",
|
|
49
|
+
affectedComponentIds: "requires-applicationId",
|
|
50
|
+
documentType: "immutable-after-creation",
|
|
51
|
+
repositorySource: "repositoryId-and-path-required",
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
|
|
32
56
|
export async function searchDocuments(args = {}) {
|
|
33
57
|
return fetchJson(
|
|
34
58
|
BASE_PATH,
|
|
@@ -2,78 +2,271 @@ import {
|
|
|
2
2
|
addDocumentObservation,
|
|
3
3
|
createDocument,
|
|
4
4
|
getDocument,
|
|
5
|
+
listDocumentTypes,
|
|
5
6
|
loadKnowledgeContext,
|
|
6
7
|
searchDocuments,
|
|
7
8
|
updateDocument,
|
|
8
9
|
} from "./service.js";
|
|
10
|
+
import {
|
|
11
|
+
DOCUMENT_TYPE_CATALOG,
|
|
12
|
+
DOCUMENT_TYPES,
|
|
13
|
+
} from "./documentTypeCatalog.js";
|
|
9
14
|
|
|
10
15
|
const ID = { type: "string", minLength: 1 };
|
|
16
|
+
const DATE = {
|
|
17
|
+
type: "string",
|
|
18
|
+
pattern: "^\\d{4}-\\d{2}-\\d{2}$",
|
|
19
|
+
description: "Data no formato YYYY-MM-DD.",
|
|
20
|
+
};
|
|
11
21
|
const DOCUMENT_TYPE = {
|
|
12
22
|
type: "string",
|
|
13
|
-
enum:
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
"guideline",
|
|
17
|
-
"feature",
|
|
18
|
-
"technical-reference",
|
|
19
|
-
"procedure",
|
|
20
|
-
],
|
|
23
|
+
enum: DOCUMENT_TYPES,
|
|
24
|
+
description:
|
|
25
|
+
"Tipo imutável do documento. Consulte document_types_list para o contrato completo.",
|
|
21
26
|
};
|
|
22
27
|
const REFERENCES = {
|
|
23
28
|
type: "array",
|
|
24
29
|
maxItems: 100,
|
|
30
|
+
description: "Relações com outros documentos do mesmo workspace.",
|
|
25
31
|
items: {
|
|
26
32
|
type: "object",
|
|
27
33
|
required: ["targetDocumentId"],
|
|
28
34
|
additionalProperties: false,
|
|
29
35
|
properties: {
|
|
30
36
|
targetDocumentId: ID,
|
|
31
|
-
relationship: {
|
|
37
|
+
relationship: {
|
|
38
|
+
type: "string",
|
|
39
|
+
maxLength: 80,
|
|
40
|
+
description: "Tipo da relação; usa related quando omitido.",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
const SOURCE = {
|
|
46
|
+
type: "object",
|
|
47
|
+
description:
|
|
48
|
+
"Origem canônica. Em mode=repository, repositoryId e path são obrigatórios.",
|
|
49
|
+
additionalProperties: false,
|
|
50
|
+
properties: {
|
|
51
|
+
mode: { type: "string", enum: ["native", "repository"] },
|
|
52
|
+
repositoryId: { type: "string", maxLength: 160 },
|
|
53
|
+
path: { type: "string", maxLength: 500 },
|
|
54
|
+
},
|
|
55
|
+
oneOf: [
|
|
56
|
+
{
|
|
57
|
+
properties: { mode: { const: "native" } },
|
|
58
|
+
required: ["mode"],
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
properties: { mode: { const: "repository" } },
|
|
62
|
+
required: ["mode", "repositoryId", "path"],
|
|
63
|
+
},
|
|
64
|
+
],
|
|
65
|
+
};
|
|
66
|
+
const CLASSIFICATION = {
|
|
67
|
+
type: "object",
|
|
68
|
+
description: "Taxonomias e tags aplicáveis ao contexto do documento.",
|
|
69
|
+
additionalProperties: false,
|
|
70
|
+
properties: {
|
|
71
|
+
primaryTaxonomyId: { type: "string" },
|
|
72
|
+
secondaryTaxonomyIds: { type: "array", items: ID },
|
|
73
|
+
tags: {
|
|
74
|
+
type: "object",
|
|
75
|
+
additionalProperties: { type: "array", items: ID },
|
|
32
76
|
},
|
|
33
77
|
},
|
|
34
78
|
};
|
|
79
|
+
|
|
80
|
+
function detailProperty(definition) {
|
|
81
|
+
if (definition.type === "date") return DATE;
|
|
82
|
+
return {
|
|
83
|
+
type: definition.type,
|
|
84
|
+
...(definition.enum ? { enum: definition.enum } : {}),
|
|
85
|
+
...(definition.maxLength ? { maxLength: definition.maxLength } : {}),
|
|
86
|
+
...(definition.default !== undefined
|
|
87
|
+
? { default: definition.default }
|
|
88
|
+
: {}),
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function detailsSchema(type, scope) {
|
|
93
|
+
const config = DOCUMENT_TYPE_CATALOG[type];
|
|
94
|
+
const properties = Object.fromEntries(
|
|
95
|
+
Object.entries(config.details).map(([field, definition]) => [
|
|
96
|
+
field,
|
|
97
|
+
detailProperty(definition),
|
|
98
|
+
]),
|
|
99
|
+
);
|
|
100
|
+
if (scope) properties.scope = { const: scope };
|
|
101
|
+
return {
|
|
102
|
+
type: "object",
|
|
103
|
+
additionalProperties: false,
|
|
104
|
+
properties,
|
|
105
|
+
...(scope ? { required: ["scope"] } : {}),
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const ALL_STATUSES = [
|
|
110
|
+
...new Set(
|
|
111
|
+
Object.values(DOCUMENT_TYPE_CATALOG).flatMap(({ statuses }) => statuses),
|
|
112
|
+
),
|
|
113
|
+
];
|
|
114
|
+
|
|
35
115
|
const COMMON = {
|
|
116
|
+
identifier: {
|
|
117
|
+
type: "string",
|
|
118
|
+
pattern: "^[a-z0-9]+(?:-[a-z0-9]+)*$",
|
|
119
|
+
maxLength: 80,
|
|
120
|
+
description:
|
|
121
|
+
"Identificador opcional e único no workspace, usando minúsculas, números e hífens simples.",
|
|
122
|
+
},
|
|
36
123
|
documentType: DOCUMENT_TYPE,
|
|
37
|
-
title: ID,
|
|
124
|
+
title: { ...ID, maxLength: 240 },
|
|
38
125
|
summary: { type: "string", minLength: 1, maxLength: 500 },
|
|
39
126
|
markdown: ID,
|
|
40
|
-
applicationId: {
|
|
41
|
-
|
|
127
|
+
applicationId: {
|
|
128
|
+
type: "string",
|
|
129
|
+
minLength: 1,
|
|
130
|
+
description:
|
|
131
|
+
"Obrigatório para regras, decisões, features e documentos cujo escopo seja aplicação ou componente; omita no escopo do workspace.",
|
|
132
|
+
},
|
|
133
|
+
affectedComponentIds: {
|
|
134
|
+
type: "array",
|
|
135
|
+
maxItems: 100,
|
|
136
|
+
items: ID,
|
|
137
|
+
description:
|
|
138
|
+
"Componentes ativos da applicationId. Não pode ser informado sem aplicação.",
|
|
139
|
+
},
|
|
42
140
|
collectionId: { type: "string" },
|
|
43
|
-
status: {
|
|
44
|
-
|
|
45
|
-
|
|
141
|
+
status: {
|
|
142
|
+
type: "string",
|
|
143
|
+
enum: ALL_STATUSES,
|
|
144
|
+
description:
|
|
145
|
+
"Estado válido para o documentType; quando omitido, usa o estado inicial do tipo.",
|
|
146
|
+
},
|
|
147
|
+
details: {
|
|
46
148
|
type: "object",
|
|
149
|
+
description:
|
|
150
|
+
"Metadados específicos do documentType, validados pelo ramo correspondente do schema.",
|
|
151
|
+
},
|
|
152
|
+
classification: CLASSIFICATION,
|
|
153
|
+
source: SOURCE,
|
|
154
|
+
references: REFERENCES,
|
|
155
|
+
definedAt: DATE,
|
|
156
|
+
lastReviewedAt: {
|
|
157
|
+
type: "string",
|
|
158
|
+
description: "YYYY-MM-DD ou vazio.",
|
|
159
|
+
},
|
|
160
|
+
nextReviewAt: { type: "string", description: "YYYY-MM-DD ou vazio." },
|
|
161
|
+
changeSummary: { type: "string" },
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
function typeBranch(type) {
|
|
165
|
+
const config = DOCUMENT_TYPE_CATALOG[type];
|
|
166
|
+
return {
|
|
167
|
+
description: `${config.label}: ${config.description}`,
|
|
168
|
+
properties: {
|
|
169
|
+
documentType: { const: type },
|
|
170
|
+
status: { type: "string", enum: config.statuses },
|
|
171
|
+
details: detailsSchema(type),
|
|
172
|
+
},
|
|
173
|
+
required: [
|
|
174
|
+
"documentType",
|
|
175
|
+
...(config.applicationRequired ? ["applicationId"] : []),
|
|
176
|
+
],
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function optionalApplicationBranches(type) {
|
|
181
|
+
const config = DOCUMENT_TYPE_CATALOG[type];
|
|
182
|
+
const properties = {
|
|
183
|
+
documentType: { const: type },
|
|
184
|
+
status: { type: "string", enum: config.statuses },
|
|
185
|
+
details: detailsSchema(type),
|
|
186
|
+
};
|
|
187
|
+
return [
|
|
188
|
+
{
|
|
189
|
+
description: `${config.label} geral do workspace; applicationId e componentes devem ser omitidos.`,
|
|
190
|
+
properties: {
|
|
191
|
+
...properties,
|
|
192
|
+
applicationId: { const: null },
|
|
193
|
+
affectedComponentIds: { type: "array", maxItems: 0 },
|
|
194
|
+
},
|
|
195
|
+
required: ["documentType"],
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
description: `${config.label} vinculada a uma aplicação e, opcionalmente, a seus componentes.`,
|
|
199
|
+
properties,
|
|
200
|
+
required: ["documentType", "applicationId"],
|
|
201
|
+
},
|
|
202
|
+
];
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
const CREATE_VARIANTS = [
|
|
206
|
+
typeBranch("business-rule"),
|
|
207
|
+
typeBranch("architecture-decision"),
|
|
208
|
+
typeBranch("feature"),
|
|
209
|
+
...optionalApplicationBranches("technical-reference"),
|
|
210
|
+
...optionalApplicationBranches("procedure"),
|
|
211
|
+
{
|
|
212
|
+
description:
|
|
213
|
+
"Guideline geral do workspace; applicationId deve ser omitido.",
|
|
47
214
|
properties: {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
additionalProperties: { type: "array", items: ID },
|
|
215
|
+
documentType: { const: "guideline" },
|
|
216
|
+
status: {
|
|
217
|
+
type: "string",
|
|
218
|
+
enum: DOCUMENT_TYPE_CATALOG.guideline.statuses,
|
|
53
219
|
},
|
|
220
|
+
details: detailsSchema("guideline", "workspace"),
|
|
221
|
+
applicationId: { const: null },
|
|
222
|
+
affectedComponentIds: { type: "array", maxItems: 0 },
|
|
54
223
|
},
|
|
224
|
+
required: ["documentType", "details"],
|
|
55
225
|
},
|
|
56
|
-
|
|
57
|
-
|
|
226
|
+
{
|
|
227
|
+
description: "Guideline vinculada a uma aplicação.",
|
|
58
228
|
properties: {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
229
|
+
documentType: { const: "guideline" },
|
|
230
|
+
status: {
|
|
231
|
+
type: "string",
|
|
232
|
+
enum: DOCUMENT_TYPE_CATALOG.guideline.statuses,
|
|
233
|
+
},
|
|
234
|
+
details: detailsSchema("guideline", "application"),
|
|
62
235
|
},
|
|
236
|
+
required: ["documentType", "details", "applicationId"],
|
|
63
237
|
},
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
238
|
+
{
|
|
239
|
+
description: "Guideline vinculada a ao menos um componente da aplicação.",
|
|
240
|
+
properties: {
|
|
241
|
+
documentType: { const: "guideline" },
|
|
242
|
+
status: {
|
|
243
|
+
type: "string",
|
|
244
|
+
enum: DOCUMENT_TYPE_CATALOG.guideline.statuses,
|
|
245
|
+
},
|
|
246
|
+
details: detailsSchema("guideline", "component"),
|
|
247
|
+
affectedComponentIds: {
|
|
248
|
+
type: "array",
|
|
249
|
+
minItems: 1,
|
|
250
|
+
maxItems: 100,
|
|
251
|
+
items: ID,
|
|
252
|
+
},
|
|
253
|
+
},
|
|
254
|
+
required: [
|
|
255
|
+
"documentType",
|
|
256
|
+
"details",
|
|
257
|
+
"applicationId",
|
|
258
|
+
"affectedComponentIds",
|
|
259
|
+
],
|
|
260
|
+
},
|
|
261
|
+
];
|
|
70
262
|
|
|
71
|
-
function schema(properties, required = []) {
|
|
263
|
+
function schema(properties, required = [], extra = {}) {
|
|
72
264
|
return {
|
|
73
265
|
type: "object",
|
|
74
266
|
...(required.length ? { required } : {}),
|
|
75
267
|
additionalProperties: false,
|
|
76
268
|
properties,
|
|
269
|
+
...extra,
|
|
77
270
|
};
|
|
78
271
|
}
|
|
79
272
|
|
|
@@ -96,6 +289,12 @@ export const knowledgeTools = [
|
|
|
96
289
|
["applicationId"],
|
|
97
290
|
),
|
|
98
291
|
),
|
|
292
|
+
definition(
|
|
293
|
+
"document_types_list",
|
|
294
|
+
"Lista o contrato oficial de cada tipo de documento: contexto exigido, estados e campos details.",
|
|
295
|
+
listDocumentTypes,
|
|
296
|
+
schema({}),
|
|
297
|
+
),
|
|
99
298
|
definition(
|
|
100
299
|
"documents_search",
|
|
101
300
|
"Busca documentos por tipo, aplicação, componente, coleção, estado ou texto.",
|
|
@@ -106,7 +305,7 @@ export const knowledgeTools = [
|
|
|
106
305
|
applicationId: ID,
|
|
107
306
|
componentId: ID,
|
|
108
307
|
collectionId: ID,
|
|
109
|
-
status: { type: "string" },
|
|
308
|
+
status: { type: "string", enum: ALL_STATUSES },
|
|
110
309
|
currentOnly: { type: "boolean" },
|
|
111
310
|
includeWorkspace: { type: "boolean" },
|
|
112
311
|
includeArchived: { type: "boolean" },
|
|
@@ -122,13 +321,15 @@ export const knowledgeTools = [
|
|
|
122
321
|
),
|
|
123
322
|
definition(
|
|
124
323
|
"documents_create",
|
|
125
|
-
"Cria um documento
|
|
324
|
+
"Cria um documento usando o contrato discriminado pelo documentType. O workspace vem da configuração do MCP; applicationId e details seguem as regras de cada tipo.",
|
|
126
325
|
createDocument,
|
|
127
|
-
schema(COMMON, ["documentType", "title", "summary", "markdown"]
|
|
326
|
+
schema(COMMON, ["documentType", "title", "summary", "markdown"], {
|
|
327
|
+
oneOf: CREATE_VARIANTS,
|
|
328
|
+
}),
|
|
128
329
|
),
|
|
129
330
|
definition(
|
|
130
331
|
"documents_update",
|
|
131
|
-
"Atualiza
|
|
332
|
+
"Atualiza um documento existente. documentType é imutável; consulte documents_get antes de alterar contexto, status ou details.",
|
|
132
333
|
updateDocument,
|
|
133
334
|
schema({ documentId: ID, ...COMMON }, ["documentId"]),
|
|
134
335
|
),
|
package/src/tools.js
CHANGED
|
@@ -236,7 +236,7 @@ const tools = [
|
|
|
236
236
|
{
|
|
237
237
|
name: "issues_create_taxonomy_item",
|
|
238
238
|
description:
|
|
239
|
-
"Inclui um item na taxonomia compartilhada de issues e
|
|
239
|
+
"Inclui um item na taxonomia compartilhada de issues e documentos, na raiz ou sob um item pai.",
|
|
240
240
|
inputSchema: {
|
|
241
241
|
type: "object",
|
|
242
242
|
required: ["id", "label"],
|
|
@@ -831,6 +831,45 @@ function validateEnum(value, schema, path, fields) {
|
|
|
831
831
|
}
|
|
832
832
|
}
|
|
833
833
|
|
|
834
|
+
function validateConst(value, schema, path, fields) {
|
|
835
|
+
if (Object.hasOwn(schema, "const") && value !== schema.const) {
|
|
836
|
+
addValidationField(
|
|
837
|
+
fields,
|
|
838
|
+
path,
|
|
839
|
+
"invalid_const",
|
|
840
|
+
`${path} must be ${JSON.stringify(schema.const)}`,
|
|
841
|
+
);
|
|
842
|
+
}
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
function validateString(value, schema, path, fields) {
|
|
846
|
+
if (typeof value !== "string") return;
|
|
847
|
+
if (schema.minLength !== undefined && value.length < schema.minLength) {
|
|
848
|
+
addValidationField(
|
|
849
|
+
fields,
|
|
850
|
+
path,
|
|
851
|
+
"min_length",
|
|
852
|
+
`${path} must contain at least ${schema.minLength} characters`,
|
|
853
|
+
);
|
|
854
|
+
}
|
|
855
|
+
if (schema.maxLength !== undefined && value.length > schema.maxLength) {
|
|
856
|
+
addValidationField(
|
|
857
|
+
fields,
|
|
858
|
+
path,
|
|
859
|
+
"max_length",
|
|
860
|
+
`${path} must contain at most ${schema.maxLength} characters`,
|
|
861
|
+
);
|
|
862
|
+
}
|
|
863
|
+
if (schema.pattern && !new RegExp(schema.pattern, "u").test(value)) {
|
|
864
|
+
addValidationField(
|
|
865
|
+
fields,
|
|
866
|
+
path,
|
|
867
|
+
"pattern",
|
|
868
|
+
`${path} must match ${schema.pattern}`,
|
|
869
|
+
);
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
|
|
834
873
|
function validateNumber(value, schema, path, fields) {
|
|
835
874
|
if (typeof value !== "number") return;
|
|
836
875
|
if (schema.minimum !== undefined && value < schema.minimum) {
|
|
@@ -921,13 +960,73 @@ function validateObject(value, schema, path, fields) {
|
|
|
921
960
|
validateObjectEntries(value, schema, path, fields);
|
|
922
961
|
}
|
|
923
962
|
|
|
963
|
+
function validateNot(value, schema, path, fields) {
|
|
964
|
+
if (!schema.not) return;
|
|
965
|
+
const nestedFields = [];
|
|
966
|
+
validateValue(value, schema.not, path, nestedFields);
|
|
967
|
+
if (!nestedFields.length) {
|
|
968
|
+
addValidationField(
|
|
969
|
+
fields,
|
|
970
|
+
path,
|
|
971
|
+
"not",
|
|
972
|
+
`${path || "arguments"} contains a forbidden combination of fields`,
|
|
973
|
+
);
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
function validateOneOf(value, schema, path, fields) {
|
|
978
|
+
if (!schema.oneOf?.length) return;
|
|
979
|
+
const candidates = schema.oneOf.map((candidate) => {
|
|
980
|
+
const candidateFields = [];
|
|
981
|
+
validateValue(value, candidate, path, candidateFields);
|
|
982
|
+
return candidateFields;
|
|
983
|
+
});
|
|
984
|
+
const matches = candidates.filter(
|
|
985
|
+
(candidateFields) => !candidateFields.length,
|
|
986
|
+
);
|
|
987
|
+
if (matches.length === 1) return;
|
|
988
|
+
if (!matches.length) {
|
|
989
|
+
const discriminatedIndexes = schema.oneOf.flatMap((candidate, index) => {
|
|
990
|
+
const matchesDiscriminator = Object.entries(
|
|
991
|
+
candidate.properties || {},
|
|
992
|
+
).some(
|
|
993
|
+
([property, definition]) =>
|
|
994
|
+
Object.hasOwn(definition, "const") &&
|
|
995
|
+
isPlainObject(value) &&
|
|
996
|
+
value[property] === definition.const,
|
|
997
|
+
);
|
|
998
|
+
return matchesDiscriminator ? [index] : [];
|
|
999
|
+
});
|
|
1000
|
+
const eligible = discriminatedIndexes.length
|
|
1001
|
+
? discriminatedIndexes.map((index) => candidates[index])
|
|
1002
|
+
: candidates;
|
|
1003
|
+
const best = eligible.reduce((selected, candidate) =>
|
|
1004
|
+
candidate.length < selected.length ? candidate : selected,
|
|
1005
|
+
);
|
|
1006
|
+
if (best.length) {
|
|
1007
|
+
fields.push(...best);
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
1010
|
+
}
|
|
1011
|
+
addValidationField(
|
|
1012
|
+
fields,
|
|
1013
|
+
path,
|
|
1014
|
+
"one_of",
|
|
1015
|
+
`${path || "arguments"} must match exactly one supported schema variant`,
|
|
1016
|
+
);
|
|
1017
|
+
}
|
|
1018
|
+
|
|
924
1019
|
function validateValue(value, schema, path, fields) {
|
|
925
1020
|
if (!schema || value === undefined) return;
|
|
926
1021
|
if (!validateSchemaType(value, schema, path, fields)) return;
|
|
1022
|
+
validateConst(value, schema, path, fields);
|
|
927
1023
|
validateEnum(value, schema, path, fields);
|
|
1024
|
+
validateString(value, schema, path, fields);
|
|
928
1025
|
validateNumber(value, schema, path, fields);
|
|
929
1026
|
validateArray(value, schema, path, fields);
|
|
930
1027
|
validateObject(value, schema, path, fields);
|
|
1028
|
+
validateNot(value, schema, path, fields);
|
|
1029
|
+
validateOneOf(value, schema, path, fields);
|
|
931
1030
|
}
|
|
932
1031
|
|
|
933
1032
|
function validateArguments(tool, args) {
|
package/src/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export const SERVER_NAME = "biaws-mcp";
|
|
2
|
-
export const SERVER_VERSION = "0.
|
|
2
|
+
export const SERVER_VERSION = "0.7.0";
|