@denik.me/mcp 0.1.0 → 0.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.
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,84 @@ 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
+ },
88
166
  {
89
167
  name: "get_org_stats",
90
168
  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.2.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": {