@kynver-app/mcp-estimator 0.2.8 → 0.2.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/server.js +16 -0
- package/dist/tools/catalog-tools.js +1 -1
- package/dist/tools/email-pdf-tools.d.ts +45 -0
- package/dist/tools/email-pdf-tools.js +21 -0
- package/dist/tools/intake-tools.d.ts +463 -0
- package/dist/tools/intake-tools.js +82 -0
- package/dist/tools/price-catalog-tools.d.ts +96 -0
- package/dist/tools/price-catalog-tools.js +72 -0
- package/dist/tools/remodel-deliverable-tools.d.ts +1868 -0
- package/dist/tools/remodel-deliverable-tools.js +138 -0
- package/dist/tools/remodel-estimate-tools.d.ts +525 -0
- package/dist/tools/remodel-estimate-tools.js +71 -0
- package/dist/tools/takeoff-tools.d.ts +274 -0
- package/dist/tools/takeoff-tools.js +38 -4
- package/dist/tools/vision-tools.js +2 -2
- package/package.json +6 -1
- package/src/index.ts +0 -18
- package/src/lib/kynver-client.ts +0 -136
- package/src/lib/mcp-sse-server.ts +0 -249
- package/src/lib/package-version.ts +0 -55
- package/src/server.ts +0 -141
- package/src/sse.ts +0 -10
- package/src/tools/catalog-tools.ts +0 -217
- package/src/tools/client-tools.ts +0 -114
- package/src/tools/company-tools.ts +0 -108
- package/src/tools/email-pdf-tools.ts +0 -27
- package/src/tools/estimate-tools.ts +0 -281
- package/src/tools/intake-tools.ts +0 -95
- package/src/tools/photo-tools.ts +0 -60
- package/src/tools/price-catalog-tools.ts +0 -80
- package/src/tools/remodel-deliverable-tools.ts +0 -163
- package/src/tools/remodel-estimate-tools.ts +0 -80
- package/src/tools/stats-pdf-tools.ts +0 -80
- package/src/tools/takeoff-tools.ts +0 -319
- package/src/tools/template-tools.ts +0 -80
- package/src/tools/version-tools.ts +0 -39
- package/src/tools/vision-tools.ts +0 -48
- package/tsconfig.json +0 -15
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
// @generated — synced from packages/kynver-mcp-sse-lib/src/index.ts via scripts/sync-mcp-sse-server.mjs
|
|
2
|
-
// Do not edit by hand; change the canonical file and re-run the sync script.
|
|
3
|
-
|
|
4
|
-
import { createServer, type IncomingMessage, type ServerResponse } from "node:http";
|
|
5
|
-
import { timingSafeEqual } from "node:crypto";
|
|
6
|
-
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
|
7
|
-
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
8
|
-
|
|
9
|
-
export const MAX_SSE_BODY_BYTES = 1 * 1024 * 1024;
|
|
10
|
-
|
|
11
|
-
export type SessionAuth =
|
|
12
|
-
| { kind: "apiKey"; apiKey: string }
|
|
13
|
-
| { kind: "internal"; userId: string };
|
|
14
|
-
|
|
15
|
-
type SessionEntry = {
|
|
16
|
-
transport: SSEServerTransport;
|
|
17
|
-
userId: string;
|
|
18
|
-
auth: SessionAuth;
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
type RequestContextStore = {
|
|
22
|
-
run: <T>(store: { userId?: string }, fn: () => Promise<T>) => Promise<T>;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
export type StartKynverMcpSseServerOptions = {
|
|
26
|
-
label: string;
|
|
27
|
-
defaultPort: number;
|
|
28
|
-
createMcpServer: () => McpServer | Promise<McpServer>;
|
|
29
|
-
requestContext: RequestContextStore;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const FORBIDDEN_QUERY_KEYS = ["secret", "userId"] as const;
|
|
33
|
-
|
|
34
|
-
export function headerValue(req: IncomingMessage, name: string): string | null {
|
|
35
|
-
const v = req.headers[name];
|
|
36
|
-
return typeof v === "string" ? v : Array.isArray(v) ? (v[0] ?? null) : null;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export function timingSafeEqualString(a: string, b: string): boolean {
|
|
40
|
-
const left = Buffer.from(a);
|
|
41
|
-
const right = Buffer.from(b);
|
|
42
|
-
if (left.length !== right.length) return false;
|
|
43
|
-
return timingSafeEqual(left, right);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export function hasForbiddenQueryAuth(url: URL): boolean {
|
|
47
|
-
return FORBIDDEN_QUERY_KEYS.some((key) => url.searchParams.has(key));
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function queryApiKey(url: URL): string {
|
|
51
|
-
return url.searchParams.get("apiKey")?.trim() ?? "";
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
export function resolveListenHost(): string {
|
|
55
|
-
const configured = process.env.MCP_SSE_HOST?.trim();
|
|
56
|
-
return configured || "127.0.0.1";
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export function parseJsonBody(req: IncomingMessage, maxBytes = MAX_SSE_BODY_BYTES): Promise<unknown> {
|
|
60
|
-
return new Promise((resolve, reject) => {
|
|
61
|
-
const chunks: Buffer[] = [];
|
|
62
|
-
let totalSize = 0;
|
|
63
|
-
req.on("data", (chunk: Buffer) => {
|
|
64
|
-
totalSize += chunk.length;
|
|
65
|
-
if (totalSize > maxBytes) {
|
|
66
|
-
req.destroy();
|
|
67
|
-
reject(new Error("Request body too large"));
|
|
68
|
-
return;
|
|
69
|
-
}
|
|
70
|
-
chunks.push(chunk);
|
|
71
|
-
});
|
|
72
|
-
req.on("end", () => {
|
|
73
|
-
try {
|
|
74
|
-
resolve(JSON.parse(Buffer.concat(chunks).toString()));
|
|
75
|
-
} catch (error) {
|
|
76
|
-
reject(error);
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
req.on("error", reject);
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export function validateMcporterServerName(name: string): string {
|
|
84
|
-
const trimmed = name.trim();
|
|
85
|
-
if (!/^[a-zA-Z0-9_-]+$/.test(trimmed)) {
|
|
86
|
-
throw new Error("Invalid mcporter server name.");
|
|
87
|
-
}
|
|
88
|
-
return trimmed;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function bearerToken(req: IncomingMessage): string {
|
|
92
|
-
const auth = headerValue(req, "authorization");
|
|
93
|
-
if (!auth) return "";
|
|
94
|
-
const match = /^Bearer\s+(.+)$/i.exec(auth);
|
|
95
|
-
return match?.[1]?.trim() ?? "";
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function resolveInternalAuth(
|
|
99
|
-
req: IncomingMessage,
|
|
100
|
-
serviceSecret: string,
|
|
101
|
-
): { userId: string; auth: SessionAuth } | null {
|
|
102
|
-
const internalUserId = headerValue(req, "x-kynver-user-id");
|
|
103
|
-
const internalSecret = headerValue(req, "x-kynver-service-secret");
|
|
104
|
-
if (!internalUserId || !serviceSecret || !internalSecret) return null;
|
|
105
|
-
if (!timingSafeEqualString(internalSecret, serviceSecret)) return null;
|
|
106
|
-
return { userId: internalUserId, auth: { kind: "internal", userId: internalUserId } };
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
function verifyPostAuth(
|
|
110
|
-
req: IncomingMessage,
|
|
111
|
-
url: URL,
|
|
112
|
-
sessionAuth: SessionAuth,
|
|
113
|
-
serviceSecret: string,
|
|
114
|
-
): boolean {
|
|
115
|
-
if (sessionAuth.kind === "apiKey") {
|
|
116
|
-
const token = bearerToken(req) || queryApiKey(url);
|
|
117
|
-
return token.length > 0 && timingSafeEqualString(token, sessionAuth.apiKey);
|
|
118
|
-
}
|
|
119
|
-
const internal = resolveInternalAuth(req, serviceSecret);
|
|
120
|
-
return (
|
|
121
|
-
internal !== null &&
|
|
122
|
-
internal.userId === sessionAuth.userId &&
|
|
123
|
-
internal.auth.kind === "internal"
|
|
124
|
-
);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
async function resolveUserFromApiKey(baseUrl: string, apiKey: string): Promise<string | null> {
|
|
128
|
-
try {
|
|
129
|
-
const res = await fetch(`${baseUrl.replace(/\/$/, "")}/api/users/me`, {
|
|
130
|
-
headers: { Authorization: `Bearer ${apiKey}` },
|
|
131
|
-
});
|
|
132
|
-
if (!res.ok) return null;
|
|
133
|
-
const data = (await res.json()) as { id?: string };
|
|
134
|
-
return data.id ?? null;
|
|
135
|
-
} catch {
|
|
136
|
-
return null;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function parseUrl(req: IncomingMessage, port: number): URL {
|
|
141
|
-
return new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
function json(res: ServerResponse, status: number, body: Record<string, unknown>) {
|
|
145
|
-
res.writeHead(status, { "Content-Type": "application/json" });
|
|
146
|
-
res.end(JSON.stringify(body));
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
export function startKynverMcpSseServer(options: StartKynverMcpSseServerOptions): void {
|
|
150
|
-
const port = parseInt(process.env.PORT ?? String(options.defaultPort), 10);
|
|
151
|
-
const baseUrl = process.env.KYNVER_API_URL ?? "https://kynver.com";
|
|
152
|
-
const serviceSecret = process.env.KYNVER_SERVICE_SECRET ?? "";
|
|
153
|
-
const host = resolveListenHost();
|
|
154
|
-
const sessions: Record<string, SessionEntry> = {};
|
|
155
|
-
|
|
156
|
-
const httpServer = createServer(async (req: IncomingMessage, res: ServerResponse) => {
|
|
157
|
-
const url = parseUrl(req, port);
|
|
158
|
-
const path = url.pathname;
|
|
159
|
-
|
|
160
|
-
if (req.method === "GET" && path === "/sse") {
|
|
161
|
-
if (hasForbiddenQueryAuth(url)) {
|
|
162
|
-
json(res, 400, {
|
|
163
|
-
error:
|
|
164
|
-
"Internal auth via query params is not allowed. Use X-Kynver-User-Id and X-Kynver-Service-Secret headers.",
|
|
165
|
-
});
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
if (url.searchParams.has("apiKey")) {
|
|
170
|
-
console.warn("[MCP SSE] WARNING: apiKey in query string may leak via logs. Prefer Authorization header when your client supports it.");
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
let userId: string | null = null;
|
|
174
|
-
let auth: SessionAuth | null = null;
|
|
175
|
-
|
|
176
|
-
const internal = serviceSecret ? resolveInternalAuth(req, serviceSecret) : null;
|
|
177
|
-
if (internal) {
|
|
178
|
-
userId = internal.userId;
|
|
179
|
-
auth = internal.auth;
|
|
180
|
-
} else {
|
|
181
|
-
const apiKey = bearerToken(req) || queryApiKey(url);
|
|
182
|
-
if (apiKey) {
|
|
183
|
-
userId = await resolveUserFromApiKey(baseUrl, apiKey);
|
|
184
|
-
if (userId) auth = { kind: "apiKey", apiKey };
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
if (!userId || !auth) {
|
|
189
|
-
json(res, 401, {
|
|
190
|
-
error:
|
|
191
|
-
"Unauthorized. Pass API key via Authorization: Bearer <key> or internal X-Kynver-User-Id + X-Kynver-Service-Secret headers.",
|
|
192
|
-
});
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
console.log(`[MCP SSE] New connection (${options.label}, user: ${userId.slice(0, 8)}...)`);
|
|
197
|
-
|
|
198
|
-
const transport = new SSEServerTransport("/messages", res);
|
|
199
|
-
sessions[transport.sessionId] = { transport, userId, auth };
|
|
200
|
-
|
|
201
|
-
res.on("close", () => {
|
|
202
|
-
delete sessions[transport.sessionId];
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
const server = await options.createMcpServer();
|
|
206
|
-
await server.connect(transport);
|
|
207
|
-
return;
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
if (req.method === "POST" && path === "/messages") {
|
|
211
|
-
const sessionId = url.searchParams.get("sessionId");
|
|
212
|
-
const entry = sessionId ? sessions[sessionId] : undefined;
|
|
213
|
-
|
|
214
|
-
if (!entry) {
|
|
215
|
-
json(res, 400, { error: "No active SSE session for this sessionId" });
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (!verifyPostAuth(req, url, entry.auth, serviceSecret)) {
|
|
220
|
-
json(res, 401, { error: "Unauthorized. Re-send the same credentials used to open the SSE session." });
|
|
221
|
-
return;
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
try {
|
|
225
|
-
const body = await parseJsonBody(req);
|
|
226
|
-
await options.requestContext.run({ userId: entry.userId }, async () => {
|
|
227
|
-
await entry.transport.handlePostMessage(req, res, body);
|
|
228
|
-
});
|
|
229
|
-
} catch (error) {
|
|
230
|
-
json(res, 400, {
|
|
231
|
-
error: error instanceof Error ? error.message : "Invalid request body",
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
if (req.method === "GET" && path === "/health") {
|
|
238
|
-
res.writeHead(200, { "Content-Type": "text/plain" });
|
|
239
|
-
res.end("ok");
|
|
240
|
-
return;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
json(res, 404, { error: "Not found" });
|
|
244
|
-
});
|
|
245
|
-
|
|
246
|
-
httpServer.listen(port, host, () => {
|
|
247
|
-
console.log(`[MCP SSE] ${options.label} listening on ${host}:${port}`);
|
|
248
|
-
});
|
|
249
|
-
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
// @generated — synced from packages/kynver-mcp-sse-lib/src/package-version.ts via scripts/sync-mcp-sse-server.mjs
|
|
2
|
-
// Do not edit by hand; change the canonical file and re-run the sync script.
|
|
3
|
-
|
|
4
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
5
|
-
import { dirname, join } from "node:path";
|
|
6
|
-
import { fileURLToPath } from "node:url";
|
|
7
|
-
|
|
8
|
-
function resolvePackageRoot(moduleUrl: string): string {
|
|
9
|
-
let dir = dirname(fileURLToPath(moduleUrl));
|
|
10
|
-
for (let depth = 0; depth < 6; depth += 1) {
|
|
11
|
-
if (existsSync(join(dir, "package.json"))) return dir;
|
|
12
|
-
const parent = dirname(dir);
|
|
13
|
-
if (parent === dir) break;
|
|
14
|
-
dir = parent;
|
|
15
|
-
}
|
|
16
|
-
throw new Error(`package.json not found above ${dirname(fileURLToPath(moduleUrl))}`);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/** Read a field from the nearest `package.json` above this module. */
|
|
20
|
-
export function readOwnPackageJsonField(
|
|
21
|
-
moduleUrl: string,
|
|
22
|
-
field: "version" | "name",
|
|
23
|
-
): string {
|
|
24
|
-
const pkgPath = join(resolvePackageRoot(moduleUrl), "package.json");
|
|
25
|
-
const pkg = JSON.parse(readFileSync(pkgPath, "utf8")) as Record<string, unknown>;
|
|
26
|
-
const value = pkg[field];
|
|
27
|
-
if (typeof value !== "string" || !value.trim()) {
|
|
28
|
-
throw new Error(`Missing package.json ${field} at ${pkgPath}`);
|
|
29
|
-
}
|
|
30
|
-
return value;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function readOwnPackageVersion(moduleUrl: string = import.meta.url): string {
|
|
34
|
-
return readOwnPackageJsonField(moduleUrl, "version");
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function wantsCliVersion(argv: string[]): boolean {
|
|
38
|
-
return argv.some((arg) => arg === "--version" || arg === "-v");
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function printCliVersionAndExit(version: string, binName?: string): never {
|
|
42
|
-
console.log(binName ? `${binName} ${version}` : version);
|
|
43
|
-
process.exit(0);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/** When `--version` / `-v` is present, print package version and exit before side effects. */
|
|
47
|
-
export function handleCliVersionFlag(
|
|
48
|
-
argv: string[],
|
|
49
|
-
moduleUrl: string = import.meta.url,
|
|
50
|
-
binName?: string,
|
|
51
|
-
): boolean {
|
|
52
|
-
if (!wantsCliVersion(argv)) return false;
|
|
53
|
-
printCliVersionAndExit(readOwnPackageVersion(moduleUrl), binName);
|
|
54
|
-
return true;
|
|
55
|
-
}
|
package/src/server.ts
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Creates and configures the estimator MCP server with all tools registered.
|
|
3
|
-
* Separated from transport so it can be used with stdio (CLI) or SSE (hosted).
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7
|
-
import * as catalogTools from "./tools/catalog-tools.js";
|
|
8
|
-
import * as priceCatalogTools from "./tools/price-catalog-tools.js";
|
|
9
|
-
import * as estimateTools from "./tools/estimate-tools.js";
|
|
10
|
-
import * as templateTools from "./tools/template-tools.js";
|
|
11
|
-
import * as versionTools from "./tools/version-tools.js";
|
|
12
|
-
import * as photoTools from "./tools/photo-tools.js";
|
|
13
|
-
import * as statsPdfTools from "./tools/stats-pdf-tools.js";
|
|
14
|
-
import * as emailPdfTools from "./tools/email-pdf-tools.js";
|
|
15
|
-
import * as visionTools from "./tools/vision-tools.js";
|
|
16
|
-
import * as companyTools from "./tools/company-tools.js";
|
|
17
|
-
import * as clientTools from "./tools/client-tools.js";
|
|
18
|
-
import * as takeoffTools from "./tools/takeoff-tools.js";
|
|
19
|
-
import * as intakeTools from "./tools/intake-tools.js";
|
|
20
|
-
import * as remodelEstimateTools from "./tools/remodel-estimate-tools.js";
|
|
21
|
-
import * as remodelDeliverableTools from "./tools/remodel-deliverable-tools.js";
|
|
22
|
-
import { readOwnPackageVersion } from "./lib/package-version.js";
|
|
23
|
-
|
|
24
|
-
const PACKAGE_VERSION = readOwnPackageVersion(import.meta.url);
|
|
25
|
-
|
|
26
|
-
type ToolConfig = { description: string; inputSchema: unknown };
|
|
27
|
-
|
|
28
|
-
function toolResult(text: string) {
|
|
29
|
-
return { content: [{ type: "text" as const, text }] };
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function createEstimatorServer(): McpServer {
|
|
33
|
-
const server = new McpServer(
|
|
34
|
-
{ name: "kynver-mcp-estimator", version: PACKAGE_VERSION },
|
|
35
|
-
{ capabilities: { tools: {} } }
|
|
36
|
-
);
|
|
37
|
-
|
|
38
|
-
function register(
|
|
39
|
-
name: string,
|
|
40
|
-
config: ToolConfig,
|
|
41
|
-
run: (args: unknown) => Promise<string>
|
|
42
|
-
) {
|
|
43
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
44
|
-
server.registerTool(name, config as any, async (args: any) => toolResult(await run(args)));
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// --- Catalog tools (9) ---
|
|
48
|
-
register(catalogTools.importCatalog.name, { description: catalogTools.importCatalog.description, inputSchema: catalogTools.importCatalog.inputSchemaZod }, (args) => catalogTools.importCatalog.execute(args as any));
|
|
49
|
-
register(catalogTools.reviewImport.name, { description: catalogTools.reviewImport.description, inputSchema: catalogTools.reviewImport.inputSchemaZod }, (args) => catalogTools.reviewImport.execute(args as any));
|
|
50
|
-
register(catalogTools.commitImport.name, { description: catalogTools.commitImport.description, inputSchema: catalogTools.commitImport.inputSchemaZod }, (args) => catalogTools.commitImport.execute(args as any));
|
|
51
|
-
register(catalogTools.setupPrice.name, { description: catalogTools.setupPrice.description, inputSchema: catalogTools.setupPrice.inputSchemaZod }, (args) => catalogTools.setupPrice.execute(args as any));
|
|
52
|
-
register(catalogTools.updatePrice.name, { description: catalogTools.updatePrice.description, inputSchema: catalogTools.updatePrice.inputSchemaZod }, (args) => catalogTools.updatePrice.execute(args as any));
|
|
53
|
-
register(catalogTools.getCatalog.name, { description: catalogTools.getCatalog.description, inputSchema: catalogTools.getCatalog.inputSchemaZod }, (args) => catalogTools.getCatalog.execute(args as any));
|
|
54
|
-
register(catalogTools.getConfig.name, { description: catalogTools.getConfig.description, inputSchema: catalogTools.getConfig.inputSchemaZod }, (args) => catalogTools.getConfig.execute(args as any));
|
|
55
|
-
register(catalogTools.updateConfig.name, { description: catalogTools.updateConfig.description, inputSchema: catalogTools.updateConfig.inputSchemaZod }, (args) => catalogTools.updateConfig.execute(args as any));
|
|
56
|
-
register(catalogTools.importTemplate.name, { description: catalogTools.importTemplate.description, inputSchema: catalogTools.importTemplate.inputSchemaZod }, (args) => catalogTools.importTemplate.execute(args as any));
|
|
57
|
-
|
|
58
|
-
// --- Price catalog tools (4) ---
|
|
59
|
-
register(priceCatalogTools.listPriceCatalogs.name, { description: priceCatalogTools.listPriceCatalogs.description, inputSchema: priceCatalogTools.listPriceCatalogs.inputSchemaZod }, (args) => priceCatalogTools.listPriceCatalogs.execute(args as any));
|
|
60
|
-
register(priceCatalogTools.getPriceCatalog.name, { description: priceCatalogTools.getPriceCatalog.description, inputSchema: priceCatalogTools.getPriceCatalog.inputSchemaZod }, (args) => priceCatalogTools.getPriceCatalog.execute(args as any));
|
|
61
|
-
register(priceCatalogTools.resolvePrice.name, { description: priceCatalogTools.resolvePrice.description, inputSchema: priceCatalogTools.resolvePrice.inputSchemaZod }, (args) => priceCatalogTools.resolvePrice.execute(args as any));
|
|
62
|
-
register(priceCatalogTools.seedPriceCatalog.name, { description: priceCatalogTools.seedPriceCatalog.description, inputSchema: priceCatalogTools.seedPriceCatalog.inputSchemaZod }, (args) => priceCatalogTools.seedPriceCatalog.execute(args as any));
|
|
63
|
-
|
|
64
|
-
// --- Estimate tools (11) ---
|
|
65
|
-
register(estimateTools.createReplacement.name, { description: estimateTools.createReplacement.description, inputSchema: estimateTools.createReplacement.inputSchemaZod }, (args) => estimateTools.createReplacement.execute(args as any));
|
|
66
|
-
register(estimateTools.createRepair.name, { description: estimateTools.createRepair.description, inputSchema: estimateTools.createRepair.inputSchemaZod }, (args) => estimateTools.createRepair.execute(args as any));
|
|
67
|
-
register(estimateTools.getEstimate.name, { description: estimateTools.getEstimate.description, inputSchema: estimateTools.getEstimate.inputSchemaZod }, (args) => estimateTools.getEstimate.execute(args as any));
|
|
68
|
-
register(estimateTools.listEstimates.name, { description: estimateTools.listEstimates.description, inputSchema: estimateTools.listEstimates.inputSchemaZod }, (args) => estimateTools.listEstimates.execute(args as any));
|
|
69
|
-
register(estimateTools.addLineItem.name, { description: estimateTools.addLineItem.description, inputSchema: estimateTools.addLineItem.inputSchemaZod }, (args) => estimateTools.addLineItem.execute(args as any));
|
|
70
|
-
register(estimateTools.removeLineItem.name, { description: estimateTools.removeLineItem.description, inputSchema: estimateTools.removeLineItem.inputSchemaZod }, (args) => estimateTools.removeLineItem.execute(args as any));
|
|
71
|
-
register(estimateTools.updateLineItem.name, { description: estimateTools.updateLineItem.description, inputSchema: estimateTools.updateLineItem.inputSchemaZod }, (args) => estimateTools.updateLineItem.execute(args as any));
|
|
72
|
-
register(estimateTools.adjustToTarget.name, { description: estimateTools.adjustToTarget.description, inputSchema: estimateTools.adjustToTarget.inputSchemaZod }, (args) => estimateTools.adjustToTarget.execute(args as any));
|
|
73
|
-
register(estimateTools.updateEstimate.name, { description: estimateTools.updateEstimate.description, inputSchema: estimateTools.updateEstimate.inputSchemaZod }, (args) => estimateTools.updateEstimate.execute(args as any));
|
|
74
|
-
register(estimateTools.deleteEstimate.name, { description: estimateTools.deleteEstimate.description, inputSchema: estimateTools.deleteEstimate.inputSchemaZod }, (args) => estimateTools.deleteEstimate.execute(args as any));
|
|
75
|
-
register(estimateTools.duplicateEstimate.name, { description: estimateTools.duplicateEstimate.description, inputSchema: estimateTools.duplicateEstimate.inputSchemaZod }, (args) => estimateTools.duplicateEstimate.execute(args as any));
|
|
76
|
-
register(remodelEstimateTools.buildRemodelEstimate.name, { description: remodelEstimateTools.buildRemodelEstimate.description, inputSchema: remodelEstimateTools.buildRemodelEstimate.inputSchemaZod }, (args) => remodelEstimateTools.buildRemodelEstimate.execute(args as any));
|
|
77
|
-
register(remodelDeliverableTools.buildRemodelDeliverable.name, { description: remodelDeliverableTools.buildRemodelDeliverable.description, inputSchema: remodelDeliverableTools.buildRemodelDeliverable.inputSchemaZod }, (args) => remodelDeliverableTools.buildRemodelDeliverable.execute(args as any));
|
|
78
|
-
register(remodelDeliverableTools.draftRemodelDeliverable.name, { description: remodelDeliverableTools.draftRemodelDeliverable.description, inputSchema: remodelDeliverableTools.draftRemodelDeliverable.inputSchemaZod }, (args) => remodelDeliverableTools.draftRemodelDeliverable.execute(args as any));
|
|
79
|
-
|
|
80
|
-
// --- Template tools (4) ---
|
|
81
|
-
register(templateTools.saveTemplate.name, { description: templateTools.saveTemplate.description, inputSchema: templateTools.saveTemplate.inputSchemaZod }, (args) => templateTools.saveTemplate.execute(args as any));
|
|
82
|
-
register(templateTools.listTemplates.name, { description: templateTools.listTemplates.description, inputSchema: templateTools.listTemplates.inputSchemaZod }, (args) => templateTools.listTemplates.execute(args as any));
|
|
83
|
-
register(templateTools.deleteTemplate.name, { description: templateTools.deleteTemplate.description, inputSchema: templateTools.deleteTemplate.inputSchemaZod }, (args) => templateTools.deleteTemplate.execute(args as any));
|
|
84
|
-
register(templateTools.createFromTemplate.name, { description: templateTools.createFromTemplate.description, inputSchema: templateTools.createFromTemplate.inputSchemaZod }, (args) => templateTools.createFromTemplate.execute(args as any));
|
|
85
|
-
|
|
86
|
-
// --- Version tools (2) ---
|
|
87
|
-
register(versionTools.listVersions.name, { description: versionTools.listVersions.description, inputSchema: versionTools.listVersions.inputSchemaZod }, (args) => versionTools.listVersions.execute(args as any));
|
|
88
|
-
register(versionTools.getVersion.name, { description: versionTools.getVersion.description, inputSchema: versionTools.getVersion.inputSchemaZod }, (args) => versionTools.getVersion.execute(args as any));
|
|
89
|
-
|
|
90
|
-
// --- Photo tools (3) ---
|
|
91
|
-
register(photoTools.uploadPhoto.name, { description: photoTools.uploadPhoto.description, inputSchema: photoTools.uploadPhoto.inputSchemaZod }, (args) => photoTools.uploadPhoto.execute(args as any));
|
|
92
|
-
register(photoTools.listPhotos.name, { description: photoTools.listPhotos.description, inputSchema: photoTools.listPhotos.inputSchemaZod }, (args) => photoTools.listPhotos.execute(args as any));
|
|
93
|
-
register(photoTools.deletePhoto.name, { description: photoTools.deletePhoto.description, inputSchema: photoTools.deletePhoto.inputSchemaZod }, (args) => photoTools.deletePhoto.execute(args as any));
|
|
94
|
-
|
|
95
|
-
// --- Stats / PDF tools (3) ---
|
|
96
|
-
register(statsPdfTools.getStats.name, { description: statsPdfTools.getStats.description, inputSchema: statsPdfTools.getStats.inputSchemaZod }, (args) => statsPdfTools.getStats.execute(args as any));
|
|
97
|
-
register(statsPdfTools.exportPdf.name, { description: statsPdfTools.exportPdf.description, inputSchema: statsPdfTools.exportPdf.inputSchemaZod }, (args) => statsPdfTools.exportPdf.execute(args as any));
|
|
98
|
-
register(statsPdfTools.updateOutputConfig.name, { description: statsPdfTools.updateOutputConfig.description, inputSchema: statsPdfTools.updateOutputConfig.inputSchemaZod }, (args) => statsPdfTools.updateOutputConfig.execute(args as any));
|
|
99
|
-
register(emailPdfTools.emailPdf.name, { description: emailPdfTools.emailPdf.description, inputSchema: emailPdfTools.emailPdf.inputSchemaZod }, (args) => emailPdfTools.emailPdf.execute(args as any));
|
|
100
|
-
|
|
101
|
-
// --- Vision tools (2) ---
|
|
102
|
-
register(visionTools.analyzePhotos.name, { description: visionTools.analyzePhotos.description, inputSchema: visionTools.analyzePhotos.inputSchemaZod }, (args) => visionTools.analyzePhotos.execute(args as any));
|
|
103
|
-
register(visionTools.analyzeDocument.name, { description: visionTools.analyzeDocument.description, inputSchema: visionTools.analyzeDocument.inputSchemaZod }, (args) => visionTools.analyzeDocument.execute(args as any));
|
|
104
|
-
|
|
105
|
-
// --- Company tools (5) ---
|
|
106
|
-
register(companyTools.createCompany.name, { description: companyTools.createCompany.description, inputSchema: companyTools.createCompany.inputSchemaZod }, (args) => companyTools.createCompany.execute(args as any));
|
|
107
|
-
register(companyTools.listCompanies.name, { description: companyTools.listCompanies.description, inputSchema: companyTools.listCompanies.inputSchemaZod }, (args) => companyTools.listCompanies.execute(args as any));
|
|
108
|
-
register(companyTools.getCompany.name, { description: companyTools.getCompany.description, inputSchema: companyTools.getCompany.inputSchemaZod }, (args) => companyTools.getCompany.execute(args as any));
|
|
109
|
-
register(companyTools.updateCompany.name, { description: companyTools.updateCompany.description, inputSchema: companyTools.updateCompany.inputSchemaZod }, (args) => companyTools.updateCompany.execute(args as any));
|
|
110
|
-
register(companyTools.deleteCompany.name, { description: companyTools.deleteCompany.description, inputSchema: companyTools.deleteCompany.inputSchemaZod }, (args) => companyTools.deleteCompany.execute(args as any));
|
|
111
|
-
|
|
112
|
-
// --- Client tools (5) ---
|
|
113
|
-
register(clientTools.createClient.name, { description: clientTools.createClient.description, inputSchema: clientTools.createClient.inputSchemaZod }, (args) => clientTools.createClient.execute(args as any));
|
|
114
|
-
register(clientTools.listClients.name, { description: clientTools.listClients.description, inputSchema: clientTools.listClients.inputSchemaZod }, (args) => clientTools.listClients.execute(args as any));
|
|
115
|
-
register(clientTools.getClient.name, { description: clientTools.getClient.description, inputSchema: clientTools.getClient.inputSchemaZod }, (args) => clientTools.getClient.execute(args as any));
|
|
116
|
-
register(clientTools.updateClient.name, { description: clientTools.updateClient.description, inputSchema: clientTools.updateClient.inputSchemaZod }, (args) => clientTools.updateClient.execute(args as any));
|
|
117
|
-
register(clientTools.deleteClient.name, { description: clientTools.deleteClient.description, inputSchema: clientTools.deleteClient.inputSchemaZod }, (args) => clientTools.deleteClient.execute(args as any));
|
|
118
|
-
|
|
119
|
-
// --- Takeoff / approval tools (16) ---
|
|
120
|
-
register(takeoffTools.createTakeoffProject.name, { description: takeoffTools.createTakeoffProject.description, inputSchema: takeoffTools.createTakeoffProject.inputSchemaZod }, (args) => takeoffTools.createTakeoffProject.execute(args as any));
|
|
121
|
-
register(takeoffTools.getTakeoffProject.name, { description: takeoffTools.getTakeoffProject.description, inputSchema: takeoffTools.getTakeoffProject.inputSchemaZod }, (args) => takeoffTools.getTakeoffProject.execute(args as any));
|
|
122
|
-
register(takeoffTools.listTakeoffProjects.name, { description: takeoffTools.listTakeoffProjects.description, inputSchema: takeoffTools.listTakeoffProjects.inputSchemaZod }, (args) => takeoffTools.listTakeoffProjects.execute(args as any));
|
|
123
|
-
register(takeoffTools.uploadTakeoffInput.name, { description: takeoffTools.uploadTakeoffInput.description, inputSchema: takeoffTools.uploadTakeoffInput.inputSchemaZod }, (args) => takeoffTools.uploadTakeoffInput.execute(args as any));
|
|
124
|
-
register(takeoffTools.runTakeoffExtract.name, { description: takeoffTools.runTakeoffExtract.description, inputSchema: takeoffTools.runTakeoffExtract.inputSchemaZod }, (args) => takeoffTools.runTakeoffExtract.execute(args as any));
|
|
125
|
-
register(takeoffTools.listTakeoffRows.name, { description: takeoffTools.listTakeoffRows.description, inputSchema: takeoffTools.listTakeoffRows.inputSchemaZod }, (args) => takeoffTools.listTakeoffRows.execute(args as any));
|
|
126
|
-
register(takeoffTools.reviewTakeoffRow.name, { description: takeoffTools.reviewTakeoffRow.description, inputSchema: takeoffTools.reviewTakeoffRow.inputSchemaZod }, (args) => takeoffTools.reviewTakeoffRow.execute(args as any));
|
|
127
|
-
register(takeoffTools.commitTakeoff.name, { description: takeoffTools.commitTakeoff.description, inputSchema: takeoffTools.commitTakeoff.inputSchemaZod }, (args) => takeoffTools.commitTakeoff.execute(args as any));
|
|
128
|
-
register(takeoffTools.listSystemPacks.name, { description: takeoffTools.listSystemPacks.description, inputSchema: takeoffTools.listSystemPacks.inputSchemaZod }, (args) => takeoffTools.listSystemPacks.execute(args as any));
|
|
129
|
-
register(takeoffTools.applySystemPack.name, { description: takeoffTools.applySystemPack.description, inputSchema: takeoffTools.applySystemPack.inputSchemaZod }, (args) => takeoffTools.applySystemPack.execute(args as any));
|
|
130
|
-
register(takeoffTools.listServiceProfiles.name, { description: takeoffTools.listServiceProfiles.description, inputSchema: takeoffTools.listServiceProfiles.inputSchemaZod }, (args) => takeoffTools.listServiceProfiles.execute(args as any));
|
|
131
|
-
register(takeoffTools.upsertServiceProfile.name, { description: takeoffTools.upsertServiceProfile.description, inputSchema: takeoffTools.upsertServiceProfile.inputSchemaZod }, (args) => takeoffTools.upsertServiceProfile.execute(args as any));
|
|
132
|
-
register(takeoffTools.generateEstimateFromTakeoff.name, { description: takeoffTools.generateEstimateFromTakeoff.description, inputSchema: takeoffTools.generateEstimateFromTakeoff.inputSchemaZod }, (args) => takeoffTools.generateEstimateFromTakeoff.execute(args as any));
|
|
133
|
-
register(takeoffTools.requestEstimateApproval.name, { description: takeoffTools.requestEstimateApproval.description, inputSchema: takeoffTools.requestEstimateApproval.inputSchemaZod }, (args) => takeoffTools.requestEstimateApproval.execute(args as any));
|
|
134
|
-
register(takeoffTools.approveEstimate.name, { description: takeoffTools.approveEstimate.description, inputSchema: takeoffTools.approveEstimate.inputSchemaZod }, (args) => takeoffTools.approveEstimate.execute(args as any));
|
|
135
|
-
register(takeoffTools.getEstimateApproval.name, { description: takeoffTools.getEstimateApproval.description, inputSchema: takeoffTools.getEstimateApproval.inputSchemaZod }, (args) => takeoffTools.getEstimateApproval.execute(args as any));
|
|
136
|
-
|
|
137
|
-
// --- Intake tools (1) ---
|
|
138
|
-
register(intakeTools.normalizeRemodelIntake.name, { description: intakeTools.normalizeRemodelIntake.description, inputSchema: intakeTools.normalizeRemodelIntake.inputSchemaZod }, (args) => intakeTools.normalizeRemodelIntake.execute(args as any));
|
|
139
|
-
|
|
140
|
-
return server;
|
|
141
|
-
}
|
package/src/sse.ts
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { startKynverMcpSseServer } from "./lib/mcp-sse-server.js";
|
|
2
|
-
import { createEstimatorServer } from "./server.js";
|
|
3
|
-
import { requestContext } from "./lib/kynver-client.js";
|
|
4
|
-
|
|
5
|
-
startKynverMcpSseServer({
|
|
6
|
-
label: "Estimator server",
|
|
7
|
-
defaultPort: 3100,
|
|
8
|
-
createMcpServer: createEstimatorServer,
|
|
9
|
-
requestContext,
|
|
10
|
-
});
|