feat(mcps): add full CRUD capabilities to klz-payload-mcp

This commit is contained in:
2026-03-05 12:53:47 +01:00
parent f0d1fb6647
commit 822e8a9d0f

View File

@@ -38,6 +38,57 @@ const SEARCH_PRODUCTS_TOOL: Tool = {
},
};
const GET_PRODUCT_TOOL: Tool = {
name: "payload_get_product",
description: "Get a specific product by its slug or ID",
inputSchema: {
type: "object",
properties: {
slug: { type: "string", description: "Product slug" },
id: { type: "string", description: "Product ID (if slug is not used)" }
},
},
};
const CREATE_PRODUCT_TOOL: Tool = {
name: "payload_create_product",
description: "Create a new product in KLZ Payload CMS",
inputSchema: {
type: "object",
properties: {
title: { type: "string", description: "Product title" },
slug: { type: "string", description: "Product slug" },
data: { type: "object", description: "Additional product data (JSON)", additionalProperties: true }
},
required: ["title"]
},
};
const UPDATE_PRODUCT_TOOL: Tool = {
name: "payload_update_product",
description: "Update an existing product in KLZ Payload CMS",
inputSchema: {
type: "object",
properties: {
id: { type: "string", description: "Product ID to update" },
data: { type: "object", description: "Product data to update (JSON)", additionalProperties: true }
},
required: ["id", "data"]
},
};
const DELETE_PRODUCT_TOOL: Tool = {
name: "payload_delete_product",
description: "Delete a product from KLZ Payload CMS",
inputSchema: {
type: "object",
properties: {
id: { type: "string", description: "Product ID to delete" }
},
required: ["id"]
},
};
const LIST_LEADS_TOOL: Tool = {
name: "payload_list_leads",
description: "List recent lead inquiries and contact requests",
@@ -49,6 +100,56 @@ const LIST_LEADS_TOOL: Tool = {
},
};
const GET_LEAD_TOOL: Tool = {
name: "payload_get_lead",
description: "Get a specific lead by ID",
inputSchema: {
type: "object",
properties: {
id: { type: "string", description: "Lead ID" }
},
required: ["id"]
},
};
const CREATE_LEAD_TOOL: Tool = {
name: "payload_create_lead",
description: "Create a new lead in KLZ Payload CMS",
inputSchema: {
type: "object",
properties: {
email: { type: "string", description: "Lead email address" },
data: { type: "object", description: "Additional lead data (JSON)", additionalProperties: true }
},
required: ["email"]
},
};
const UPDATE_LEAD_TOOL: Tool = {
name: "payload_update_lead",
description: "Update an existing lead in KLZ Payload CMS",
inputSchema: {
type: "object",
properties: {
id: { type: "string", description: "Lead ID to update" },
data: { type: "object", description: "Lead data to update (JSON)", additionalProperties: true }
},
required: ["id", "data"]
},
};
const DELETE_LEAD_TOOL: Tool = {
name: "payload_delete_lead",
description: "Delete a lead from KLZ Payload CMS",
inputSchema: {
type: "object",
properties: {
id: { type: "string", description: "Lead ID to delete" }
},
required: ["id"]
},
};
const LIST_PAGES_TOOL: Tool = {
name: "payload_list_pages",
description: "List pages from KLZ Payload CMS",
@@ -181,7 +282,15 @@ const server = new Server(
server.setRequestHandler(ListToolsRequestSchema, async () => ({
tools: [
SEARCH_PRODUCTS_TOOL,
GET_PRODUCT_TOOL,
CREATE_PRODUCT_TOOL,
UPDATE_PRODUCT_TOOL,
DELETE_PRODUCT_TOOL,
LIST_LEADS_TOOL,
GET_LEAD_TOOL,
CREATE_LEAD_TOOL,
UPDATE_LEAD_TOOL,
DELETE_LEAD_TOOL,
LIST_PAGES_TOOL,
GET_PAGE_TOOL,
CREATE_PAGE_TOOL,
@@ -213,7 +322,54 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
});
return { content: [{ type: "text", text: JSON.stringify(res.data.docs, null, 2) }] };
} catch (e: any) {
return { isError: true, content: [{ type: "text", text: `Error: ${e.message}` }] };
return { isError: true, content: [{ type: "text", text: `Error: ${e.response?.data?.errors?.[0]?.message || e.message}` }] };
}
}
if (request.params.name === "payload_get_product") {
const { slug, id } = request.params.arguments as any;
try {
if (id) {
const res = await payloadClient.get(`/products/${id}`);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
} else if (slug) {
const res = await payloadClient.get('/products', { params: { where: { slug: { equals: slug } }, limit: 1 } });
return { content: [{ type: "text", text: JSON.stringify(res.data.docs[0] || {}, null, 2) }] };
}
return { isError: true, content: [{ type: "text", text: "Error: must provide slug or id" }] };
} catch (e: any) {
return { isError: true, content: [{ type: "text", text: `Error: ${e.response?.data?.errors?.[0]?.message || e.message}` }] };
}
}
if (request.params.name === "payload_create_product") {
const { title, slug, data = {} } = request.params.arguments as any;
try {
const payload = { title, slug, _status: 'draft', ...data };
const res = await payloadClient.post('/products', payload);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
} catch (e: any) {
return { isError: true, content: [{ type: "text", text: `Error: ${JSON.stringify(e.response?.data) || e.message}` }] };
}
}
if (request.params.name === "payload_update_product") {
const { id, data } = request.params.arguments as any;
try {
const res = await payloadClient.patch(`/products/${id}`, data);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
} catch (e: any) {
return { isError: true, content: [{ type: "text", text: `Error: ${JSON.stringify(e.response?.data) || e.message}` }] };
}
}
if (request.params.name === "payload_delete_product") {
const { id } = request.params.arguments as any;
try {
const res = await payloadClient.delete(`/products/${id}`);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
} catch (e: any) {
return { isError: true, content: [{ type: "text", text: `Error: ${JSON.stringify(e.response?.data) || e.message}` }] };
}
}
@@ -225,10 +381,52 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
});
return { content: [{ type: "text", text: JSON.stringify(res.data.docs, null, 2) }] };
} catch (e: any) {
return { isError: true, content: [{ type: "text", text: `Error: ${e.message}` }] };
return { isError: true, content: [{ type: "text", text: `Error: ${e.response?.data?.errors?.[0]?.message || e.message}` }] };
}
}
if (request.params.name === "payload_get_lead") {
const { id } = request.params.arguments as any;
try {
const res = await payloadClient.get(`/leads/${id}`);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
} catch (e: any) {
return { isError: true, content: [{ type: "text", text: `Error: ${e.response?.data?.errors?.[0]?.message || e.message}` }] };
}
}
if (request.params.name === "payload_create_lead") {
const { email, data = {} } = request.params.arguments as any;
try {
const payload = { email, ...data };
const res = await payloadClient.post('/leads', payload);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
} catch (e: any) {
return { isError: true, content: [{ type: "text", text: `Error: ${JSON.stringify(e.response?.data) || e.message}` }] };
}
}
if (request.params.name === "payload_update_lead") {
const { id, data } = request.params.arguments as any;
try {
const res = await payloadClient.patch(`/leads/${id}`, data);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
} catch (e: any) {
return { isError: true, content: [{ type: "text", text: `Error: ${JSON.stringify(e.response?.data) || e.message}` }] };
}
}
if (request.params.name === "payload_delete_lead") {
const { id } = request.params.arguments as any;
try {
const res = await payloadClient.delete(`/leads/${id}`);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
} catch (e: any) {
return { isError: true, content: [{ type: "text", text: `Error: ${JSON.stringify(e.response?.data) || e.message}` }] };
}
}
if (request.params.name === "payload_list_pages") {
const { limit = 10 } = request.params.arguments as any;
try {