1+ import { invariant } from '@epic-web/invariant'
12import { type GetPromptResult } from '@modelcontextprotocol/sdk/types.js'
23import { z } from 'zod'
34import { type DB } from './db/index.ts'
@@ -6,60 +7,41 @@ import { getErrorMessage, formatDate, timeAgo } from './utils.ts'
67
78export async function initializePrompts ( agent : EpicMeMCP ) {
89 agent . server . prompt (
9- 'summarize-journal-entries ' ,
10- 'Summarize your past journal entries ' ,
10+ 'suggest-tags ' ,
11+ 'Suggest tags for a journal entry ' ,
1112 {
12- tagIds : z
13+ entryId : z
1314 . string ( )
14- . optional ( )
15- . describe (
16- 'Optional comma-separated set of tag IDs to filter entries by' ,
17- ) ,
18- from : z
19- . string ( )
20- . optional ( )
21- . describe (
22- 'Optional date string in YYYY-MM-DD format to filter entries by' ,
23- ) ,
24- to : z
25- . string ( )
26- . optional ( )
27- . describe (
28- 'Optional date string in YYYY-MM-DD format to filter entries by' ,
29- ) ,
15+ . describe ( 'The ID of the journal entry to suggest tags for' ) ,
3016 } ,
31- async ( { tagIds , from , to } ) => {
17+ async ( { entryId } ) => {
3218 try {
33- const entries = await agent . db . getEntriesWithTags ( {
34- tagIds : tagIds ? tagIds . split ( ',' ) . map ( Number ) : undefined ,
35- from : from ? new Date ( from ) . getTime ( ) : undefined ,
36- to : to ? new Date ( to ) . getTime ( ) : undefined ,
37- } )
38- if ( entries . length === 0 ) {
39- return {
40- messages : [
41- {
42- role : 'assistant' ,
43- content : {
44- type : 'text' ,
45- text : 'You have no journal entries yet. Would you like to create one?' ,
46- } ,
47- } ,
48- ] ,
49- } satisfies GetPromptResult
50- }
19+ const entry = await agent . db . getEntry ( Number ( entryId ) )
20+ invariant ( entry , `Entry with ID "${ entryId } " not found` )
5121
52- const formattedEntries = entries
53- . map ( ( entry ) => getFormattedEntry ( entry ) )
54- . join ( '\n\n' )
22+ const unusedTags = await getUnusedTags ( agent . db , entry )
23+ const formattedEntry = getFormattedEntry ( entry )
5524
5625 return {
5726 messages : [
5827 {
5928 role : 'user' ,
6029 content : {
6130 type : 'text' ,
62- text : `Here are my journal entries:\n\n${ formattedEntries } \n\nCan you please summarize them for me?` ,
31+ text : [
32+ `Here is my journal entry (ID: ${ entryId } ):` ,
33+ '' ,
34+ '---' ,
35+ formattedEntry ,
36+ '---' ,
37+ '' ,
38+ unusedTags . length
39+ ? `Here are other tags I have available:`
40+ : `I do not have any other tags available.` ,
41+ `${ unusedTags . map ( ( tag ) => `${ tag . name } : ${ tag . description } (${ tag . id } )` ) . join ( '\n' ) } ` ,
42+ '' ,
43+ `Can you please suggest some tags to add to my entry? For those that I approve, if it does not yet exist, create it with the EpicMe "create_tag". Then add it with the EpicMe "add_tag_to_entry" tool.` ,
44+ ] . join ( '\n' ) ,
6345 } ,
6446 } ,
6547 ] ,
@@ -71,6 +53,22 @@ export async function initializePrompts(agent: EpicMeMCP) {
7153 )
7254}
7355
56+ async function getUnusedTags (
57+ db : DB ,
58+ entry : Awaited < ReturnType < DB [ 'getEntriesWithTags' ] > > [ number ] ,
59+ ) {
60+ const tags = await db . listTags ( )
61+ const unusedTagIds = tags
62+ . filter ( ( tag ) => ! entry . tags . includes ( tag ) )
63+ . map ( ( t ) => t . id )
64+ const unusedTags : Array < NonNullable < Awaited < ReturnType < DB [ 'getTag' ] > > > > = [ ]
65+ for ( const tagId of unusedTagIds ) {
66+ const tag = await db . getTag ( tagId )
67+ if ( tag ) unusedTags . push ( tag )
68+ }
69+ return unusedTags
70+ }
71+
7472function getFormattedEntry (
7573 entry : Awaited < ReturnType < DB [ 'getEntriesWithTags' ] > > [ number ] ,
7674) {
@@ -83,20 +81,18 @@ function getFormattedEntry(
8381 const createdAtAgo = timeAgo ( entry . createdAt )
8482 const updatedAtAgo = timeAgo ( entry . updatedAt )
8583 return [
86- '---' ,
8784 `# ${ entry . title } ` ,
8885 '' ,
8986 entry . content ,
9087 '' ,
9188 `Mood: ${ entry . mood ?? 'N/A' } ` ,
9289 `Weather: ${ entry . weather ?? 'N/A' } ` ,
9390 `Location: ${ entry . location ?? 'N/A' } ` ,
94- `Is Private: ${ entry . isPrivate } ` ,
95- `Is Favorite: ${ entry . isFavorite } ` ,
91+ `Is Private: ${ entry . isPrivate ? 'Yes' : 'No' } ` ,
92+ `Is Favorite: ${ entry . isFavorite ? 'Yes' : 'No' } ` ,
9693 `Created At: ${ createdAtDate } (${ createdAtAgo } )` ,
9794 `Updated At: ${ updatedAtDate } (${ updatedAtAgo } )` ,
9895 `Tags: ${ tagList } ` ,
99- '---' ,
10096 ] . join ( '\n' )
10197}
10298
0 commit comments