@frihet/mcp-server 1.3.2 → 1.5.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 +94 -18
- package/dist/client-interface.d.ts +57 -0
- package/dist/client-interface.d.ts.map +1 -1
- package/dist/client.d.ts +57 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +115 -0
- package/dist/client.js.map +1 -1
- package/dist/index.js +10 -9
- package/dist/index.js.map +1 -1
- package/dist/prompts/register-all.d.ts.map +1 -1
- package/dist/prompts/register-all.js +305 -0
- package/dist/prompts/register-all.js.map +1 -1
- package/dist/resources/register-all.d.ts +6 -4
- package/dist/resources/register-all.d.ts.map +1 -1
- package/dist/resources/register-all.js +221 -10
- package/dist/resources/register-all.js.map +1 -1
- package/dist/tools/clients.d.ts.map +1 -1
- package/dist/tools/clients.js +21 -4
- package/dist/tools/clients.js.map +1 -1
- package/dist/tools/crm.d.ts +9 -0
- package/dist/tools/crm.d.ts.map +1 -0
- package/dist/tools/crm.js +181 -0
- package/dist/tools/crm.js.map +1 -0
- package/dist/tools/expenses.d.ts.map +1 -1
- package/dist/tools/expenses.js +25 -6
- package/dist/tools/expenses.js.map +1 -1
- package/dist/tools/intelligence.d.ts +15 -0
- package/dist/tools/intelligence.d.ts.map +1 -0
- package/dist/tools/intelligence.js +127 -0
- package/dist/tools/intelligence.js.map +1 -0
- package/dist/tools/invoices.d.ts.map +1 -1
- package/dist/tools/invoices.js +94 -10
- package/dist/tools/invoices.js.map +1 -1
- package/dist/tools/products.d.ts.map +1 -1
- package/dist/tools/products.js +18 -2
- package/dist/tools/products.js.map +1 -1
- package/dist/tools/quotes.d.ts.map +1 -1
- package/dist/tools/quotes.js +40 -4
- package/dist/tools/quotes.js.map +1 -1
- package/dist/tools/register-all.d.ts +1 -1
- package/dist/tools/register-all.d.ts.map +1 -1
- package/dist/tools/register-all.js +7 -1
- package/dist/tools/register-all.js.map +1 -1
- package/dist/tools/shared.d.ts +62 -0
- package/dist/tools/shared.d.ts.map +1 -1
- package/dist/tools/shared.js +140 -1
- package/dist/tools/shared.js.map +1 -1
- package/dist/tools/vendors.d.ts +7 -0
- package/dist/tools/vendors.d.ts.map +1 -0
- package/dist/tools/vendors.js +125 -0
- package/dist/tools/vendors.js.map +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/scripts/postinstall.js +1 -1
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CRM subcollection tools for the Frihet MCP server.
|
|
3
|
+
*
|
|
4
|
+
* Contacts, activities, and notes — all scoped under a client.
|
|
5
|
+
*/
|
|
6
|
+
import { z } from "zod/v4";
|
|
7
|
+
import { withToolLogging, formatPaginatedResponse, formatRecord, listContent, mutateContent, enrichResponse, READ_ONLY_ANNOTATIONS, CREATE_ANNOTATIONS, DELETE_ANNOTATIONS, paginatedOutput, deleteResultOutput, contactItemOutput, activityItemOutput, noteItemOutput, } from "./shared.js";
|
|
8
|
+
export function registerCrmTools(server, client) {
|
|
9
|
+
// ================================================================
|
|
10
|
+
// Contacts
|
|
11
|
+
// ================================================================
|
|
12
|
+
// -- list_client_contacts --
|
|
13
|
+
server.registerTool("list_client_contacts", {
|
|
14
|
+
title: "List Client Contacts",
|
|
15
|
+
description: "List all contacts for a client with optional pagination. " +
|
|
16
|
+
"Returns name, email, phone, role, and primary flag. " +
|
|
17
|
+
"/ Lista todos los contactos de un cliente con paginacion opcional.",
|
|
18
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
19
|
+
inputSchema: {
|
|
20
|
+
clientId: z.string().describe("Client ID / ID del cliente"),
|
|
21
|
+
limit: z.number().int().min(1).max(100).optional().describe("Max results (1-100) / Resultados maximos"),
|
|
22
|
+
offset: z.number().int().min(0).optional().describe("Offset / Desplazamiento"),
|
|
23
|
+
},
|
|
24
|
+
outputSchema: paginatedOutput(contactItemOutput),
|
|
25
|
+
}, async ({ clientId, limit, offset }) => withToolLogging("list_client_contacts", async () => {
|
|
26
|
+
const result = await client.listClientContacts(clientId, { limit, offset });
|
|
27
|
+
return {
|
|
28
|
+
content: [listContent(formatPaginatedResponse("contacts", result))],
|
|
29
|
+
structuredContent: result,
|
|
30
|
+
};
|
|
31
|
+
}));
|
|
32
|
+
// -- create_client_contact --
|
|
33
|
+
server.registerTool("create_client_contact", {
|
|
34
|
+
title: "Create Client Contact",
|
|
35
|
+
description: "Add a new contact person to a client. Requires a name at minimum. " +
|
|
36
|
+
"Example: clientId='abc123', name='Ana Garcia', email='ana@acme.com', role='CTO', isPrimary=true " +
|
|
37
|
+
"/ Anade un nuevo contacto a un cliente. Requiere al menos un nombre.",
|
|
38
|
+
annotations: CREATE_ANNOTATIONS,
|
|
39
|
+
inputSchema: {
|
|
40
|
+
clientId: z.string().describe("Client ID / ID del cliente"),
|
|
41
|
+
name: z.string().describe("Contact name / Nombre del contacto"),
|
|
42
|
+
email: z.string().optional().describe("Email address / Correo electronico"),
|
|
43
|
+
phone: z.string().optional().describe("Phone number / Telefono"),
|
|
44
|
+
role: z.string().optional().describe("Role or title (e.g. CEO, CTO, Billing) / Cargo o rol"),
|
|
45
|
+
isPrimary: z.boolean().optional().describe("Whether this is the primary contact / Si es el contacto principal"),
|
|
46
|
+
},
|
|
47
|
+
outputSchema: contactItemOutput,
|
|
48
|
+
}, async ({ clientId, ...data }) => withToolLogging("create_client_contact", async () => {
|
|
49
|
+
const result = await client.createClientContact(clientId, data);
|
|
50
|
+
const hints = enrichResponse("contacts", "create", result);
|
|
51
|
+
return {
|
|
52
|
+
content: [mutateContent(formatRecord("Contact created", result))],
|
|
53
|
+
structuredContent: { ...result, ...hints },
|
|
54
|
+
};
|
|
55
|
+
}));
|
|
56
|
+
// -- delete_client_contact --
|
|
57
|
+
server.registerTool("delete_client_contact", {
|
|
58
|
+
title: "Delete Client Contact",
|
|
59
|
+
description: "Permanently delete a contact from a client. This action cannot be undone. " +
|
|
60
|
+
"/ Elimina permanentemente un contacto de un cliente. Esta accion no se puede deshacer.",
|
|
61
|
+
annotations: DELETE_ANNOTATIONS,
|
|
62
|
+
inputSchema: {
|
|
63
|
+
clientId: z.string().describe("Client ID / ID del cliente"),
|
|
64
|
+
contactId: z.string().describe("Contact ID / ID del contacto"),
|
|
65
|
+
},
|
|
66
|
+
outputSchema: deleteResultOutput,
|
|
67
|
+
}, async ({ clientId, contactId }) => withToolLogging("delete_client_contact", async () => {
|
|
68
|
+
await client.deleteClientContact(clientId, contactId);
|
|
69
|
+
return {
|
|
70
|
+
content: [mutateContent(`Contact ${contactId} deleted from client ${clientId}. / Contacto ${contactId} eliminado del cliente ${clientId}.`)],
|
|
71
|
+
structuredContent: { success: true, id: contactId },
|
|
72
|
+
};
|
|
73
|
+
}));
|
|
74
|
+
// ================================================================
|
|
75
|
+
// Activities
|
|
76
|
+
// ================================================================
|
|
77
|
+
// -- list_client_activities --
|
|
78
|
+
server.registerTool("list_client_activities", {
|
|
79
|
+
title: "List Client Activities",
|
|
80
|
+
description: "List all CRM activities for a client with optional pagination. " +
|
|
81
|
+
"Returns calls, emails, meetings, and tasks logged against the client. " +
|
|
82
|
+
"/ Lista todas las actividades CRM de un cliente con paginacion opcional.",
|
|
83
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
84
|
+
inputSchema: {
|
|
85
|
+
clientId: z.string().describe("Client ID / ID del cliente"),
|
|
86
|
+
limit: z.number().int().min(1).max(100).optional().describe("Max results (1-100) / Resultados maximos"),
|
|
87
|
+
offset: z.number().int().min(0).optional().describe("Offset / Desplazamiento"),
|
|
88
|
+
},
|
|
89
|
+
outputSchema: paginatedOutput(activityItemOutput),
|
|
90
|
+
}, async ({ clientId, limit, offset }) => withToolLogging("list_client_activities", async () => {
|
|
91
|
+
const result = await client.listClientActivities(clientId, { limit, offset });
|
|
92
|
+
return {
|
|
93
|
+
content: [listContent(formatPaginatedResponse("activities", result))],
|
|
94
|
+
structuredContent: result,
|
|
95
|
+
};
|
|
96
|
+
}));
|
|
97
|
+
// -- log_client_activity --
|
|
98
|
+
server.registerTool("log_client_activity", {
|
|
99
|
+
title: "Log Client Activity",
|
|
100
|
+
description: "Log a CRM activity against a client. Use to track calls, emails, meetings, or tasks. " +
|
|
101
|
+
"Example: clientId='abc123', type='call', title='Discussed Q2 proposal', description='Client interested in upgrade' " +
|
|
102
|
+
"/ Registra una actividad CRM para un cliente. Usa para rastrear llamadas, emails, reuniones o tareas.",
|
|
103
|
+
annotations: CREATE_ANNOTATIONS,
|
|
104
|
+
inputSchema: {
|
|
105
|
+
clientId: z.string().describe("Client ID / ID del cliente"),
|
|
106
|
+
type: z
|
|
107
|
+
.enum(["call", "email", "meeting", "task"])
|
|
108
|
+
.describe("Activity type / Tipo de actividad"),
|
|
109
|
+
title: z.string().describe("Activity title / Titulo de la actividad"),
|
|
110
|
+
description: z.string().optional().describe("Detailed description / Descripcion detallada"),
|
|
111
|
+
date: z.string().optional().describe("Activity date (ISO 8601, defaults to now) / Fecha de la actividad"),
|
|
112
|
+
},
|
|
113
|
+
outputSchema: activityItemOutput,
|
|
114
|
+
}, async ({ clientId, ...data }) => withToolLogging("log_client_activity", async () => {
|
|
115
|
+
const result = await client.logClientActivity(clientId, data);
|
|
116
|
+
return {
|
|
117
|
+
content: [mutateContent(formatRecord("Activity logged", result))],
|
|
118
|
+
structuredContent: result,
|
|
119
|
+
};
|
|
120
|
+
}));
|
|
121
|
+
// ================================================================
|
|
122
|
+
// Notes
|
|
123
|
+
// ================================================================
|
|
124
|
+
// -- list_client_notes --
|
|
125
|
+
server.registerTool("list_client_notes", {
|
|
126
|
+
title: "List Client Notes",
|
|
127
|
+
description: "List all notes for a client with optional pagination. " +
|
|
128
|
+
"/ Lista todas las notas de un cliente con paginacion opcional.",
|
|
129
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
130
|
+
inputSchema: {
|
|
131
|
+
clientId: z.string().describe("Client ID / ID del cliente"),
|
|
132
|
+
limit: z.number().int().min(1).max(100).optional().describe("Max results (1-100) / Resultados maximos"),
|
|
133
|
+
offset: z.number().int().min(0).optional().describe("Offset / Desplazamiento"),
|
|
134
|
+
},
|
|
135
|
+
outputSchema: paginatedOutput(noteItemOutput),
|
|
136
|
+
}, async ({ clientId, limit, offset }) => withToolLogging("list_client_notes", async () => {
|
|
137
|
+
const result = await client.listClientNotes(clientId, { limit, offset });
|
|
138
|
+
return {
|
|
139
|
+
content: [listContent(formatPaginatedResponse("notes", result))],
|
|
140
|
+
structuredContent: result,
|
|
141
|
+
};
|
|
142
|
+
}));
|
|
143
|
+
// -- create_client_note --
|
|
144
|
+
server.registerTool("create_client_note", {
|
|
145
|
+
title: "Create Client Note",
|
|
146
|
+
description: "Add a note to a client. Notes are free-form text entries useful for keeping context. " +
|
|
147
|
+
"Example: clientId='abc123', content='Prefers invoices in English. Payment NET 30.' " +
|
|
148
|
+
"/ Anade una nota a un cliente. Las notas son texto libre para mantener contexto.",
|
|
149
|
+
annotations: CREATE_ANNOTATIONS,
|
|
150
|
+
inputSchema: {
|
|
151
|
+
clientId: z.string().describe("Client ID / ID del cliente"),
|
|
152
|
+
content: z.string().describe("Note content / Contenido de la nota"),
|
|
153
|
+
},
|
|
154
|
+
outputSchema: noteItemOutput,
|
|
155
|
+
}, async ({ clientId, content }) => withToolLogging("create_client_note", async () => {
|
|
156
|
+
const result = await client.createClientNote(clientId, { content });
|
|
157
|
+
return {
|
|
158
|
+
content: [mutateContent(formatRecord("Note created", result))],
|
|
159
|
+
structuredContent: result,
|
|
160
|
+
};
|
|
161
|
+
}));
|
|
162
|
+
// -- delete_client_note --
|
|
163
|
+
server.registerTool("delete_client_note", {
|
|
164
|
+
title: "Delete Client Note",
|
|
165
|
+
description: "Permanently delete a note from a client. This action cannot be undone. " +
|
|
166
|
+
"/ Elimina permanentemente una nota de un cliente. Esta accion no se puede deshacer.",
|
|
167
|
+
annotations: DELETE_ANNOTATIONS,
|
|
168
|
+
inputSchema: {
|
|
169
|
+
clientId: z.string().describe("Client ID / ID del cliente"),
|
|
170
|
+
noteId: z.string().describe("Note ID / ID de la nota"),
|
|
171
|
+
},
|
|
172
|
+
outputSchema: deleteResultOutput,
|
|
173
|
+
}, async ({ clientId, noteId }) => withToolLogging("delete_client_note", async () => {
|
|
174
|
+
await client.deleteClientNote(clientId, noteId);
|
|
175
|
+
return {
|
|
176
|
+
content: [mutateContent(`Note ${noteId} deleted from client ${clientId}. / Nota ${noteId} eliminada del cliente ${clientId}.`)],
|
|
177
|
+
structuredContent: { success: true, id: noteId },
|
|
178
|
+
};
|
|
179
|
+
}));
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=crm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crm.js","sourceRoot":"","sources":["../../src/tools/crm.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expenses.d.ts","sourceRoot":"","sources":["../../src/tools/expenses.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAG5D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"expenses.d.ts","sourceRoot":"","sources":["../../src/tools/expenses.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAG5D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CA8KnF"}
|
package/dist/tools/expenses.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Expense tools for the Frihet MCP server.
|
|
3
3
|
*/
|
|
4
4
|
import { z } from "zod/v4";
|
|
5
|
-
import { withToolLogging, formatPaginatedResponse, formatRecord, listContent, getContent, mutateContent, READ_ONLY_ANNOTATIONS, CREATE_ANNOTATIONS, UPDATE_ANNOTATIONS, DELETE_ANNOTATIONS, paginatedOutput, deleteResultOutput, expenseItemOutput } from "./shared.js";
|
|
5
|
+
import { withToolLogging, formatPaginatedResponse, formatRecord, listContent, getContent, mutateContent, enrichResponse, READ_ONLY_ANNOTATIONS, CREATE_ANNOTATIONS, UPDATE_ANNOTATIONS, DELETE_ANNOTATIONS, paginatedOutput, deleteResultOutput, expenseItemOutput } from "./shared.js";
|
|
6
6
|
export function registerExpenseTools(server, client) {
|
|
7
7
|
// -- list_expenses --
|
|
8
8
|
server.registerTool("list_expenses", {
|
|
@@ -13,6 +13,14 @@ export function registerExpenseTools(server, client) {
|
|
|
13
13
|
"/ Lista todos los gastos con paginacion y filtros de fecha opcionales.",
|
|
14
14
|
annotations: READ_ONLY_ANNOTATIONS,
|
|
15
15
|
inputSchema: {
|
|
16
|
+
vendorId: z
|
|
17
|
+
.string()
|
|
18
|
+
.optional()
|
|
19
|
+
.describe("Filter by vendor ID / Filtrar por ID de proveedor"),
|
|
20
|
+
category: z
|
|
21
|
+
.string()
|
|
22
|
+
.optional()
|
|
23
|
+
.describe("Filter by expense category (e.g. 'office', 'travel') / Filtrar por categoria"),
|
|
16
24
|
from: z
|
|
17
25
|
.string()
|
|
18
26
|
.optional()
|
|
@@ -21,15 +29,24 @@ export function registerExpenseTools(server, client) {
|
|
|
21
29
|
.string()
|
|
22
30
|
.optional()
|
|
23
31
|
.describe("End date filter (YYYY-MM-DD) / Fecha fin"),
|
|
32
|
+
fields: z
|
|
33
|
+
.string()
|
|
34
|
+
.optional()
|
|
35
|
+
.describe("Comma-separated field names to return (e.g. 'id,description,amount') / Campos a devolver"),
|
|
24
36
|
limit: z.number().int().min(1).max(100).optional().describe("Max results (1-100) / Resultados maximos"),
|
|
25
37
|
offset: z.number().int().min(0).optional().describe("Offset / Desplazamiento"),
|
|
38
|
+
after: z
|
|
39
|
+
.string()
|
|
40
|
+
.optional()
|
|
41
|
+
.describe("Cursor for cursor-based pagination (document ID) / Cursor para paginacion basada en cursor"),
|
|
26
42
|
},
|
|
27
43
|
outputSchema: paginatedOutput(expenseItemOutput),
|
|
28
|
-
}, async ({ from, to, limit, offset }) => withToolLogging("list_expenses", async () => {
|
|
29
|
-
const result = await client.listExpenses({ limit, offset, from, to });
|
|
44
|
+
}, async ({ from, to, limit, offset, vendorId, category, fields, after }) => withToolLogging("list_expenses", async () => {
|
|
45
|
+
const result = await client.listExpenses({ limit, offset, after, fields, from, to, vendorId, category });
|
|
46
|
+
const hints = enrichResponse("expenses", "list", result.data);
|
|
30
47
|
return {
|
|
31
48
|
content: [listContent(formatPaginatedResponse("expenses", result))],
|
|
32
|
-
structuredContent: result,
|
|
49
|
+
structuredContent: { ...result, ...hints },
|
|
33
50
|
};
|
|
34
51
|
}));
|
|
35
52
|
// -- get_expense --
|
|
@@ -78,9 +95,10 @@ export function registerExpenseTools(server, client) {
|
|
|
78
95
|
outputSchema: expenseItemOutput,
|
|
79
96
|
}, async (input) => withToolLogging("create_expense", async () => {
|
|
80
97
|
const result = await client.createExpense(input);
|
|
98
|
+
const hints = enrichResponse("expenses", "create", result);
|
|
81
99
|
return {
|
|
82
100
|
content: [mutateContent(formatRecord("Expense created", result))],
|
|
83
|
-
structuredContent: result,
|
|
101
|
+
structuredContent: { ...result, ...hints },
|
|
84
102
|
};
|
|
85
103
|
}));
|
|
86
104
|
// -- update_expense --
|
|
@@ -119,9 +137,10 @@ export function registerExpenseTools(server, client) {
|
|
|
119
137
|
outputSchema: deleteResultOutput,
|
|
120
138
|
}, async ({ id }) => withToolLogging("delete_expense", async () => {
|
|
121
139
|
await client.deleteExpense(id);
|
|
140
|
+
const hints = enrichResponse("expenses", "delete", { id });
|
|
122
141
|
return {
|
|
123
142
|
content: [mutateContent(`Expense ${id} deleted successfully. / Gasto ${id} eliminado correctamente.`)],
|
|
124
|
-
structuredContent: { success: true, id },
|
|
143
|
+
structuredContent: { success: true, id, ...hints },
|
|
125
144
|
};
|
|
126
145
|
}));
|
|
127
146
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expenses.js","sourceRoot":"","sources":["../../src/tools/expenses.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,eAAe,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"expenses.js","sourceRoot":"","sources":["../../src/tools/expenses.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intelligence tools for the Frihet MCP server.
|
|
3
|
+
*
|
|
4
|
+
* These tools go beyond CRUD — they provide contextual business intelligence
|
|
5
|
+
* that helps AI agents understand the user's business at a glance.
|
|
6
|
+
*
|
|
7
|
+
* - get_business_context: Full business snapshot (call FIRST in any session)
|
|
8
|
+
* - get_monthly_summary: Monthly P&L and invoice stats
|
|
9
|
+
* - get_quarterly_taxes: Tax prep data for Modelo 303/130
|
|
10
|
+
* - duplicate_invoice: Clone an invoice for a new period
|
|
11
|
+
*/
|
|
12
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
13
|
+
import type { IFrihetClient } from "../client-interface.js";
|
|
14
|
+
export declare function registerIntelligenceTools(server: McpServer, client: IFrihetClient): void;
|
|
15
|
+
//# sourceMappingURL=intelligence.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intelligence.d.ts","sourceRoot":"","sources":["../../src/tools/intelligence.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAU5D,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CA6JxF"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Intelligence tools for the Frihet MCP server.
|
|
3
|
+
*
|
|
4
|
+
* These tools go beyond CRUD — they provide contextual business intelligence
|
|
5
|
+
* that helps AI agents understand the user's business at a glance.
|
|
6
|
+
*
|
|
7
|
+
* - get_business_context: Full business snapshot (call FIRST in any session)
|
|
8
|
+
* - get_monthly_summary: Monthly P&L and invoice stats
|
|
9
|
+
* - get_quarterly_taxes: Tax prep data for Modelo 303/130
|
|
10
|
+
* - duplicate_invoice: Clone an invoice for a new period
|
|
11
|
+
*/
|
|
12
|
+
import { z } from "zod/v4";
|
|
13
|
+
import { withToolLogging, formatRecord, getContent, mutateContent, READ_ONLY_ANNOTATIONS, CREATE_ANNOTATIONS, } from "./shared.js";
|
|
14
|
+
export function registerIntelligenceTools(server, client) {
|
|
15
|
+
// -- get_business_context --
|
|
16
|
+
server.registerTool("get_business_context", {
|
|
17
|
+
title: "Get Business Context",
|
|
18
|
+
description: "Get complete business context — profile, defaults, plan limits, recent activity, top clients, " +
|
|
19
|
+
"and current month summary. Call this FIRST in any session to understand the user's business. " +
|
|
20
|
+
"Returns everything an AI agent needs to provide personalized help without multiple round-trips. " +
|
|
21
|
+
"/ Obtiene el contexto completo del negocio — perfil, limites del plan, actividad reciente, " +
|
|
22
|
+
"principales clientes y resumen del mes actual. Llama a esto PRIMERO en cualquier sesion.",
|
|
23
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
24
|
+
inputSchema: {},
|
|
25
|
+
}, async () => withToolLogging("get_business_context", async () => {
|
|
26
|
+
const result = await client.getBusinessContext();
|
|
27
|
+
return {
|
|
28
|
+
content: [getContent(formatRecord("Business Context", result))],
|
|
29
|
+
structuredContent: result,
|
|
30
|
+
};
|
|
31
|
+
}));
|
|
32
|
+
// -- get_monthly_summary --
|
|
33
|
+
server.registerTool("get_monthly_summary", {
|
|
34
|
+
title: "Get Monthly Summary",
|
|
35
|
+
description: "Get complete monthly financial summary — revenue, expenses, profit, tax liability, " +
|
|
36
|
+
"invoice stats, expense breakdown by category. Defaults to current month. " +
|
|
37
|
+
"Use this to answer questions about financial performance, cash flow, or monthly P&L. " +
|
|
38
|
+
"/ Resumen financiero mensual completo — ingresos, gastos, beneficio, impuestos, " +
|
|
39
|
+
"estadisticas de facturas, desglose de gastos por categoria. Por defecto el mes actual.",
|
|
40
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
41
|
+
inputSchema: {
|
|
42
|
+
month: z
|
|
43
|
+
.string()
|
|
44
|
+
.optional()
|
|
45
|
+
.describe("Month in YYYY-MM format (defaults to current month). Example: '2026-03' " +
|
|
46
|
+
"/ Mes en formato YYYY-MM (por defecto el mes actual)"),
|
|
47
|
+
},
|
|
48
|
+
}, async ({ month }) => withToolLogging("get_monthly_summary", async () => {
|
|
49
|
+
const result = await client.getMonthlySummary(month);
|
|
50
|
+
const label = month ? `Monthly Summary (${month})` : "Monthly Summary (current month)";
|
|
51
|
+
return {
|
|
52
|
+
content: [getContent(formatRecord(label, result))],
|
|
53
|
+
structuredContent: result,
|
|
54
|
+
};
|
|
55
|
+
}));
|
|
56
|
+
// -- get_quarterly_taxes --
|
|
57
|
+
server.registerTool("get_quarterly_taxes", {
|
|
58
|
+
title: "Get Quarterly Taxes",
|
|
59
|
+
description: "Get quarterly tax preparation data — Modelo 303 (IVA/IGIC), Modelo 130 (IRPF income tax advance), " +
|
|
60
|
+
"revenue/expense totals, tax collected vs deductible. Defaults to current quarter. " +
|
|
61
|
+
"Essential for filing quarterly tax returns with AEAT or ATC (Canary Islands). " +
|
|
62
|
+
"/ Datos de preparacion de impuestos trimestrales — Modelo 303, Modelo 130, " +
|
|
63
|
+
"totales de ingresos/gastos, impuesto repercutido vs soportado. Por defecto trimestre actual.",
|
|
64
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
65
|
+
inputSchema: {
|
|
66
|
+
quarter: z
|
|
67
|
+
.string()
|
|
68
|
+
.optional()
|
|
69
|
+
.describe("Quarter in YYYY-Q# format (defaults to current quarter). Example: '2026-Q1' " +
|
|
70
|
+
"/ Trimestre en formato YYYY-Q# (por defecto trimestre actual)"),
|
|
71
|
+
},
|
|
72
|
+
}, async ({ quarter }) => withToolLogging("get_quarterly_taxes", async () => {
|
|
73
|
+
const result = await client.getQuarterlyTaxes(quarter);
|
|
74
|
+
const label = quarter ? `Quarterly Taxes (${quarter})` : "Quarterly Taxes (current quarter)";
|
|
75
|
+
return {
|
|
76
|
+
content: [getContent(formatRecord(label, result))],
|
|
77
|
+
structuredContent: result,
|
|
78
|
+
};
|
|
79
|
+
}));
|
|
80
|
+
// -- duplicate_invoice --
|
|
81
|
+
server.registerTool("duplicate_invoice", {
|
|
82
|
+
title: "Duplicate Invoice",
|
|
83
|
+
description: "Duplicate an existing invoice for a new period. Copies all line items, client data, tax rate, and notes. " +
|
|
84
|
+
"Strips the original ID, document number, status, and timestamps. " +
|
|
85
|
+
"The new invoice starts as 'draft' with today's date (or the provided date). " +
|
|
86
|
+
"Perfect for recurring invoices — duplicate last month's invoice and adjust if needed. " +
|
|
87
|
+
"/ Duplica una factura existente para un nuevo periodo. Copia conceptos, cliente, impuestos y notas. " +
|
|
88
|
+
"La nueva factura empieza como 'borrador' con fecha de hoy.",
|
|
89
|
+
annotations: CREATE_ANNOTATIONS,
|
|
90
|
+
inputSchema: {
|
|
91
|
+
id: z.string().describe("ID of the invoice to duplicate / ID de la factura a duplicar"),
|
|
92
|
+
newIssueDate: z
|
|
93
|
+
.string()
|
|
94
|
+
.optional()
|
|
95
|
+
.describe("Issue date for the new invoice (YYYY-MM-DD), defaults to today / Fecha de emision de la nueva factura"),
|
|
96
|
+
newDueDate: z
|
|
97
|
+
.string()
|
|
98
|
+
.optional()
|
|
99
|
+
.describe("Due date for the new invoice (YYYY-MM-DD) / Fecha de vencimiento de la nueva factura"),
|
|
100
|
+
},
|
|
101
|
+
}, async ({ id, newIssueDate, newDueDate }) => withToolLogging("duplicate_invoice", async () => {
|
|
102
|
+
// 1. Fetch the original invoice
|
|
103
|
+
const original = await client.getInvoice(id);
|
|
104
|
+
// 2. Strip fields that shouldn't be copied
|
|
105
|
+
const { id: _id, documentNumber: _docNum, status: _status, createdAt: _createdAt, updatedAt: _updatedAt, total: _total, ...copyData } = original;
|
|
106
|
+
// 3. Set new values
|
|
107
|
+
const today = new Date().toISOString().split("T")[0];
|
|
108
|
+
const invoiceData = {
|
|
109
|
+
...copyData,
|
|
110
|
+
status: "draft",
|
|
111
|
+
issueDate: newIssueDate || today,
|
|
112
|
+
};
|
|
113
|
+
if (newDueDate) {
|
|
114
|
+
invoiceData.dueDate = newDueDate;
|
|
115
|
+
}
|
|
116
|
+
// 4. Create the duplicate
|
|
117
|
+
const result = await client.createInvoice(invoiceData);
|
|
118
|
+
return {
|
|
119
|
+
content: [
|
|
120
|
+
mutateContent(formatRecord("Invoice duplicated", result) +
|
|
121
|
+
`\n\nDuplicated from invoice ${id}. Status set to 'draft'. / Duplicada de la factura ${id}. Estado: borrador.`),
|
|
122
|
+
],
|
|
123
|
+
structuredContent: result,
|
|
124
|
+
};
|
|
125
|
+
}));
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=intelligence.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"intelligence.js","sourceRoot":"","sources":["../../src/tools/intelligence.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"invoices.d.ts","sourceRoot":"","sources":["../../src/tools/invoices.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAS5D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"invoices.d.ts","sourceRoot":"","sources":["../../src/tools/invoices.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AAEzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAS5D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAqVnF"}
|
package/dist/tools/invoices.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Invoice tools for the Frihet MCP server.
|
|
3
3
|
*/
|
|
4
4
|
import { z } from "zod/v4";
|
|
5
|
-
import { withToolLogging, formatPaginatedResponse, formatRecord, listContent, getContent, mutateContent, READ_ONLY_ANNOTATIONS, CREATE_ANNOTATIONS, UPDATE_ANNOTATIONS, DELETE_ANNOTATIONS, paginatedOutput, deleteResultOutput, invoiceItemOutput } from "./shared.js";
|
|
5
|
+
import { withToolLogging, formatPaginatedResponse, formatRecord, listContent, getContent, mutateContent, enrichResponse, READ_ONLY_ANNOTATIONS, CREATE_ANNOTATIONS, UPDATE_ANNOTATIONS, DELETE_ANNOTATIONS, paginatedOutput, deleteResultOutput, invoiceItemOutput, actionResultOutput, pdfResultOutput } from "./shared.js";
|
|
6
6
|
const invoiceItemSchema = z.object({
|
|
7
7
|
description: z.string().describe("Description of the line item / Descripcion del concepto"),
|
|
8
8
|
quantity: z.number().describe("Quantity / Cantidad"),
|
|
@@ -24,6 +24,14 @@ export function registerInvoiceTools(server, client) {
|
|
|
24
24
|
.enum(["draft", "sent", "paid", "overdue", "cancelled"])
|
|
25
25
|
.optional()
|
|
26
26
|
.describe("Filter by invoice status / Filtrar por estado"),
|
|
27
|
+
clientId: z
|
|
28
|
+
.string()
|
|
29
|
+
.optional()
|
|
30
|
+
.describe("Filter by client ID / Filtrar por ID de cliente"),
|
|
31
|
+
seriesId: z
|
|
32
|
+
.string()
|
|
33
|
+
.optional()
|
|
34
|
+
.describe("Filter by invoice series ID / Filtrar por ID de serie"),
|
|
27
35
|
from: z
|
|
28
36
|
.string()
|
|
29
37
|
.optional()
|
|
@@ -32,6 +40,10 @@ export function registerInvoiceTools(server, client) {
|
|
|
32
40
|
.string()
|
|
33
41
|
.optional()
|
|
34
42
|
.describe("End date filter in ISO 8601 (YYYY-MM-DD) / Fecha fin"),
|
|
43
|
+
fields: z
|
|
44
|
+
.string()
|
|
45
|
+
.optional()
|
|
46
|
+
.describe("Comma-separated field names to return (e.g. 'id,clientName,total') / Campos a devolver"),
|
|
35
47
|
limit: z
|
|
36
48
|
.number()
|
|
37
49
|
.int()
|
|
@@ -45,13 +57,18 @@ export function registerInvoiceTools(server, client) {
|
|
|
45
57
|
.min(0)
|
|
46
58
|
.optional()
|
|
47
59
|
.describe("Number of results to skip / Resultados a saltar"),
|
|
60
|
+
after: z
|
|
61
|
+
.string()
|
|
62
|
+
.optional()
|
|
63
|
+
.describe("Cursor for cursor-based pagination (document ID) / Cursor para paginacion basada en cursor"),
|
|
48
64
|
},
|
|
49
65
|
outputSchema: paginatedOutput(invoiceItemOutput),
|
|
50
|
-
}, async ({ status, from, to, limit, offset }) => withToolLogging("list_invoices", async () => {
|
|
51
|
-
const result = await client.listInvoices({ limit, offset, status, from, to });
|
|
66
|
+
}, async ({ status, from, to, limit, offset, clientId, seriesId, fields, after }) => withToolLogging("list_invoices", async () => {
|
|
67
|
+
const result = await client.listInvoices({ limit, offset, after, fields, status, from, to, clientId, seriesId });
|
|
68
|
+
const hints = enrichResponse("invoices", "list", result.data);
|
|
52
69
|
return {
|
|
53
70
|
content: [listContent(formatPaginatedResponse("invoices", result))],
|
|
54
|
-
structuredContent: result,
|
|
71
|
+
structuredContent: { ...result, ...hints },
|
|
55
72
|
};
|
|
56
73
|
}));
|
|
57
74
|
// -- get_invoice --
|
|
@@ -112,9 +129,10 @@ export function registerInvoiceTools(server, client) {
|
|
|
112
129
|
outputSchema: invoiceItemOutput,
|
|
113
130
|
}, async (input) => withToolLogging("create_invoice", async () => {
|
|
114
131
|
const result = await client.createInvoice(input);
|
|
132
|
+
const hints = enrichResponse("invoices", "create", result);
|
|
115
133
|
return {
|
|
116
134
|
content: [mutateContent(formatRecord("Invoice created", result))],
|
|
117
|
-
structuredContent: result,
|
|
135
|
+
structuredContent: { ...result, ...hints },
|
|
118
136
|
};
|
|
119
137
|
}));
|
|
120
138
|
// -- update_invoice --
|
|
@@ -144,9 +162,10 @@ export function registerInvoiceTools(server, client) {
|
|
|
144
162
|
outputSchema: invoiceItemOutput,
|
|
145
163
|
}, async ({ id, ...data }) => withToolLogging("update_invoice", async () => {
|
|
146
164
|
const result = await client.updateInvoice(id, data);
|
|
165
|
+
const hints = enrichResponse("invoices", "update", result);
|
|
147
166
|
return {
|
|
148
167
|
content: [mutateContent(formatRecord("Invoice updated", result))],
|
|
149
|
-
structuredContent: result,
|
|
168
|
+
structuredContent: { ...result, ...hints },
|
|
150
169
|
};
|
|
151
170
|
}));
|
|
152
171
|
// -- delete_invoice --
|
|
@@ -161,9 +180,10 @@ export function registerInvoiceTools(server, client) {
|
|
|
161
180
|
outputSchema: deleteResultOutput,
|
|
162
181
|
}, async ({ id }) => withToolLogging("delete_invoice", async () => {
|
|
163
182
|
await client.deleteInvoice(id);
|
|
183
|
+
const hints = enrichResponse("invoices", "delete", { id });
|
|
164
184
|
return {
|
|
165
185
|
content: [mutateContent(`Invoice ${id} deleted successfully. / Factura ${id} eliminada correctamente.`)],
|
|
166
|
-
structuredContent: { success: true, id },
|
|
186
|
+
structuredContent: { success: true, id, ...hints },
|
|
167
187
|
};
|
|
168
188
|
}));
|
|
169
189
|
// -- search_invoices --
|
|
@@ -189,17 +209,81 @@ export function registerInvoiceTools(server, client) {
|
|
|
189
209
|
.string()
|
|
190
210
|
.optional()
|
|
191
211
|
.describe("End date filter (YYYY-MM-DD) / Fecha fin"),
|
|
212
|
+
fields: z
|
|
213
|
+
.string()
|
|
214
|
+
.optional()
|
|
215
|
+
.describe("Comma-separated field names to return / Campos a devolver"),
|
|
192
216
|
limit: z.number().int().min(1).max(100).optional().describe("Max results (1-100) / Resultados maximos"),
|
|
193
217
|
offset: z.number().int().min(0).optional().describe("Offset / Desplazamiento"),
|
|
218
|
+
after: z
|
|
219
|
+
.string()
|
|
220
|
+
.optional()
|
|
221
|
+
.describe("Cursor for cursor-based pagination (document ID) / Cursor para paginacion"),
|
|
194
222
|
},
|
|
195
223
|
outputSchema: paginatedOutput(invoiceItemOutput),
|
|
196
|
-
}, async ({ query, status, from, to, limit, offset }) => withToolLogging("search_invoices", async () => {
|
|
224
|
+
}, async ({ query, status, from, to, limit, offset, fields, after }) => withToolLogging("search_invoices", async () => {
|
|
197
225
|
const result = query
|
|
198
|
-
? await client.searchInvoices(query, { limit, offset, status, from, to })
|
|
199
|
-
: await client.listInvoices({ limit, offset, status, from, to });
|
|
226
|
+
? await client.searchInvoices(query, { limit, offset, after, fields, status, from, to })
|
|
227
|
+
: await client.listInvoices({ limit, offset, after, fields, status, from, to });
|
|
200
228
|
const label = query ? `invoices matching "${query}"` : "invoices";
|
|
229
|
+
const hints = enrichResponse("invoices", "list", result.data);
|
|
201
230
|
return {
|
|
202
231
|
content: [listContent(formatPaginatedResponse(label, result))],
|
|
232
|
+
structuredContent: { ...result, ...hints },
|
|
233
|
+
};
|
|
234
|
+
}));
|
|
235
|
+
// -- send_invoice --
|
|
236
|
+
server.registerTool("send_invoice", {
|
|
237
|
+
title: "Send Invoice",
|
|
238
|
+
description: "Send an invoice to the client via email. Optionally override the recipient email address. " +
|
|
239
|
+
"The invoice must exist and should not already be cancelled. " +
|
|
240
|
+
"/ Envia una factura al cliente por email. Opcionalmente se puede cambiar el email destinatario.",
|
|
241
|
+
annotations: UPDATE_ANNOTATIONS,
|
|
242
|
+
inputSchema: {
|
|
243
|
+
id: z.string().describe("Invoice ID / ID de la factura"),
|
|
244
|
+
to: z.string().optional().describe("Override recipient email / Email destinatario alternativo"),
|
|
245
|
+
},
|
|
246
|
+
outputSchema: actionResultOutput,
|
|
247
|
+
}, async ({ id, to }) => withToolLogging("send_invoice", async () => {
|
|
248
|
+
const result = await client.sendInvoice(id, to);
|
|
249
|
+
return {
|
|
250
|
+
content: [mutateContent(formatRecord("Invoice sent", result))],
|
|
251
|
+
structuredContent: result,
|
|
252
|
+
};
|
|
253
|
+
}));
|
|
254
|
+
// -- mark_invoice_paid --
|
|
255
|
+
server.registerTool("mark_invoice_paid", {
|
|
256
|
+
title: "Mark Invoice Paid",
|
|
257
|
+
description: "Mark an invoice as paid. Optionally specify the payment date. " +
|
|
258
|
+
"Defaults to today if no date is provided. " +
|
|
259
|
+
"/ Marca una factura como pagada. Opcionalmente especifica la fecha de pago.",
|
|
260
|
+
annotations: UPDATE_ANNOTATIONS,
|
|
261
|
+
inputSchema: {
|
|
262
|
+
id: z.string().describe("Invoice ID / ID de la factura"),
|
|
263
|
+
paidDate: z.string().optional().describe("Payment date (YYYY-MM-DD), defaults to today / Fecha de pago"),
|
|
264
|
+
},
|
|
265
|
+
outputSchema: actionResultOutput,
|
|
266
|
+
}, async ({ id, paidDate }) => withToolLogging("mark_invoice_paid", async () => {
|
|
267
|
+
const result = await client.markInvoicePaid(id, paidDate);
|
|
268
|
+
return {
|
|
269
|
+
content: [mutateContent(formatRecord("Invoice marked as paid", result))],
|
|
270
|
+
structuredContent: result,
|
|
271
|
+
};
|
|
272
|
+
}));
|
|
273
|
+
// -- get_invoice_pdf --
|
|
274
|
+
server.registerTool("get_invoice_pdf", {
|
|
275
|
+
title: "Get Invoice PDF",
|
|
276
|
+
description: "Get the PDF for an invoice. Returns a URL to download the PDF or binary info. " +
|
|
277
|
+
"/ Obtiene el PDF de una factura. Devuelve una URL de descarga o informacion del binario.",
|
|
278
|
+
annotations: READ_ONLY_ANNOTATIONS,
|
|
279
|
+
inputSchema: {
|
|
280
|
+
id: z.string().describe("Invoice ID / ID de la factura"),
|
|
281
|
+
},
|
|
282
|
+
outputSchema: pdfResultOutput,
|
|
283
|
+
}, async ({ id }) => withToolLogging("get_invoice_pdf", async () => {
|
|
284
|
+
const result = await client.getInvoicePdf(id);
|
|
285
|
+
return {
|
|
286
|
+
content: [getContent(formatRecord("Invoice PDF", result))],
|
|
203
287
|
structuredContent: result,
|
|
204
288
|
};
|
|
205
289
|
}));
|