@mgsoftwarebv/mcp-server-bridge 3.4.0 → 3.4.1
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/index.js +326 -11
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -106277,6 +106277,106 @@ var TOOLS = [
|
|
|
106277
106277
|
required: ["documentId", "invoiceId"]
|
|
106278
106278
|
}
|
|
106279
106279
|
},
|
|
106280
|
+
{
|
|
106281
|
+
name: "get-products",
|
|
106282
|
+
description: "List catalog products used on invoices AND quotes (the shared `invoice_products` catalog). Each entry includes its ID (UUID), name, unit price, currency, unit, active/archived flag, configurable flag, and usage stats. Editing or archiving a catalog product never changes existing invoices/quotes \u2014 those keep an immutable line-item snapshot; catalog changes only affect documents created afterwards.",
|
|
106283
|
+
inputSchema: {
|
|
106284
|
+
type: "object",
|
|
106285
|
+
properties: {
|
|
106286
|
+
teamId: teamIdProp,
|
|
106287
|
+
q: {
|
|
106288
|
+
type: "string",
|
|
106289
|
+
description: "Search query for product name/description"
|
|
106290
|
+
},
|
|
106291
|
+
status: {
|
|
106292
|
+
type: "string",
|
|
106293
|
+
enum: ["active", "archived", "all"],
|
|
106294
|
+
default: "active",
|
|
106295
|
+
description: "Filter by catalog status (archived = isActive false)"
|
|
106296
|
+
},
|
|
106297
|
+
currency: {
|
|
106298
|
+
type: "string",
|
|
106299
|
+
description: "Filter by currency code (e.g. EUR)"
|
|
106300
|
+
},
|
|
106301
|
+
pageSize: { type: "number", default: 20, maximum: 100 }
|
|
106302
|
+
},
|
|
106303
|
+
required: []
|
|
106304
|
+
}
|
|
106305
|
+
},
|
|
106306
|
+
{
|
|
106307
|
+
name: "get-product-by-id",
|
|
106308
|
+
description: "Get a single catalog product by its ID (UUID), including name, unit price, currency, unit, active/archived flag, configurable flag, and usage stats.",
|
|
106309
|
+
inputSchema: {
|
|
106310
|
+
type: "object",
|
|
106311
|
+
properties: {
|
|
106312
|
+
teamId: teamIdProp,
|
|
106313
|
+
productId: { type: "string", description: "Product ID (UUID)" }
|
|
106314
|
+
},
|
|
106315
|
+
required: ["productId"]
|
|
106316
|
+
}
|
|
106317
|
+
},
|
|
106318
|
+
{
|
|
106319
|
+
name: "create-product",
|
|
106320
|
+
description: "Create a catalog product for use on invoices and quotes. Stored in the shared `invoice_products` catalog. This only adds a reusable catalog entry; it does not place the product on any document. Returns the created product with its ID and normalized fields.",
|
|
106321
|
+
inputSchema: {
|
|
106322
|
+
type: "object",
|
|
106323
|
+
properties: {
|
|
106324
|
+
teamId: teamIdProp,
|
|
106325
|
+
name: { type: "string", description: "Product name" },
|
|
106326
|
+
description: { type: "string" },
|
|
106327
|
+
price: {
|
|
106328
|
+
type: "number",
|
|
106329
|
+
description: "Unit price (catalog default, excl. quantity)"
|
|
106330
|
+
},
|
|
106331
|
+
currency: { type: "string", description: "Currency code (e.g. EUR)" },
|
|
106332
|
+
unit: {
|
|
106333
|
+
type: "string",
|
|
106334
|
+
description: "Unit label (e.g. hour, piece, month)"
|
|
106335
|
+
}
|
|
106336
|
+
},
|
|
106337
|
+
required: ["name"]
|
|
106338
|
+
}
|
|
106339
|
+
},
|
|
106340
|
+
{
|
|
106341
|
+
name: "update-product",
|
|
106342
|
+
description: "Update a catalog product's editable fields (name, description, price, currency, unit) or reactivate it (isActive: true). Only provided fields change. IMPORTANT: updates apply only to FUTURE invoices/quotes. Existing/sent/accepted/paid documents keep their immutable line-item snapshot and are never mutated. Find the product id via get-products.",
|
|
106343
|
+
inputSchema: {
|
|
106344
|
+
type: "object",
|
|
106345
|
+
properties: {
|
|
106346
|
+
teamId: teamIdProp,
|
|
106347
|
+
productId: { type: "string", description: "Product ID (UUID)" },
|
|
106348
|
+
name: { type: "string" },
|
|
106349
|
+
description: { type: ["string", "null"] },
|
|
106350
|
+
price: {
|
|
106351
|
+
type: ["number", "null"],
|
|
106352
|
+
description: "Unit price (catalog default)"
|
|
106353
|
+
},
|
|
106354
|
+
currency: { type: ["string", "null"] },
|
|
106355
|
+
unit: { type: ["string", "null"] },
|
|
106356
|
+
isActive: {
|
|
106357
|
+
type: "boolean",
|
|
106358
|
+
description: "Set true to reactivate an archived product"
|
|
106359
|
+
}
|
|
106360
|
+
},
|
|
106361
|
+
required: ["productId"]
|
|
106362
|
+
}
|
|
106363
|
+
},
|
|
106364
|
+
{
|
|
106365
|
+
name: "archive-product",
|
|
106366
|
+
description: "Archive (soft-disable) a catalog product so it no longer appears in invoice/quote product pickers. Preferred over deletion: products referenced historically stay safe because invoices/quotes hold their own line-item snapshots. Reactivate later via update-product (isActive: true).",
|
|
106367
|
+
inputSchema: {
|
|
106368
|
+
type: "object",
|
|
106369
|
+
properties: {
|
|
106370
|
+
teamId: teamIdProp,
|
|
106371
|
+
productId: { type: "string", description: "Product ID (UUID)" },
|
|
106372
|
+
reason: {
|
|
106373
|
+
type: "string",
|
|
106374
|
+
description: "Optional note about why it was archived (not persisted)"
|
|
106375
|
+
}
|
|
106376
|
+
},
|
|
106377
|
+
required: ["productId"]
|
|
106378
|
+
}
|
|
106379
|
+
},
|
|
106280
106380
|
{
|
|
106281
106381
|
name: "log-hours",
|
|
106282
106382
|
description: "Analyze current chat conversation and log hours as draft tracker entry. AI analyzes chat context to estimate hours as a senior developer would (without AI assistance). Cursor AI matches workspace name to correct project from list (optional).",
|
|
@@ -113005,6 +113105,203 @@ async function handleRemoveProjectMember(input) {
|
|
|
113005
113105
|
return textResponse(text3);
|
|
113006
113106
|
}
|
|
113007
113107
|
|
|
113108
|
+
// src/tools/products.ts
|
|
113109
|
+
var PRODUCT_STATUSES = ["active", "archived", "all"];
|
|
113110
|
+
var PRODUCT_COLUMNS = {
|
|
113111
|
+
id: schema_exports.invoiceProducts.id,
|
|
113112
|
+
teamId: schema_exports.invoiceProducts.teamId,
|
|
113113
|
+
name: schema_exports.invoiceProducts.name,
|
|
113114
|
+
description: schema_exports.invoiceProducts.description,
|
|
113115
|
+
price: schema_exports.invoiceProducts.price,
|
|
113116
|
+
currency: schema_exports.invoiceProducts.currency,
|
|
113117
|
+
unit: schema_exports.invoiceProducts.unit,
|
|
113118
|
+
isConfigurable: schema_exports.invoiceProducts.isConfigurable,
|
|
113119
|
+
isActive: schema_exports.invoiceProducts.isActive,
|
|
113120
|
+
usageCount: schema_exports.invoiceProducts.usageCount,
|
|
113121
|
+
lastUsedAt: schema_exports.invoiceProducts.lastUsedAt,
|
|
113122
|
+
createdAt: schema_exports.invoiceProducts.createdAt,
|
|
113123
|
+
updatedAt: schema_exports.invoiceProducts.updatedAt
|
|
113124
|
+
};
|
|
113125
|
+
function textResponse2(text3) {
|
|
113126
|
+
return { content: [{ type: "text", text: text3 }] };
|
|
113127
|
+
}
|
|
113128
|
+
function formatPrice(p3) {
|
|
113129
|
+
if (p3.price == null) return "(no price)";
|
|
113130
|
+
return `${p3.price}${p3.currency ? ` ${p3.currency}` : ""}${p3.unit ? ` / ${p3.unit}` : ""}`;
|
|
113131
|
+
}
|
|
113132
|
+
function formatProduct(p3) {
|
|
113133
|
+
const flags = [p3.isActive ? "active" : "archived"];
|
|
113134
|
+
if (p3.isConfigurable) flags.push("configurable");
|
|
113135
|
+
return `**${p3.name}** (${flags.join(", ")})
|
|
113136
|
+
ID: ${p3.id}
|
|
113137
|
+
Price: ${formatPrice(p3)}
|
|
113138
|
+
${p3.description ? `Description: ${p3.description}
|
|
113139
|
+
` : ""}Used: ${p3.usageCount}x${p3.lastUsedAt ? ` (last ${new Date(p3.lastUsedAt).toLocaleDateString()})` : ""}
|
|
113140
|
+
`;
|
|
113141
|
+
}
|
|
113142
|
+
async function handleGetProducts(input) {
|
|
113143
|
+
const { q: q3, currency, pageSize = 20 } = input;
|
|
113144
|
+
const status = input.status ?? "active";
|
|
113145
|
+
if (!PRODUCT_STATUSES.includes(status)) {
|
|
113146
|
+
return textResponse2(
|
|
113147
|
+
`Error: invalid status "${status}". Allowed: ${PRODUCT_STATUSES.join(", ")}.`
|
|
113148
|
+
);
|
|
113149
|
+
}
|
|
113150
|
+
const scope = await resolveTeamScope(input.teamId);
|
|
113151
|
+
if (!scope.ok) return scope.response;
|
|
113152
|
+
if (scope.teamIds.length === 0) {
|
|
113153
|
+
return textResponse2("No accessible teams found.");
|
|
113154
|
+
}
|
|
113155
|
+
const filters = [inArray(schema_exports.invoiceProducts.teamId, scope.teamIds)];
|
|
113156
|
+
if (status === "active") {
|
|
113157
|
+
filters.push(eq(schema_exports.invoiceProducts.isActive, true));
|
|
113158
|
+
} else if (status === "archived") {
|
|
113159
|
+
filters.push(eq(schema_exports.invoiceProducts.isActive, false));
|
|
113160
|
+
}
|
|
113161
|
+
if (currency) filters.push(eq(schema_exports.invoiceProducts.currency, currency));
|
|
113162
|
+
if (q3) {
|
|
113163
|
+
filters.push(
|
|
113164
|
+
or(
|
|
113165
|
+
sql`${schema_exports.invoiceProducts.fts} @@ plainto_tsquery('english', ${q3})`,
|
|
113166
|
+
ilike(schema_exports.invoiceProducts.name, `%${q3}%`)
|
|
113167
|
+
)
|
|
113168
|
+
);
|
|
113169
|
+
}
|
|
113170
|
+
const rows = await db.select(PRODUCT_COLUMNS).from(schema_exports.invoiceProducts).where(and(...filters)).orderBy(
|
|
113171
|
+
desc(schema_exports.invoiceProducts.usageCount),
|
|
113172
|
+
desc(schema_exports.invoiceProducts.lastUsedAt),
|
|
113173
|
+
asc(schema_exports.invoiceProducts.name)
|
|
113174
|
+
).limit(Math.min(pageSize, 100));
|
|
113175
|
+
if (rows.length === 0) {
|
|
113176
|
+
return textResponse2(
|
|
113177
|
+
`No products found${status !== "all" ? ` (status: ${status})` : ""}.`
|
|
113178
|
+
);
|
|
113179
|
+
}
|
|
113180
|
+
return textResponse2(
|
|
113181
|
+
`Found ${rows.length} product(s):
|
|
113182
|
+
|
|
113183
|
+
${rows.map(formatProduct).join("\n")}`
|
|
113184
|
+
);
|
|
113185
|
+
}
|
|
113186
|
+
async function handleGetProductById(input) {
|
|
113187
|
+
const { productId } = input;
|
|
113188
|
+
if (!productId) return textResponse2("Error: `productId` is required.");
|
|
113189
|
+
const scope = await resolveTeamScope(input.teamId);
|
|
113190
|
+
if (!scope.ok) return scope.response;
|
|
113191
|
+
if (scope.teamIds.length === 0) {
|
|
113192
|
+
return textResponse2("No accessible teams found.");
|
|
113193
|
+
}
|
|
113194
|
+
const [row] = await db.select(PRODUCT_COLUMNS).from(schema_exports.invoiceProducts).where(
|
|
113195
|
+
and(
|
|
113196
|
+
eq(schema_exports.invoiceProducts.id, productId),
|
|
113197
|
+
inArray(schema_exports.invoiceProducts.teamId, scope.teamIds)
|
|
113198
|
+
)
|
|
113199
|
+
).limit(1);
|
|
113200
|
+
if (!row) {
|
|
113201
|
+
return textResponse2(
|
|
113202
|
+
`Product ${productId} not found or you don't have access to it.`
|
|
113203
|
+
);
|
|
113204
|
+
}
|
|
113205
|
+
return textResponse2(formatProduct(row));
|
|
113206
|
+
}
|
|
113207
|
+
async function loadProductInTeam(productId, teamId) {
|
|
113208
|
+
const accessibleTeamIds = await getAccessibleTeamIds(teamId);
|
|
113209
|
+
const [row] = await db.select(PRODUCT_COLUMNS).from(schema_exports.invoiceProducts).where(
|
|
113210
|
+
and(
|
|
113211
|
+
eq(schema_exports.invoiceProducts.id, productId),
|
|
113212
|
+
inArray(schema_exports.invoiceProducts.teamId, accessibleTeamIds)
|
|
113213
|
+
)
|
|
113214
|
+
).limit(1);
|
|
113215
|
+
return row ?? null;
|
|
113216
|
+
}
|
|
113217
|
+
async function handleCreateProduct(input) {
|
|
113218
|
+
const { name: name21, description, price, currency, unit } = input;
|
|
113219
|
+
if (!name21 || name21.trim().length === 0) {
|
|
113220
|
+
return textResponse2("Error: `name` is required.");
|
|
113221
|
+
}
|
|
113222
|
+
const resolved = await resolveTeamId(input.teamId);
|
|
113223
|
+
if (!resolved.ok) return resolved.response;
|
|
113224
|
+
const [created] = await db.insert(schema_exports.invoiceProducts).values({
|
|
113225
|
+
teamId: resolved.teamId,
|
|
113226
|
+
name: name21.trim(),
|
|
113227
|
+
description: description ?? null,
|
|
113228
|
+
price: price ?? null,
|
|
113229
|
+
currency: currency ?? null,
|
|
113230
|
+
unit: unit ?? null,
|
|
113231
|
+
isActive: true,
|
|
113232
|
+
lastUsedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
113233
|
+
}).returning(PRODUCT_COLUMNS);
|
|
113234
|
+
if (!created) return textResponse2("Failed to create product.");
|
|
113235
|
+
return textResponse2(
|
|
113236
|
+
`\u2705 **Product created**
|
|
113237
|
+
|
|
113238
|
+
${formatProduct(created)}`
|
|
113239
|
+
);
|
|
113240
|
+
}
|
|
113241
|
+
async function handleUpdateProduct(input) {
|
|
113242
|
+
const { productId } = input;
|
|
113243
|
+
if (!productId) return textResponse2("Error: `productId` is required.");
|
|
113244
|
+
const resolved = await resolveTeamId(input.teamId);
|
|
113245
|
+
if (!resolved.ok) return resolved.response;
|
|
113246
|
+
const existing = await loadProductInTeam(productId, resolved.teamId);
|
|
113247
|
+
if (!existing) {
|
|
113248
|
+
return textResponse2(
|
|
113249
|
+
`Product ${productId} not found, or it is not owned by this team.`
|
|
113250
|
+
);
|
|
113251
|
+
}
|
|
113252
|
+
const updates = {};
|
|
113253
|
+
if (input.name !== void 0) {
|
|
113254
|
+
if (!input.name || input.name.trim().length === 0) {
|
|
113255
|
+
return textResponse2("Error: `name` cannot be empty.");
|
|
113256
|
+
}
|
|
113257
|
+
updates.name = input.name.trim();
|
|
113258
|
+
}
|
|
113259
|
+
if (input.description !== void 0) updates.description = input.description;
|
|
113260
|
+
if (input.price !== void 0) updates.price = input.price;
|
|
113261
|
+
if (input.currency !== void 0) updates.currency = input.currency;
|
|
113262
|
+
if (input.unit !== void 0) updates.unit = input.unit;
|
|
113263
|
+
if (input.isActive !== void 0) updates.isActive = input.isActive;
|
|
113264
|
+
if (Object.keys(updates).length === 0) {
|
|
113265
|
+
return textResponse2(
|
|
113266
|
+
"No fields to update. Provide at least one of: name, description, price, currency, unit, isActive."
|
|
113267
|
+
);
|
|
113268
|
+
}
|
|
113269
|
+
updates.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
113270
|
+
const [updated] = await db.update(schema_exports.invoiceProducts).set(updates).where(eq(schema_exports.invoiceProducts.id, existing.id)).returning(PRODUCT_COLUMNS);
|
|
113271
|
+
if (!updated) return textResponse2(`Failed to update product ${productId}.`);
|
|
113272
|
+
return textResponse2(
|
|
113273
|
+
`\u2705 **Product updated**
|
|
113274
|
+
|
|
113275
|
+
${formatProduct(updated)}
|
|
113276
|
+
Note: this only affects future invoices/quotes. Existing documents keep their line-item snapshots.`
|
|
113277
|
+
);
|
|
113278
|
+
}
|
|
113279
|
+
async function handleArchiveProduct(input) {
|
|
113280
|
+
const { productId, reason } = input;
|
|
113281
|
+
if (!productId) return textResponse2("Error: `productId` is required.");
|
|
113282
|
+
const resolved = await resolveTeamId(input.teamId);
|
|
113283
|
+
if (!resolved.ok) return resolved.response;
|
|
113284
|
+
const existing = await loadProductInTeam(productId, resolved.teamId);
|
|
113285
|
+
if (!existing) {
|
|
113286
|
+
return textResponse2(
|
|
113287
|
+
`Product ${productId} not found, or it is not owned by this team.`
|
|
113288
|
+
);
|
|
113289
|
+
}
|
|
113290
|
+
if (!existing.isActive) {
|
|
113291
|
+
return textResponse2(
|
|
113292
|
+
`Product "${existing.name}" (${existing.id}) is already archived.`
|
|
113293
|
+
);
|
|
113294
|
+
}
|
|
113295
|
+
const [archived] = await db.update(schema_exports.invoiceProducts).set({ isActive: false, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }).where(eq(schema_exports.invoiceProducts.id, existing.id)).returning(PRODUCT_COLUMNS);
|
|
113296
|
+
if (!archived) return textResponse2(`Failed to archive product ${productId}.`);
|
|
113297
|
+
return textResponse2(
|
|
113298
|
+
`\u2705 **Product archived** (hidden from new invoices/quotes; existing documents are untouched).
|
|
113299
|
+
|
|
113300
|
+
${formatProduct(archived)}${reason ? `Reason: ${reason}
|
|
113301
|
+
` : ""}Reactivate it with update-product (isActive: true).`
|
|
113302
|
+
);
|
|
113303
|
+
}
|
|
113304
|
+
|
|
113008
113305
|
// src/tools/teams.ts
|
|
113009
113306
|
async function handleGetTeams() {
|
|
113010
113307
|
const ctx = getAuthContext();
|
|
@@ -118496,7 +118793,7 @@ var EXT_MIME = {
|
|
|
118496
118793
|
ppt: "application/vnd.ms-powerpoint",
|
|
118497
118794
|
pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation"
|
|
118498
118795
|
};
|
|
118499
|
-
function
|
|
118796
|
+
function textResponse3(text3) {
|
|
118500
118797
|
return { content: [{ type: "text", text: text3 }] };
|
|
118501
118798
|
}
|
|
118502
118799
|
function mimeFromName(name21) {
|
|
@@ -118577,12 +118874,12 @@ async function handleUploadTicketAttachment(input) {
|
|
|
118577
118874
|
(v2) => typeof v2 === "string" && v2.trim().length > 0
|
|
118578
118875
|
);
|
|
118579
118876
|
if (sources.length === 0) {
|
|
118580
|
-
return
|
|
118877
|
+
return textResponse3(
|
|
118581
118878
|
"Provide exactly one source: filePath (absolute local path), imageUrl, or base64Data."
|
|
118582
118879
|
);
|
|
118583
118880
|
}
|
|
118584
118881
|
if (sources.length > 1) {
|
|
118585
|
-
return
|
|
118882
|
+
return textResponse3(
|
|
118586
118883
|
"Provide only one source (filePath, imageUrl, or base64Data), not several."
|
|
118587
118884
|
);
|
|
118588
118885
|
}
|
|
@@ -118602,7 +118899,7 @@ async function handleUploadTicketAttachment(input) {
|
|
|
118602
118899
|
} else if (input.imageUrl) {
|
|
118603
118900
|
const res = await fetch(input.imageUrl);
|
|
118604
118901
|
if (!res.ok) {
|
|
118605
|
-
return
|
|
118902
|
+
return textResponse3(
|
|
118606
118903
|
`Could not download from URL: HTTP ${res.status}.`
|
|
118607
118904
|
);
|
|
118608
118905
|
}
|
|
@@ -118630,22 +118927,22 @@ async function handleUploadTicketAttachment(input) {
|
|
|
118630
118927
|
}
|
|
118631
118928
|
}
|
|
118632
118929
|
} catch (error49) {
|
|
118633
|
-
return
|
|
118930
|
+
return textResponse3(
|
|
118634
118931
|
`Failed to read the file: ${error49 instanceof Error ? error49.message : String(error49)}`
|
|
118635
118932
|
);
|
|
118636
118933
|
}
|
|
118637
118934
|
if (buffer2.byteLength === 0) {
|
|
118638
|
-
return
|
|
118935
|
+
return textResponse3("The file is empty (0 bytes); nothing to upload.");
|
|
118639
118936
|
}
|
|
118640
118937
|
if (buffer2.byteLength > MAX_FILE_SIZE) {
|
|
118641
|
-
return
|
|
118938
|
+
return textResponse3(
|
|
118642
118939
|
`File too large (${(buffer2.byteLength / 1024 / 1024).toFixed(
|
|
118643
118940
|
1
|
|
118644
118941
|
)} MB). Max: 25 MB.`
|
|
118645
118942
|
);
|
|
118646
118943
|
}
|
|
118647
118944
|
if (!ALLOWED_MIME_TYPES.has(mimeType)) {
|
|
118648
|
-
return
|
|
118945
|
+
return textResponse3(
|
|
118649
118946
|
`Unsupported file type: ${mimeType}. Allowed: JPEG, PNG, GIF, WebP, PDF, DOC(X), XLS(X), PPT(X), TXT, CSV.`
|
|
118650
118947
|
);
|
|
118651
118948
|
}
|
|
@@ -118658,7 +118955,7 @@ async function handleUploadTicketAttachment(input) {
|
|
|
118658
118955
|
options: { contentType: mimeType, upsert: true }
|
|
118659
118956
|
});
|
|
118660
118957
|
} catch (error49) {
|
|
118661
|
-
return
|
|
118958
|
+
return textResponse3(
|
|
118662
118959
|
`Upload failed: ${error49 instanceof Error ? error49.message : String(error49)}`
|
|
118663
118960
|
);
|
|
118664
118961
|
}
|
|
@@ -118681,7 +118978,7 @@ async function handleUploadTicketAttachment(input) {
|
|
|
118681
118978
|
url3 = signed.url;
|
|
118682
118979
|
} catch {
|
|
118683
118980
|
}
|
|
118684
|
-
return
|
|
118981
|
+
return textResponse3(
|
|
118685
118982
|
`\u{1F4CE} **Attached to ${ticket.ticketNumber}**
|
|
118686
118983
|
File: ${fileName}
|
|
118687
118984
|
Type: ${mimeType}
|
|
@@ -119825,7 +120122,7 @@ ${tagErrors.map((e6) => ` \u2022 ${e6}`).join("\n")}
|
|
|
119825
120122
|
}
|
|
119826
120123
|
|
|
119827
120124
|
// src/server.ts
|
|
119828
|
-
var SERVER_VERSION = "3.
|
|
120125
|
+
var SERVER_VERSION = "3.5.0";
|
|
119829
120126
|
function createMcpServer() {
|
|
119830
120127
|
const server = new Server(
|
|
119831
120128
|
{
|
|
@@ -119949,6 +120246,24 @@ function createMcpServer() {
|
|
|
119949
120246
|
return await handleLinkDocumentToInvoice(
|
|
119950
120247
|
asToolArgs(toolArgs)
|
|
119951
120248
|
);
|
|
120249
|
+
case "get-products":
|
|
120250
|
+
return await handleGetProducts(asToolArgs(toolArgs));
|
|
120251
|
+
case "get-product-by-id":
|
|
120252
|
+
return await handleGetProductById(
|
|
120253
|
+
asToolArgs(toolArgs)
|
|
120254
|
+
);
|
|
120255
|
+
case "create-product":
|
|
120256
|
+
return await handleCreateProduct(
|
|
120257
|
+
asToolArgs(toolArgs)
|
|
120258
|
+
);
|
|
120259
|
+
case "update-product":
|
|
120260
|
+
return await handleUpdateProduct(
|
|
120261
|
+
asToolArgs(toolArgs)
|
|
120262
|
+
);
|
|
120263
|
+
case "archive-product":
|
|
120264
|
+
return await handleArchiveProduct(
|
|
120265
|
+
asToolArgs(toolArgs)
|
|
120266
|
+
);
|
|
119952
120267
|
case "log-hours":
|
|
119953
120268
|
return await handleLogHours(asToolArgs(toolArgs));
|
|
119954
120269
|
case "get-github-file":
|