@kynver-app/mcp-estimator 0.2.11 → 0.2.13

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.
@@ -4,7 +4,7 @@ import { createServer } from "node:http";
4
4
  import { timingSafeEqual } from "node:crypto";
5
5
  import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
6
6
  export const MAX_SSE_BODY_BYTES = 1 * 1024 * 1024;
7
- const FORBIDDEN_QUERY_KEYS = ["secret", "userId"];
7
+ const FORBIDDEN_QUERY_KEYS = ["apiKey", "secret", "userId"];
8
8
  export function headerValue(req, name) {
9
9
  const v = req.headers[name];
10
10
  return typeof v === "string" ? v : Array.isArray(v) ? (v[0] ?? null) : null;
@@ -19,9 +19,6 @@ export function timingSafeEqualString(a, b) {
19
19
  export function hasForbiddenQueryAuth(url) {
20
20
  return FORBIDDEN_QUERY_KEYS.some((key) => url.searchParams.has(key));
21
21
  }
22
- function queryApiKey(url) {
23
- return url.searchParams.get("apiKey")?.trim() ?? "";
24
- }
25
22
  export function resolveListenHost() {
26
23
  const configured = process.env.MCP_SSE_HOST?.trim();
27
24
  return configured || "127.0.0.1";
@@ -130,7 +127,7 @@ function resolveInternalAuth(req, serviceSecret) {
130
127
  }
131
128
  function verifyPostAuth(req, url, sessionAuth, serviceSecret) {
132
129
  if (sessionAuth.kind === "apiKey") {
133
- const token = bearerToken(req) || queryApiKey(url);
130
+ const token = bearerToken(req);
134
131
  return token.length > 0 && timingSafeEqualString(token, sessionAuth.apiKey);
135
132
  }
136
133
  const internal = resolveInternalAuth(req, serviceSecret);
@@ -170,7 +167,6 @@ export function startKynverMcpSseServer(options) {
170
167
  const maxSessionsPerUser = intFromEnv("MCP_SSE_MAX_SESSIONS_PER_USER", 20);
171
168
  const idleTimeoutMs = intFromEnv("MCP_SSE_IDLE_TIMEOUT_MS", 5 * 60 * 1000);
172
169
  const rateLimitPerMin = intFromEnv("MCP_SSE_RATE_LIMIT_PER_MIN", 120);
173
- const rejectQueryApiKey = /^(1|true|yes)$/i.test(process.env.MCP_SSE_REJECT_QUERY_APIKEY ?? "");
174
170
  const rateLimiter = createFixedWindowRateLimiter(rateLimitPerMin, 60 * 1000);
175
171
  // Close idle SSE sessions so a flood of half-open connections can't pin memory.
176
172
  const idleSweep = setInterval(() => {
@@ -198,15 +194,6 @@ export function startKynverMcpSseServer(options) {
198
194
  });
199
195
  return;
200
196
  }
201
- if (url.searchParams.has("apiKey")) {
202
- if (rejectQueryApiKey) {
203
- json(res, 400, {
204
- error: "apiKey via query param is disabled. Use Authorization: Bearer <key>.",
205
- });
206
- return;
207
- }
208
- console.warn("[MCP SSE] WARNING: apiKey in query string may leak via logs. Prefer Authorization header when your client supports it.");
209
- }
210
197
  let userId = null;
211
198
  let auth = null;
212
199
  const internal = serviceSecret ? resolveInternalAuth(req, serviceSecret) : null;
@@ -215,7 +202,7 @@ export function startKynverMcpSseServer(options) {
215
202
  auth = internal.auth;
216
203
  }
217
204
  else {
218
- const apiKey = bearerToken(req) || queryApiKey(url);
205
+ const apiKey = bearerToken(req);
219
206
  if (apiKey) {
220
207
  userId = await resolveUserFromApiKey(baseUrl, apiKey);
221
208
  if (userId)
package/dist/server.js CHANGED
@@ -18,6 +18,7 @@ import * as takeoffTools from "./tools/takeoff-tools.js";
18
18
  import * as intakeTools from "./tools/intake-tools.js";
19
19
  import * as remodelEstimateTools from "./tools/remodel-estimate-tools.js";
20
20
  import * as remodelDeliverableTools from "./tools/remodel-deliverable-tools.js";
21
+ import * as signingTools from "./tools/signing-tools.js";
21
22
  import { readOwnPackageVersion } from "./lib/package-version.js";
22
23
  const PACKAGE_VERSION = readOwnPackageVersion(import.meta.url);
23
24
  function toolResult(text) {
@@ -110,5 +111,9 @@ export function createEstimatorServer() {
110
111
  register(takeoffTools.getEstimateApproval.name, { description: takeoffTools.getEstimateApproval.description, inputSchema: takeoffTools.getEstimateApproval.inputSchemaZod }, (args) => takeoffTools.getEstimateApproval.execute(args));
111
112
  // --- Intake tools (1) ---
112
113
  register(intakeTools.normalizeRemodelIntake.name, { description: intakeTools.normalizeRemodelIntake.description, inputSchema: intakeTools.normalizeRemodelIntake.inputSchemaZod }, (args) => intakeTools.normalizeRemodelIntake.execute(args));
114
+ // --- Signing tools (3) ---
115
+ register(signingTools.createSigningRequest.name, { description: signingTools.createSigningRequest.description, inputSchema: signingTools.createSigningRequest.inputSchemaZod }, (args) => signingTools.createSigningRequest.execute(args));
116
+ register(signingTools.getSigningRequests.name, { description: signingTools.getSigningRequests.description, inputSchema: signingTools.getSigningRequests.inputSchemaZod }, (args) => signingTools.getSigningRequests.execute(args));
117
+ register(signingTools.cancelSigningRequest.name, { description: signingTools.cancelSigningRequest.description, inputSchema: signingTools.cancelSigningRequest.inputSchemaZod }, (args) => signingTools.cancelSigningRequest.execute(args));
113
118
  return server;
114
119
  }
@@ -301,7 +301,6 @@ declare const updateConfigSchema: z.ZodObject<{
301
301
  companyAddress: z.ZodOptional<z.ZodString>;
302
302
  companyLogo: z.ZodOptional<z.ZodString>;
303
303
  licenseNumber: z.ZodOptional<z.ZodString>;
304
- defaultNotes: z.ZodOptional<z.ZodString>;
305
304
  defaultTerms: z.ZodOptional<z.ZodString>;
306
305
  }, "strip", z.ZodTypeAny, {
307
306
  defaultMarkup?: number | undefined;
@@ -312,7 +311,6 @@ declare const updateConfigSchema: z.ZodObject<{
312
311
  companyAddress?: string | undefined;
313
312
  companyLogo?: string | undefined;
314
313
  licenseNumber?: string | undefined;
315
- defaultNotes?: string | undefined;
316
314
  defaultTerms?: string | undefined;
317
315
  }, {
318
316
  defaultMarkup?: number | undefined;
@@ -323,7 +321,6 @@ declare const updateConfigSchema: z.ZodObject<{
323
321
  companyAddress?: string | undefined;
324
322
  companyLogo?: string | undefined;
325
323
  licenseNumber?: string | undefined;
326
- defaultNotes?: string | undefined;
327
324
  defaultTerms?: string | undefined;
328
325
  }>;
329
326
  export declare const updateConfig: {
@@ -338,7 +335,6 @@ export declare const updateConfig: {
338
335
  companyAddress: z.ZodOptional<z.ZodString>;
339
336
  companyLogo: z.ZodOptional<z.ZodString>;
340
337
  licenseNumber: z.ZodOptional<z.ZodString>;
341
- defaultNotes: z.ZodOptional<z.ZodString>;
342
338
  defaultTerms: z.ZodOptional<z.ZodString>;
343
339
  }, "strip", z.ZodTypeAny, {
344
340
  defaultMarkup?: number | undefined;
@@ -349,7 +345,6 @@ export declare const updateConfig: {
349
345
  companyAddress?: string | undefined;
350
346
  companyLogo?: string | undefined;
351
347
  licenseNumber?: string | undefined;
352
- defaultNotes?: string | undefined;
353
348
  defaultTerms?: string | undefined;
354
349
  }, {
355
350
  defaultMarkup?: number | undefined;
@@ -360,7 +355,6 @@ export declare const updateConfig: {
360
355
  companyAddress?: string | undefined;
361
356
  companyLogo?: string | undefined;
362
357
  licenseNumber?: string | undefined;
363
- defaultNotes?: string | undefined;
364
358
  defaultTerms?: string | undefined;
365
359
  }>;
366
360
  execute: (args: z.infer<typeof updateConfigSchema>) => Promise<string>;
@@ -156,12 +156,11 @@ const updateConfigSchema = z.object({
156
156
  companyAddress: z.string().optional(),
157
157
  companyLogo: z.string().optional(),
158
158
  licenseNumber: z.string().optional(),
159
- defaultNotes: z.string().optional(),
160
159
  defaultTerms: z.string().optional(),
161
160
  });
162
161
  export const updateConfig = {
163
162
  name: "estimator_update_config",
164
- description: "Update the user's estimator settings. You can set: companyName, defaultMarkup (waste %), taxRate, companyPhone, companyEmail, companyAddress, companyLogo (URL), licenseNumber, defaultNotes (appended to every estimate), and defaultTerms (terms & conditions).",
163
+ description: "Update the user's estimator settings. You can set: companyName, defaultMarkup (waste %), taxRate, companyPhone, companyEmail, companyAddress, companyLogo (URL), licenseNumber (contractor CCB/license number), and defaultTerms (terms & conditions appended to estimates).",
165
164
  inputSchemaZod: updateConfigSchema,
166
165
  execute: async (args) => {
167
166
  if (!client.hasApiKey())
@@ -0,0 +1,89 @@
1
+ import { z } from "zod";
2
+ declare const createSigningRequestSchema: z.ZodObject<{
3
+ estimateId: z.ZodString;
4
+ recipientEmail: z.ZodOptional<z.ZodString>;
5
+ recipientName: z.ZodOptional<z.ZodString>;
6
+ senderNote: z.ZodOptional<z.ZodString>;
7
+ expiresInDays: z.ZodOptional<z.ZodNumber>;
8
+ }, "strip", z.ZodTypeAny, {
9
+ estimateId: string;
10
+ recipientEmail?: string | undefined;
11
+ recipientName?: string | undefined;
12
+ senderNote?: string | undefined;
13
+ expiresInDays?: number | undefined;
14
+ }, {
15
+ estimateId: string;
16
+ recipientEmail?: string | undefined;
17
+ recipientName?: string | undefined;
18
+ senderNote?: string | undefined;
19
+ expiresInDays?: number | undefined;
20
+ }>;
21
+ export declare const createSigningRequest: {
22
+ name: string;
23
+ description: string;
24
+ inputSchemaZod: z.ZodObject<{
25
+ estimateId: z.ZodString;
26
+ recipientEmail: z.ZodOptional<z.ZodString>;
27
+ recipientName: z.ZodOptional<z.ZodString>;
28
+ senderNote: z.ZodOptional<z.ZodString>;
29
+ expiresInDays: z.ZodOptional<z.ZodNumber>;
30
+ }, "strip", z.ZodTypeAny, {
31
+ estimateId: string;
32
+ recipientEmail?: string | undefined;
33
+ recipientName?: string | undefined;
34
+ senderNote?: string | undefined;
35
+ expiresInDays?: number | undefined;
36
+ }, {
37
+ estimateId: string;
38
+ recipientEmail?: string | undefined;
39
+ recipientName?: string | undefined;
40
+ senderNote?: string | undefined;
41
+ expiresInDays?: number | undefined;
42
+ }>;
43
+ execute: (args: z.infer<typeof createSigningRequestSchema>) => Promise<string>;
44
+ };
45
+ declare const getSigningRequestsSchema: z.ZodObject<{
46
+ estimateId: z.ZodString;
47
+ }, "strip", z.ZodTypeAny, {
48
+ estimateId: string;
49
+ }, {
50
+ estimateId: string;
51
+ }>;
52
+ export declare const getSigningRequests: {
53
+ name: string;
54
+ description: string;
55
+ inputSchemaZod: z.ZodObject<{
56
+ estimateId: z.ZodString;
57
+ }, "strip", z.ZodTypeAny, {
58
+ estimateId: string;
59
+ }, {
60
+ estimateId: string;
61
+ }>;
62
+ execute: (args: z.infer<typeof getSigningRequestsSchema>) => Promise<string>;
63
+ };
64
+ declare const cancelSigningRequestSchema: z.ZodObject<{
65
+ estimateId: z.ZodString;
66
+ requestId: z.ZodString;
67
+ }, "strip", z.ZodTypeAny, {
68
+ estimateId: string;
69
+ requestId: string;
70
+ }, {
71
+ estimateId: string;
72
+ requestId: string;
73
+ }>;
74
+ export declare const cancelSigningRequest: {
75
+ name: string;
76
+ description: string;
77
+ inputSchemaZod: z.ZodObject<{
78
+ estimateId: z.ZodString;
79
+ requestId: z.ZodString;
80
+ }, "strip", z.ZodTypeAny, {
81
+ estimateId: string;
82
+ requestId: string;
83
+ }, {
84
+ estimateId: string;
85
+ requestId: string;
86
+ }>;
87
+ execute: (args: z.infer<typeof cancelSigningRequestSchema>) => Promise<string>;
88
+ };
89
+ export {};
@@ -0,0 +1,51 @@
1
+ import { z } from "zod";
2
+ import * as client from "../lib/kynver-client.js";
3
+ const createSigningRequestSchema = z.object({
4
+ estimateId: z.string(),
5
+ recipientEmail: z.string().email().optional(),
6
+ recipientName: z.string().max(200).optional(),
7
+ senderNote: z.string().max(2000).optional(),
8
+ expiresInDays: z.number().int().min(1).max(365).optional(),
9
+ });
10
+ export const createSigningRequest = {
11
+ name: "estimator_create_signing_request",
12
+ description: "Create a contract signing request for an estimate. Returns a tokenized signing URL that can be shared with the client. The client can review and electronically sign the estimate at that URL. The signing request expires after expiresInDays (default 30). Does not send emails during implementation.",
13
+ inputSchemaZod: createSigningRequestSchema,
14
+ execute: async (args) => {
15
+ if (!client.hasApiKey())
16
+ return client.noApiKeyMessage();
17
+ const { estimateId, ...body } = args;
18
+ const data = await client.post(`/estimator/estimates/${estimateId}/signing-requests`, body);
19
+ return JSON.stringify(data);
20
+ },
21
+ };
22
+ const getSigningRequestsSchema = z.object({
23
+ estimateId: z.string(),
24
+ });
25
+ export const getSigningRequests = {
26
+ name: "estimator_get_signing_requests",
27
+ description: "List all signing requests for an estimate. Returns status (pending/signed/expired/cancelled), signing URL, recipient, and audit metadata for each request.",
28
+ inputSchemaZod: getSigningRequestsSchema,
29
+ execute: async (args) => {
30
+ if (!client.hasApiKey())
31
+ return client.noApiKeyMessage();
32
+ const data = await client.get(`/estimator/estimates/${args.estimateId}/signing-requests`);
33
+ return JSON.stringify(data);
34
+ },
35
+ };
36
+ const cancelSigningRequestSchema = z.object({
37
+ estimateId: z.string(),
38
+ requestId: z.string(),
39
+ });
40
+ export const cancelSigningRequest = {
41
+ name: "estimator_cancel_signing_request",
42
+ description: "Cancel a pending signing request. Cannot cancel a request that has already been signed. The signing URL will become invalid immediately.",
43
+ inputSchemaZod: cancelSigningRequestSchema,
44
+ execute: async (args) => {
45
+ if (!client.hasApiKey())
46
+ return client.noApiKeyMessage();
47
+ const { estimateId, requestId } = args;
48
+ const data = await client.patch(`/estimator/estimates/${estimateId}/signing-requests`, { requestId });
49
+ return JSON.stringify(data);
50
+ },
51
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kynver-app/mcp-estimator",
3
- "version": "0.2.11",
3
+ "version": "0.2.13",
4
4
  "files": [
5
5
  "dist",
6
6
  "!dist/**/__tests__/**",
@@ -1,107 +0,0 @@
1
- import { z } from "zod";
2
- declare const inputSchema: z.ZodObject<{
3
- type: z.ZodEnum<["replacement", "repair_service"]>;
4
- projectName: z.ZodString;
5
- roofMaterial: z.ZodOptional<z.ZodString>;
6
- footprintSqFt: z.ZodOptional<z.ZodNumber>;
7
- pitch: z.ZodOptional<z.ZodString>;
8
- layers: z.ZodOptional<z.ZodNumber>;
9
- ridgeLengthFt: z.ZodOptional<z.ZodNumber>;
10
- eavesFt: z.ZodOptional<z.ZodNumber>;
11
- lineItems: z.ZodOptional<z.ZodArray<z.ZodObject<{
12
- serviceCode: z.ZodString;
13
- materialType: z.ZodOptional<z.ZodString>;
14
- quantity: z.ZodNumber;
15
- }, "strip", z.ZodTypeAny, {
16
- serviceCode: string;
17
- quantity: number;
18
- materialType?: string | undefined;
19
- }, {
20
- serviceCode: string;
21
- quantity: number;
22
- materialType?: string | undefined;
23
- }>, "many">>;
24
- }, "strip", z.ZodTypeAny, {
25
- type: "replacement" | "repair_service";
26
- projectName: string;
27
- roofMaterial?: string | undefined;
28
- footprintSqFt?: number | undefined;
29
- pitch?: string | undefined;
30
- layers?: number | undefined;
31
- ridgeLengthFt?: number | undefined;
32
- eavesFt?: number | undefined;
33
- lineItems?: {
34
- serviceCode: string;
35
- quantity: number;
36
- materialType?: string | undefined;
37
- }[] | undefined;
38
- }, {
39
- type: "replacement" | "repair_service";
40
- projectName: string;
41
- roofMaterial?: string | undefined;
42
- footprintSqFt?: number | undefined;
43
- pitch?: string | undefined;
44
- layers?: number | undefined;
45
- ridgeLengthFt?: number | undefined;
46
- eavesFt?: number | undefined;
47
- lineItems?: {
48
- serviceCode: string;
49
- quantity: number;
50
- materialType?: string | undefined;
51
- }[] | undefined;
52
- }>;
53
- export declare const name = "estimator_create_estimate";
54
- export declare const description = "Create a roofing estimate. For replacement: provide dimensions and material. For repair: provide service items with quantities.";
55
- export declare const inputSchemaZod: z.ZodObject<{
56
- type: z.ZodEnum<["replacement", "repair_service"]>;
57
- projectName: z.ZodString;
58
- roofMaterial: z.ZodOptional<z.ZodString>;
59
- footprintSqFt: z.ZodOptional<z.ZodNumber>;
60
- pitch: z.ZodOptional<z.ZodString>;
61
- layers: z.ZodOptional<z.ZodNumber>;
62
- ridgeLengthFt: z.ZodOptional<z.ZodNumber>;
63
- eavesFt: z.ZodOptional<z.ZodNumber>;
64
- lineItems: z.ZodOptional<z.ZodArray<z.ZodObject<{
65
- serviceCode: z.ZodString;
66
- materialType: z.ZodOptional<z.ZodString>;
67
- quantity: z.ZodNumber;
68
- }, "strip", z.ZodTypeAny, {
69
- serviceCode: string;
70
- quantity: number;
71
- materialType?: string | undefined;
72
- }, {
73
- serviceCode: string;
74
- quantity: number;
75
- materialType?: string | undefined;
76
- }>, "many">>;
77
- }, "strip", z.ZodTypeAny, {
78
- type: "replacement" | "repair_service";
79
- projectName: string;
80
- roofMaterial?: string | undefined;
81
- footprintSqFt?: number | undefined;
82
- pitch?: string | undefined;
83
- layers?: number | undefined;
84
- ridgeLengthFt?: number | undefined;
85
- eavesFt?: number | undefined;
86
- lineItems?: {
87
- serviceCode: string;
88
- quantity: number;
89
- materialType?: string | undefined;
90
- }[] | undefined;
91
- }, {
92
- type: "replacement" | "repair_service";
93
- projectName: string;
94
- roofMaterial?: string | undefined;
95
- footprintSqFt?: number | undefined;
96
- pitch?: string | undefined;
97
- layers?: number | undefined;
98
- ridgeLengthFt?: number | undefined;
99
- eavesFt?: number | undefined;
100
- lineItems?: {
101
- serviceCode: string;
102
- quantity: number;
103
- materialType?: string | undefined;
104
- }[] | undefined;
105
- }>;
106
- export declare function execute(args: z.infer<typeof inputSchema>): Promise<string>;
107
- export {};
@@ -1,64 +0,0 @@
1
- import { z } from "zod";
2
- import * as client from "../lib/kynver-client.js";
3
- const lineItemSchema = z.object({
4
- serviceCode: z.string(),
5
- materialType: z.string().optional(),
6
- quantity: z.number(),
7
- });
8
- const inputSchema = z.object({
9
- type: z.enum(["replacement", "repair_service"]),
10
- projectName: z.string(),
11
- roofMaterial: z.string().optional(),
12
- // For replacement
13
- footprintSqFt: z.number().optional(),
14
- pitch: z.string().optional(),
15
- layers: z.number().optional(),
16
- ridgeLengthFt: z.number().optional(),
17
- eavesFt: z.number().optional(),
18
- // For repair
19
- lineItems: z.array(lineItemSchema).optional(),
20
- });
21
- export const name = "estimator_create_estimate";
22
- export const description = "Create a roofing estimate. For replacement: provide dimensions and material. For repair: provide service items with quantities.";
23
- export const inputSchemaZod = inputSchema;
24
- export async function execute(args) {
25
- if (!client.hasApiKey())
26
- return client.noApiKeyMessage();
27
- // Build a descriptive message for the estimator agent
28
- let message;
29
- if (args.type === "replacement") {
30
- const parts = [
31
- `Create a roof replacement estimate for project "${args.projectName}".`,
32
- ];
33
- if (args.roofMaterial)
34
- parts.push(`Material: ${args.roofMaterial}.`);
35
- if (args.footprintSqFt != null)
36
- parts.push(`Footprint: ${args.footprintSqFt} sq ft.`);
37
- if (args.pitch)
38
- parts.push(`Pitch: ${args.pitch}.`);
39
- if (args.layers != null)
40
- parts.push(`Layers: ${args.layers}.`);
41
- if (args.ridgeLengthFt != null)
42
- parts.push(`Ridge length: ${args.ridgeLengthFt} ft.`);
43
- if (args.eavesFt != null)
44
- parts.push(`Eaves: ${args.eavesFt} ft.`);
45
- message = parts.join(" ");
46
- }
47
- else {
48
- const parts = [
49
- `Create a roof repair/service estimate for project "${args.projectName}".`,
50
- ];
51
- if (args.roofMaterial)
52
- parts.push(`Material: ${args.roofMaterial}.`);
53
- if (args.lineItems && args.lineItems.length > 0) {
54
- const itemDescriptions = args.lineItems.map((item) => {
55
- const mat = item.materialType ? ` (${item.materialType})` : "";
56
- return `${item.serviceCode}${mat} x${item.quantity}`;
57
- });
58
- parts.push(`Line items: ${itemDescriptions.join(", ")}.`);
59
- }
60
- message = parts.join(" ");
61
- }
62
- const data = await client.post("/v1/agents/kynver-estimator/chat", { message });
63
- return JSON.stringify(data);
64
- }
@@ -1,25 +0,0 @@
1
- import { z } from "zod";
2
- declare const inputSchema: z.ZodObject<{
3
- message: z.ZodString;
4
- conversationId: z.ZodOptional<z.ZodString>;
5
- }, "strip", z.ZodTypeAny, {
6
- message: string;
7
- conversationId?: string | undefined;
8
- }, {
9
- message: string;
10
- conversationId?: string | undefined;
11
- }>;
12
- export declare const name = "estimator_chat";
13
- export declare const description = "Chat with the Kynver roofing estimator agent. Describe work to get estimates, manage your price catalog, or ask questions about your pricing.";
14
- export declare const inputSchemaZod: z.ZodObject<{
15
- message: z.ZodString;
16
- conversationId: z.ZodOptional<z.ZodString>;
17
- }, "strip", z.ZodTypeAny, {
18
- message: string;
19
- conversationId?: string | undefined;
20
- }, {
21
- message: string;
22
- conversationId?: string | undefined;
23
- }>;
24
- export declare function execute(args: z.infer<typeof inputSchema>): Promise<string>;
25
- export {};
@@ -1,15 +0,0 @@
1
- import { z } from "zod";
2
- import * as client from "../lib/kynver-client.js";
3
- const inputSchema = z.object({
4
- message: z.string(),
5
- conversationId: z.string().optional(),
6
- });
7
- export const name = "estimator_chat";
8
- export const description = "Chat with the Kynver roofing estimator agent. Describe work to get estimates, manage your price catalog, or ask questions about your pricing.";
9
- export const inputSchemaZod = inputSchema;
10
- export async function execute(args) {
11
- if (!client.hasApiKey())
12
- return client.noApiKeyMessage();
13
- const data = await client.post("/v1/agents/kynver-estimator/chat", { message: args.message, conversationId: args.conversationId });
14
- return JSON.stringify(data);
15
- }
@@ -1,19 +0,0 @@
1
- import { z } from "zod";
2
- declare const inputSchema: z.ZodObject<{
3
- estimateId: z.ZodString;
4
- }, "strip", z.ZodTypeAny, {
5
- estimateId: string;
6
- }, {
7
- estimateId: string;
8
- }>;
9
- export declare const name = "estimator_get_estimate";
10
- export declare const description = "Get a specific estimate with all line items and totals.";
11
- export declare const inputSchemaZod: z.ZodObject<{
12
- estimateId: z.ZodString;
13
- }, "strip", z.ZodTypeAny, {
14
- estimateId: string;
15
- }, {
16
- estimateId: string;
17
- }>;
18
- export declare function execute(args: z.infer<typeof inputSchema>): Promise<string>;
19
- export {};
@@ -1,14 +0,0 @@
1
- import { z } from "zod";
2
- import * as client from "../lib/kynver-client.js";
3
- const inputSchema = z.object({
4
- estimateId: z.string(),
5
- });
6
- export const name = "estimator_get_estimate";
7
- export const description = "Get a specific estimate with all line items and totals.";
8
- export const inputSchemaZod = inputSchema;
9
- export async function execute(args) {
10
- if (!client.hasApiKey())
11
- return client.noApiKeyMessage();
12
- const data = await client.get(`/estimator/estimates/${args.estimateId}`);
13
- return JSON.stringify(data);
14
- }
@@ -1,25 +0,0 @@
1
- import { z } from "zod";
2
- declare const inputSchema: z.ZodObject<{
3
- category: z.ZodOptional<z.ZodString>;
4
- materialType: z.ZodOptional<z.ZodString>;
5
- }, "strip", z.ZodTypeAny, {
6
- materialType?: string | undefined;
7
- category?: string | undefined;
8
- }, {
9
- materialType?: string | undefined;
10
- category?: string | undefined;
11
- }>;
12
- export declare const name = "estimator_list_catalog";
13
- export declare const description = "List items in the service catalog (your prices). Optionally filter by category or material type.";
14
- export declare const inputSchemaZod: z.ZodObject<{
15
- category: z.ZodOptional<z.ZodString>;
16
- materialType: z.ZodOptional<z.ZodString>;
17
- }, "strip", z.ZodTypeAny, {
18
- materialType?: string | undefined;
19
- category?: string | undefined;
20
- }, {
21
- materialType?: string | undefined;
22
- category?: string | undefined;
23
- }>;
24
- export declare function execute(args: z.infer<typeof inputSchema>): Promise<string>;
25
- export {};
@@ -1,22 +0,0 @@
1
- import { z } from "zod";
2
- import * as client from "../lib/kynver-client.js";
3
- const inputSchema = z.object({
4
- category: z.string().optional(),
5
- materialType: z.string().optional(),
6
- });
7
- export const name = "estimator_list_catalog";
8
- export const description = "List items in the service catalog (your prices). Optionally filter by category or material type.";
9
- export const inputSchemaZod = inputSchema;
10
- export async function execute(args) {
11
- if (!client.hasApiKey())
12
- return client.noApiKeyMessage();
13
- const params = new URLSearchParams();
14
- if (args.category)
15
- params.set("category", args.category);
16
- if (args.materialType)
17
- params.set("materialType", args.materialType);
18
- const q = params.toString();
19
- const path = q ? `/estimator/catalog?${q}` : "/estimator/catalog";
20
- const data = await client.get(path);
21
- return JSON.stringify(data);
22
- }