innov-mcp-tasks 1.5.0 → 1.6.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
@@ -82,6 +82,14 @@ Na raiz do repo existe [`.cursor/mcp.json`](../.cursor/mcp.json) com **dois** se
82
82
  - `agents_list` — agentes utilizáveis pelo token (`GET /api/v1/ai-agents?scope=usable`); opcional `scope=manageable` para gestão
83
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`
84
84
 
85
+ ### Infraestrutura / servidores (SPEC-022)
86
+
87
+ - `servers_dashboard` — resumo online/offline, alertas e aplicações (`GET /server-monitoring/dashboard`)
88
+ - `servers_list` — lista servidores com métricas; filtros opcionais `status`, `search`
89
+ - `server_get` — detalhe por `server_ulid` (métricas + aplicações com tipo/versão)
90
+ - `server_alerts` — alertas ativos de CPU, RAM, disco e aplicações
91
+ - `server_applications_search` — busca apps (`search`, `type`, `server_ulid`, `env_production`, `debug_enabled`, paginação)
92
+
85
93
  ## Publicar no npm (mantenedor)
86
94
 
87
95
  1. Define o **nome** em `package.json` (`innov-mcp-tasks` ou `@scope/innov-mcp-tasks` se o nome simples estiver tomado).
package/index.mjs CHANGED
@@ -7,6 +7,13 @@ 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
9
  import { agentChat, agentsList } from './lib/agents.mjs';
10
+ import {
11
+ serverAlerts,
12
+ serverApplicationsSearch,
13
+ serverGet,
14
+ serversDashboard,
15
+ serversList,
16
+ } from './lib/serverMonitoring.mjs';
10
17
 
11
18
  const base = (process.env.INNOV_API_BASE_URL || '').replace(/\/$/, '');
12
19
  const token = (process.env.INNOV_API_TOKEN || '').trim();
@@ -862,5 +869,103 @@ server.registerTool(
862
869
  },
863
870
  );
864
871
 
872
+ server.registerTool(
873
+ 'servers_dashboard',
874
+ {
875
+ description:
876
+ 'Resumo do monitoramento de servidores (GET /server-monitoring/dashboard): online/offline, alertas e aplicações.',
877
+ inputSchema: {},
878
+ },
879
+ async () => {
880
+ try {
881
+ const data = await serversDashboard(apiFetch);
882
+ return jsonText(data);
883
+ } catch (e) {
884
+ return jsonError(e instanceof Error ? e.message : String(e));
885
+ }
886
+ },
887
+ );
888
+
889
+ server.registerTool(
890
+ 'servers_list',
891
+ {
892
+ description:
893
+ 'Lista servidores monitorados com métricas recentes (GET /server-monitoring/servers).',
894
+ inputSchema: {
895
+ status: z.enum(['active', 'inactive']).optional(),
896
+ search: z.string().optional().describe('Hostname, IP ou descrição'),
897
+ },
898
+ },
899
+ async (args) => {
900
+ try {
901
+ const data = await serversList(apiFetch, args);
902
+ return jsonText(data);
903
+ } catch (e) {
904
+ return jsonError(e instanceof Error ? e.message : String(e));
905
+ }
906
+ },
907
+ );
908
+
909
+ server.registerTool(
910
+ 'server_get',
911
+ {
912
+ description:
913
+ 'Detalhe de um servidor: métricas, histórico e aplicações detectadas (GET /server-monitoring/servers/{ulid}).',
914
+ inputSchema: {
915
+ server_ulid: z.string().min(1).describe('ULID do servidor'),
916
+ },
917
+ },
918
+ async (args) => {
919
+ try {
920
+ const data = await serverGet(apiFetch, args);
921
+ return jsonText(data);
922
+ } catch (e) {
923
+ return jsonError(e instanceof Error ? e.message : String(e));
924
+ }
925
+ },
926
+ );
927
+
928
+ server.registerTool(
929
+ 'server_alerts',
930
+ {
931
+ description:
932
+ 'Alertas ativos de infraestrutura: CPU, RAM, disco e aplicações (GET /server-monitoring/alerts).',
933
+ inputSchema: {},
934
+ },
935
+ async () => {
936
+ try {
937
+ const data = await serverAlerts(apiFetch);
938
+ return jsonText(data);
939
+ } catch (e) {
940
+ return jsonError(e instanceof Error ? e.message : String(e));
941
+ }
942
+ },
943
+ );
944
+
945
+ server.registerTool(
946
+ 'server_applications_search',
947
+ {
948
+ description:
949
+ 'Busca aplicações nos servidores: stack (laravel, vuejs…), versão, ambiente (GET /server-monitoring/applications/search).',
950
+ inputSchema: {
951
+ search: z.string().optional(),
952
+ type: z.string().optional().describe('laravel, vuejs, symfony, wordpress, etc.'),
953
+ server_ulid: z.string().optional(),
954
+ env_production: z.boolean().optional(),
955
+ debug_enabled: z.boolean().optional(),
956
+ limit: z.number().int().min(1).max(50).optional(),
957
+ page: z.number().int().min(1).optional(),
958
+ },
959
+ },
960
+ async (args) => {
961
+ try {
962
+ const data = await serverApplicationsSearch(apiFetch, args);
963
+ return jsonText(data);
964
+ } catch (e) {
965
+ return jsonError(e instanceof Error ? e.message : String(e));
966
+ }
967
+ },
968
+ );
969
+
865
970
  const transport = new StdioServerTransport();
866
971
  await server.connect(transport);
@@ -0,0 +1,98 @@
1
+ /** Helpers e handlers para ferramentas de monitoramento de servidores (SPEC-022). */
2
+
3
+ /**
4
+ * @param {Record<string, string | number | boolean | undefined | null>} [params]
5
+ */
6
+ export function serverMonitoringQueryString(params = {}) {
7
+ const search = new URLSearchParams();
8
+ for (const [key, value] of Object.entries(params)) {
9
+ if (value === undefined || value === null || value === '') {
10
+ continue;
11
+ }
12
+ search.set(key, String(value));
13
+ }
14
+ const qs = search.toString();
15
+ return qs ? `?${qs}` : '';
16
+ }
17
+
18
+ export function serversDashboardPath() {
19
+ return '/api/v1/server-monitoring/dashboard';
20
+ }
21
+
22
+ /**
23
+ * @param {{ status?: string, search?: string }} [args]
24
+ */
25
+ export function serversListPath(args = {}) {
26
+ return `/api/v1/server-monitoring/servers${serverMonitoringQueryString({
27
+ status: args.status,
28
+ search: args.search,
29
+ })}`;
30
+ }
31
+
32
+ /**
33
+ * @param {string} serverUlid
34
+ */
35
+ export function serverGetPath(serverUlid) {
36
+ const trimmed = String(serverUlid ?? '').trim();
37
+ if (!trimmed) {
38
+ throw new Error('server_ulid é obrigatório');
39
+ }
40
+ return `/api/v1/server-monitoring/servers/${encodeURIComponent(trimmed)}`;
41
+ }
42
+
43
+ export function serverAlertsPath() {
44
+ return '/api/v1/server-monitoring/alerts';
45
+ }
46
+
47
+ /**
48
+ * @param {Record<string, string | number | boolean | undefined | null>} [args]
49
+ */
50
+ export function serverApplicationsSearchPath(args = {}) {
51
+ const { limit, page, ...rest } = args;
52
+ return `/api/v1/server-monitoring/applications/search${serverMonitoringQueryString({
53
+ ...rest,
54
+ per_page: limit ?? rest.per_page,
55
+ page,
56
+ })}`;
57
+ }
58
+
59
+ /**
60
+ * @param {(path: string, init?: RequestInit) => Promise<unknown>} apiFetch
61
+ */
62
+ export async function serversDashboard(apiFetch) {
63
+ return apiFetch(serversDashboardPath());
64
+ }
65
+
66
+ /**
67
+ * @param {(path: string, init?: RequestInit) => Promise<unknown>} apiFetch
68
+ * @param {{ status?: string, search?: string }} [args]
69
+ */
70
+ export async function serversList(apiFetch, args = {}) {
71
+ const data = await apiFetch(serversListPath(args));
72
+ return data?.data ?? data;
73
+ }
74
+
75
+ /**
76
+ * @param {(path: string, init?: RequestInit) => Promise<unknown>} apiFetch
77
+ * @param {{ server_ulid: string }} args
78
+ */
79
+ export async function serverGet(apiFetch, args) {
80
+ const data = await apiFetch(serverGetPath(args.server_ulid));
81
+ return data?.data ?? data;
82
+ }
83
+
84
+ /**
85
+ * @param {(path: string, init?: RequestInit) => Promise<unknown>} apiFetch
86
+ */
87
+ export async function serverAlerts(apiFetch) {
88
+ const data = await apiFetch(serverAlertsPath());
89
+ return data?.data ?? data;
90
+ }
91
+
92
+ /**
93
+ * @param {(path: string, init?: RequestInit) => Promise<unknown>} apiFetch
94
+ * @param {Record<string, string | number | boolean | undefined | null>} [args]
95
+ */
96
+ export async function serverApplicationsSearch(apiFetch, args = {}) {
97
+ return apiFetch(serverApplicationsSearchPath(args));
98
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "innov-mcp-tasks",
3
- "version": "1.5.0",
3
+ "version": "1.6.0",
4
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",