@formmy.app/mcp-server 0.3.0 → 0.4.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.
@@ -33,5 +33,22 @@ export declare function listConversationEstados(agentId: string): Promise<unknow
33
33
  export declare function setConversationStatus(conversationId: string, label: string, color: string): Promise<unknown>;
34
34
  export declare function addConversationTag(conversationId: string, label: string, color: string, comment?: string): Promise<unknown>;
35
35
  export declare function removeConversationTag(conversationId: string, tagLabel: string): Promise<unknown>;
36
+ export declare function createOrder(conversationId: string, data: {
37
+ folio?: string;
38
+ cliente?: string;
39
+ tel?: string;
40
+ total?: number;
41
+ estatus?: string;
42
+ status?: "ABIERTA" | "CERRADA";
43
+ notas?: string;
44
+ cotizacionUrl?: string;
45
+ direccionEntrega?: {
46
+ label?: string;
47
+ direccion?: string;
48
+ cp?: string;
49
+ ciudad?: string;
50
+ mapsUrl?: string;
51
+ };
52
+ }): Promise<unknown>;
36
53
  export declare function shareAgent(agentId: string, email: string, role?: string): Promise<unknown>;
37
54
  export declare function connectIntegration(agentId: string, integration: string, config: Record<string, string>): Promise<unknown>;
@@ -162,6 +162,9 @@ export async function addConversationTag(conversationId, label, color, comment)
162
162
  export async function removeConversationTag(conversationId, tagLabel) {
163
163
  return bridgeFetch("remove_tag", { conversationId, tagLabel });
164
164
  }
165
+ export async function createOrder(conversationId, data) {
166
+ return bridgeFetch("create_order", { conversationId, ...data });
167
+ }
165
168
  // --- Sharing ---
166
169
  export async function shareAgent(agentId, email, role) {
167
170
  return sdkFetch("agents.share", {
@@ -43,4 +43,40 @@ export function registerConversationTools(server) {
43
43
  const result = await sdk.removeConversationTag(conversationId, tagLabel);
44
44
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
45
45
  });
46
+ server.tool("create_order", "Record an order (cotización/pedido) for a conversation in Formmy, mirroring what is sent to Kommo. It shows in the contact panel's Órdenes accordion, moves the kanban card when `estatus` matches a CRM estado (call list_conversation_estados first), and bumps the conversation to the top. Does NOT replace the Kommo push — call it IN ADDITION. Use when an order/quote is confirmed or its status changes; only the most recent order drives the card and the board value.", {
47
+ conversationId: z.string().describe("Conversation ID"),
48
+ folio: z.string().optional().describe("Order folio/number, e.g. '260521-007'"),
49
+ cliente: z.string().optional().describe("Customer name"),
50
+ tel: z.string().optional().describe("Contact phone"),
51
+ total: z
52
+ .number()
53
+ .optional()
54
+ .describe("Order total / budget as a number, e.g. 783"),
55
+ estatus: z
56
+ .string()
57
+ .optional()
58
+ .describe("Free-form status; match a CRM estado label (list_conversation_estados) so the card moves to that column, e.g. 'Pago a contra entrega'"),
59
+ status: z
60
+ .enum(["ABIERTA", "CERRADA"])
61
+ .optional()
62
+ .describe("Order lifecycle (default ABIERTA). Use CERRADA when delivered/closed."),
63
+ notas: z.string().optional().describe("Special instructions / internal notes"),
64
+ cotizacionUrl: z
65
+ .string()
66
+ .optional()
67
+ .describe("URL to the quote PDF deployed on EasyBits"),
68
+ direccionEntrega: z
69
+ .object({
70
+ label: z.string().optional(),
71
+ direccion: z.string().optional(),
72
+ cp: z.string().optional(),
73
+ ciudad: z.string().optional(),
74
+ mapsUrl: z.string().optional(),
75
+ })
76
+ .optional()
77
+ .describe("Delivery address snapshot { label, direccion, cp, ciudad, mapsUrl }"),
78
+ }, async ({ conversationId, ...data }) => {
79
+ const result = await sdk.createOrder(conversationId, data);
80
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
81
+ });
46
82
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formmy.app/mcp-server",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "MCP server for managing Formmy agents via Claude Code",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
package/src/sdk-client.ts CHANGED
@@ -196,7 +196,7 @@ export async function listConversationEstados(agentId: string) {
196
196
  const BRIDGE_SECRET = process.env.NANOCLAW_WEBHOOK_SECRET || "";
197
197
 
198
198
  async function bridgeFetch(
199
- intent: "set_estado" | "add_tag" | "remove_tag",
199
+ intent: "set_estado" | "add_tag" | "remove_tag" | "create_order",
200
200
  body: Record<string, unknown>,
201
201
  ): Promise<unknown> {
202
202
  if (!BRIDGE_SECRET) {
@@ -244,6 +244,29 @@ export async function removeConversationTag(
244
244
  return bridgeFetch("remove_tag", { conversationId, tagLabel });
245
245
  }
246
246
 
247
+ export async function createOrder(
248
+ conversationId: string,
249
+ data: {
250
+ folio?: string;
251
+ cliente?: string;
252
+ tel?: string;
253
+ total?: number;
254
+ estatus?: string;
255
+ status?: "ABIERTA" | "CERRADA";
256
+ notas?: string;
257
+ cotizacionUrl?: string;
258
+ direccionEntrega?: {
259
+ label?: string;
260
+ direccion?: string;
261
+ cp?: string;
262
+ ciudad?: string;
263
+ mapsUrl?: string;
264
+ };
265
+ },
266
+ ) {
267
+ return bridgeFetch("create_order", { conversationId, ...data });
268
+ }
269
+
247
270
  // --- Sharing ---
248
271
 
249
272
  export async function shareAgent(
@@ -80,4 +80,48 @@ export function registerConversationTools(server: McpServer) {
80
80
  return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
81
81
  }
82
82
  );
83
+
84
+ server.tool(
85
+ "create_order",
86
+ "Record an order (cotización/pedido) for a conversation in Formmy, mirroring what is sent to Kommo. It shows in the contact panel's Órdenes accordion, moves the kanban card when `estatus` matches a CRM estado (call list_conversation_estados first), and bumps the conversation to the top. Does NOT replace the Kommo push — call it IN ADDITION. Use when an order/quote is confirmed or its status changes; only the most recent order drives the card and the board value.",
87
+ {
88
+ conversationId: z.string().describe("Conversation ID"),
89
+ folio: z.string().optional().describe("Order folio/number, e.g. '260521-007'"),
90
+ cliente: z.string().optional().describe("Customer name"),
91
+ tel: z.string().optional().describe("Contact phone"),
92
+ total: z
93
+ .number()
94
+ .optional()
95
+ .describe("Order total / budget as a number, e.g. 783"),
96
+ estatus: z
97
+ .string()
98
+ .optional()
99
+ .describe(
100
+ "Free-form status; match a CRM estado label (list_conversation_estados) so the card moves to that column, e.g. 'Pago a contra entrega'",
101
+ ),
102
+ status: z
103
+ .enum(["ABIERTA", "CERRADA"])
104
+ .optional()
105
+ .describe("Order lifecycle (default ABIERTA). Use CERRADA when delivered/closed."),
106
+ notas: z.string().optional().describe("Special instructions / internal notes"),
107
+ cotizacionUrl: z
108
+ .string()
109
+ .optional()
110
+ .describe("URL to the quote PDF deployed on EasyBits"),
111
+ direccionEntrega: z
112
+ .object({
113
+ label: z.string().optional(),
114
+ direccion: z.string().optional(),
115
+ cp: z.string().optional(),
116
+ ciudad: z.string().optional(),
117
+ mapsUrl: z.string().optional(),
118
+ })
119
+ .optional()
120
+ .describe("Delivery address snapshot { label, direccion, cp, ciudad, mapsUrl }"),
121
+ },
122
+ async ({ conversationId, ...data }) => {
123
+ const result = await sdk.createOrder(conversationId, data);
124
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
125
+ }
126
+ );
83
127
  }