feat(vikunja-mcp): add task attachments and extra metadata parameters support
Some checks failed
Monorepo Pipeline / ⚡ Prioritize Release (push) Successful in 2s
Monorepo Pipeline / 🧹 Lint (push) Failing after 1m38s
Monorepo Pipeline / 🧪 Test (push) Successful in 54s
Monorepo Pipeline / 🏗️ Build (push) Successful in 2m38s
Monorepo Pipeline / 🚀 Release (push) Has been skipped
Monorepo Pipeline / 🐳 Build Gatekeeper (Product) (push) Has been skipped
Monorepo Pipeline / 🐳 Build Build-Base (push) Has been skipped
Monorepo Pipeline / 🐳 Build Production Runtime (push) Has been skipped

This commit is contained in:
2026-06-21 12:26:44 +02:00
parent 04462f21e1
commit 985e532c61
4 changed files with 205 additions and 16 deletions

View File

@@ -14,10 +14,14 @@
"@modelcontextprotocol/sdk": "^1.5.0",
"axios": "^1.7.2",
"dotenv": "^17.3.1",
"express": "^4.19.2"
"express": "^4.19.2",
"form-data": "^4.0.5",
"marked": "^18.0.5"
},
"devDependencies": {
"@types/express": "^4.17.21",
"@types/form-data": "^2.5.2",
"@types/marked": "^6.0.0",
"@types/node": "^20.14.10",
"tsx": "^4.19.2",
"typescript": "^5.5.3",

View File

@@ -177,4 +177,29 @@ describe('Vikunja MCP Server - New Tools (RED)', () => {
{ id: 1, comment: 'New Comment', task_id: 42 }
]);
});
it('should support vikunja_create_task and convert markdown description to HTML', async () => {
mockPut.mockResolvedValueOnce({
data: { id: 11, title: 'Markdown Task', description: '<p><strong>Bold</strong> and <em>italic</em></p>\n' }
});
const handler = (server as any)._requestHandlers.get('tools/call');
const response = await handler({
method: 'tools/call',
params: {
name: 'vikunja_create_task',
arguments: {
project_id: 1,
title: 'Markdown Task',
description: '**Bold** and *italic*'
},
},
});
expect(mockPut).toHaveBeenCalledWith('/projects/1/tasks', expect.objectContaining({
title: 'Markdown Task',
description: '<p><strong>Bold</strong> and <em>italic</em></p>\n'
}));
expect(response.isError).toBeUndefined();
});
});

View File

@@ -8,6 +8,9 @@ import {
} from "@modelcontextprotocol/sdk/types.js";
import axios from "axios";
import https from "https";
import fs from "fs";
import path from "path";
import { marked } from "marked";
const VIKUNJA_BASE_URL = process.env.VIKUNJA_BASE_URL || "https://tasks.infra.mintel.me";
const VIKUNJA_API_TOKEN = process.env.VIKUNJA_API_TOKEN;
@@ -63,6 +66,14 @@ const CREATE_TASK_TOOL: Tool = {
project_id: { type: "number", description: "The ID of the project to add the task to" },
title: { type: "string", description: "The title of the task" },
description: { type: "string", description: "Optional description of the task" },
parent_task_id: { type: "number", description: "Optional ID of a parent task to create a subtask" },
due_date: { type: "string", description: "ISO 8601 Date string for due date" },
start_date: { type: "string", description: "ISO 8601 Date string for start date" },
end_date: { type: "string", description: "ISO 8601 Date string for end date" },
priority: { type: "number", description: "Priority level (e.g. 1-5)" },
percent_done: { type: "number", description: "Progress percentage" },
hex_color: { type: "string", description: "Hex color code" },
is_favorite: { type: "boolean", description: "Mark as favorite" }
},
required: ["project_id", "title"],
},
@@ -77,7 +88,14 @@ const UPDATE_TASK_TOOL: Tool = {
task_id: { type: "number", description: "The ID of the task to update" },
done: { type: "boolean", description: "Set to true to mark the task as done" },
title: { type: "string", description: "Update the title" },
description: { type: "string", description: "Update the description" }
description: { type: "string", description: "Update the description" },
due_date: { type: "string", description: "ISO 8601 Date string for due date" },
start_date: { type: "string", description: "ISO 8601 Date string for start date" },
end_date: { type: "string", description: "ISO 8601 Date string for end date" },
priority: { type: "number", description: "Priority level (e.g. 1-5)" },
percent_done: { type: "number", description: "Progress percentage (0-1 or 0-100 depending on API version, try decimals like 0.5 first)" },
hex_color: { type: "string", description: "Hex color code" },
is_favorite: { type: "boolean", description: "Mark as favorite" }
},
required: ["task_id"],
},
@@ -146,6 +164,33 @@ const GET_TASK_COMMENTS_TOOL: Tool = {
}
};
const GET_TASK_ATTACHMENT_TOOL: Tool = {
name: "vikunja_get_task_attachment",
description: "Download a task attachment to a local file",
inputSchema: {
type: "object",
properties: {
task_id: { type: "number", description: "The ID of the task" },
attachment_id: { type: "number", description: "The ID of the attachment" },
save_path: { type: "string", description: "Absolute path to save the file to" }
},
required: ["task_id", "attachment_id", "save_path"]
}
};
const CREATE_TASK_ATTACHMENT_TOOL: Tool = {
name: "vikunja_upload_task_attachment",
description: "Upload an attachment file to a specific task",
inputSchema: {
type: "object",
properties: {
task_id: { type: "number", description: "The ID of the task" },
file_path: { type: "string", description: "Absolute path to the local file to upload" }
},
required: ["task_id", "file_path"]
}
};
// --- Server Setup ---
export const server = new Server(
{ name: "vikunja-mcp", version: "1.0.0" },
@@ -162,7 +207,9 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
GET_TASK_TOOL,
DELETE_TASK_TOOL,
CREATE_TASK_COMMENT_TOOL,
GET_TASK_COMMENTS_TOOL
GET_TASK_COMMENTS_TOOL,
GET_TASK_ATTACHMENT_TOOL,
CREATE_TASK_ATTACHMENT_TOOL
],
}));
@@ -182,20 +229,47 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
}
if (request.params.name === "vikunja_create_task") {
const { project_id, title, description } = request.params.arguments as any;
const res = await api.put(`/projects/${project_id}/tasks`, {
const {
project_id, title, description, parent_task_id,
due_date, start_date, end_date, priority, percent_done, hex_color, is_favorite
} = request.params.arguments as any;
const payload: any = {
title,
description: description || ""
});
description: description ? await marked.parse(description) : ""
};
if (parent_task_id !== undefined) payload.parent_task_id = parent_task_id;
if (due_date !== undefined) payload.due_date = due_date;
if (start_date !== undefined) payload.start_date = start_date;
if (end_date !== undefined) payload.end_date = end_date;
if (priority !== undefined) payload.priority = priority;
if (percent_done !== undefined) payload.percent_done = percent_done;
if (hex_color !== undefined) payload.hex_color = hex_color;
if (is_favorite !== undefined) payload.is_favorite = is_favorite;
const res = await api.put(`/projects/${project_id}/tasks`, payload);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
}
if (request.params.name === "vikunja_update_task") {
const { task_id, done, title, description } = request.params.arguments as any;
const {
task_id, done, title, description,
due_date, start_date, end_date,
priority, percent_done, hex_color, is_favorite
} = request.params.arguments as any;
const payload: any = {};
if (done !== undefined) payload.done = done;
if (title !== undefined) payload.title = title;
if (description !== undefined) payload.description = description;
if (description !== undefined) payload.description = await marked.parse(description);
if (due_date !== undefined) payload.due_date = due_date;
if (start_date !== undefined) payload.start_date = start_date;
if (end_date !== undefined) payload.end_date = end_date;
if (priority !== undefined) payload.priority = priority;
if (percent_done !== undefined) payload.percent_done = percent_done;
if (hex_color !== undefined) payload.hex_color = hex_color;
if (is_favorite !== undefined) payload.is_favorite = is_favorite;
const res = await api.post(`/tasks/${task_id}`, payload);
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
@@ -237,6 +311,34 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
return { content: [{ type: "text", text: JSON.stringify(res.data, null, 2) }] };
}
if (request.params.name === "vikunja_get_task_attachment") {
const { task_id, attachment_id, save_path } = request.params.arguments as any;
const res = await api.get(`/tasks/${task_id}/attachments/${attachment_id}`, {
responseType: 'arraybuffer'
});
fs.writeFileSync(save_path, Buffer.from(res.data));
return { content: [{ type: "text", text: `Successfully saved attachment to ${save_path}` }] };
}
if (request.params.name === "vikunja_upload_task_attachment") {
const { task_id, file_path } = request.params.arguments as any;
if (!fs.existsSync(file_path)) {
throw new Error(`File not found: ${file_path}`);
}
const buffer = fs.readFileSync(file_path);
const blob = new Blob([buffer]);
const formData = new FormData();
formData.append('files', blob, path.basename(file_path));
const res = await api.put(`/tasks/${task_id}/attachments`, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
});
return { content: [{ type: "text", text: `Successfully uploaded attachment to task ${task_id}.\nResponse: ${JSON.stringify(res.data)}` }] };
}
throw new Error(`Unknown tool: ${request.params.name}`);
} catch (e: any) {
const msg = e.response?.data?.message || e.message;

72
pnpm-lock.yaml generated
View File

@@ -235,7 +235,7 @@ importers:
version: 5.9.3
vitest:
specifier: ^3.0.5
version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.33)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jiti@2.6.1)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.33)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jiti@2.6.1)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
packages/content-engine:
dependencies:
@@ -537,7 +537,7 @@ importers:
version: 5.9.3
vitest:
specifier: ^3.0.4
version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.10)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jiti@2.6.1)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
version: 3.2.4(@types/debug@4.1.12)(@types/node@22.19.10)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jiti@2.6.1)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
packages/meme-generator:
dependencies:
@@ -752,7 +752,7 @@ importers:
version: 5.9.3
vitest:
specifier: ^2.0.0
version: 2.1.9(@types/node@22.19.10)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0)
version: 2.1.9(@types/node@22.19.10)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0)
packages/outline-mcp:
dependencies:
@@ -928,7 +928,7 @@ importers:
version: 5.9.3
vitest:
specifier: ^3.0.5
version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.33)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jiti@2.6.1)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
version: 3.2.4(@types/debug@4.1.12)(@types/node@20.19.33)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jiti@2.6.1)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2)
packages/serpbear-mcp:
dependencies:
@@ -1024,10 +1024,22 @@ importers:
express:
specifier: ^4.19.2
version: 4.22.1
form-data:
specifier: ^4.0.5
version: 4.0.5
marked:
specifier: ^18.0.5
version: 18.0.5
devDependencies:
'@types/express':
specifier: ^4.17.21
version: 4.17.25
'@types/form-data':
specifier: ^2.5.2
version: 2.5.2
'@types/marked':
specifier: ^6.0.0
version: 6.0.0
'@types/node':
specifier: ^20.14.10
version: 20.19.33
@@ -2816,95 +2828,111 @@ packages:
'@react-email/body@0.0.11':
resolution: {integrity: sha512-ZSD2SxVSgUjHGrB0Wi+4tu3MEpB4fYSbezsFNEJk2xCWDBkFiOeEsjTmR5dvi+CxTK691hQTQlHv0XWuP7ENTg==}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/button@0.0.19':
resolution: {integrity: sha512-HYHrhyVGt7rdM/ls6FuuD6XE7fa7bjZTJqB2byn6/oGsfiEZaogY77OtoLL/mrQHjHjZiJadtAMSik9XLcm7+A==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/code-block@0.0.11':
resolution: {integrity: sha512-4D43p+LIMjDzm66gTDrZch0Flkip5je91mAT7iGs6+SbPyalHgIA+lFQoQwhz/VzHHLxuD0LV6gwmU/WUQ2WEg==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/code-inline@0.0.5':
resolution: {integrity: sha512-MmAsOzdJpzsnY2cZoPHFPk6uDO/Ncpb4Kh1hAt9UZc1xOW3fIzpe1Pi9y9p6wwUmpaeeDalJxAxH6/fnTquinA==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/column@0.0.13':
resolution: {integrity: sha512-Lqq17l7ShzJG/d3b1w/+lVO+gp2FM05ZUo/nW0rjxB8xBICXOVv6PqjDnn3FXKssvhO5qAV20lHM6S+spRhEwQ==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/components@0.0.33':
resolution: {integrity: sha512-/GKdT3YijT1iEWPAXF644jr12w5xVgzUr0zlbZGt2KOkGeFHNZUCL5UtRopmnjrH/Fayf8Gjv6q/4E2cZgDtdQ==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/container@0.0.15':
resolution: {integrity: sha512-Qo2IQo0ru2kZq47REmHW3iXjAQaKu4tpeq/M8m1zHIVwKduL2vYOBQWbC2oDnMtWPmkBjej6XxgtZByxM6cCFg==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/font@0.0.9':
resolution: {integrity: sha512-4zjq23oT9APXkerqeslPH3OZWuh5X4crHK6nx82mVHV2SrLba8+8dPEnWbaACWTNjOCbcLIzaC9unk7Wq2MIXw==}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/head@0.0.12':
resolution: {integrity: sha512-X2Ii6dDFMF+D4niNwMAHbTkeCjlYYnMsd7edXOsi0JByxt9wNyZ9EnhFiBoQdqkE+SMDcu8TlNNttMrf5sJeMA==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/heading@0.0.15':
resolution: {integrity: sha512-xF2GqsvBrp/HbRHWEfOgSfRFX+Q8I5KBEIG5+Lv3Vb2R/NYr0s8A5JhHHGf2pWBMJdbP4B2WHgj/VUrhy8dkIg==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/hr@0.0.11':
resolution: {integrity: sha512-S1gZHVhwOsd1Iad5IFhpfICwNPMGPJidG/Uysy1AwmspyoAP5a4Iw3OWEpINFdgh9MHladbxcLKO2AJO+cA9Lw==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/html@0.0.11':
resolution: {integrity: sha512-qJhbOQy5VW5qzU74AimjAR9FRFQfrMa7dn4gkEXKMB/S9xZN8e1yC1uA9C15jkXI/PzmJ0muDIWmFwatm5/+VA==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/img@0.0.11':
resolution: {integrity: sha512-aGc8Y6U5C3igoMaqAJKsCpkbm1XjguQ09Acd+YcTKwjnC2+0w3yGUJkjWB2vTx4tN8dCqQCXO8FmdJpMfOA9EQ==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/link@0.0.12':
resolution: {integrity: sha512-vF+xxQk2fGS1CN7UPQDbzvcBGfffr+GjTPNiWM38fhBfsLv6A/YUfaqxWlmL7zLzVmo0K2cvvV9wxlSyNba1aQ==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/markdown@0.0.14':
resolution: {integrity: sha512-5IsobCyPkb4XwnQO8uFfGcNOxnsg3311GRXhJ3uKv51P7Jxme4ycC/MITnwIZ10w2zx7HIyTiqVzTj4XbuIHbg==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/preview@0.0.12':
resolution: {integrity: sha512-g/H5fa9PQPDK6WUEG7iTlC19sAktI23qyoiJtMLqQiXFCfWeQMhqjLGKeLSKkfzszqmfJCjZtpSiKtBoOdxp3Q==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
@@ -2918,24 +2946,28 @@ packages:
'@react-email/row@0.0.12':
resolution: {integrity: sha512-HkCdnEjvK3o+n0y0tZKXYhIXUNPDx+2vq1dJTmqappVHXS5tXS6W5JOPZr5j+eoZ8gY3PShI2LWj5rWF7ZEtIQ==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/section@0.0.16':
resolution: {integrity: sha512-FjqF9xQ8FoeUZYKSdt8sMIKvoT9XF8BrzhT3xiFKdEMwYNbsDflcjfErJe3jb7Wj/es/lKTbV5QR1dnLzGpL3w==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/tailwind@1.0.4':
resolution: {integrity: sha512-tJdcusncdqgvTUYZIuhNC6LYTfL9vNTSQpwWdTCQhQ1lsrNCEE4OKCSdzSV3S9F32pi0i0xQ+YPJHKIzGjdTSA==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
'@react-email/text@0.0.11':
resolution: {integrity: sha512-a7nl/2KLpRHOYx75YbYZpWspUbX1DFY7JIZbOv5x0QU8SvwDbJt+Hm01vG34PffFyYvHEXrc6Qnip2RTjljNjg==}
engines: {node: '>=18.0.0'}
deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.
peerDependencies:
react: ^18.0 || ^19.0 || ^19.0.0-rc
@@ -3468,6 +3500,10 @@ packages:
'@types/express@4.17.25':
resolution: {integrity: sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==}
'@types/form-data@2.5.2':
resolution: {integrity: sha512-tfmcyHn1Pp9YHAO5r40+UuZUPAZbUEgqTel3EuEKpmF9hPkXgR4l41853raliXnb4gwyPNoQOfvgGGlHN5WSog==}
deprecated: This is a stub types definition. form-data provides its own type definitions, so you do not need this installed.
'@types/fs-extra@11.0.4':
resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==}
@@ -3495,6 +3531,10 @@ packages:
'@types/long@4.0.2':
resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==}
'@types/marked@6.0.0':
resolution: {integrity: sha512-jmjpa4BwUsmhxcfsgUit/7A9KbrC48Q0q8KvnY107ogcjGgTFDlIL3RpihNpx2Mu1hM4mdFQjoVc4O6JoGKHsA==}
deprecated: This is a stub types definition. marked provides its own type definitions, so you do not need this installed.
'@types/mime@1.3.5':
resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==}
@@ -4212,6 +4252,7 @@ packages:
basic-ftp@5.2.0:
resolution: {integrity: sha512-VoMINM2rqJwJgfdHq6RiUudKt2BV+FY5ZFezP/ypmwayk68+NzzAQy4XXLlqsGD4MCzq3DrmNFD/uUmBJuGoXw==}
engines: {node: '>=10.0.0'}
deprecated: Security vulnerability fixed in 5.2.1, please upgrade
better-path-resolve@1.0.0:
resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==}
@@ -6373,6 +6414,11 @@ packages:
engines: {node: '>= 18'}
hasBin: true
marked@18.0.5:
resolution: {integrity: sha512-S6GcvALHg6K4ohtu4E7x0a1AqhAjp6cV8KhLSyN9qVapnzJkusVBxZRcIU9AeYsbe6P1hKDusSbEOzGyyuce6w==}
engines: {node: '>= 20'}
hasBin: true
marked@7.0.4:
resolution: {integrity: sha512-t8eP0dXRJMtMvBojtkcsA7n48BkauktUKzfkPSCq85ZMTJ0v76Rke4DYz01omYpPTUh4p/f7HePgRo3ebG8+QQ==}
engines: {node: '>= 16'}
@@ -8279,10 +8325,12 @@ packages:
uuid@10.0.0:
resolution: {integrity: sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==}
deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).
hasBin: true
uuid@9.0.1:
resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
deprecated: uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).
hasBin: true
vali-date@1.0.0:
@@ -11417,6 +11465,10 @@ snapshots:
'@types/qs': 6.14.0
'@types/serve-static': 1.15.10
'@types/form-data@2.5.2':
dependencies:
form-data: 4.0.5
'@types/fs-extra@11.0.4':
dependencies:
'@types/jsonfile': 6.1.4
@@ -11444,6 +11496,10 @@ snapshots:
'@types/long@4.0.2': {}
'@types/marked@6.0.0':
dependencies:
marked: 18.0.5
'@types/mime@1.3.5': {}
'@types/ms@2.1.0':
@@ -14728,6 +14784,8 @@ snapshots:
marked@14.0.0: {}
marked@18.0.5: {}
marked@7.0.4: {}
math-intrinsics@1.1.0: {}
@@ -17148,7 +17206,7 @@ snapshots:
- supports-color
- terser
vitest@2.1.9(@types/node@22.19.10)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0):
vitest@2.1.9(@types/node@22.19.10)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0):
dependencies:
'@vitest/expect': 2.1.9
'@vitest/mocker': 2.1.9(vite@5.4.21(@types/node@22.19.10)(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0))
@@ -17186,7 +17244,7 @@ snapshots:
- supports-color
- terser
vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.33)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jiti@2.6.1)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2):
vitest@3.2.4(@types/debug@4.1.12)(@types/node@20.19.33)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jiti@2.6.1)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2):
dependencies:
'@types/chai': 5.2.3
'@vitest/expect': 3.2.4
@@ -17231,7 +17289,7 @@ snapshots:
- tsx
- yaml
vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.19.10)(@vitest/ui@4.0.18)(happy-dom@20.5.3)(jiti@2.6.1)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2):
vitest@3.2.4(@types/debug@4.1.12)(@types/node@22.19.10)(@vitest/ui@4.0.18(vitest@4.0.18))(happy-dom@20.5.3)(jiti@2.6.1)(jsdom@27.4.0(canvas@3.2.1))(lightningcss@1.30.2)(sass@1.97.3)(terser@5.46.0)(tsx@4.21.0)(yaml@2.8.2):
dependencies:
'@types/chai': 5.2.3
'@vitest/expect': 3.2.4