innov-mcp-tasks 1.4.0 → 1.5.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 CHANGED
@@ -75,6 +75,12 @@ Na raiz do repo existe [`.cursor/mcp.json`](../.cursor/mcp.json) com **dois** se
75
75
  - `notebooks_list` — lista com filtro opcional `project_id`
76
76
  - `notebook_get`, `notebook_create`, `notebook_update`, `notebook_delete`
77
77
  - `notebook_documentation` — notas + fontes do caderno
78
+ - `annotations_semantic_search` — busca semântica em notas e metadados (`q` ≥ 2 caracteres)
79
+
80
+ ### Agentes de IA (SPEC-015)
81
+
82
+ - `agents_list` — agentes utilizáveis pelo token (`GET /api/v1/ai-agents?scope=usable`); opcional `scope=manageable` para gestão
83
+ - `agent_chat` — envia `message` a um agente (`POST /api/v1/ai-agents/{ulid}/chat`); devolve `response` e `citations`; opcional `conversation_ulid`, `project_id`, `notebook_id`
78
84
 
79
85
  ## Publicar no npm (mantenedor)
80
86
 
package/index.mjs CHANGED
@@ -6,6 +6,7 @@ import 'dotenv/config';
6
6
  import { z } from 'zod';
7
7
  import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
8
8
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
9
+ import { agentChat, agentsList } from './lib/agents.mjs';
9
10
 
10
11
  const base = (process.env.INNOV_API_BASE_URL || '').replace(/\/$/, '');
11
12
  const token = (process.env.INNOV_API_TOKEN || '').trim();
@@ -757,6 +758,40 @@ server.registerTool(
757
758
  },
758
759
  );
759
760
 
761
+ server.registerTool(
762
+ 'annotations_semantic_search',
763
+ {
764
+ description:
765
+ 'Busca semântica em notas e metadados de cadernos (GET /annotations/semantic-search).',
766
+ inputSchema: {
767
+ q: z.string().min(2),
768
+ notebook_id: z.number().int().positive().optional(),
769
+ limit: z.number().int().min(1).max(30).optional(),
770
+ min_score: z.number().min(0).max(1).optional(),
771
+ },
772
+ },
773
+ async (args) => {
774
+ try {
775
+ const params = new URLSearchParams({ q: args.q });
776
+ if (args.notebook_id != null) {
777
+ params.set('notebook_id', String(args.notebook_id));
778
+ }
779
+ if (args.limit != null) {
780
+ params.set('limit', String(args.limit));
781
+ }
782
+ if (args.min_score != null) {
783
+ params.set('min_score', String(args.min_score));
784
+ }
785
+ const data = await apiFetch(
786
+ `/api/v1/annotations/semantic-search?${params.toString()}`,
787
+ );
788
+ return jsonText(data);
789
+ } catch (e) {
790
+ return jsonError(e instanceof Error ? e.message : String(e));
791
+ }
792
+ },
793
+ );
794
+
760
795
  server.registerTool(
761
796
  'notebook_documentation',
762
797
  {
@@ -776,5 +811,56 @@ server.registerTool(
776
811
  },
777
812
  );
778
813
 
814
+ server.registerTool(
815
+ 'agents_list',
816
+ {
817
+ description:
818
+ 'Lista agentes de IA (GET /ai-agents). Padrão scope=usable — agentes que o token pode usar no chat (ACL). ' +
819
+ 'Use scope=manageable para gestão (/agentes; requer can_manage_agents).',
820
+ inputSchema: {
821
+ scope: z
822
+ .enum(['usable', 'manageable'])
823
+ .optional()
824
+ .describe('Padrão: usable (selector de chat conforme ACL)'),
825
+ },
826
+ },
827
+ async (args) => {
828
+ try {
829
+ const data = await agentsList(apiFetch, args.scope ?? 'usable');
830
+ return jsonText(data);
831
+ } catch (e) {
832
+ return jsonError(e instanceof Error ? e.message : String(e));
833
+ }
834
+ },
835
+ );
836
+
837
+ server.registerTool(
838
+ 'agent_chat',
839
+ {
840
+ description:
841
+ 'Envia mensagem a um agente de IA (POST /ai-agents/{ulid}/chat). ' +
842
+ 'Devolve resposta do agente e citações quando ferramentas de KB forem usadas. ' +
843
+ 'Opcional conversation_ulid para continuar conversa; project_id/notebook_id para contexto.',
844
+ inputSchema: {
845
+ agent_ulid: z.string().min(1).describe('ULID do agente (ver agents_list)'),
846
+ message: z.string().min(1),
847
+ conversation_ulid: z
848
+ .string()
849
+ .optional()
850
+ .describe('ULID da conversa para continuar o turno'),
851
+ project_id: z.number().int().positive().optional(),
852
+ notebook_id: z.number().int().positive().optional(),
853
+ },
854
+ },
855
+ async (args) => {
856
+ try {
857
+ const data = await agentChat(apiFetch, args);
858
+ return jsonText(data);
859
+ } catch (e) {
860
+ return jsonError(e instanceof Error ? e.message : String(e));
861
+ }
862
+ },
863
+ );
864
+
779
865
  const transport = new StdioServerTransport();
780
866
  await server.connect(transport);
package/lib/agents.mjs ADDED
@@ -0,0 +1,97 @@
1
+ /** Helpers e handlers testáveis para tools de agentes de IA (SPEC-015 Fase 8). */
2
+
3
+ export const AGENT_SCOPES = ['usable', 'manageable'];
4
+
5
+ /**
6
+ * @param {'usable' | 'manageable'} [scope]
7
+ */
8
+ export function agentsListPath(scope = 'usable') {
9
+ if (!AGENT_SCOPES.includes(scope)) {
10
+ throw new Error(`scope inválido: ${scope}. Use manageable ou usable.`);
11
+ }
12
+ return `/api/v1/ai-agents?scope=${encodeURIComponent(scope)}`;
13
+ }
14
+
15
+ /**
16
+ * @param {string} ulid
17
+ */
18
+ export function agentChatPath(ulid) {
19
+ const trimmed = String(ulid ?? '').trim();
20
+ if (!trimmed) {
21
+ throw new Error('agent_ulid é obrigatório');
22
+ }
23
+ return `/api/v1/ai-agents/${encodeURIComponent(trimmed)}/chat`;
24
+ }
25
+
26
+ /**
27
+ * @param {{
28
+ * message: string;
29
+ * conversation_ulid?: string;
30
+ * project_id?: number;
31
+ * notebook_id?: number;
32
+ * }} args
33
+ */
34
+ export function buildAgentChatBody(args) {
35
+ const body = { message: args.message };
36
+ if (args.conversation_ulid != null) {
37
+ body.conversation_ulid = args.conversation_ulid;
38
+ }
39
+ if (args.project_id != null) {
40
+ body.project_id = args.project_id;
41
+ }
42
+ if (args.notebook_id != null) {
43
+ body.notebook_id = args.notebook_id;
44
+ }
45
+ return body;
46
+ }
47
+
48
+ /**
49
+ * Normaliza resposta do chat para o consumidor MCP (resposta + citações).
50
+ * @param {unknown} data
51
+ */
52
+ export function formatAgentChatResponse(data) {
53
+ if (!data || typeof data !== 'object') {
54
+ return { response: null, citations: [] };
55
+ }
56
+ const payload = /** @type {Record<string, unknown>} */ (data);
57
+ return {
58
+ success: payload.success,
59
+ response:
60
+ typeof payload.response === 'string'
61
+ ? payload.response
62
+ : typeof payload.message === 'string'
63
+ ? payload.message
64
+ : null,
65
+ citations: Array.isArray(payload.citations) ? payload.citations : [],
66
+ conversation_ulid: payload.conversation_ulid ?? null,
67
+ actions: payload.actions,
68
+ token_usage: payload.token_usage,
69
+ pending_approval: payload.pending_approval ?? null,
70
+ };
71
+ }
72
+
73
+ /**
74
+ * @param {(path: string, init?: RequestInit) => Promise<unknown>} apiFetch
75
+ * @param {'usable' | 'manageable'} [scope]
76
+ */
77
+ export async function agentsList(apiFetch, scope = 'usable') {
78
+ return apiFetch(agentsListPath(scope));
79
+ }
80
+
81
+ /**
82
+ * @param {(path: string, init?: RequestInit) => Promise<unknown>} apiFetch
83
+ * @param {{
84
+ * agent_ulid: string;
85
+ * message: string;
86
+ * conversation_ulid?: string;
87
+ * project_id?: number;
88
+ * notebook_id?: number;
89
+ * }} args
90
+ */
91
+ export async function agentChat(apiFetch, args) {
92
+ const data = await apiFetch(agentChatPath(args.agent_ulid), {
93
+ method: 'POST',
94
+ body: JSON.stringify(buildAgentChatBody(args)),
95
+ });
96
+ return formatAgentChatResponse(data);
97
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "innov-mcp-tasks",
3
- "version": "1.4.0",
4
- "description": "MCP stdio — tarefas e anotações Innov (INNOV_API_BASE_URL + token Sanctum)",
3
+ "version": "1.5.0",
4
+ "description": "MCP stdio — tarefas, anotações e agentes de IA Innov (INNOV_API_BASE_URL + token Sanctum)",
5
5
  "type": "module",
6
6
  "main": "index.mjs",
7
7
  "bin": {
@@ -9,13 +9,14 @@
9
9
  },
10
10
  "files": [
11
11
  "index.mjs",
12
+ "lib/**",
12
13
  "README.md",
13
14
  ".env.example",
14
15
  "scripts/postinstall-notice.mjs"
15
16
  ],
16
17
  "scripts": {
17
18
  "start": "node index.mjs",
18
- "test": "node --check index.mjs",
19
+ "test": "node --check index.mjs && node --test test/*.test.mjs",
19
20
  "prepack": "node --check index.mjs",
20
21
  "postinstall": "node ./scripts/postinstall-notice.mjs"
21
22
  },
@@ -28,6 +29,8 @@
28
29
  "tasks",
29
30
  "notes",
30
31
  "annotations",
32
+ "ai-agents",
33
+ "agents",
31
34
  "innov"
32
35
  ],
33
36
  "author": "",