innov-mcp-tasks 1.1.0 → 1.2.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.
Files changed (3) hide show
  1. package/README.md +16 -25
  2. package/index.mjs +133 -0
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -6,18 +6,16 @@ Servidor [MCP](https://modelcontextprotocol.io) em **stdio** para ferramentas de
6
6
 
7
7
  ## Variáveis obrigatórias
8
8
 
9
-
10
- | Variável | Descrição |
11
- | -------------------- | -------------------------------------------------------------------------------- |
9
+ | Variável | Descrição |
10
+ |----------|-----------|
12
11
  | `INNOV_API_BASE_URL` | URL base **sem** `/api/v1` (definida por ti: dev local, staging, produção, etc.) |
13
- | `INNOV_API_TOKEN` | Token pessoal Sanctum (ex.: **Perfil** → Tokens de API na app Innov) |
14
-
12
+ | `INNOV_API_TOKEN` | Token pessoal Sanctum (ex.: **Perfil** → Tokens de API na app Innov) |
15
13
 
16
- Copia `[.env.example](./.env.example)` para um ficheiro `.env` à tua escolha e preenche (esse ficheiro **não** vem do npm com valores; no repo monorepo, mantém `.env` fora do Git).
14
+ Copia [`.env.example`](./.env.example) para um ficheiro `.env` à tua escolha e preenche (esse ficheiro **não** vem do npm com valores; no repo monorepo, mantém `.env` fora do Git).
17
15
 
18
16
  ## Cursor com pacote npm (`npx`)
19
17
 
20
- Nome do pacote no npm: `**innov-mcp-tasks`** (se o nome estiver ocupado, publica como scoped, ex. `@tua-org/innov-mcp-tasks`, e ajusta os exemplos).
18
+ Nome do pacote no npm: **`innov-mcp-tasks`** (se o nome estiver ocupado, publica como scoped, ex. `@tua-org/innov-mcp-tasks`, e ajusta os exemplos).
21
19
 
22
20
  ```json
23
21
  {
@@ -35,20 +33,18 @@ Nome do pacote no npm: `**innov-mcp-tasks`** (se o nome estiver ocupado, publica
35
33
  }
36
34
  ```
37
35
 
38
- Segredos: prefere `[${env:INNOV_API_TOKEN}](https://cursor.com/docs/mcp)` apontando para variáveis já definidas no SO, ou `envFile` para um `.env` **fora** do repositório (ex. `C:\\Users\\…\\.config\\innov\\mcp.env`).
36
+ Segredos: prefere [`${env:INNOV_API_TOKEN}`](https://cursor.com/docs/mcp) apontando para variáveis já definidas no SO, ou `envFile` para um `.env` **fora** do repositório (ex. `C:\\Users\\…\\.config\\innov\\mcp.env`).
39
37
 
40
38
  Também podes apontar o binário instalado globalmente: `"command": "innov-mcp-tasks"` (após `npm install -g innov-mcp-tasks`).
41
39
 
42
40
  ## Monorepo (desenvolvimento)
43
41
 
44
- Na raiz do repo existe `[.cursor/mcp.json](../.cursor/mcp.json)` com **dois** servidores que partilham o mesmo `mcp-tasks/.env`:
42
+ Na raiz do repo existe [`.cursor/mcp.json`](../.cursor/mcp.json) com **dois** servidores que partilham o mesmo `mcp-tasks/.env`:
45
43
 
46
-
47
- | Servidor | Uso |
48
- | ------------------- | -------------------------------------------------------- |
44
+ | Servidor | Uso |
45
+ |----------|-----|
49
46
  | `innov-tasks-local` | Corre o `index.mjs` do clon (óptimo para alterar o MCP). |
50
- | `innov-tasks-npm` | Usa `npx -y innov-mcp-tasks` (testa o pacote publicado). |
51
-
47
+ | `innov-tasks-npm` | Usa `npx -y innov-mcp-tasks` (testa o pacote publicado). |
52
48
 
53
49
  **Ativa só um** em *Settings → Features → Model Context Protocol* (dois ao mesmo tempo duplicam ferramentas com o mesmo nome). Se publicares com scope (`@org/innov-mcp-tasks`), edita os `args` em `innov-tasks-npm` para esse nome.
54
50
 
@@ -72,6 +68,12 @@ Na raiz do repo existe `[.cursor/mcp.json](../.cursor/mcp.json)` com **dois** se
72
68
  - `notes_trashed`, `note_restore`
73
69
  - `annotations_search` — busca em cadernos, notas e fontes (`q` ≥ 2 caracteres)
74
70
 
71
+ ### Cadernos (notebooks)
72
+
73
+ - `notebooks_list` — lista com filtro opcional `project_id`
74
+ - `notebook_get`, `notebook_create`, `notebook_update`, `notebook_delete`
75
+ - `notebook_documentation` — notas + fontes do caderno
76
+
75
77
  ## Publicar no npm (mantenedor)
76
78
 
77
79
  1. Define o **nome** em `package.json` (`innov-mcp-tasks` ou `@scope/innov-mcp-tasks` se o nome simples estiver tomado).
@@ -84,16 +86,6 @@ npm test
84
86
  npm publish --access public
85
87
  ```
86
88
 
87
-
88
-
89
- Se estiver deslogado para logar faça o comando
90
-
91
- ```bash
92
- npm login
93
- ```
94
-
95
-
96
-
97
89
  Para **scoped** (`@org/pkg`): a primeira vez costuma precisar de `--access public` se for pacote OSS.
98
90
 
99
91
  ## Testes
@@ -101,4 +93,3 @@ Para **scoped** (`@org/pkg`): a primeira vez costuma precisar de `--access publi
101
93
  ```bash
102
94
  npm test
103
95
  ```
104
-
package/index.mjs CHANGED
@@ -496,5 +496,138 @@ server.registerTool(
496
496
  },
497
497
  );
498
498
 
499
+ server.registerTool(
500
+ 'notebooks_list',
501
+ {
502
+ description:
503
+ 'Lista cadernos visíveis ao utilizador do token (GET /notebooks). Filtro opcional project_id.',
504
+ inputSchema: {
505
+ project_id: z.number().int().positive().optional(),
506
+ },
507
+ },
508
+ async (args) => {
509
+ try {
510
+ const qs =
511
+ args.project_id != null
512
+ ? `?project_id=${encodeURIComponent(String(args.project_id))}`
513
+ : '';
514
+ const data = await apiFetch(`/api/v1/notebooks${qs}`);
515
+ return jsonText(data);
516
+ } catch (e) {
517
+ return jsonError(e instanceof Error ? e.message : String(e));
518
+ }
519
+ },
520
+ );
521
+
522
+ server.registerTool(
523
+ 'notebook_get',
524
+ {
525
+ description: 'Obtém um caderno por id (GET /notebooks/{id}).',
526
+ inputSchema: { notebook_id: z.number().int().positive() },
527
+ },
528
+ async (args) => {
529
+ try {
530
+ const data = await apiFetch(`/api/v1/notebooks/${args.notebook_id}`);
531
+ return jsonText(data);
532
+ } catch (e) {
533
+ return jsonError(e instanceof Error ? e.message : String(e));
534
+ }
535
+ },
536
+ );
537
+
538
+ server.registerTool(
539
+ 'notebook_create',
540
+ {
541
+ description:
542
+ 'Cria caderno (POST /notebooks). Pessoal sem project_id; de projeto com project_id. name obrigatório.',
543
+ inputSchema: {
544
+ name: z.string().min(1).max(255),
545
+ description: z.string().optional(),
546
+ project_id: z.number().int().positive().optional(),
547
+ },
548
+ },
549
+ async (args) => {
550
+ try {
551
+ const body = {
552
+ name: args.name,
553
+ description: args.description ?? null,
554
+ project_id: args.project_id ?? null,
555
+ };
556
+ const data = await apiFetch('/api/v1/notebooks', {
557
+ method: 'POST',
558
+ body: JSON.stringify(body),
559
+ });
560
+ return jsonText(data);
561
+ } catch (e) {
562
+ return jsonError(e instanceof Error ? e.message : String(e));
563
+ }
564
+ },
565
+ );
566
+
567
+ server.registerTool(
568
+ 'notebook_update',
569
+ {
570
+ description: 'Atualiza caderno (PATCH /notebooks/{id}). Só cadernos do utilizador.',
571
+ inputSchema: {
572
+ notebook_id: z.number().int().positive(),
573
+ name: z.string().min(1).max(255).optional(),
574
+ description: z.string().optional(),
575
+ project_id: z.number().int().positive().optional(),
576
+ },
577
+ },
578
+ async (args) => {
579
+ try {
580
+ const { notebook_id, ...fields } = args;
581
+ const body = Object.fromEntries(
582
+ Object.entries(fields).filter(([, v]) => v !== undefined),
583
+ );
584
+ const data = await apiFetch(`/api/v1/notebooks/${notebook_id}`, {
585
+ method: 'PATCH',
586
+ body: JSON.stringify(body),
587
+ });
588
+ return jsonText(data);
589
+ } catch (e) {
590
+ return jsonError(e instanceof Error ? e.message : String(e));
591
+ }
592
+ },
593
+ );
594
+
595
+ server.registerTool(
596
+ 'notebook_delete',
597
+ {
598
+ description: 'Apaga caderno (DELETE /notebooks/{id}). Só cadernos do utilizador.',
599
+ inputSchema: { notebook_id: z.number().int().positive() },
600
+ },
601
+ async (args) => {
602
+ try {
603
+ const data = await apiFetch(`/api/v1/notebooks/${args.notebook_id}`, {
604
+ method: 'DELETE',
605
+ });
606
+ return jsonText(data);
607
+ } catch (e) {
608
+ return jsonError(e instanceof Error ? e.message : String(e));
609
+ }
610
+ },
611
+ );
612
+
613
+ server.registerTool(
614
+ 'notebook_documentation',
615
+ {
616
+ description:
617
+ 'Documentação agregada do caderno: notas do utilizador + fontes (GET /notebooks/{id}/documentation).',
618
+ inputSchema: { notebook_id: z.number().int().positive() },
619
+ },
620
+ async (args) => {
621
+ try {
622
+ const data = await apiFetch(
623
+ `/api/v1/notebooks/${args.notebook_id}/documentation`,
624
+ );
625
+ return jsonText(data);
626
+ } catch (e) {
627
+ return jsonError(e instanceof Error ? e.message : String(e));
628
+ }
629
+ },
630
+ );
631
+
499
632
  const transport = new StdioServerTransport();
500
633
  await server.connect(transport);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "innov-mcp-tasks",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "MCP stdio — tarefas e anotações Innov (INNOV_API_BASE_URL + token Sanctum)",
5
5
  "type": "module",
6
6
  "main": "index.mjs",