@denik.me/mcp 0.1.0 → 0.3.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/dist/client.d.ts CHANGED
@@ -1 +1,2 @@
1
1
  export declare function denikGet<T = unknown>(path: string, params?: Record<string, string | number | boolean | undefined>): Promise<T>;
2
+ export declare function denikPost<T = unknown>(path: string, body: Record<string, any>): Promise<T>;
package/dist/client.js CHANGED
@@ -26,3 +26,22 @@ export async function denikGet(path, params = {}) {
26
26
  }
27
27
  return res.json();
28
28
  }
29
+ export async function denikPost(path, body) {
30
+ if (!API_KEY)
31
+ throw new Error("DENIK_API_KEY env var is required");
32
+ const url = new URL(`/api/mcp/${path}`, BASE_URL);
33
+ const res = await fetch(url, {
34
+ method: "POST",
35
+ headers: {
36
+ "X-Denik-Api-Key": API_KEY,
37
+ "Content-Type": "application/json",
38
+ Accept: "application/json",
39
+ },
40
+ body: JSON.stringify(body),
41
+ });
42
+ if (!res.ok) {
43
+ const text = await res.text();
44
+ throw new Error(`Denik API ${res.status}: ${text}`);
45
+ }
46
+ return res.json();
47
+ }
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { Server } from "@modelcontextprotocol/sdk/server/index.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
4
  import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
5
- import { denikGet } from "./client.js";
5
+ import { denikGet, denikPost } from "./client.js";
6
6
  const server = new Server({ name: "denik-mcp", version: "0.1.0" }, { capabilities: { tools: {} } });
7
7
  // ==================== Tool definitions ====================
8
8
  const tools = [
@@ -85,6 +85,121 @@ const tools = [
85
85
  inputSchema: { type: "object", properties: {} },
86
86
  handler: async () => denikGet("org", { intent: "today" }),
87
87
  },
88
+ // ==================== Mutations (Phase 2) ====================
89
+ {
90
+ name: "cancel_event",
91
+ description: "Cancela una cita (borra Meet/Zoom, jobs, marca CANCELLED).",
92
+ inputSchema: {
93
+ type: "object",
94
+ required: ["eventId"],
95
+ properties: { eventId: { type: "string" } },
96
+ },
97
+ handler: async (args) => denikPost("events", { intent: "cancel", eventId: args.eventId }),
98
+ },
99
+ {
100
+ name: "reschedule_event",
101
+ description: "Mueve una cita a un nuevo horario. Si no se pasa `end`, mantiene la duración original.",
102
+ inputSchema: {
103
+ type: "object",
104
+ required: ["eventId", "start"],
105
+ properties: {
106
+ eventId: { type: "string" },
107
+ start: { type: "string", description: "Nuevo inicio ISO" },
108
+ end: { type: "string", description: "Nuevo fin ISO (opcional)" },
109
+ },
110
+ },
111
+ handler: async (args) => denikPost("events", { intent: "reschedule", ...args }),
112
+ },
113
+ {
114
+ name: "mark_attendance",
115
+ description: "Marca si el cliente asistió a la cita (true/false) o limpia (null).",
116
+ inputSchema: {
117
+ type: "object",
118
+ required: ["eventId", "attended"],
119
+ properties: {
120
+ eventId: { type: "string" },
121
+ attended: { type: ["boolean", "null"] },
122
+ },
123
+ },
124
+ handler: async (args) => denikPost("events", { intent: "mark_attendance", ...args }),
125
+ },
126
+ {
127
+ name: "create_event",
128
+ description: "Agenda una cita manual. Requiere serviceId, customerId, start ISO.",
129
+ inputSchema: {
130
+ type: "object",
131
+ required: ["serviceId", "customerId", "start"],
132
+ properties: {
133
+ serviceId: { type: "string" },
134
+ customerId: { type: "string" },
135
+ start: { type: "string" },
136
+ notes: { type: "string" },
137
+ },
138
+ },
139
+ handler: async (args) => denikPost("events", { intent: "create", ...args }),
140
+ },
141
+ {
142
+ name: "create_customer",
143
+ description: "Da de alta un cliente nuevo en la org. Si ya existe uno con ese email, devuelve el existente.",
144
+ inputSchema: {
145
+ type: "object",
146
+ required: ["displayName"],
147
+ properties: {
148
+ displayName: { type: "string" },
149
+ email: { type: "string" },
150
+ tel: { type: "string" },
151
+ notes: { type: "string" },
152
+ },
153
+ },
154
+ handler: async (args) => denikPost("customers", { intent: "create", ...args }),
155
+ },
156
+ {
157
+ name: "send_appointment_reminder",
158
+ description: "Envía email de recordatorio manual al cliente de una cita.",
159
+ inputSchema: {
160
+ type: "object",
161
+ required: ["eventId"],
162
+ properties: { eventId: { type: "string" } },
163
+ },
164
+ handler: async (args) => denikPost("events", { intent: "send_reminder", eventId: args.eventId }),
165
+ },
166
+ // ==================== Landing (Phase 3) ====================
167
+ {
168
+ name: "get_landing",
169
+ description: "Devuelve las secciones actuales de la landing de la org (id, label, tipo, preview). Útil antes de editar.",
170
+ inputSchema: {
171
+ type: "object",
172
+ properties: {
173
+ includeHtml: {
174
+ type: "boolean",
175
+ description: "true para devolver HTML completo (muy verboso). Default false.",
176
+ },
177
+ },
178
+ },
179
+ handler: async (args) => denikGet("landing", { intent: "get", includeHtml: args.includeHtml }),
180
+ },
181
+ {
182
+ name: "refine_landing_section",
183
+ description: "Modifica una sección de la landing con una instrucción en lenguaje natural (ej: 'hazla más formal', 'añade testimonios', 'cambia el copy del CTA a NAVIDAD2026').",
184
+ inputSchema: {
185
+ type: "object",
186
+ required: ["sectionId", "instruction"],
187
+ properties: {
188
+ sectionId: { type: "string" },
189
+ instruction: { type: "string" },
190
+ },
191
+ },
192
+ handler: async (args) => denikPost("landing", { intent: "refine_section", ...args }),
193
+ },
194
+ {
195
+ name: "publish_landing",
196
+ description: "Publica (o despublica con published=false) la landing de la org.",
197
+ inputSchema: {
198
+ type: "object",
199
+ properties: { published: { type: "boolean", default: true } },
200
+ },
201
+ handler: async (args) => denikPost("landing", { intent: "publish", ...args }),
202
+ },
88
203
  {
89
204
  name: "get_org_stats",
90
205
  description: "Estadísticas de la org en un rango custom (from/to ISO).",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@denik.me/mcp",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "description": "Denik Agenda MCP stdio server — tools para operar una org desde un agente (p.ej. bot de WhatsApp).",
5
5
  "type": "module",
6
6
  "bin": {