import { z } from 'zod';
import type { MCPTool, MCPToolHandler } from '../types.js';
import { getToolContext, getApiBaseUrl } from '../utils/api.js';
export const memoListTool: MCPTool = {
name: 'memo_list',
description: 'Retrieves a list of memos from a specified channel. When no channel ID is provided, uses the currently active channel. Returns paginated results with memo information.',
inputSchema: {
type: 'object',
properties: {
channelId: {
type: 'string',
description: 'Channel ID to retrieve memos from (defaults to currently active channel if omitted)'
},
skip: {
type: 'number',
description: 'Number of memos to skip for pagination (default: 0)',
minimum: 0
},
take: {
type: 'number',
description: 'Maximum number of memos to return (default: 50)',
minimum: 1,
maximum: 100
}
},
required: []
}
};
export const handleMemoList: MCPToolHandler = async (args: any) => {
try {
const schema = z.object({
channelId: z.string().optional(),
skip: z.number().min(0).default(0),
take: z.number().min(1).max(100).default(50)
});
const { channelId, skip, take } = schema.parse(args);
const toolContext = await getToolContext();
const targetChannelId = channelId || toolContext.activeChannelId;
if (!targetChannelId) {
return {
content: [
{
type: 'text',
text: JSON.stringify({
success: false,
error: 'No channel ID specified and no active channel is set',
memos: []
})
}
]
};
}
const url = new URL(`${getApiBaseUrl()}/api/memos`);
url.searchParams.set('channelId', targetChannelId);
url.searchParams.set('skip', skip.toString());
url.searchParams.set('take', take.toString());
const response = await fetch(url.toString(), {
method: 'GET',
headers: {
'Content-Type': 'application/json',
}
});
if (!response.ok) {
const errorData = await response.json().catch(() => ({})) as { error?: string };
return {
content: [
{
type: 'text',
text: JSON.stringify({
success: false,
error: `API Error: ${response.statusText} - ${errorData.error || 'Unknown error'}`,
memos: []
})
}
]
};
}
const result = await response.json() as { memos: any[] };
// Filter out secret memos
const filteredMemos = result.memos.filter(memo => !memo.isSecret);
return {
content: [
{
type: 'text',
text: JSON.stringify({
success: true,
count: filteredMemos.length,
channelId: targetChannelId,
pagination: {
skip,
take,
hasMore: result.memos.length === take
},
memos: filteredMemos
})
}
]
};
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : String(error);
return {
content: [
{
type: 'text',
text: JSON.stringify({
success: false,
error: `Error occurred during memo list retrieval: ${errorMessage}`,
memos: []
})
}
]
};
}
};