From 1d4dbad33f8a3d193af4dbb101d2c1437618e816 Mon Sep 17 00:00:00 2001 From: Hein Date: Sun, 5 Apr 2026 18:55:18 +0200 Subject: [PATCH] refactor(tools): remove household, calendar, meals, and CRM tools from core - Moved to future plugin as part of project scope adjustment - Updated tool registration and descriptions accordingly --- README.md | 32 ++- internal/app/app.go | 4 - internal/mcpserver/server.go | 271 +++--------------- internal/mcpserver/server_test.go | 25 -- .../mcpserver/streamable_integration_test.go | 4 - llm/plan.md | 3 +- llm/todo.md | 46 +++ 7 files changed, 100 insertions(+), 285 deletions(-) diff --git a/README.md b/README.md index 3b256f4..75d2ba9 100644 --- a/README.md +++ b/README.md @@ -46,21 +46,29 @@ A Go MCP server for capturing and retrieving thoughts, memory, and project conte | `load_file` | Retrieve a stored file by ID; returns metadata, base64 content, and an embedded MCP binary resource | | `list_files` | Browse stored files by thought, project, or kind | | `backfill_embeddings` | Generate missing embeddings for stored thoughts | -| `reparse_thought_metadata` | Re-extract and normalize metadata for stored thoughts | -| `retry_failed_metadata` | Retry metadata extraction for thoughts still pending or failed | -| `add_skill` | Store a reusable agent skill (behavioural instruction or capability prompt) | +| `reparse_thought_metadata` | Re-extract metadata from thought content | +| `retry_failed_metadata` | Retry pending/failed metadata extraction | +| `add_maintenance_task` | Create a recurring or one-time home maintenance task | +| `log_maintenance` | Log completed maintenance; updates next due date | +| `get_upcoming_maintenance` | List maintenance tasks due within the next N days | +| `search_maintenance_history` | Search the maintenance log by task name, category, or date range | +| `save_chat_history` | Save chat messages with optional title, summary, channel, agent, and project | +| `get_chat_history` | Fetch chat history by UUID or session_id | +| `list_chat_histories` | List chat histories; filter by project, channel, agent_id, session_id, or days | +| `delete_chat_history` | Delete a chat history by id | +| `add_skill` | Store an agent skill (instruction or capability prompt) | | `remove_skill` | Delete an agent skill by id | | `list_skills` | List all agent skills, optionally filtered by tag | -| `add_guardrail` | Store a reusable agent guardrail (constraint or safety rule) | +| `add_guardrail` | Store an agent guardrail (constraint or safety rule) | | `remove_guardrail` | Delete an agent guardrail by id | | `list_guardrails` | List all agent guardrails, optionally filtered by tag or severity | -| `add_project_skill` | Link an agent skill to a project; pass `project` explicitly if your client does not preserve MCP sessions | -| `remove_project_skill` | Unlink an agent skill from a project; pass `project` explicitly if your client does not preserve MCP sessions | -| `list_project_skills` | List all skills linked to a project; pass `project` explicitly if your client does not preserve MCP sessions | -| `add_project_guardrail` | Link an agent guardrail to a project; pass `project` explicitly if your client does not preserve MCP sessions | -| `remove_project_guardrail` | Unlink an agent guardrail from a project; pass `project` explicitly if your client does not preserve MCP sessions | -| `list_project_guardrails` | List all guardrails linked to a project; pass `project` explicitly if your client does not preserve MCP sessions | -| `get_version_info` | Return the server build version information, including version, tag name, commit, and build date | +| `add_project_skill` | Link a skill to a project; pass `project` if client is stateless | +| `remove_project_skill` | Unlink a skill from a project; pass `project` if client is stateless | +| `list_project_skills` | Skills for a project; pass `project` if client is stateless | +| `add_project_guardrail` | Link a guardrail to a project; pass `project` if client is stateless | +| `remove_project_guardrail` | Unlink a guardrail from a project; pass `project` if client is stateless | +| `list_project_guardrails` | Guardrails for a project; pass `project` if client is stateless | +| `get_version_info` | Build version, commit, and date | | `describe_tools` | List all available MCP tools with names, descriptions, categories, and model-authored usage notes; call this at the start of a session to orient yourself | | `annotate_tool` | Persist your own usage notes for a specific tool; notes are returned by `describe_tools` in future sessions | @@ -74,7 +82,7 @@ AMCS includes a built-in tool directory that models can read and annotate. { "category": "thoughts" } ``` -Available categories: `system`, `thoughts`, `projects`, `files`, `admin`, `household`, `maintenance`, `calendar`, `meals`, `crm`, `skills`, `chat`, `meta`. +Available categories: `system`, `thoughts`, `projects`, `files`, `admin`, `maintenance`, `skills`, `chat`, `meta`. **`annotate_tool`** lets a model write persistent usage notes against a tool name. Notes survive across sessions and are returned by `describe_tools`: diff --git a/internal/app/app.go b/internal/app/app.go index ef4bf00..df3a310 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -183,11 +183,7 @@ func routes(logger *slog.Logger, cfg *config.Config, info buildinfo.Info, db *st Backfill: tools.NewBackfillTool(db, provider, activeProjects, logger), Reparse: tools.NewReparseMetadataTool(db, provider, cfg.Capture, activeProjects, logger), RetryMetadata: tools.NewRetryMetadataTool(metadataRetryer), - Household: tools.NewHouseholdTool(db), Maintenance: tools.NewMaintenanceTool(db), - Calendar: tools.NewCalendarTool(db), - Meals: tools.NewMealsTool(db), - CRM: tools.NewCRMTool(db), Skills: tools.NewSkillsTool(db, activeProjects), ChatHistory: tools.NewChatHistoryTool(db, activeProjects), Describe: tools.NewDescribeTool(db, mcpserver.BuildToolCatalog()), diff --git a/internal/mcpserver/server.go b/internal/mcpserver/server.go index 212e931..8f3426f 100644 --- a/internal/mcpserver/server.go +++ b/internal/mcpserver/server.go @@ -36,11 +36,7 @@ type ToolSet struct { Backfill *tools.BackfillTool Reparse *tools.ReparseMetadataTool RetryMetadata *tools.RetryMetadataTool - Household *tools.HouseholdTool Maintenance *tools.MaintenanceTool - Calendar *tools.CalendarTool - Meals *tools.MealsTool - CRM *tools.CRMTool Skills *tools.SkillsTool ChatHistory *tools.ChatHistoryTool Describe *tools.DescribeTool @@ -89,10 +85,6 @@ func NewHandlers(cfg config.MCPConfig, logger *slog.Logger, toolSet ToolSet, onS registerProjectTools, registerFileTools, registerMaintenanceTools, - registerHouseholdTools, - registerCalendarTools, - registerMealTools, - registerCRMTools, registerSkillTools, registerChatHistoryTools, registerDescribeTools, @@ -140,7 +132,7 @@ func buildServerIcons(publicURL string) []mcp.Icon { func registerSystemTools(server *mcp.Server, logger *slog.Logger, toolSet ToolSet) error { if err := addTool(server, logger, &mcp.Tool{ Name: "get_version_info", - Description: "Return the server build version information, including version, tag name, commit, and build date.", + Description: "Build version, commit, and date.", }, toolSet.Version.GetInfo); err != nil { return err } @@ -150,13 +142,13 @@ func registerSystemTools(server *mcp.Server, logger *slog.Logger, toolSet ToolSe func registerThoughtTools(server *mcp.Server, logger *slog.Logger, toolSet ToolSet) error { if err := addTool(server, logger, &mcp.Tool{ Name: "capture_thought", - Description: "Store a thought with generated embeddings and extracted metadata. The thought is saved immediately even if metadata extraction times out; pending thoughts are retried in the background.", + Description: "Store a thought; embeddings and metadata extracted async.", }, toolSet.Capture.Handle); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "search_thoughts", - Description: "Search stored thoughts by semantic similarity. Falls back to Postgres full-text search automatically when no embeddings exist for the active model.", + Description: "Semantic search; falls back to full-text if no embeddings.", }, toolSet.Search.Handle); err != nil { return err } @@ -168,7 +160,7 @@ func registerThoughtTools(server *mcp.Server, logger *slog.Logger, toolSet ToolS } if err := addTool(server, logger, &mcp.Tool{ Name: "thought_stats", - Description: "Get counts and top metadata buckets across stored thoughts.", + Description: "Counts and top metadata buckets for stored thoughts.", }, toolSet.Stats.Handle); err != nil { return err } @@ -192,19 +184,19 @@ func registerThoughtTools(server *mcp.Server, logger *slog.Logger, toolSet ToolS } if err := addTool(server, logger, &mcp.Tool{ Name: "archive_thought", - Description: "Archive a thought so it is hidden from default search and listing.", + Description: "Hide a thought from default search and listing.", }, toolSet.Archive.Handle); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "summarize_thoughts", - Description: "Produce an LLM prose summary of a filtered or searched set of thoughts.", + Description: "LLM summary of a filtered set of thoughts.", }, toolSet.Summarize.Handle); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "recall_context", - Description: "Recall semantically relevant and recent context for prompt injection. Combines vector similarity with recency. Falls back to full-text search when no embeddings exist.", + Description: "Semantic + recency context for prompt injection; falls back to full-text.", }, toolSet.Recall.Handle); err != nil { return err } @@ -216,7 +208,7 @@ func registerThoughtTools(server *mcp.Server, logger *slog.Logger, toolSet ToolS } if err := addTool(server, logger, &mcp.Tool{ Name: "related_thoughts", - Description: "Retrieve explicit links and semantic neighbours for a thought. Falls back to full-text search when no embeddings exist.", + Description: "Explicit links and semantic neighbours; falls back to full-text.", }, toolSet.Links.Related); err != nil { return err } @@ -238,19 +230,19 @@ func registerProjectTools(server *mcp.Server, logger *slog.Logger, toolSet ToolS } if err := addTool(server, logger, &mcp.Tool{ Name: "set_active_project", - Description: "Set the active project for the current MCP session. Requires a stateful MCP client that reuses the same session across calls. If your client does not preserve sessions, pass project explicitly to each tool instead.", + Description: "Set session's active project. Pass project per call if client is stateless.", }, toolSet.Projects.SetActive); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "get_active_project", - Description: "Return the active project for the current MCP session. If your client does not preserve MCP sessions, pass project explicitly to project-scoped tools instead of relying on this.", + Description: "Return session's active project. Pass project per call if client is stateless.", }, toolSet.Projects.GetActive); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "get_project_context", - Description: "Get recent and semantic context for a project. Uses the explicit project when provided, otherwise the active MCP session project. Falls back to full-text search when no embeddings exist.", + Description: "Recent and semantic context for a project; falls back to full-text.", }, toolSet.Context.Handle); err != nil { return err } @@ -266,19 +258,19 @@ func registerFileTools(server *mcp.Server, logger *slog.Logger, toolSet ToolSet) if err := addTool(server, logger, &mcp.Tool{ Name: "upload_file", - Description: "Stage a file and get an amcs://files/{id} resource URI. Use content_path (absolute server-side path, no size limit) for large or binary files, or content_base64 (≤10 MB) for small files. Pass thought_id/project to link immediately, or omit and pass the URI to save_file later.", + Description: "Stage a file; returns amcs://files/{id}. content_path for large/binary, content_base64 for ≤10 MB. Link now or pass URI to save_file.", }, toolSet.Files.Upload); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "save_file", - Description: "Store a file and optionally link it to a thought. Use content_base64 (≤10 MB) for small files, or content_uri (amcs://files/{id} from a prior upload_file) for previously staged files. For files larger than 10 MB, use upload_file with content_path first. If the goal is to retain the artifact, store the file directly instead of reading or summarising it first.", + Description: "Store and optionally link a file. content_base64 (≤10 MB) or content_uri from upload_file. >10 MB: use upload_file first.", }, toolSet.Files.Save); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "load_file", - Description: "Load a stored file by id. Returns metadata, base64 content, and an embedded MCP binary resource at amcs://files/{id}. Prefer the embedded resource when your client supports it. The id field accepts a bare UUID or full amcs://files/{id} URI.", + Description: "Fetch file metadata and content by id (UUID or amcs://files/{id}); includes embedded MCP resource.", }, toolSet.Files.Load); err != nil { return err } @@ -294,19 +286,19 @@ func registerFileTools(server *mcp.Server, logger *slog.Logger, toolSet ToolSet) func registerMaintenanceTools(server *mcp.Server, logger *slog.Logger, toolSet ToolSet) error { if err := addTool(server, logger, &mcp.Tool{ Name: "backfill_embeddings", - Description: "Generate missing embeddings for stored thoughts using the active embedding model. Run this after switching embedding models or importing thoughts that have no vectors.", + Description: "Generate missing embeddings. Run after model switch or bulk import.", }, toolSet.Backfill.Handle); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "reparse_thought_metadata", - Description: "Re-extract and normalize metadata for stored thoughts from their content.", + Description: "Re-extract metadata from thought content.", }, toolSet.Reparse.Handle); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "retry_failed_metadata", - Description: "Retry metadata extraction for thoughts still marked pending or failed.", + Description: "Retry pending/failed metadata extraction.", }, toolSet.RetryMetadata.Handle); err != nil { return err } @@ -318,7 +310,7 @@ func registerMaintenanceTools(server *mcp.Server, logger *slog.Logger, toolSet T } if err := addTool(server, logger, &mcp.Tool{ Name: "log_maintenance", - Description: "Log completed maintenance work; automatically updates the task's next due date.", + Description: "Log completed maintenance; updates next due date.", }, toolSet.Maintenance.LogWork); err != nil { return err } @@ -337,176 +329,10 @@ func registerMaintenanceTools(server *mcp.Server, logger *slog.Logger, toolSet T return nil } -func registerHouseholdTools(server *mcp.Server, logger *slog.Logger, toolSet ToolSet) error { - if err := addTool(server, logger, &mcp.Tool{ - Name: "add_household_item", - Description: "Store a household fact (paint color, appliance details, measurement, document, etc.).", - }, toolSet.Household.AddItem); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "search_household_items", - Description: "Search household items by name, category, or location.", - }, toolSet.Household.SearchItems); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "get_household_item", - Description: "Retrieve a household item by id.", - }, toolSet.Household.GetItem); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "add_vendor", - Description: "Add a service provider (plumber, electrician, landscaper, etc.).", - }, toolSet.Household.AddVendor); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "list_vendors", - Description: "List household service vendors, optionally filtered by service type.", - }, toolSet.Household.ListVendors); err != nil { - return err - } - return nil -} - -func registerCalendarTools(server *mcp.Server, logger *slog.Logger, toolSet ToolSet) error { - if err := addTool(server, logger, &mcp.Tool{ - Name: "add_family_member", - Description: "Add a family member to the household.", - }, toolSet.Calendar.AddMember); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "list_family_members", - Description: "List all family members.", - }, toolSet.Calendar.ListMembers); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "add_activity", - Description: "Schedule a one-time or recurring family activity.", - }, toolSet.Calendar.AddActivity); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "get_week_schedule", - Description: "Get all activities scheduled for a given week.", - }, toolSet.Calendar.GetWeekSchedule); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "search_activities", - Description: "Search activities by title, type, or family member.", - }, toolSet.Calendar.SearchActivities); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "add_important_date", - Description: "Track a birthday, anniversary, deadline, or other important date.", - }, toolSet.Calendar.AddImportantDate); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "get_upcoming_dates", - Description: "Get important dates coming up in the next N days.", - }, toolSet.Calendar.GetUpcomingDates); err != nil { - return err - } - return nil -} - -func registerMealTools(server *mcp.Server, logger *slog.Logger, toolSet ToolSet) error { - if err := addTool(server, logger, &mcp.Tool{ - Name: "add_recipe", - Description: "Save a recipe with ingredients and instructions.", - }, toolSet.Meals.AddRecipe); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "search_recipes", - Description: "Search recipes by name, cuisine, tags, or ingredient.", - }, toolSet.Meals.SearchRecipes); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "update_recipe", - Description: "Update an existing recipe.", - }, toolSet.Meals.UpdateRecipe); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "create_meal_plan", - Description: "Set the meal plan for a week; replaces any existing plan for that week.", - }, toolSet.Meals.CreateMealPlan); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "get_meal_plan", - Description: "Get the meal plan for a given week.", - }, toolSet.Meals.GetMealPlan); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "generate_shopping_list", - Description: "Auto-generate a shopping list from the meal plan for a given week.", - }, toolSet.Meals.GenerateShoppingList); err != nil { - return err - } - return nil -} - -func registerCRMTools(server *mcp.Server, logger *slog.Logger, toolSet ToolSet) error { - if err := addTool(server, logger, &mcp.Tool{ - Name: "add_professional_contact", - Description: "Add a professional contact to the CRM.", - }, toolSet.CRM.AddContact); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "search_contacts", - Description: "Search professional contacts by name, company, title, notes, or tags.", - }, toolSet.CRM.SearchContacts); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "log_interaction", - Description: "Log an interaction with a professional contact.", - }, toolSet.CRM.LogInteraction); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "get_contact_history", - Description: "Get full history (interactions and opportunities) for a contact.", - }, toolSet.CRM.GetHistory); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "create_opportunity", - Description: "Create a deal, project, or opportunity linked to a contact.", - }, toolSet.CRM.CreateOpportunity); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "get_follow_ups_due", - Description: "List contacts with a follow-up date due within the next N days.", - }, toolSet.CRM.GetFollowUpsDue); err != nil { - return err - } - if err := addTool(server, logger, &mcp.Tool{ - Name: "link_thought_to_contact", - Description: "Append a stored thought to a contact's notes.", - }, toolSet.CRM.LinkThought); err != nil { - return err - } - return nil -} - func registerSkillTools(server *mcp.Server, logger *slog.Logger, toolSet ToolSet) error { if err := addTool(server, logger, &mcp.Tool{ Name: "add_skill", - Description: "Store a reusable agent skill (behavioural instruction or capability prompt).", + Description: "Store an agent skill (instruction or capability prompt).", }, toolSet.Skills.AddSkill); err != nil { return err } @@ -524,7 +350,7 @@ func registerSkillTools(server *mcp.Server, logger *slog.Logger, toolSet ToolSet } if err := addTool(server, logger, &mcp.Tool{ Name: "add_guardrail", - Description: "Store a reusable agent guardrail (constraint or safety rule).", + Description: "Store an agent guardrail (constraint or safety rule).", }, toolSet.Skills.AddGuardrail); err != nil { return err } @@ -542,37 +368,37 @@ func registerSkillTools(server *mcp.Server, logger *slog.Logger, toolSet ToolSet } if err := addTool(server, logger, &mcp.Tool{ Name: "add_project_skill", - Description: "Link an agent skill to a project. Pass project explicitly when your client does not preserve MCP sessions.", + Description: "Link a skill to a project. Pass project if client is stateless.", }, toolSet.Skills.AddProjectSkill); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "remove_project_skill", - Description: "Unlink an agent skill from a project. Pass project explicitly when your client does not preserve MCP sessions.", + Description: "Unlink a skill from a project. Pass project if client is stateless.", }, toolSet.Skills.RemoveProjectSkill); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "list_project_skills", - Description: "List all skills linked to a project. Call this at the start of every project session to load agent behaviour instructions before generating new ones. Only create new skills if none are returned. Pass project explicitly when your client does not preserve MCP sessions.", + Description: "Skills for a project. Load at session start; only add new if none returned. Pass project if stateless.", }, toolSet.Skills.ListProjectSkills); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "add_project_guardrail", - Description: "Link an agent guardrail to a project. Pass project explicitly when your client does not preserve MCP sessions.", + Description: "Link a guardrail to a project. Pass project if client is stateless.", }, toolSet.Skills.AddProjectGuardrail); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "remove_project_guardrail", - Description: "Unlink an agent guardrail from a project. Pass project explicitly when your client does not preserve MCP sessions.", + Description: "Unlink a guardrail from a project. Pass project if client is stateless.", }, toolSet.Skills.RemoveProjectGuardrail); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "list_project_guardrails", - Description: "List all guardrails linked to a project. Call this at the start of every project session to load agent constraints before generating new ones. Only create new guardrails if none are returned. Pass project explicitly when your client does not preserve MCP sessions.", + Description: "Guardrails for a project. Load at session start; only add new if none returned. Pass project if stateless.", }, toolSet.Skills.ListProjectGuardrails); err != nil { return err } @@ -582,25 +408,25 @@ func registerSkillTools(server *mcp.Server, logger *slog.Logger, toolSet ToolSet func registerChatHistoryTools(server *mcp.Server, logger *slog.Logger, toolSet ToolSet) error { if err := addTool(server, logger, &mcp.Tool{ Name: "save_chat_history", - Description: "Save a chat session's message history for later retrieval. Stores messages with optional title, summary, channel, agent, and project metadata.", + Description: "Save chat messages with optional title, summary, channel, agent, and project.", }, toolSet.ChatHistory.SaveChatHistory); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "get_chat_history", - Description: "Retrieve a saved chat history by its UUID or session_id. Returns the full message list.", + Description: "Fetch chat history by UUID or session_id.", }, toolSet.ChatHistory.GetChatHistory); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "list_chat_histories", - Description: "List saved chat histories with optional filters: project, channel, agent_id, session_id, or recent days.", + Description: "List chat histories; filter by project, channel, agent_id, session_id, or days.", }, toolSet.ChatHistory.ListChatHistories); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "delete_chat_history", - Description: "Permanently delete a saved chat history by id.", + Description: "Delete a chat history by id.", }, toolSet.ChatHistory.DeleteChatHistory); err != nil { return err } @@ -610,13 +436,13 @@ func registerChatHistoryTools(server *mcp.Server, logger *slog.Logger, toolSet T func registerDescribeTools(server *mcp.Server, logger *slog.Logger, toolSet ToolSet) error { if err := addTool(server, logger, &mcp.Tool{ Name: "describe_tools", - Description: "Call this first in every session. Returns all available MCP tools with names, descriptions, categories, and your accumulated usage notes. Filter by category to narrow results. Available categories: system, thoughts, projects, files, admin, household, maintenance, calendar, meals, crm, skills, chat, meta.", + Description: "Call first each session. All tools with categories and usage notes. Categories: system, thoughts, projects, files, admin, maintenance, skills, chat, meta.", }, toolSet.Describe.Describe); err != nil { return err } if err := addTool(server, logger, &mcp.Tool{ Name: "annotate_tool", - Description: "Persist usage notes, gotchas, or workflow patterns for a specific tool. Notes survive across sessions and are returned by describe_tools. Call this whenever you discover something non-obvious about a tool's behaviour. Pass an empty string to clear notes.", + Description: "Save usage notes for a tool; returned by describe_tools. Empty string clears.", }, toolSet.Describe.Annotate); err != nil { return err } @@ -662,45 +488,12 @@ func BuildToolCatalog() []tools.ToolEntry { {Name: "reparse_thought_metadata", Description: "Re-extract and normalize metadata for stored thoughts from their content.", Category: "admin"}, {Name: "retry_failed_metadata", Description: "Retry metadata extraction for thoughts still marked pending or failed.", Category: "admin"}, - // household - {Name: "add_household_item", Description: "Store a household fact (paint color, appliance details, measurement, document, etc.).", Category: "household"}, - {Name: "search_household_items", Description: "Search household items by name, category, or location.", Category: "household"}, - {Name: "get_household_item", Description: "Retrieve a household item by id.", Category: "household"}, - {Name: "add_vendor", Description: "Add a service provider (plumber, electrician, landscaper, etc.).", Category: "household"}, - {Name: "list_vendors", Description: "List household service vendors, optionally filtered by service type.", Category: "household"}, - // maintenance {Name: "add_maintenance_task", Description: "Create a recurring or one-time home maintenance task.", Category: "maintenance"}, {Name: "log_maintenance", Description: "Log completed maintenance work; automatically updates the task's next due date.", Category: "maintenance"}, {Name: "get_upcoming_maintenance", Description: "List maintenance tasks due within the next N days.", Category: "maintenance"}, {Name: "search_maintenance_history", Description: "Search the maintenance log by task name, category, or date range.", Category: "maintenance"}, - // calendar - {Name: "add_family_member", Description: "Add a family member to the household.", Category: "calendar"}, - {Name: "list_family_members", Description: "List all family members.", Category: "calendar"}, - {Name: "add_activity", Description: "Schedule a one-time or recurring family activity.", Category: "calendar"}, - {Name: "get_week_schedule", Description: "Get all activities scheduled for a given week.", Category: "calendar"}, - {Name: "search_activities", Description: "Search activities by title, type, or family member.", Category: "calendar"}, - {Name: "add_important_date", Description: "Track a birthday, anniversary, deadline, or other important date.", Category: "calendar"}, - {Name: "get_upcoming_dates", Description: "Get important dates coming up in the next N days.", Category: "calendar"}, - - // meals - {Name: "add_recipe", Description: "Save a recipe with ingredients and instructions.", Category: "meals"}, - {Name: "search_recipes", Description: "Search recipes by name, cuisine, tags, or ingredient.", Category: "meals"}, - {Name: "update_recipe", Description: "Update an existing recipe.", Category: "meals"}, - {Name: "create_meal_plan", Description: "Set the meal plan for a week; replaces any existing plan for that week.", Category: "meals"}, - {Name: "get_meal_plan", Description: "Get the meal plan for a given week.", Category: "meals"}, - {Name: "generate_shopping_list", Description: "Auto-generate a shopping list from the meal plan for a given week.", Category: "meals"}, - - // crm - {Name: "add_professional_contact", Description: "Add a professional contact to the CRM.", Category: "crm"}, - {Name: "search_contacts", Description: "Search professional contacts by name, company, title, notes, or tags.", Category: "crm"}, - {Name: "log_interaction", Description: "Log an interaction with a professional contact.", Category: "crm"}, - {Name: "get_contact_history", Description: "Get full history (interactions and opportunities) for a contact.", Category: "crm"}, - {Name: "create_opportunity", Description: "Create a deal, project, or opportunity linked to a contact.", Category: "crm"}, - {Name: "get_follow_ups_due", Description: "List contacts with a follow-up date due within the next N days.", Category: "crm"}, - {Name: "link_thought_to_contact", Description: "Append a stored thought to a contact's notes.", Category: "crm"}, - // skills {Name: "add_skill", Description: "Store a reusable agent skill (behavioural instruction or capability prompt).", Category: "skills"}, {Name: "remove_skill", Description: "Delete an agent skill by id.", Category: "skills"}, diff --git a/internal/mcpserver/server_test.go b/internal/mcpserver/server_test.go index f61945b..4fcee5c 100644 --- a/internal/mcpserver/server_test.go +++ b/internal/mcpserver/server_test.go @@ -28,45 +28,27 @@ func TestNewListsAllRegisteredTools(t *testing.T) { sort.Strings(got) want := []string{ - "add_activity", - "add_family_member", "add_guardrail", - "add_household_item", - "add_important_date", "add_maintenance_task", - "add_professional_contact", "add_project_guardrail", "add_project_skill", - "add_recipe", "add_skill", - "add_vendor", "annotate_tool", "archive_thought", "backfill_embeddings", "capture_thought", - "create_meal_plan", - "create_opportunity", "create_project", "delete_chat_history", "delete_thought", "describe_tools", - "generate_shopping_list", "get_active_project", "get_chat_history", - "get_contact_history", - "get_follow_ups_due", - "get_household_item", - "get_meal_plan", "get_project_context", "get_thought", - "get_upcoming_dates", "get_upcoming_maintenance", "get_version_info", - "get_week_schedule", - "link_thought_to_contact", "link_thoughts", "list_chat_histories", - "list_family_members", "list_files", "list_guardrails", "list_project_guardrails", @@ -74,9 +56,7 @@ func TestNewListsAllRegisteredTools(t *testing.T) { "list_projects", "list_skills", "list_thoughts", - "list_vendors", "load_file", - "log_interaction", "log_maintenance", "recall_context", "related_thoughts", @@ -88,16 +68,11 @@ func TestNewListsAllRegisteredTools(t *testing.T) { "retry_failed_metadata", "save_chat_history", "save_file", - "search_activities", - "search_contacts", - "search_household_items", "search_maintenance_history", - "search_recipes", "search_thoughts", "set_active_project", "summarize_thoughts", "thought_stats", - "update_recipe", "update_thought", "upload_file", } diff --git a/internal/mcpserver/streamable_integration_test.go b/internal/mcpserver/streamable_integration_test.go index 83d0ef1..699b178 100644 --- a/internal/mcpserver/streamable_integration_test.go +++ b/internal/mcpserver/streamable_integration_test.go @@ -127,11 +127,7 @@ func streamableTestToolSet() ToolSet { Backfill: new(tools.BackfillTool), Reparse: new(tools.ReparseMetadataTool), RetryMetadata: new(tools.RetryMetadataTool), - Household: new(tools.HouseholdTool), Maintenance: new(tools.MaintenanceTool), - Calendar: new(tools.CalendarTool), - Meals: new(tools.MealsTool), - CRM: new(tools.CRMTool), Skills: new(tools.SkillsTool), } } diff --git a/llm/plan.md b/llm/plan.md index d40e7c1..7593345 100644 --- a/llm/plan.md +++ b/llm/plan.md @@ -33,7 +33,8 @@ In practice, the project has also grown beyond the original v1 scope with additi - stored files and binary resources - agent skills and guardrails - chat history tools -- household / maintenance / calendar / meal / CRM tools +- maintenance tools +- household / calendar / meal / CRM tools (moved to future plugin; see `llm/todo.md`) - OAuth client-credentials support - Ollama support - tool discovery and persistent tool annotations diff --git a/llm/todo.md b/llm/todo.md index 13a0d28..0d2f624 100644 --- a/llm/todo.md +++ b/llm/todo.md @@ -1,4 +1,50 @@ # AMCS TODO + +## Future Plugin: Lifestyle Tools (calendar, meals, household, CRM) + +The following tool groups have been removed from the core server and are candidates for a separate optional plugin or extension server. The store/tool implementations remain in the codebase but are no longer registered. + +### calendar +- `add_family_member` — Add a family member to the household. +- `list_family_members` — List all family members. +- `add_activity` — Schedule a one-time or recurring family activity. +- `get_week_schedule` — Get all activities scheduled for a given week. +- `search_activities` — Search activities by title, type, or family member. +- `add_important_date` — Track a birthday, anniversary, deadline, or other important date. +- `get_upcoming_dates` — Get important dates coming up in the next N days. + +### meals +- `add_recipe` — Save a recipe with ingredients and instructions. +- `search_recipes` — Search recipes by name, cuisine, tags, or ingredient. +- `update_recipe` — Update an existing recipe. +- `create_meal_plan` — Set the weekly meal plan; replaces existing. +- `get_meal_plan` — Get the meal plan for a given week. +- `generate_shopping_list` — Generate shopping list from the weekly meal plan. + +### household +- `add_household_item` — Store a household fact (paint, appliance, measurement, etc.). +- `search_household_items` — Search household items by name, category, or location. +- `get_household_item` — Retrieve a household item by id. +- `add_vendor` — Add a service provider (plumber, electrician, landscaper, etc.). +- `list_vendors` — List household service vendors, optionally filtered by service type. + +### crm +- `add_professional_contact` — Add a professional contact to the CRM. +- `search_contacts` — Search professional contacts by name, company, title, notes, or tags. +- `log_interaction` — Log an interaction with a professional contact. +- `get_contact_history` — Get full history (interactions and opportunities) for a contact. +- `create_opportunity` — Create a deal, project, or opportunity linked to a contact. +- `get_follow_ups_due` — List contacts with a follow-up date due within the next N days. +- `link_thought_to_contact` — Append a stored thought to a contact's notes. + +**Implementation notes:** +- Store implementations: `internal/tools/calendar.go`, `internal/tools/meals.go`, `internal/tools/household.go`, `internal/tools/crm.go` +- DB store layers: `internal/store/calendar.go`, `internal/store/meals.go`, `internal/store/household.go`, `internal/store/crm.go` +- Re-register via `mcpserver.ToolSet` fields: `Household`, `Calendar`, `Meals`, `CRM` +- Re-add `registerHouseholdTools`, `registerCalendarTools`, `registerMealTools`, `registerCRMTools` to the register slice in `NewHandlers` +- Add catalog entries back in `BuildToolCatalog` + +--- ## Embedding Backfill and Text-Search Fallback Audit This file originally described the planned `backfill_embeddings` work and semantic-to-text fallback behavior. Most of that work is now implemented. This document now tracks what landed, what still needs verification, and what follow-up work remains.