openhive-mcp-server 1.0.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 (2) hide show
  1. package/index.js +223 -0
  2. package/package.json +19 -0
package/index.js ADDED
@@ -0,0 +1,223 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * OpenHive MCP CLI
5
+ *
6
+ * Connects IDEs (Antigravity, Claude Desktop, Cursor, etc.) to your OpenHive instance.
7
+ *
8
+ * Environment variables:
9
+ * OPENHIVE_API_URL - Your OpenHive API URL (e.g., https://your-server.com)
10
+ * OPENHIVE_API_TOKEN - Your API token (from Settings > MCP Token)
11
+ *
12
+ * Usage in IDE config:
13
+ * {
14
+ * "mcpServers": {
15
+ * "openhive": {
16
+ * "command": "npx",
17
+ * "args": ["-y", "openhive-mcp"],
18
+ * "env": {
19
+ * "OPENHIVE_API_URL": "https://your-api-url",
20
+ * "OPENHIVE_API_TOKEN": "your-token"
21
+ * }
22
+ * }
23
+ * }
24
+ * }
25
+ */
26
+
27
+ const { McpServer } = require('@modelcontextprotocol/sdk/server/mcp.js');
28
+ const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
29
+ const { z } = require('zod');
30
+
31
+ const API_URL = process.env.OPENHIVE_API_URL || process.env.OPENHIVE_URL || '';
32
+ const API_TOKEN = process.env.OPENHIVE_API_TOKEN || process.env.OPENHIVE_TOKEN || '';
33
+
34
+ if (!API_URL) {
35
+ console.error('Error: OPENHIVE_API_URL environment variable is required');
36
+ console.error('Set it in your IDE MCP config env section');
37
+ process.exit(1);
38
+ }
39
+
40
+ async function apiRequest(path, options = {}) {
41
+ const url = `${API_URL.replace(/\/$/, '')}${path}`;
42
+ const res = await fetch(url, {
43
+ ...options,
44
+ headers: {
45
+ 'Content-Type': 'application/json',
46
+ 'Authorization': `Bearer ${API_TOKEN}`,
47
+ ...options.headers,
48
+ },
49
+ });
50
+ const data = await res.json();
51
+ if (!res.ok) throw new Error(data.error || 'API request failed');
52
+ return data.data;
53
+ }
54
+
55
+ const server = new McpServer({ name: 'openhive', version: '1.0.0' });
56
+
57
+ // ── Posts ──
58
+
59
+ server.tool('create_post', 'Cria um novo post', {
60
+ caption: z.string().optional().describe('Legenda do post'),
61
+ imageUrl: z.string().optional().describe('URL da imagem'),
62
+ hashtags: z.array(z.string()).optional().describe('Lista de hashtags'),
63
+ scheduledAt: z.string().optional().describe('Data de agendamento ISO'),
64
+ }, async (input) => {
65
+ const result = await apiRequest('/api/posts', { method: 'POST', body: JSON.stringify(input) });
66
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
67
+ });
68
+
69
+ server.tool('list_posts', 'Lista posts com filtros', {
70
+ status: z.string().optional().describe('Filtrar por status: DRAFT, SCHEDULED, PUBLISHED, FAILED'),
71
+ limit: z.string().optional().describe('Limite de resultados'),
72
+ page: z.string().optional().describe('Pagina'),
73
+ }, async (input) => {
74
+ const params = new URLSearchParams();
75
+ if (input.status) params.set('status', input.status);
76
+ if (input.limit) params.set('limit', input.limit);
77
+ if (input.page) params.set('page', input.page);
78
+ const result = await apiRequest(`/api/posts?${params}`);
79
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
80
+ });
81
+
82
+ server.tool('publish_now', 'Publica um post imediatamente no Instagram', {
83
+ post_id: z.string().describe('ID do post'),
84
+ }, async (input) => {
85
+ const result = await apiRequest(`/api/posts/${input.post_id}/publish`, { method: 'POST' });
86
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
87
+ });
88
+
89
+ server.tool('schedule_post', 'Agenda um post para publicacao', {
90
+ post_id: z.string().describe('ID do post'),
91
+ datetime: z.string().describe('Data e hora ISO'),
92
+ }, async (input) => {
93
+ const result = await apiRequest(`/api/posts/${input.post_id}/schedule`, {
94
+ method: 'POST', body: JSON.stringify({ scheduledAt: input.datetime }),
95
+ });
96
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
97
+ });
98
+
99
+ server.tool('generate_image', 'Gera imagem com IA (Gemini)', {
100
+ prompt: z.string().describe('Descricao da imagem'),
101
+ aspectRatio: z.string().optional().describe('Formato: 1:1, 4:5, 9:16'),
102
+ }, async (input) => {
103
+ const result = await apiRequest('/api/generate/image', {
104
+ method: 'POST', body: JSON.stringify(input),
105
+ });
106
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
107
+ });
108
+
109
+ server.tool('generate_caption', 'Gera legenda com IA', {
110
+ topic: z.string().describe('Tema do post'),
111
+ tone: z.string().optional().describe('Tom: educativo, inspirador, humor, noticia'),
112
+ }, async (input) => {
113
+ const result = await apiRequest('/api/generate/caption', {
114
+ method: 'POST', body: JSON.stringify(input),
115
+ });
116
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
117
+ });
118
+
119
+ server.tool('render_html_to_image', 'Renderiza HTML/CSS/Tailwind em imagem PNG', {
120
+ html: z.string().describe('Codigo HTML do post (suporta Tailwind CSS)'),
121
+ width: z.number().optional().describe('Largura em pixels (default: 1080)'),
122
+ height: z.number().optional().describe('Altura em pixels (default: 1080)'),
123
+ }, async (input) => {
124
+ const result = await apiRequest('/api/generate/html', {
125
+ method: 'POST', body: JSON.stringify(input),
126
+ });
127
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
128
+ });
129
+
130
+ server.tool('generate_template_image', 'Gera imagem usando template HTML pre-definido', {
131
+ title: z.string().describe('Texto principal'),
132
+ subtitle: z.string().optional().describe('Subtitulo'),
133
+ template: z.string().optional().describe('Template: bold-gradient, minimal-dark, neon-card, quote-elegant, stats-impact, split-color'),
134
+ aspect_ratio: z.string().optional().describe('Formato: 1:1, 4:5, 9:16'),
135
+ }, async (input) => {
136
+ const result = await apiRequest('/api/generate/template', {
137
+ method: 'POST', body: JSON.stringify({
138
+ title: input.title, subtitle: input.subtitle,
139
+ template: input.template || 'bold-gradient',
140
+ aspectRatio: input.aspect_ratio || '1:1',
141
+ }),
142
+ });
143
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
144
+ });
145
+
146
+ // ── Tasks ──
147
+
148
+ server.tool('create_task', 'Cria uma tarefa', {
149
+ title: z.string().describe('Titulo da tarefa'),
150
+ description: z.string().optional().describe('Descricao'),
151
+ platform: z.string().optional().describe('Plataforma: YOUTUBE, INSTAGRAM, TIKTOK, OTHER'),
152
+ priority: z.string().optional().describe('Prioridade: LOW, MEDIUM, HIGH, URGENT'),
153
+ }, async (input) => {
154
+ const result = await apiRequest('/api/tasks', { method: 'POST', body: JSON.stringify(input) });
155
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
156
+ });
157
+
158
+ server.tool('list_tasks', 'Lista tarefas', {
159
+ status: z.string().optional().describe('Status: PENDING, IN_PROGRESS, COMPLETED, CANCELLED'),
160
+ limit: z.string().optional().describe('Limite'),
161
+ }, async (input) => {
162
+ const params = new URLSearchParams();
163
+ if (input.status) params.set('status', input.status);
164
+ if (input.limit) params.set('limit', input.limit);
165
+ const result = await apiRequest(`/api/tasks?${params}`);
166
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
167
+ });
168
+
169
+ server.tool('update_task', 'Atualiza uma tarefa', {
170
+ task_id: z.string().describe('ID da tarefa'),
171
+ title: z.string().optional(),
172
+ status: z.string().optional(),
173
+ priority: z.string().optional(),
174
+ }, async (input) => {
175
+ const { task_id, ...body } = input;
176
+ const result = await apiRequest(`/api/tasks/${task_id}`, { method: 'PUT', body: JSON.stringify(body) });
177
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
178
+ });
179
+
180
+ server.tool('delete_task', 'Remove uma tarefa', {
181
+ task_id: z.string().describe('ID da tarefa'),
182
+ }, async (input) => {
183
+ const result = await apiRequest(`/api/tasks/${input.task_id}`, { method: 'DELETE' });
184
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
185
+ });
186
+
187
+ // ── Projects ──
188
+
189
+ server.tool('create_project', 'Cria um projeto', {
190
+ title: z.string().describe('Titulo'),
191
+ description: z.string().optional(),
192
+ }, async (input) => {
193
+ const result = await apiRequest('/api/projects', { method: 'POST', body: JSON.stringify(input) });
194
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
195
+ });
196
+
197
+ server.tool('list_projects', 'Lista projetos', {
198
+ limit: z.string().optional(),
199
+ }, async (input) => {
200
+ const params = new URLSearchParams();
201
+ if (input.limit) params.set('limit', input.limit);
202
+ const result = await apiRequest(`/api/projects?${params}`);
203
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
204
+ });
205
+
206
+ server.tool('get_project', 'Detalhes de um projeto', {
207
+ project_id: z.string().describe('ID do projeto'),
208
+ }, async (input) => {
209
+ const result = await apiRequest(`/api/projects/${input.project_id}`);
210
+ return { content: [{ type: 'text', text: JSON.stringify(result, null, 2) }] };
211
+ });
212
+
213
+ // ── Start ──
214
+
215
+ async function main() {
216
+ const transport = new StdioServerTransport();
217
+ await server.connect(transport);
218
+ }
219
+
220
+ main().catch((err) => {
221
+ console.error('MCP server error:', err);
222
+ process.exit(1);
223
+ });
package/package.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "name": "openhive-mcp-server",
3
+ "version": "1.0.0",
4
+ "description": "OpenHive AI MCP Server - Connect Claude, Antigravity, Cursor and other IDEs to your OpenHive instance",
5
+ "main": "index.js",
6
+ "bin": {
7
+ "openhive-mcp": "./index.js"
8
+ },
9
+ "keywords": ["mcp", "openhive", "claude", "antigravity", "ai", "social-media", "instagram"],
10
+ "license": "AGPL-3.0",
11
+ "author": "OpenHive",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/NetoNetoArreche/Projeto-Hive"
15
+ },
16
+ "dependencies": {
17
+ "@modelcontextprotocol/sdk": "^1.0.0"
18
+ }
19
+ }