tududi/backend/modules/mcp/tools/miscTools.js

212 lines
6.5 KiB
JavaScript

'use strict';
const { Area, Tag, Task, Project, Note } = require('../../../models');
const { Op } = require('sequelize');
/**
* Register miscellaneous MCP tools
*/
function registerMiscTools(server, context, tools) {
// 1. list_areas - List all areas
tools.push({
name: 'list_areas',
description: 'List all organizational areas',
inputSchema: {
type: 'object',
properties: {},
},
handler: async (params) => {
const areas = await Area.findAll({
where: { user_id: context.userId },
order: [['name', 'ASC']],
});
const serialized = areas.map((area) => ({
id: area.id,
uid: area.uid,
name: area.name,
description: area.description,
created_at: area.created_at,
}));
return {
content: [
{
type: 'text',
text: JSON.stringify(
{
count: serialized.length,
areas: serialized,
},
null,
2
),
},
],
};
},
});
// 2. list_tags - List all tags
tools.push({
name: 'list_tags',
description: 'List all available tags',
inputSchema: {
type: 'object',
properties: {},
},
handler: async (params) => {
const tags = await Tag.findAll({
where: { user_id: context.userId },
order: [['name', 'ASC']],
});
const serialized = tags.map((tag) => ({
id: tag.id,
uid: tag.uid,
name: tag.name,
created_at: tag.created_at,
}));
return {
content: [
{
type: 'text',
text: JSON.stringify(
{
count: serialized.length,
tags: serialized,
},
null,
2
),
},
],
};
},
});
// 3. search - Universal search across tasks, projects, notes
tools.push({
name: 'search',
description: 'Search across tasks, projects, and notes',
inputSchema: {
type: 'object',
properties: {
query: {
type: 'string',
description: 'Search query (required)',
},
type: {
type: 'string',
enum: ['task', 'project', 'note', 'all'],
description: 'Resource type to search (default: all)',
default: 'all',
},
limit: {
type: 'number',
description: 'Maximum results per type',
default: 10,
},
},
required: ['query'],
},
handler: async (params) => {
const query = params.query;
const type = params.type || 'all';
const limit = params.limit || 10;
const results = {};
const searchCondition = {
[Op.or]: [
{ name: { [Op.like]: `%${query}%` } },
{ note: { [Op.like]: `%${query}%` } },
],
};
// Search tasks
if (type === 'task' || type === 'all') {
const tasks = await Task.findAll({
where: {
user_id: context.userId,
[Op.or]: [
{ name: { [Op.like]: `%${query}%` } },
{ note: { [Op.like]: `%${query}%` } },
],
},
limit: limit,
order: [['created_at', 'DESC']],
});
results.tasks = tasks.map((t) => ({
id: t.id,
uid: t.uid,
name: t.name,
status: t.status,
priority: t.priority,
}));
}
// Search projects
if (type === 'project' || type === 'all') {
const projects = await Project.findAll({
where: {
user_id: context.userId,
[Op.or]: [
{ name: { [Op.like]: `%${query}%` } },
{ description: { [Op.like]: `%${query}%` } },
],
},
limit: limit,
order: [['created_at', 'DESC']],
});
results.projects = projects.map((p) => ({
id: p.id,
uid: p.uid,
name: p.name,
status: p.status,
}));
}
// Search notes
if (type === 'note' || type === 'all') {
const notes = await Note.findAll({
where: {
user_id: context.userId,
[Op.or]: [
{ name: { [Op.like]: `%${query}%` } },
{ content: { [Op.like]: `%${query}%` } },
],
},
limit: limit,
order: [['created_at', 'DESC']],
});
results.notes = notes.map((n) => ({
id: n.id,
uid: n.uid,
name: n.name,
}));
}
return {
content: [
{
type: 'text',
text: JSON.stringify(
{
query: query,
results: results,
},
null,
2
),
},
],
};
},
});
}
module.exports = { registerMiscTools };