7.0 KiB
7.0 KiB
Handoff: update_category_image Feature Request Analysis
1. Observation
From inspecting the codebase, the following files and lines were analyzed:
- Prisma Schema (
apps/backend/prisma/schema.prismalines 33-42):Observation: The database schema modelmodel Category { id Int @id @default(autoincrement()) name String @unique imageUrl String? products Product[] attributes AttributeDefinition[] translations CategoryTranslation[] createdAt DateTime @default(now()) updatedAt DateTime @updatedAt }Categoryalready contains a nullableimageUrlfield. - Shared Types (
packages/types/index.tslines 9-17):Observation: The shared TypeScript types forexport interface Category { id: number name: TranslatableString imageUrl?: string | null _count?: { products: number } translations?: { langCode: string; name: string }[] createdAt?: string updatedAt?: string }Categoryalready declareimageUrlas optional/nullable (imageUrl?: string | null). - Backend Category Routes (
apps/backend/src/routes/categories.tslines 190-218): The existing PUT route performs full/partial category updates:.put("/:id", async ({ params, body, status }) => { const id = parseInt(params.id); if (isNaN(id)) return status(400, { message: "Invalid category ID" }); try { const category = await prisma.category.update({ where: { id }, data: { name: body.name, imageUrl: body.imageUrl, }, }); return category; ... }, { body: t.Object({ name: t.Optional(t.String()), imageUrl: t.Optional(t.Union([t.String(), t.Null()])), }) }) - MCP Server Schema and Handler (
apps/mcp-server/index.tslines 121-132, 862-870): Exposed categories tools likeupdate_category_translationdefine and route requests via a custom axiosapiinstance:// Tool definition { name: "update_category_translation", description: "Add or update translations for a specific category. Do NOT use this tool for products.", inputSchema: { type: "object", properties: { id: { type: "number", description: "Category ID" }, lang: { type: "string", description: "Language code (th, en, ja, zh, vi, ko)" }, name: { type: "string", description: "Translated category name" } }, required: ["id", "lang", "name"] } } // Tool handler case "update_category_translation": { const { id, lang, name } = params as any; const res = await api.patch(`/categories/${id}/translations`, { name: { [lang]: name } }); return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] }; }
2. Logic Chain
- Since the Category model in the database (
prisma/schema.prisma) and theCategorytype interface inpackages/types/index.tsalready support theimageUrlfield, no modifications to database structures, Prisma migrations, or the types package are needed. - In
apps/backend/src/routes/categories.ts, we need to implementPATCH /categories/:id/image. It should accept a body withimageUrl: t.Union([t.String(), t.Null()])to update/clear the category image. - In
apps/mcp-server/index.ts, we need to define theupdate_category_imagetool schema underListToolsRequestSchemaand map its invocation underCallToolRequestSchema's switch-case block, forwarding the payload to the new backend PATCH endpoint.
3. Caveats
- In-place backend compilation: The backend TypeScript config includes
"declaration": truewithout"outDir", meaning transpiled files (.js,.d.ts, and.js.map) are produced directly inside thesrc/directory. If these transpiled files are checked into the repository, they should be regenerated after modifying.tsfiles by runningnpm run buildor similar. - JSON Schema type support: The MCP tool definition schema uses
type: ["string", "null"]forimageUrlto explicitly support clearing images. If an MCP client doesn't support array types, passing an empty string""is also a valid fallback.
4. Conclusion
To implement the update_category_image feature:
-
Implement the following route in
apps/backend/src/routes/categories.ts(e.g. before the.post("/")route):.patch("/:id/image", async ({ params, body, status }) => { const id = parseInt(params.id); if (isNaN(id)) return status(400, { message: "Invalid category ID" }); try { const category = await prisma.category.update({ where: { id }, data: { imageUrl: body.imageUrl, }, }); return category; } catch (err: any) { if (err.code === "P2025") { return status(404, { message: "Category not found" }); } console.error("Update category image error:", err); return status(500, { message: "Failed to update category image" }); } }, { body: t.Object({ imageUrl: t.Union([t.String(), t.Null()]), }) }) -
Register the tool in
apps/mcp-server/index.tsunderListToolsRequestSchematools list:{ name: "update_category_image", description: "Update the image URL for a specific category.", inputSchema: { type: "object", properties: { id: { type: "number", description: "Category ID" }, imageUrl: { type: ["string", "null"], description: "New image URL, or null/empty string to remove the image" } }, required: ["id", "imageUrl"] } }, -
Implement the handler in
apps/mcp-server/index.tsunderCallToolRequestSchema'sswitch (request.params.name)block:case "update_category_image": { const { id, imageUrl } = params as any; const res = await api.patch(`/categories/${id}/image`, { imageUrl: imageUrl || null }); return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] }; }
5. Verification Method
- Endpoint Verification:
Start the backend server (
bun run devinapps/backend). Call the new endpoint usingcurl:Verify that the response returns the updated category object withcurl -X PATCH http://localhost:3051/api/categories/1/image \ -H "Content-Type: application/json" \ -d '{"imageUrl": "https://example.com/test-image.png"}'imageUrlmatching the provided URL. - MCP Tool Verification:
Start the MCP server and run the tool
update_category_imagevia an MCP client:Verify that the tool succeeds and returns the JSON representation of the updated category.{ "name": "update_category_image", "arguments": { "id": 1, "imageUrl": "https://example.com/test-image.png" } }