fix(mcp): exclude archived records
This commit is contained in:
@@ -1,16 +1,42 @@
|
|||||||
import { McpToolResult } from "./types"
|
import { McpToolResult } from "./types"
|
||||||
|
|
||||||
|
const OMIT_ARCHIVED = Symbol("omit-archived")
|
||||||
|
|
||||||
|
function omitArchivedRecords(value: unknown): unknown | typeof OMIT_ARCHIVED {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
return value
|
||||||
|
.map(omitArchivedRecords)
|
||||||
|
.filter((item) => item !== OMIT_ARCHIVED)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!value || typeof value !== "object") return value
|
||||||
|
|
||||||
|
const prototype = Object.getPrototypeOf(value)
|
||||||
|
if (prototype !== Object.prototype && prototype !== null) return value
|
||||||
|
|
||||||
|
const record = value as Record<string, unknown>
|
||||||
|
if (record.archived === true) return OMIT_ARCHIVED
|
||||||
|
|
||||||
|
return Object.fromEntries(
|
||||||
|
Object.entries(record)
|
||||||
|
.map(([key, item]) => [key, omitArchivedRecords(item)] as const)
|
||||||
|
.filter(([, item]) => item !== OMIT_ARCHIVED),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export function asToolResult(payload: unknown): McpToolResult {
|
export function asToolResult(payload: unknown): McpToolResult {
|
||||||
|
const sanitizedPayload = omitArchivedRecords(payload)
|
||||||
|
const resultPayload = sanitizedPayload === OMIT_ARCHIVED ? {} : sanitizedPayload
|
||||||
const structuredContent =
|
const structuredContent =
|
||||||
payload && typeof payload === "object" && !Array.isArray(payload)
|
resultPayload && typeof resultPayload === "object" && !Array.isArray(resultPayload)
|
||||||
? payload as Record<string, unknown>
|
? resultPayload as Record<string, unknown>
|
||||||
: { result: payload }
|
: { result: resultPayload }
|
||||||
|
|
||||||
return {
|
return {
|
||||||
content: [
|
content: [
|
||||||
{
|
{
|
||||||
type: "text",
|
type: "text",
|
||||||
text: JSON.stringify(payload, null, 2),
|
text: JSON.stringify(resultPayload, null, 2),
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
structuredContent,
|
structuredContent,
|
||||||
@@ -33,4 +59,3 @@ export function asToolError(error: unknown): McpToolResult {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -437,7 +437,6 @@ export const accountingTools: McpTool[] = [
|
|||||||
state: { type: "string", description: "Optionaler Statusfilter, z. B. Entwurf oder Gebucht." },
|
state: { type: "string", description: "Optionaler Statusfilter, z. B. Entwurf oder Gebucht." },
|
||||||
customer: { type: "number" },
|
customer: { type: "number" },
|
||||||
project: { type: "number" },
|
project: { type: "number" },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -455,7 +454,7 @@ export const accountingTools: McpTool[] = [
|
|||||||
if (state) conditions.push(eq(createddocuments.state, state))
|
if (state) conditions.push(eq(createddocuments.state, state))
|
||||||
if (customer) conditions.push(eq(createddocuments.customer, customer))
|
if (customer) conditions.push(eq(createddocuments.customer, customer))
|
||||||
if (project) conditions.push(eq(createddocuments.project, project))
|
if (project) conditions.push(eq(createddocuments.project, project))
|
||||||
if (args.includeArchived !== true) conditions.push(eq(createddocuments.archived, false))
|
conditions.push(eq(createddocuments.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
@@ -486,7 +485,7 @@ export const accountingTools: McpTool[] = [
|
|||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
.from(createddocuments)
|
.from(createddocuments)
|
||||||
.where(and(eq(createddocuments.id, id), eq(createddocuments.tenant, context.tenantId)))
|
.where(and(eq(createddocuments.id, id), eq(createddocuments.tenant, context.tenantId), eq(createddocuments.archived, false)))
|
||||||
.limit(1)
|
.limit(1)
|
||||||
|
|
||||||
if (!rows[0]) throw new Error("Ausgangsbeleg nicht gefunden")
|
if (!rows[0]) throw new Error("Ausgangsbeleg nicht gefunden")
|
||||||
@@ -754,7 +753,6 @@ export const accountingTools: McpTool[] = [
|
|||||||
properties: {
|
properties: {
|
||||||
state: { type: "string", description: "Optionaler Statusfilter." },
|
state: { type: "string", description: "Optionaler Statusfilter." },
|
||||||
paid: { type: "boolean", description: "Optionaler Zahlungsstatus." },
|
paid: { type: "boolean", description: "Optionaler Zahlungsstatus." },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -764,7 +762,7 @@ export const accountingTools: McpTool[] = [
|
|||||||
|
|
||||||
if (state) conditions.push(eq(incominginvoices.state, state))
|
if (state) conditions.push(eq(incominginvoices.state, state))
|
||||||
if (typeof args.paid === "boolean") conditions.push(eq(incominginvoices.paid, args.paid))
|
if (typeof args.paid === "boolean") conditions.push(eq(incominginvoices.paid, args.paid))
|
||||||
if (args.includeArchived !== true) conditions.push(eq(incominginvoices.archived, false))
|
conditions.push(eq(incominginvoices.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
@@ -795,7 +793,7 @@ export const accountingTools: McpTool[] = [
|
|||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
.from(incominginvoices)
|
.from(incominginvoices)
|
||||||
.where(and(eq(incominginvoices.id, id), eq(incominginvoices.tenant, context.tenantId)))
|
.where(and(eq(incominginvoices.id, id), eq(incominginvoices.tenant, context.tenantId), eq(incominginvoices.archived, false)))
|
||||||
.limit(1)
|
.limit(1)
|
||||||
|
|
||||||
if (!rows[0]) throw new Error("Eingangsrechnung nicht gefunden")
|
if (!rows[0]) throw new Error("Eingangsrechnung nicht gefunden")
|
||||||
@@ -1142,7 +1140,6 @@ export const accountingTools: McpTool[] = [
|
|||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
account: { type: "number", description: "Optionale Bankkonto-ID." },
|
account: { type: "number", description: "Optionale Bankkonto-ID." },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1151,7 +1148,7 @@ export const accountingTools: McpTool[] = [
|
|||||||
const account = numberArg(args, "account")
|
const account = numberArg(args, "account")
|
||||||
|
|
||||||
if (account) conditions.push(eq(bankstatements.account, account))
|
if (account) conditions.push(eq(bankstatements.account, account))
|
||||||
if (args.includeArchived !== true) conditions.push(eq(bankstatements.archived, false))
|
conditions.push(eq(bankstatements.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
@@ -1182,7 +1179,7 @@ export const accountingTools: McpTool[] = [
|
|||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
.from(bankstatements)
|
.from(bankstatements)
|
||||||
.where(and(eq(bankstatements.id, id), eq(bankstatements.tenant, context.tenantId)))
|
.where(and(eq(bankstatements.id, id), eq(bankstatements.tenant, context.tenantId), eq(bankstatements.archived, false)))
|
||||||
.limit(1)
|
.limit(1)
|
||||||
|
|
||||||
if (!rows[0]) throw new Error("Bankumsatz nicht gefunden")
|
if (!rows[0]) throw new Error("Bankumsatz nicht gefunden")
|
||||||
@@ -1199,7 +1196,6 @@ export const accountingTools: McpTool[] = [
|
|||||||
properties: {
|
properties: {
|
||||||
bankstatement: { type: "number" },
|
bankstatement: { type: "number" },
|
||||||
incominginvoice: { type: "number" },
|
incominginvoice: { type: "number" },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -1210,7 +1206,7 @@ export const accountingTools: McpTool[] = [
|
|||||||
|
|
||||||
if (bankstatement) conditions.push(eq(statementallocations.bankstatement, bankstatement))
|
if (bankstatement) conditions.push(eq(statementallocations.bankstatement, bankstatement))
|
||||||
if (incominginvoice) conditions.push(eq(statementallocations.incominginvoice, incominginvoice))
|
if (incominginvoice) conditions.push(eq(statementallocations.incominginvoice, incominginvoice))
|
||||||
if (args.includeArchived !== true) conditions.push(eq(statementallocations.archived, false))
|
conditions.push(eq(statementallocations.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ export const masterdataTools: McpTool[] = [
|
|||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
.from(customers)
|
.from(customers)
|
||||||
.where(and(eq(customers.id, id), eq(customers.tenant, context.tenantId)))
|
.where(and(eq(customers.id, id), eq(customers.tenant, context.tenantId), eq(customers.archived, false)))
|
||||||
.limit(1)
|
.limit(1)
|
||||||
|
|
||||||
if (!rows[0]) throw new Error("Kunde nicht gefunden")
|
if (!rows[0]) throw new Error("Kunde nicht gefunden")
|
||||||
@@ -71,7 +71,6 @@ export const masterdataTools: McpTool[] = [
|
|||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
query: { type: "string", description: "Suchtext für Name, Lieferantennummer oder Notizen." },
|
query: { type: "string", description: "Suchtext für Name, Lieferantennummer oder Notizen." },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -86,7 +85,7 @@ export const masterdataTools: McpTool[] = [
|
|||||||
ilike(vendors.notes, `%${query}%`)
|
ilike(vendors.notes, `%${query}%`)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
if (args.includeArchived !== true) conditions.push(eq(vendors.archived, false))
|
conditions.push(eq(vendors.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
@@ -115,7 +114,7 @@ export const masterdataTools: McpTool[] = [
|
|||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
.from(vendors)
|
.from(vendors)
|
||||||
.where(and(eq(vendors.id, id), eq(vendors.tenant, context.tenantId)))
|
.where(and(eq(vendors.id, id), eq(vendors.tenant, context.tenantId), eq(vendors.archived, false)))
|
||||||
.limit(1)
|
.limit(1)
|
||||||
|
|
||||||
if (!rows[0]) throw new Error("Lieferant nicht gefunden")
|
if (!rows[0]) throw new Error("Lieferant nicht gefunden")
|
||||||
@@ -133,7 +132,6 @@ export const masterdataTools: McpTool[] = [
|
|||||||
query: { type: "string", description: "Suchtext für Name, E-Mail, Telefon, Rolle oder Notizen." },
|
query: { type: "string", description: "Suchtext für Name, E-Mail, Telefon, Rolle oder Notizen." },
|
||||||
customer: { type: "number" },
|
customer: { type: "number" },
|
||||||
vendor: { type: "number" },
|
vendor: { type: "number" },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -157,7 +155,7 @@ export const masterdataTools: McpTool[] = [
|
|||||||
}
|
}
|
||||||
if (customer) conditions.push(eq(contacts.customer, customer))
|
if (customer) conditions.push(eq(contacts.customer, customer))
|
||||||
if (vendor) conditions.push(eq(contacts.vendor, vendor))
|
if (vendor) conditions.push(eq(contacts.vendor, vendor))
|
||||||
if (args.includeArchived !== true) conditions.push(eq(contacts.archived, false))
|
conditions.push(eq(contacts.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
@@ -178,7 +176,6 @@ export const masterdataTools: McpTool[] = [
|
|||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
query: { type: "string", description: "Suchtext für Name, Artikelnummer, Hersteller, EAN, Barcode oder Beschreibung." },
|
query: { type: "string", description: "Suchtext für Name, Artikelnummer, Hersteller, EAN, Barcode oder Beschreibung." },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -197,7 +194,7 @@ export const masterdataTools: McpTool[] = [
|
|||||||
ilike(products.description, `%${query}%`)
|
ilike(products.description, `%${query}%`)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
if (args.includeArchived !== true) conditions.push(eq(products.archived, false))
|
conditions.push(eq(products.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
@@ -226,7 +223,7 @@ export const masterdataTools: McpTool[] = [
|
|||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
.from(products)
|
.from(products)
|
||||||
.where(and(eq(products.id, id), eq(products.tenant, context.tenantId)))
|
.where(and(eq(products.id, id), eq(products.tenant, context.tenantId), eq(products.archived, false)))
|
||||||
.limit(1)
|
.limit(1)
|
||||||
|
|
||||||
if (!rows[0]) throw new Error("Artikel nicht gefunden")
|
if (!rows[0]) throw new Error("Artikel nicht gefunden")
|
||||||
@@ -242,7 +239,6 @@ export const masterdataTools: McpTool[] = [
|
|||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
query: { type: "string", description: "Suchtext für Name, Leistungsnummer oder Beschreibung." },
|
query: { type: "string", description: "Suchtext für Name, Leistungsnummer oder Beschreibung." },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -256,7 +252,7 @@ export const masterdataTools: McpTool[] = [
|
|||||||
ilike(services.description, `%${query}%`)
|
ilike(services.description, `%${query}%`)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
if (args.includeArchived !== true) conditions.push(eq(services.archived, false))
|
conditions.push(eq(services.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
@@ -285,7 +281,7 @@ export const masterdataTools: McpTool[] = [
|
|||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
.from(services)
|
.from(services)
|
||||||
.where(and(eq(services.id, id), eq(services.tenant, context.tenantId)))
|
.where(and(eq(services.id, id), eq(services.tenant, context.tenantId), eq(services.archived, false)))
|
||||||
.limit(1)
|
.limit(1)
|
||||||
|
|
||||||
if (!rows[0]) throw new Error("Leistung nicht gefunden")
|
if (!rows[0]) throw new Error("Leistung nicht gefunden")
|
||||||
@@ -303,7 +299,6 @@ export const masterdataTools: McpTool[] = [
|
|||||||
query: { type: "string", description: "Suchtext für Nummer, Name oder Beschreibung." },
|
query: { type: "string", description: "Suchtext für Nummer, Name oder Beschreibung." },
|
||||||
branch: { type: "number" },
|
branch: { type: "number" },
|
||||||
project: { type: "number" },
|
project: { type: "number" },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -322,7 +317,7 @@ export const masterdataTools: McpTool[] = [
|
|||||||
}
|
}
|
||||||
if (branch) conditions.push(eq(costcentres.branch, branch))
|
if (branch) conditions.push(eq(costcentres.branch, branch))
|
||||||
if (project) conditions.push(eq(costcentres.project, project))
|
if (project) conditions.push(eq(costcentres.project, project))
|
||||||
if (args.includeArchived !== true) conditions.push(eq(costcentres.archived, false))
|
conditions.push(eq(costcentres.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
@@ -351,7 +346,7 @@ export const masterdataTools: McpTool[] = [
|
|||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
.from(costcentres)
|
.from(costcentres)
|
||||||
.where(and(eq(costcentres.id, id), eq(costcentres.tenant, context.tenantId)))
|
.where(and(eq(costcentres.id, id), eq(costcentres.tenant, context.tenantId), eq(costcentres.archived, false)))
|
||||||
.limit(1)
|
.limit(1)
|
||||||
|
|
||||||
if (!rows[0]) throw new Error("Kostenstelle nicht gefunden")
|
if (!rows[0]) throw new Error("Kostenstelle nicht gefunden")
|
||||||
@@ -367,7 +362,6 @@ export const masterdataTools: McpTool[] = [
|
|||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
query: { type: "string", description: "Suchtext für Nummer, Name oder Beschreibung." },
|
query: { type: "string", description: "Suchtext für Nummer, Name oder Beschreibung." },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -382,7 +376,7 @@ export const masterdataTools: McpTool[] = [
|
|||||||
ilike(branches.description, `%${query}%`)
|
ilike(branches.description, `%${query}%`)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
if (args.includeArchived !== true) conditions.push(eq(branches.archived, false))
|
conditions.push(eq(branches.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
@@ -404,7 +398,6 @@ export const masterdataTools: McpTool[] = [
|
|||||||
properties: {
|
properties: {
|
||||||
query: { type: "string", description: "Suchtext für Name oder Beschreibung." },
|
query: { type: "string", description: "Suchtext für Name oder Beschreibung." },
|
||||||
branch: { type: "number" },
|
branch: { type: "number" },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -420,7 +413,7 @@ export const masterdataTools: McpTool[] = [
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
if (branch) conditions.push(eq(teams.branch, branch))
|
if (branch) conditions.push(eq(teams.branch, branch))
|
||||||
if (args.includeArchived !== true) conditions.push(eq(teams.archived, false))
|
conditions.push(eq(teams.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
@@ -441,7 +434,6 @@ export const masterdataTools: McpTool[] = [
|
|||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
query: { type: "string", description: "Suchtext für Name, Kennzeichen, FIN oder Farbe." },
|
query: { type: "string", description: "Suchtext für Name, Kennzeichen, FIN oder Farbe." },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -457,7 +449,7 @@ export const masterdataTools: McpTool[] = [
|
|||||||
ilike(vehicles.color, `%${query}%`)
|
ilike(vehicles.color, `%${query}%`)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
if (args.includeArchived !== true) conditions.push(eq(vehicles.archived, false))
|
conditions.push(eq(vehicles.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
@@ -479,7 +471,6 @@ export const masterdataTools: McpTool[] = [
|
|||||||
properties: {
|
properties: {
|
||||||
query: { type: "string", description: "Suchtext für Name, Artikelnummer, Seriennummer, Hersteller oder Beschreibung." },
|
query: { type: "string", description: "Suchtext für Name, Artikelnummer, Seriennummer, Hersteller oder Beschreibung." },
|
||||||
vendor: { type: "number" },
|
vendor: { type: "number" },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -499,7 +490,7 @@ export const masterdataTools: McpTool[] = [
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
if (vendor) conditions.push(eq(inventoryitems.vendor, vendor))
|
if (vendor) conditions.push(eq(inventoryitems.vendor, vendor))
|
||||||
if (args.includeArchived !== true) conditions.push(eq(inventoryitems.archived, false))
|
conditions.push(eq(inventoryitems.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
@@ -528,7 +519,7 @@ export const masterdataTools: McpTool[] = [
|
|||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
.from(inventoryitems)
|
.from(inventoryitems)
|
||||||
.where(and(eq(inventoryitems.id, id), eq(inventoryitems.tenant, context.tenantId)))
|
.where(and(eq(inventoryitems.id, id), eq(inventoryitems.tenant, context.tenantId), eq(inventoryitems.archived, false)))
|
||||||
.limit(1)
|
.limit(1)
|
||||||
|
|
||||||
if (!rows[0]) throw new Error("Inventar nicht gefunden")
|
if (!rows[0]) throw new Error("Inventar nicht gefunden")
|
||||||
@@ -568,4 +559,3 @@ export const masterdataTools: McpTool[] = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ export const organisationTools: McpTool[] = [
|
|||||||
type: "object",
|
type: "object",
|
||||||
properties: {
|
properties: {
|
||||||
query: { type: "string", description: "Suchtext für Name, Kundennummer, Vorname, Nachname oder Notizen." },
|
query: { type: "string", description: "Suchtext für Name, Kundennummer, Vorname, Nachname oder Notizen." },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -47,7 +46,7 @@ export const organisationTools: McpTool[] = [
|
|||||||
ilike(customers.notes, `%${query}%`)
|
ilike(customers.notes, `%${query}%`)
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
if (args.includeArchived !== true) conditions.push(eq(customers.archived, false))
|
conditions.push(eq(customers.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select({
|
.select({
|
||||||
@@ -80,7 +79,6 @@ export const organisationTools: McpTool[] = [
|
|||||||
query: { type: "string", description: "Suchtext für Name, Projektnummer, Kundenreferenz oder Notizen." },
|
query: { type: "string", description: "Suchtext für Name, Projektnummer, Kundenreferenz oder Notizen." },
|
||||||
customer: { type: "number" },
|
customer: { type: "number" },
|
||||||
activePhase: { type: "string" },
|
activePhase: { type: "string" },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -100,7 +98,7 @@ export const organisationTools: McpTool[] = [
|
|||||||
}
|
}
|
||||||
if (customer) conditions.push(eq(projects.customer, customer))
|
if (customer) conditions.push(eq(projects.customer, customer))
|
||||||
if (activePhase) conditions.push(eq(projects.active_phase, activePhase))
|
if (activePhase) conditions.push(eq(projects.active_phase, activePhase))
|
||||||
if (args.includeArchived !== true) conditions.push(eq(projects.archived, false))
|
conditions.push(eq(projects.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
@@ -131,7 +129,7 @@ export const organisationTools: McpTool[] = [
|
|||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
.from(projects)
|
.from(projects)
|
||||||
.where(and(eq(projects.id, id), eq(projects.tenant, context.tenantId)))
|
.where(and(eq(projects.id, id), eq(projects.tenant, context.tenantId), eq(projects.archived, false)))
|
||||||
.limit(1)
|
.limit(1)
|
||||||
|
|
||||||
if (!rows[0]) throw new Error("Projekt nicht gefunden")
|
if (!rows[0]) throw new Error("Projekt nicht gefunden")
|
||||||
@@ -219,7 +217,6 @@ export const organisationTools: McpTool[] = [
|
|||||||
properties: {
|
properties: {
|
||||||
query: { type: "string", description: "Suchtext für Name." },
|
query: { type: "string", description: "Suchtext für Name." },
|
||||||
customer: { type: "number" },
|
customer: { type: "number" },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -230,7 +227,7 @@ export const organisationTools: McpTool[] = [
|
|||||||
|
|
||||||
if (query) conditions.push(ilike(plants.name, `%${query}%`))
|
if (query) conditions.push(ilike(plants.name, `%${query}%`))
|
||||||
if (customer) conditions.push(eq(plants.customer, customer))
|
if (customer) conditions.push(eq(plants.customer, customer))
|
||||||
if (args.includeArchived !== true) conditions.push(eq(plants.archived, false))
|
conditions.push(eq(plants.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
@@ -254,7 +251,6 @@ export const organisationTools: McpTool[] = [
|
|||||||
project: { type: "number" },
|
project: { type: "number" },
|
||||||
customer: { type: "number" },
|
customer: { type: "number" },
|
||||||
eventtype: { type: "string" },
|
eventtype: { type: "string" },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -275,7 +271,7 @@ export const organisationTools: McpTool[] = [
|
|||||||
if (project) conditions.push(eq(events.project, project))
|
if (project) conditions.push(eq(events.project, project))
|
||||||
if (customer) conditions.push(eq(events.customer, customer))
|
if (customer) conditions.push(eq(events.customer, customer))
|
||||||
if (eventtype) conditions.push(eq(events.eventtype, eventtype))
|
if (eventtype) conditions.push(eq(events.eventtype, eventtype))
|
||||||
if (args.includeArchived !== true) conditions.push(eq(events.archived, false))
|
conditions.push(eq(events.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
@@ -298,7 +294,6 @@ export const organisationTools: McpTool[] = [
|
|||||||
query: { type: "string", description: "Suchtext für Name, Beschreibung oder Kategorie." },
|
query: { type: "string", description: "Suchtext für Name, Beschreibung oder Kategorie." },
|
||||||
project: { type: "number" },
|
project: { type: "number" },
|
||||||
customer: { type: "number" },
|
customer: { type: "number" },
|
||||||
includeArchived: { type: "boolean", default: false },
|
|
||||||
limit: { type: "number", minimum: 1, maximum: 100 },
|
limit: { type: "number", minimum: 1, maximum: 100 },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -317,7 +312,7 @@ export const organisationTools: McpTool[] = [
|
|||||||
}
|
}
|
||||||
if (project) conditions.push(eq(tasks.project, project))
|
if (project) conditions.push(eq(tasks.project, project))
|
||||||
if (customer) conditions.push(eq(tasks.customer, customer))
|
if (customer) conditions.push(eq(tasks.customer, customer))
|
||||||
if (args.includeArchived !== true) conditions.push(eq(tasks.archived, false))
|
conditions.push(eq(tasks.archived, false))
|
||||||
|
|
||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
@@ -348,7 +343,7 @@ export const organisationTools: McpTool[] = [
|
|||||||
const rows = await context.server.db
|
const rows = await context.server.db
|
||||||
.select()
|
.select()
|
||||||
.from(tasks)
|
.from(tasks)
|
||||||
.where(and(eq(tasks.id, id), eq(tasks.tenant, context.tenantId)))
|
.where(and(eq(tasks.id, id), eq(tasks.tenant, context.tenantId), eq(tasks.archived, false)))
|
||||||
.limit(1)
|
.limit(1)
|
||||||
|
|
||||||
if (!rows[0]) throw new Error("Aufgabe nicht gefunden")
|
if (!rows[0]) throw new Error("Aufgabe nicht gefunden")
|
||||||
|
|||||||
37
backend/tests/mcpArchivedResults.test.ts
Normal file
37
backend/tests/mcpArchivedResults.test.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import assert from "node:assert/strict"
|
||||||
|
import test from "node:test"
|
||||||
|
import { mcpTools } from "../src/mcp/registry"
|
||||||
|
import { asToolResult } from "../src/mcp/result"
|
||||||
|
|
||||||
|
test("removes archived records from MCP text and structured output", () => {
|
||||||
|
const result = asToolResult({
|
||||||
|
rows: [
|
||||||
|
{ id: 1, archived: false, name: "Aktiv" },
|
||||||
|
{ id: 2, archived: true, name: "Archiviert" },
|
||||||
|
],
|
||||||
|
nested: {
|
||||||
|
current: { id: 3, archived: false },
|
||||||
|
previous: { id: 4, archived: true },
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.deepEqual(result.structuredContent, {
|
||||||
|
rows: [{ id: 1, archived: false, name: "Aktiv" }],
|
||||||
|
nested: { current: { id: 3, archived: false } },
|
||||||
|
})
|
||||||
|
assert.deepEqual(JSON.parse(result.content[0].text), result.structuredContent)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("does not expose a singular archived record", () => {
|
||||||
|
const result = asToolResult({ task: { id: 1, archived: true } })
|
||||||
|
|
||||||
|
assert.deepEqual(result.structuredContent, {})
|
||||||
|
assert.deepEqual(JSON.parse(result.content[0].text), {})
|
||||||
|
})
|
||||||
|
|
||||||
|
test("does not advertise includeArchived on MCP tools", () => {
|
||||||
|
for (const tool of mcpTools) {
|
||||||
|
const properties = (tool.inputSchema.properties || {}) as Record<string, unknown>
|
||||||
|
assert.equal(properties.includeArchived, undefined, tool.name)
|
||||||
|
}
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user