mcp-supabase-crm-biancode 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.
package/.env.example ADDED
@@ -0,0 +1 @@
1
+ SUPABASE_CRM_API_TOKEN=your_api_token_here
@@ -0,0 +1,42 @@
1
+ /**
2
+ * HTTP client for CRM Biancode Edge Functions (list-sellers, create-sale).
3
+ * Auth via x-api-token header.
4
+ */
5
+ export interface Seller {
6
+ id: string;
7
+ name: string;
8
+ role: string;
9
+ email?: string | null;
10
+ phone?: string | null;
11
+ commission_percentage?: number;
12
+ }
13
+ export interface ListSellersResponse {
14
+ sellers: Seller[];
15
+ }
16
+ export interface CreateSaleBody {
17
+ client_id: string;
18
+ title: string;
19
+ total_amount: number;
20
+ sale_date: string;
21
+ description?: string;
22
+ installments?: number;
23
+ due_day?: number;
24
+ installment_start_date?: string;
25
+ status?: string;
26
+ goal_id?: string;
27
+ tax_percentage?: number;
28
+ gateway_fee_percentage?: number;
29
+ sellers?: Array<{
30
+ seller_id: string;
31
+ commission_amount: number;
32
+ }>;
33
+ }
34
+ export interface CreateSaleResponse {
35
+ success: boolean;
36
+ sale_id: string;
37
+ installments_created: number;
38
+ receivables_created: number;
39
+ sellers_linked: number;
40
+ }
41
+ export declare function getSellers(): Promise<ListSellersResponse>;
42
+ export declare function createSale(body: CreateSaleBody): Promise<CreateSaleResponse>;
package/dist/client.js ADDED
@@ -0,0 +1,66 @@
1
+ /**
2
+ * HTTP client for CRM Biancode Edge Functions (list-sellers, create-sale).
3
+ * Auth via x-api-token header.
4
+ */
5
+ import pRetry from "p-retry";
6
+ import { fetch as undiciFetch } from "undici";
7
+ const BASE_URL = "https://pxfjpxepjcvuiftbztar.supabase.co/functions/v1";
8
+ const REQUEST_TIMEOUT_MS = 15_000;
9
+ function getConfig() {
10
+ const token = process.env.SUPABASE_CRM_API_TOKEN;
11
+ if (!token) {
12
+ throw new Error("SUPABASE_CRM_API_TOKEN is required");
13
+ }
14
+ return { token };
15
+ }
16
+ function headers(token) {
17
+ return {
18
+ "x-api-token": token,
19
+ "Content-Type": "application/json",
20
+ Accept: "application/json",
21
+ };
22
+ }
23
+ async function request(path, token, options = {}) {
24
+ const run = async () => {
25
+ const ac = new AbortController();
26
+ const timer = setTimeout(() => ac.abort(), REQUEST_TIMEOUT_MS);
27
+ try {
28
+ const res = await undiciFetch(`${BASE_URL}${path}`, {
29
+ method: options.method ?? "GET",
30
+ headers: headers(token),
31
+ body: options.body,
32
+ signal: ac.signal,
33
+ });
34
+ if (res.status === 429 || (res.status >= 500 && res.status < 600)) {
35
+ throw new Error(`HTTP ${res.status}`);
36
+ }
37
+ if (!res.ok) {
38
+ const text = await res.text();
39
+ throw new Error(`CRM API ${res.status}: ${text.slice(0, 300)}`);
40
+ }
41
+ return res.json();
42
+ }
43
+ finally {
44
+ clearTimeout(timer);
45
+ }
46
+ };
47
+ return pRetry(run, {
48
+ retries: 3,
49
+ onFailedAttempt: (e) => {
50
+ if (e.retriesLeft > 0) {
51
+ console.error(`[supabase-crm] Retry after ${e.message}`);
52
+ }
53
+ },
54
+ });
55
+ }
56
+ export async function getSellers() {
57
+ const { token } = getConfig();
58
+ return request("/list-sellers", token);
59
+ }
60
+ export async function createSale(body) {
61
+ const { token } = getConfig();
62
+ return request("/create-sale", token, {
63
+ method: "POST",
64
+ body: JSON.stringify(body),
65
+ });
66
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,54 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
5
+ import { createServer } from "node:http";
6
+ import { sellersList } from "./tools/sellers.js";
7
+ import { createSaleTool } from "./tools/sales.js";
8
+ import * as schemas from "./schemas/inputs.js";
9
+ function safe(name, fn) {
10
+ return async (args) => {
11
+ try {
12
+ return await fn(args);
13
+ }
14
+ catch (e) {
15
+ const msg = e instanceof Error ? e.message : String(e);
16
+ console.error(`[mcp-supabase-crm-biancode] ${name} failed: ${msg}`);
17
+ return { content: [{ type: "text", text: JSON.stringify({ error: msg }) }] };
18
+ }
19
+ };
20
+ }
21
+ const server = new McpServer({
22
+ name: "supabase-crm-biancode",
23
+ version: "1.0.0",
24
+ });
25
+ server.registerTool("sellers_list", {
26
+ title: "List sellers",
27
+ description: "Lista vendedores cadastrados no CRM. Use para obter os IDs ao cadastrar uma venda e escolher quem participou (comissao).",
28
+ inputSchema: schemas.sellersListSchema,
29
+ }, safe("sellers_list", (a) => sellersList(a)));
30
+ server.registerTool("create_sale", {
31
+ title: "Create sale",
32
+ description: "Cadastra nova venda no CRM. Insere em sales, sale_installments, accounts_receivable e sale_sellers. Chame sellers_list antes para obter IDs dos vendedores.",
33
+ inputSchema: schemas.createSaleSchema,
34
+ }, safe("create_sale", (a) => createSaleTool(a)));
35
+ const port = parseInt(process.env.MCP_PORT ?? "", 10);
36
+ if (port > 0) {
37
+ const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
38
+ const httpServer = createServer((req, res) => {
39
+ if (req.url === "/health") {
40
+ res.writeHead(200, { "Content-Type": "application/json" });
41
+ res.end(JSON.stringify({ status: "ok" }));
42
+ return;
43
+ }
44
+ transport.handleRequest(req, res);
45
+ });
46
+ await server.connect(transport);
47
+ httpServer.listen(port, () => {
48
+ console.error(`[mcp-supabase-crm-biancode] HTTP transport listening on port ${port}`);
49
+ });
50
+ }
51
+ else {
52
+ const transport = new StdioServerTransport();
53
+ await server.connect(transport);
54
+ }
@@ -0,0 +1,70 @@
1
+ import { z } from "zod";
2
+ export declare const sellersListSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
3
+ export declare const sellerEntrySchema: z.ZodObject<{
4
+ seller_id: z.ZodString;
5
+ commission_amount: z.ZodNumber;
6
+ }, "strip", z.ZodTypeAny, {
7
+ seller_id: string;
8
+ commission_amount: number;
9
+ }, {
10
+ seller_id: string;
11
+ commission_amount: number;
12
+ }>;
13
+ export declare const createSaleSchema: z.ZodObject<{
14
+ client_id: z.ZodString;
15
+ title: z.ZodString;
16
+ total_amount: z.ZodNumber;
17
+ sale_date: z.ZodString;
18
+ description: z.ZodOptional<z.ZodString>;
19
+ installments: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
20
+ due_day: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
21
+ installment_start_date: z.ZodOptional<z.ZodString>;
22
+ status: z.ZodDefault<z.ZodOptional<z.ZodString>>;
23
+ goal_id: z.ZodOptional<z.ZodString>;
24
+ tax_percentage: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
25
+ gateway_fee_percentage: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
26
+ sellers: z.ZodOptional<z.ZodArray<z.ZodObject<{
27
+ seller_id: z.ZodString;
28
+ commission_amount: z.ZodNumber;
29
+ }, "strip", z.ZodTypeAny, {
30
+ seller_id: string;
31
+ commission_amount: number;
32
+ }, {
33
+ seller_id: string;
34
+ commission_amount: number;
35
+ }>, "many">>;
36
+ }, "strip", z.ZodTypeAny, {
37
+ status: string;
38
+ client_id: string;
39
+ title: string;
40
+ total_amount: number;
41
+ sale_date: string;
42
+ installments: number;
43
+ due_day: number;
44
+ tax_percentage: number;
45
+ gateway_fee_percentage: number;
46
+ description?: string | undefined;
47
+ installment_start_date?: string | undefined;
48
+ goal_id?: string | undefined;
49
+ sellers?: {
50
+ seller_id: string;
51
+ commission_amount: number;
52
+ }[] | undefined;
53
+ }, {
54
+ client_id: string;
55
+ title: string;
56
+ total_amount: number;
57
+ sale_date: string;
58
+ status?: string | undefined;
59
+ description?: string | undefined;
60
+ installments?: number | undefined;
61
+ due_day?: number | undefined;
62
+ installment_start_date?: string | undefined;
63
+ goal_id?: string | undefined;
64
+ tax_percentage?: number | undefined;
65
+ gateway_fee_percentage?: number | undefined;
66
+ sellers?: {
67
+ seller_id: string;
68
+ commission_amount: number;
69
+ }[] | undefined;
70
+ }>;
@@ -0,0 +1,25 @@
1
+ import { z } from "zod";
2
+ const dateStr = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Formato YYYY-MM-DD");
3
+ export const sellersListSchema = z.object({});
4
+ export const sellerEntrySchema = z.object({
5
+ seller_id: z.string().uuid().describe("UUID do vendedor (use sellers_list para obter os IDs)"),
6
+ commission_amount: z.number().min(0).describe("Valor da comissao em reais (total da venda)"),
7
+ });
8
+ export const createSaleSchema = z.object({
9
+ client_id: z.string().uuid().describe("UUID do cliente no CRM"),
10
+ title: z.string().min(1).describe("Nome/titulo da venda"),
11
+ total_amount: z.number().positive().describe("Valor total da venda em reais"),
12
+ sale_date: dateStr.describe("Data da venda (YYYY-MM-DD)"),
13
+ description: z.string().optional().describe("Descricao opcional"),
14
+ installments: z.number().int().min(1).max(24).optional().default(1).describe("Numero de parcelas"),
15
+ due_day: z.number().int().min(1).max(28).optional().default(15).describe("Dia do vencimento de cada parcela"),
16
+ installment_start_date: dateStr.optional().describe("Data da primeira parcela (YYYY-MM-DD)"),
17
+ status: z.string().optional().default("pending").describe("Status da venda"),
18
+ goal_id: z.string().uuid().optional().describe("UUID da meta associada"),
19
+ tax_percentage: z.number().min(0).max(100).optional().default(0).describe("Percentual de imposto"),
20
+ gateway_fee_percentage: z.number().min(0).max(100).optional().default(0).describe("Percentual de taxa gateway"),
21
+ sellers: z
22
+ .array(sellerEntrySchema)
23
+ .optional()
24
+ .describe("Vendedores que participaram da venda e suas comissoes (use sellers_list para obter IDs)"),
25
+ });
@@ -0,0 +1,10 @@
1
+ import type { z } from "zod";
2
+ import type { createSaleSchema } from "../schemas/inputs.js";
3
+ type ToolResult = {
4
+ content: Array<{
5
+ type: "text";
6
+ text: string;
7
+ }>;
8
+ };
9
+ export declare function createSaleTool(args: z.infer<typeof createSaleSchema>): Promise<ToolResult>;
10
+ export {};
@@ -0,0 +1,23 @@
1
+ import { createSale } from "../client.js";
2
+ function text(data) {
3
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
4
+ }
5
+ export async function createSaleTool(args) {
6
+ const body = {
7
+ client_id: args.client_id,
8
+ title: args.title,
9
+ total_amount: args.total_amount,
10
+ sale_date: args.sale_date,
11
+ description: args.description,
12
+ installments: args.installments,
13
+ due_day: args.due_day,
14
+ installment_start_date: args.installment_start_date,
15
+ status: args.status,
16
+ goal_id: args.goal_id,
17
+ tax_percentage: args.tax_percentage,
18
+ gateway_fee_percentage: args.gateway_fee_percentage,
19
+ sellers: args.sellers,
20
+ };
21
+ const result = await createSale(body);
22
+ return text(result);
23
+ }
@@ -0,0 +1,10 @@
1
+ import type { z } from "zod";
2
+ import type { sellersListSchema } from "../schemas/inputs.js";
3
+ type ToolResult = {
4
+ content: Array<{
5
+ type: "text";
6
+ text: string;
7
+ }>;
8
+ };
9
+ export declare function sellersList(_args: z.infer<typeof sellersListSchema>): Promise<ToolResult>;
10
+ export {};
@@ -0,0 +1,19 @@
1
+ import { getSellers } from "../client.js";
2
+ function text(data) {
3
+ return { content: [{ type: "text", text: JSON.stringify(data, null, 2) }] };
4
+ }
5
+ export async function sellersList(_args) {
6
+ const { sellers } = await getSellers();
7
+ return text({
8
+ total: sellers.length,
9
+ sellers: sellers.map((s) => ({
10
+ id: s.id,
11
+ name: s.name,
12
+ role: s.role,
13
+ email: s.email,
14
+ phone: s.phone,
15
+ commission_percentage: s.commission_percentage,
16
+ })),
17
+ hint: "Use os IDs acima no campo sellers da tool create_sale para vincular vendedores e comissoes.",
18
+ });
19
+ }
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "mcp-supabase-crm-biancode",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for CRM Biancode - list sellers and create sales via Supabase Edge Functions",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "bin": {
8
+ "mcp-supabase-crm-biancode": "dist/index.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc && chmod +x dist/index.js",
12
+ "start": "node dist/index.js",
13
+ "dev": "tsx src/index.ts",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "engines": {
17
+ "node": ">=18"
18
+ },
19
+ "dependencies": {
20
+ "@modelcontextprotocol/sdk": "^1.0.0",
21
+ "p-retry": "^6.2.0",
22
+ "undici": "^6.0.0",
23
+ "zod": "^3.23.0"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^20.0.0",
27
+ "tsx": "^4.0.0",
28
+ "typescript": "^5.0.0"
29
+ }
30
+ }
package/src/client.ts ADDED
@@ -0,0 +1,114 @@
1
+ /**
2
+ * HTTP client for CRM Biancode Edge Functions (list-sellers, create-sale).
3
+ * Auth via x-api-token header.
4
+ */
5
+
6
+ import pRetry from "p-retry";
7
+ import { fetch as undiciFetch } from "undici";
8
+
9
+ const BASE_URL = "https://pxfjpxepjcvuiftbztar.supabase.co/functions/v1";
10
+ const REQUEST_TIMEOUT_MS = 15_000;
11
+
12
+ function getConfig() {
13
+ const token = process.env.SUPABASE_CRM_API_TOKEN;
14
+ if (!token) {
15
+ throw new Error("SUPABASE_CRM_API_TOKEN is required");
16
+ }
17
+ return { token };
18
+ }
19
+
20
+ function headers(token: string): Record<string, string> {
21
+ return {
22
+ "x-api-token": token,
23
+ "Content-Type": "application/json",
24
+ Accept: "application/json",
25
+ };
26
+ }
27
+
28
+ async function request<T>(
29
+ path: string,
30
+ token: string,
31
+ options: { method?: string; body?: string } = {}
32
+ ): Promise<T> {
33
+ const run = async () => {
34
+ const ac = new AbortController();
35
+ const timer = setTimeout(() => ac.abort(), REQUEST_TIMEOUT_MS);
36
+ try {
37
+ const res = await undiciFetch(`${BASE_URL}${path}`, {
38
+ method: options.method ?? "GET",
39
+ headers: headers(token),
40
+ body: options.body,
41
+ signal: ac.signal as AbortSignal,
42
+ });
43
+ if (res.status === 429 || (res.status >= 500 && res.status < 600)) {
44
+ throw new Error(`HTTP ${res.status}`);
45
+ }
46
+ if (!res.ok) {
47
+ const text = await res.text();
48
+ throw new Error(`CRM API ${res.status}: ${text.slice(0, 300)}`);
49
+ }
50
+ return res.json() as Promise<T>;
51
+ } finally {
52
+ clearTimeout(timer);
53
+ }
54
+ };
55
+
56
+ return pRetry(run, {
57
+ retries: 3,
58
+ onFailedAttempt: (e) => {
59
+ if (e.retriesLeft > 0) {
60
+ console.error(`[supabase-crm] Retry after ${e.message}`);
61
+ }
62
+ },
63
+ });
64
+ }
65
+
66
+ export interface Seller {
67
+ id: string;
68
+ name: string;
69
+ role: string;
70
+ email?: string | null;
71
+ phone?: string | null;
72
+ commission_percentage?: number;
73
+ }
74
+
75
+ export interface ListSellersResponse {
76
+ sellers: Seller[];
77
+ }
78
+
79
+ export interface CreateSaleBody {
80
+ client_id: string;
81
+ title: string;
82
+ total_amount: number;
83
+ sale_date: string;
84
+ description?: string;
85
+ installments?: number;
86
+ due_day?: number;
87
+ installment_start_date?: string;
88
+ status?: string;
89
+ goal_id?: string;
90
+ tax_percentage?: number;
91
+ gateway_fee_percentage?: number;
92
+ sellers?: Array<{ seller_id: string; commission_amount: number }>;
93
+ }
94
+
95
+ export interface CreateSaleResponse {
96
+ success: boolean;
97
+ sale_id: string;
98
+ installments_created: number;
99
+ receivables_created: number;
100
+ sellers_linked: number;
101
+ }
102
+
103
+ export async function getSellers(): Promise<ListSellersResponse> {
104
+ const { token } = getConfig();
105
+ return request<ListSellersResponse>("/list-sellers", token);
106
+ }
107
+
108
+ export async function createSale(body: CreateSaleBody): Promise<CreateSaleResponse> {
109
+ const { token } = getConfig();
110
+ return request<CreateSaleResponse>("/create-sale", token, {
111
+ method: "POST",
112
+ body: JSON.stringify(body),
113
+ });
114
+ }
package/src/index.ts ADDED
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
5
+ import { createServer } from "node:http";
6
+ import { sellersList } from "./tools/sellers.js";
7
+ import { createSaleTool } from "./tools/sales.js";
8
+ import * as schemas from "./schemas/inputs.js";
9
+
10
+ type ToolResult = { content: Array<{ type: "text"; text: string }> };
11
+
12
+ function safe<T>(
13
+ name: string,
14
+ fn: (args: T) => Promise<ToolResult>
15
+ ): (args: T) => Promise<ToolResult> {
16
+ return async (args: T) => {
17
+ try {
18
+ return await fn(args);
19
+ } catch (e) {
20
+ const msg = e instanceof Error ? e.message : String(e);
21
+ console.error(`[mcp-supabase-crm-biancode] ${name} failed: ${msg}`);
22
+ return { content: [{ type: "text" as const, text: JSON.stringify({ error: msg }) }] };
23
+ }
24
+ };
25
+ }
26
+
27
+ const server = new McpServer({
28
+ name: "supabase-crm-biancode",
29
+ version: "1.0.0",
30
+ });
31
+
32
+ server.registerTool(
33
+ "sellers_list",
34
+ {
35
+ title: "List sellers",
36
+ description:
37
+ "Lista vendedores cadastrados no CRM. Use para obter os IDs ao cadastrar uma venda e escolher quem participou (comissao).",
38
+ inputSchema: schemas.sellersListSchema,
39
+ },
40
+ safe("sellers_list", (a) => sellersList(a))
41
+ );
42
+
43
+ server.registerTool(
44
+ "create_sale",
45
+ {
46
+ title: "Create sale",
47
+ description:
48
+ "Cadastra nova venda no CRM. Insere em sales, sale_installments, accounts_receivable e sale_sellers. Chame sellers_list antes para obter IDs dos vendedores.",
49
+ inputSchema: schemas.createSaleSchema,
50
+ },
51
+ safe("create_sale", (a) => createSaleTool(a))
52
+ );
53
+
54
+ const port = parseInt(process.env.MCP_PORT ?? "", 10);
55
+
56
+ if (port > 0) {
57
+ const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
58
+ const httpServer = createServer((req, res) => {
59
+ if (req.url === "/health") {
60
+ res.writeHead(200, { "Content-Type": "application/json" });
61
+ res.end(JSON.stringify({ status: "ok" }));
62
+ return;
63
+ }
64
+ transport.handleRequest(req, res);
65
+ });
66
+ await server.connect(transport);
67
+ httpServer.listen(port, () => {
68
+ console.error(`[mcp-supabase-crm-biancode] HTTP transport listening on port ${port}`);
69
+ });
70
+ } else {
71
+ const transport = new StdioServerTransport();
72
+ await server.connect(transport);
73
+ }
@@ -0,0 +1,29 @@
1
+ import { z } from "zod";
2
+
3
+ const dateStr = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Formato YYYY-MM-DD");
4
+
5
+ export const sellersListSchema = z.object({});
6
+
7
+ export const sellerEntrySchema = z.object({
8
+ seller_id: z.string().uuid().describe("UUID do vendedor (use sellers_list para obter os IDs)"),
9
+ commission_amount: z.number().min(0).describe("Valor da comissao em reais (total da venda)"),
10
+ });
11
+
12
+ export const createSaleSchema = z.object({
13
+ client_id: z.string().uuid().describe("UUID do cliente no CRM"),
14
+ title: z.string().min(1).describe("Nome/titulo da venda"),
15
+ total_amount: z.number().positive().describe("Valor total da venda em reais"),
16
+ sale_date: dateStr.describe("Data da venda (YYYY-MM-DD)"),
17
+ description: z.string().optional().describe("Descricao opcional"),
18
+ installments: z.number().int().min(1).max(24).optional().default(1).describe("Numero de parcelas"),
19
+ due_day: z.number().int().min(1).max(28).optional().default(15).describe("Dia do vencimento de cada parcela"),
20
+ installment_start_date: dateStr.optional().describe("Data da primeira parcela (YYYY-MM-DD)"),
21
+ status: z.string().optional().default("pending").describe("Status da venda"),
22
+ goal_id: z.string().uuid().optional().describe("UUID da meta associada"),
23
+ tax_percentage: z.number().min(0).max(100).optional().default(0).describe("Percentual de imposto"),
24
+ gateway_fee_percentage: z.number().min(0).max(100).optional().default(0).describe("Percentual de taxa gateway"),
25
+ sellers: z
26
+ .array(sellerEntrySchema)
27
+ .optional()
28
+ .describe("Vendedores que participaram da venda e suas comissoes (use sellers_list para obter IDs)"),
29
+ });
@@ -0,0 +1,31 @@
1
+ import { createSale } from "../client.js";
2
+ import type { z } from "zod";
3
+ import type { createSaleSchema } from "../schemas/inputs.js";
4
+
5
+ type ToolResult = { content: Array<{ type: "text"; text: string }> };
6
+
7
+ function text(data: unknown): ToolResult {
8
+ return { content: [{ type: "text" as const, text: JSON.stringify(data, null, 2) }] };
9
+ }
10
+
11
+ export async function createSaleTool(
12
+ args: z.infer<typeof createSaleSchema>
13
+ ): Promise<ToolResult> {
14
+ const body = {
15
+ client_id: args.client_id,
16
+ title: args.title,
17
+ total_amount: args.total_amount,
18
+ sale_date: args.sale_date,
19
+ description: args.description,
20
+ installments: args.installments,
21
+ due_day: args.due_day,
22
+ installment_start_date: args.installment_start_date,
23
+ status: args.status,
24
+ goal_id: args.goal_id,
25
+ tax_percentage: args.tax_percentage,
26
+ gateway_fee_percentage: args.gateway_fee_percentage,
27
+ sellers: args.sellers,
28
+ };
29
+ const result = await createSale(body);
30
+ return text(result);
31
+ }
@@ -0,0 +1,27 @@
1
+ import { getSellers } from "../client.js";
2
+ import type { z } from "zod";
3
+ import type { sellersListSchema } from "../schemas/inputs.js";
4
+
5
+ type ToolResult = { content: Array<{ type: "text"; text: string }> };
6
+
7
+ function text(data: unknown): ToolResult {
8
+ return { content: [{ type: "text" as const, text: JSON.stringify(data, null, 2) }] };
9
+ }
10
+
11
+ export async function sellersList(
12
+ _args: z.infer<typeof sellersListSchema>
13
+ ): Promise<ToolResult> {
14
+ const { sellers } = await getSellers();
15
+ return text({
16
+ total: sellers.length,
17
+ sellers: sellers.map((s) => ({
18
+ id: s.id,
19
+ name: s.name,
20
+ role: s.role,
21
+ email: s.email,
22
+ phone: s.phone,
23
+ commission_percentage: s.commission_percentage,
24
+ })),
25
+ hint: "Use os IDs acima no campo sellers da tool create_sale para vincular vendedores e comissoes.",
26
+ });
27
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "Node16",
5
+ "moduleResolution": "Node16",
6
+ "outDir": "dist",
7
+ "rootDir": "src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "declaration": true,
12
+ "resolveJsonModule": true,
13
+ "forceConsistentCasingInFileNames": true
14
+ },
15
+ "include": ["src"],
16
+ "exclude": ["node_modules", "dist"]
17
+ }