Forgetful MCP Server - Complete Tool Reference
August 14, 2026 · View on GitHub
This guide provides comprehensive documentation for all tools available in the Forgetful MCP server.
Table of Contents
- Meta-Tools Pattern
- Tool Categories Overview
- User Tools
- Memory Tools
- Project Tools
- Code Artifact Tools
- Document Tools
- Skill Tools
- Entity Tools
- Plan Tools
- Task Tools
- Cross-Category Workflows
Meta-Tools Pattern
Forgetful uses a meta-tools pattern to preserve your LLM's context window. Only 3 meta-tools are visible to MCP clients; the inner tool catalog depends on the enabled feature flags.
The Three Meta-Tools
1. discover_forgetful_tools
List available tools, optionally filtered by category.
Parameters:
category(optional): Filter by category (user,memory,project,code_artifact,document,entity,plan,task,skill)
Returns:
tools_by_category: Tools grouped by categorytotal_count: Total number of toolscategories_available: List of all categoriesfiltered_by: Applied filter (if any)
Example:
# Discover all memory tools
discover_forgetful_tools(category="memory")
# Discover all available tools
discover_forgetful_tools()
2. how_to_use_forgetful_tool
Get detailed documentation for a specific tool.
Parameters:
tool_name: Name of the tool
Returns:
- Complete tool documentation with JSON schema, parameters, and examples
Example:
how_to_use_forgetful_tool(tool_name="create_memory")
3. execute_forgetful_tool
Execute any registered tool dynamically.
Parameters:
tool_name: Name of the tool to executearguments: Dictionary of arguments for the tool
Returns:
- Tool execution result (format depends on specific tool)
Example:
execute_forgetful_tool(
tool_name="create_memory",
arguments={
"title": "Database choice: PostgreSQL",
"content": "Selected PostgreSQL for pgvector support",
"context": "Choosing the database for vector search",
"keywords": ["postgresql", "pgvector"],
"tags": ["database", "decision"],
"importance": 9
}
)
Tool Categories Overview
The core catalog covers users, memories, projects, code artifacts, documents, and entities.
Skills, files, plans, and tasks appear only when their feature flags are enabled. Call
discover_forgetful_tools() for the exact catalog exposed by the running server.
User Tools
Manage user authentication and profile information.
get_current_user
Returns information about the currently authenticated user.
Parameters: None
Returns:
user_id: Unique user identifierusername: User's usernameemail: User's emailnotes: User profile notescreated_at: Account creation timestamp
Example:
user = execute_forgetful_tool("get_current_user", {})
# Returns: {"user_id": 1, "username": "alex_smith", "email": "alex@example.com", ...}
update_user_notes
Update the notes field for the current user's profile.
Parameters:
notes: Text content for user notes
Returns:
- Updated user object
Example:
execute_forgetful_tool(
"update_user_notes",
{"notes": "Prefers TypeScript over JavaScript. Works on microservices architecture."}
)
Memory Tools
The core of Forgetful - atomic knowledge storage and semantic retrieval.
create_memory
Create an atomic memory with automatic linking to related memories.
Parameters:
title(required): Short, searchable title (max 200 chars)content(required): Memory content - ONE concept (max 2000 chars, ~300-400 words)importance(required): Importance score 1-10 (9-10 = foundational, 7-8 = patterns, 5-6 = context)context(required): Why the memory matters (max 500 chars)keywords(required): Search keywords (max 10)tags(required): Categorization tags (max 10)project_ids(optional): Project IDs to linkdocument_ids(optional): Document IDs to linkcode_artifact_ids(optional): Code artifact IDs to link
Provenance Tracking (optional):
source_repo(optional): Repository source (e.g., 'owner/repo', max 200 chars)source_files(optional): List of file paths that informed this memorysource_url(optional): URL to original source material (max 2048 chars)confidence(optional): Encoding confidence score (0.0-1.0)encoding_agent(optional): Agent/process that created this memory (max 100 chars)encoding_version(optional): Version of encoding process/prompt (max 50 chars)
Returns:
id: Created memory IDtitle: Created memory titlelinked_memory_ids: Automatically linked memory IDssimilar_memories: Summaries of the automatic-link candidates
Example:
memory = execute_forgetful_tool(
"create_memory",
{
"title": "API rate limiting: 100 req/min per user",
"content": "Implemented rate limiting at 100 requests per minute per authenticated user to prevent abuse. Uses Redis for distributed counting across instances.",
"importance": 8,
"context": "Performance and security discussion during API redesign",
"keywords": ["rate-limiting", "api", "redis", "performance"],
"tags": ["api", "security", "performance"],
"project_ids": [12]
}
)
# Returns: {"id": 156, "linked_memory_ids": [142, 148, 151], ...}
Example with provenance:
# Memory created by AI agent with source tracking
memory = execute_forgetful_tool(
"create_memory",
{
"title": "FastAPI dependency injection pattern",
"content": "Use Depends() for request-scoped dependencies.",
"context": "Recording a reusable FastAPI implementation pattern",
"keywords": ["fastapi", "depends", "dependency-injection"],
"tags": ["fastapi", "pattern", "dependency-injection"],
"importance": 8,
"source_repo": "tiangolo/fastapi",
"source_files": ["docs/tutorial/dependencies.md", "docs/advanced/async-database.md"],
"source_url": "https://fastapi.tiangolo.com/tutorial/dependencies/",
"confidence": 0.92,
"encoding_agent": "claude-sonnet-4-20250514",
"encoding_version": "1.0.0"
}
)
query_memory
Semantic search across all memories with context-aware ranking.
Parameters:
query(required): Natural language search queryquery_context(required): Why the search is being performedk(optional): Number of primary results (default: 3, maximum: 20)include_links(optional): Include linked memories (default: true)max_links_per_primary(optional): Linked memories per primary result (default: 5)importance_threshold(optional): Minimum importance scoreproject_ids(optional): Project IDs to searchstrict_project_filter(optional): Apply the project filter to linked memories
Returns:
- List of memories ranked by semantic relevance
- Each memory includes linked artifacts and 1-hop graph connections
Example:
results = execute_forgetful_tool(
"query_memory",
{
"query": "how do we handle authentication",
"query_context": "Implementing authentication for the API",
"project_ids": [12],
"importance_threshold": 7,
"k": 5
}
)
# Returns: {"primary_memories": [...], "linked_memories": [...], ...}
get_memory
Retrieve complete memory details by ID.
Parameters:
memory_id(required): Memory ID
Returns:
- Complete memory object with all fields and relationships
Example:
memory = execute_forgetful_tool("get_memory", {"memory_id": 156})
update_memory
Update existing memory fields (PATCH semantics - only updates provided fields).
Parameters:
memory_id(required): Memory IDtitle(optional): Updated titlecontent(optional): Updated contentimportance(optional): Updated importance scorecontext(optional): Updated contextkeywords(optional): Updated keywordstags(optional): Updated tags
Provenance Tracking (optional):
source_repo(optional): Repository source (e.g., 'owner/repo')source_files(optional): List of file pathssource_url(optional): URL to source materialconfidence(optional): Confidence score (0.0-1.0)encoding_agent(optional): Agent/process identifierencoding_version(optional): Version of encoding process
Returns:
- Updated memory object
Example:
execute_forgetful_tool(
"update_memory",
{
"memory_id": 156,
"importance": 9, # Increased importance after realizing how critical this is
"tags": ["api", "security", "performance", "production"]
}
)
Example - Adding provenance after creation:
# Add provenance to an existing memory
execute_forgetful_tool(
"update_memory",
{
"memory_id": 156,
"source_repo": "company/api-gateway",
"confidence": 0.95,
"encoding_agent": "manual-review"
}
)
link_memories
Manually create bidirectional links between memories.
Parameters:
memory_id(required): Source memory IDrelated_ids(required): Target memory IDs
Returns:
- Confirmation of link creation
Example:
# Link related architecture decisions
execute_forgetful_tool(
"link_memories",
{
"memory_id": 156, # Rate limiting decision
"related_ids": [201] # Redis caching strategy
}
)
mark_memory_obsolete
Soft delete a memory with audit trail and supersession tracking.
Parameters:
memory_id(required): Memory ID to mark obsoletereason(required): Reason for obsolescencesuperseded_by(optional): ID of replacement memory
Returns:
- Updated memory with obsolete flag
Example:
execute_forgetful_tool(
"mark_memory_obsolete",
{
"memory_id": 78, # Old "Docker Swarm deployment" memory
"reason": "Migrated to Kubernetes",
"superseded_by": 312 # New K8s memory
}
)
get_recent_memories
Retrieve most recent memories sorted by creation timestamp.
Parameters:
limit(optional): Max memories to return (default: 10)project_ids(optional): Scope to specific projects
Returns:
- An object (not a bare list) with two keys:
memories: list of recent memories, sorted bycreated_atDESC (newest first)total_count: total number of matching memories
- Each memory's
linked_memory_idsincludes both directions of links (same set asget_memory).
Example:
result = execute_forgetful_tool(
"get_recent_memories",
{"limit": 10, "project_ids": [12]}
)
recent = result["memories"] # the list of memories
total = result["total_count"] # how many matched in total
Behavior change (PR #49) — the return shape is now an envelope.
This tool used to return a bare JSON array of memories. It now returns an object:
{"memories": [...], "total_count": N}.Why: MCP structured content requires an object root. A bare
[]carries no structured content over the wire, so an empty result collapsed tonullfor remote consumers and could not be told apart from "no result". Wrapping the list in an object lets empty results survive the wire and matches thelist_*tool family.Migration: read
result["memories"]instead of indexing the bare result, and readresult["total_count"]if you need the total. For example, replacefor m in result:withfor m in result["memories"]:. The REST endpoint is unaffected — this change is only in the MCP tool surface.
Project Tools
Organize memories, code artifacts, and documents by project context.
Project Types
personal,work,learning,development,infrastructuretemplate,product,marketing,finance,documentationdevelopment-environment,third-party-library,open-source
Project Statuses
active,archived,completed
create_project
Create a new project for organizing knowledge.
Parameters:
name(required): Project nameproject_type(optional): Project type (see list above)description(optional): Project descriptionstatus(optional): Project status (default:active)repository_url(optional): Git repository URLmetadata(optional): Additional JSON metadata
Returns:
- Created project with
project_id
Example:
project = execute_forgetful_tool(
"create_project",
{
"name": "E-Commerce Platform Redesign",
"project_type": "work",
"description": "Complete redesign of checkout and payment flows",
"status": "active",
"repository_url": "https://github.com/company/ecommerce-v2"
}
)
# Returns: {"project_id": 22, "name": "E-Commerce Platform Redesign", ...}
list_projects
List projects with optional filtering.
Parameters:
project_type(optional): Filter by project typestatus(optional): Filter by statusrepository_url(optional): Filter by repository
Returns:
- List of matching projects
Example:
# Get all active work projects
active_work = execute_forgetful_tool(
"list_projects",
{"project_type": "work", "status": "active"}
)
get_project
Retrieve complete project details by ID.
Parameters:
project_id(required): Project ID
Returns:
- Complete project object
Errors:
- Raises an error (not
null) whenproject_iddoes not exist or is not visible to the caller
Example:
project = execute_forgetful_tool("get_project", {"project_id": 22})
update_project
Update project metadata (PATCH semantics).
Parameters:
project_id(required): Project IDname(optional): Updated namedescription(optional): Updated descriptionstatus(optional): Updated statusrepository_url(optional): Updated repository URLmetadata(optional): Updated metadata
Returns:
- Updated project object
Example:
# Mark project as completed
execute_forgetful_tool(
"update_project",
{
"project_id": 22,
"status": "completed",
"metadata": {"completion_date": "2025-01-15", "outcome": "shipped to production"}
}
)
delete_project
Delete project while preserving linked memories, artifacts, and documents.
Parameters:
project_id(required): Project ID
Returns:
- Confirmation of deletion
Example:
execute_forgetful_tool("delete_project", {"project_id": 22})
Code Artifact Tools
Store and retrieve reusable code snippets and patterns.
create_code_artifact
Store a reusable code snippet.
Parameters:
title(required): Artifact titlecontent(required): Code contentlanguage(required): Programming languagedescription(optional): Artifact descriptiontags(optional): Categorization tagsproject_id(optional): Link to projectframework(optional): Framework name (e.g., "React", "FastAPI")version(optional): Version string
Returns:
- Created artifact with
code_artifact_id
Example:
artifact = execute_forgetful_tool(
"create_code_artifact",
{
"title": "Async Retry Decorator with Exponential Backoff",
"content": '''
import asyncio
from functools import wraps
def async_retry(max_attempts=3, base_delay=1.0):
def decorator(func):
@wraps(func)
async def wrapper(*args, **kwargs):
for attempt in range(max_attempts):
try:
return await func(*args, **kwargs)
except Exception as e:
if attempt == max_attempts - 1:
raise
delay = base_delay * (2 ** attempt)
await asyncio.sleep(delay)
return wrapper
return decorator
''',
"language": "python",
"description": "Reusable retry logic for async operations - use for API calls",
"tags": ["async", "retry", "decorator", "resilience"],
"project_id": 12
}
)
# Returns: {"code_artifact_id": 45, ...}
list_code_artifacts
List code artifacts with optional filtering.
Parameters:
project_id(optional): Filter by projectlanguage(optional): Filter by programming languagetags(optional): Filter by tags
Returns:
- List of matching code artifacts
Example:
# Find all Python utilities
python_utils = execute_forgetful_tool(
"list_code_artifacts",
{"language": "python", "tags": ["utility"]}
)
get_code_artifact
Retrieve complete code artifact by ID.
Parameters:
code_artifact_id(required): Artifact ID
Returns:
- Complete artifact object with code content
Example:
artifact = execute_forgetful_tool("get_code_artifact", {"code_artifact_id": 45})
update_code_artifact
Update code artifact (PATCH semantics).
Parameters:
code_artifact_id(required): Artifact IDtitle,content,language,description,tags,framework,version(all optional)
Returns:
- Updated artifact object
Example:
execute_forgetful_tool(
"update_code_artifact",
{
"code_artifact_id": 45,
"version": "2.0.0",
"tags": ["async", "retry", "decorator", "resilience", "production"]
}
)
delete_code_artifact
Delete code artifact (cascades memory associations).
Parameters:
code_artifact_id(required): Artifact ID
Returns:
- Confirmation of deletion
Example:
execute_forgetful_tool("delete_code_artifact", {"code_artifact_id": 45})
Document Tools
Store long-form content (>400 words) like architecture decision records, research notes, and detailed documentation.
Document Types
text- Plain text documentsmarkdown- Markdown-formatted documentscode- Code documentation- Custom types - Define your own
create_document
Create a document for long-form content.
Parameters:
title(required): Document titlecontent(required): Document content (no character limit)document_type(optional): Document type (default:text)description(optional): Document descriptiontags(optional): Categorization tagsproject_id(optional): Link to project
Returns:
- Created document with
document_id
Example:
doc = execute_forgetful_tool(
"create_document",
{
"title": "ADR-003: Migration to Event-Driven Architecture",
"content": '''
# Architecture Decision Record: Event-Driven Architecture
## Status
Accepted
## Context
Our monolithic architecture faces scaling challenges:
- Tight coupling between services creates deployment bottlenecks
- Database contention during peak loads
- Difficulty adding new features without affecting existing systems
[... 2000+ words of detailed analysis ...]
## Decision
Adopt event-driven architecture using Apache Kafka as message broker.
## Consequences
### Positive
- Loose coupling enables independent service scaling
- Event sourcing provides audit trail
- Easier to add new consumers
### Negative
- Increased operational complexity
- Eventual consistency requires careful handling
- Team needs training on distributed systems
## Implementation Plan
[... detailed steps ...]
''',
"document_type": "markdown",
"tags": ["adr", "architecture", "event-driven", "kafka"],
"project_id": 22
}
)
# Returns: {"id": 89, ...}
# Extract atomic memories from this document
memory1 = execute_forgetful_tool(
"create_memory",
{
"title": "Architecture decision: Event-driven with Kafka",
"content": "Adopted event-driven architecture using Kafka.",
"context": "Capturing the decision from the architecture document",
"keywords": ["architecture", "kafka", "events"],
"tags": ["architecture", "decision"],
"importance": 10,
"document_ids": [89],
"project_ids": [22]
}
)
list_documents
List documents with optional filtering.
Parameters:
project_id(optional): Filter by projectdocument_type(optional): Filter by typetags(optional): Filter by tags
Returns:
- List of matching documents
Example:
# Find all ADRs
adrs = execute_forgetful_tool(
"list_documents",
{"tags": ["adr"], "document_type": "markdown"}
)
get_document
Retrieve complete document by ID.
Parameters:
document_id(required): Document ID
Returns:
- Complete document object with full content
Example:
doc = execute_forgetful_tool("get_document", {"document_id": 89})
update_document
Update document (PATCH semantics).
Parameters:
document_id(required): Document IDtitle,content,document_type,description,tags(all optional)
Returns:
- Updated document object
Example:
execute_forgetful_tool(
"update_document",
{
"document_id": 89,
"tags": ["adr", "architecture", "event-driven", "kafka", "implemented"]
}
)
delete_document
Delete document (cascades memory associations).
Parameters:
document_id(required): Document ID
Returns:
- Confirmation of deletion
Example:
execute_forgetful_tool("delete_document", {"document_id": 89})
Skill Tools
Store and manage procedural knowledge (step-by-step instructions, agent capabilities) following the Agent Skills open standard.
create_skill
Create a skill for storing procedural knowledge.
Parameters:
name(required): Kebab-case skill name (e.g., 'code-review'). Must match^[a-z0-9]+(-[a-z0-9]+)*$description(required): What the skill does and when to use it. Gets embedded for semantic search (max 1024 chars)content(required): Full SKILL.md body - markdown instructions, steps, examples (max 100KB)license(optional): License identifier (e.g., 'MIT', 'Apache-2.0')compatibility(optional): Environment requirements (e.g., 'Requires Python 3.14+ and uv')allowed_tools(optional): Tool restrictions (e.g.,['Bash(python:*)', 'Read', 'WebFetch'])metadata(optional): Custom key-value pairs (author, version, mcp-server, etc.)tags(optional): Categorization tags (max 10)importance(optional): Importance 1-10 (default: 7)project_id(optional): Link to project
Returns:
- Complete Skill with generated ID and timestamps
Example:
skill = execute_forgetful_tool(
"create_skill",
{
"name": "code-review",
"description": "Systematic code review process for pull requests",
"content": "# Code Review\n\n## Steps\n1. Check for breaking changes...",
"tags": ["development", "review", "quality"],
"importance": 8
}
)
list_skills
List skills with optional filtering.
Parameters:
project_id(optional): Filter by projecttags(optional): Filter by tags (OR logic - skills with ANY of these tags)importance_threshold(optional): Minimum importance level (1-10)
Returns:
- List of SkillSummary (excludes full content)
Example:
skills = execute_forgetful_tool(
"list_skills",
{"tags": ["deployment"], "importance_threshold": 7}
)
get_skill
Retrieve complete skill by ID.
Parameters:
skill_id(required): Skill ID
Returns:
- Complete skill with full content and metadata
Example:
skill = execute_forgetful_tool("get_skill", {"skill_id": 5})
update_skill
Update skill (PATCH semantics).
Parameters:
skill_id(required): Skill IDname,description,content,license,compatibility,allowed_tools,metadata,tags,importance,project_id(all optional)
Returns:
- Updated skill object
Example:
execute_forgetful_tool(
"update_skill",
{
"skill_id": 5,
"content": "# Updated Code Review\n\n## Steps\n1. Run linter first...",
"importance": 9
}
)
delete_skill
Delete skill (cascades memory and artifact associations).
Parameters:
skill_id(required): Skill ID
Returns:
- Confirmation of deletion
Example:
execute_forgetful_tool("delete_skill", {"skill_id": 5})
search_skills
Semantic search across skills by description similarity.
Parameters:
query(required): Search query string (semantic, not keyword-only)k(optional): Number of results (default: 5)project_id(optional): Filter by project
Returns:
- List of SkillSummary ranked by relevance
Example:
results = execute_forgetful_tool(
"search_skills",
{"query": "how to deploy to production", "k": 3}
)
import_skill
Import a skill from Agent Skills markdown format (SKILL.md).
Parameters:
skill_md_content(required): Raw SKILL.md content with YAML frontmatterproject_id(optional): Project associationimportance(optional): Importance level (default: 7)
Scalar frontmatter values may contain unquoted colons (for example Keywords: in a description); the importer quotes them before parsing.
Returns:
- Created Skill with generated ID
Example:
skill_md = """---
name: code-review
description: Systematic code review
license: MIT
---
# Code Review
## Steps
1. Check for...
"""
skill = execute_forgetful_tool(
"import_skill",
{
"skill_md_content": skill_md,
"project_id": 3,
"importance": 8
}
)
export_skill
Export a skill to Agent Skills markdown format (SKILL.md).
Parameters:
skill_id(required): Skill ID to export
Returns:
- Formatted SKILL.md string with YAML frontmatter
Example:
skill_md = execute_forgetful_tool("export_skill", {"skill_id": 5})
# Returns: "---\nname: code-review\ndescription: ...\n---\n\n# Code Review\n..."
link_skill_to_memory
Link a skill to a memory (bidirectional association).
Parameters:
skill_id(required): Skill IDmemory_id(required): Memory ID
Returns:
- Confirmation dict
Example:
execute_forgetful_tool(
"link_skill_to_memory",
{"skill_id": 5, "memory_id": 123}
)
unlink_skill_from_memory
Remove association between a skill and a memory.
Parameters:
skill_id(required): Skill IDmemory_id(required): Memory ID
Returns:
- Confirmation dict
Example:
execute_forgetful_tool(
"unlink_skill_from_memory",
{"skill_id": 5, "memory_id": 123}
)
Entity Tools
Track real-world entities (people, organizations, teams, devices) and build knowledge graphs through relationships.
Entity Types
Organization- Companies, institutionsIndividual- People, team membersTeam- Groups within organizationsDevice- Servers, infrastructureOther- Custom entity types (requirescustom_typefield)
Relationship Types
works_for- Employment relationshipsmember_of- Team membershipowns- Ownershipreports_to- Reporting structurecollaborates_with- Collaboration- Custom types - Define your own
Entity CRUD Operations
create_entity
Create an entity representing a real-world thing.
Parameters:
name(required): Entity nameentity_type(required): Type (Organization,Individual,Team,Device,System,Other)description(optional): Entity descriptiontags(optional): Categorization tagsaka(optional): Alternative names/aliases (max 10). Searchable viasearch_entities.project_id(optional): Link to projectcustom_type(optional): Custom type name (required if entity_type isOther)metadata(optional): Additional JSON metadata
Returns:
- Created entity with
entity_id
Example:
# Create a person with aliases
person = execute_forgetful_tool(
"create_entity",
{
"name": "Sarah Chen",
"entity_type": "Individual",
"description": "Senior Backend Engineer, specializes in distributed systems",
"tags": ["engineering", "backend", "distributed-systems"],
"aka": ["Sarah", "S.C."], # Alternative names for search
"metadata": {"start_date": "2024-03-15", "location": "San Francisco"}
}
)
# Returns: {"entity_id": 42, "name": "Sarah Chen", "aka": ["Sarah", "S.C."], ...}
# Create an organization with stock ticker alias
org = execute_forgetful_tool(
"create_entity",
{
"name": "TechFlow Systems",
"entity_type": "Organization",
"description": "SaaS platform for workflow automation",
"tags": ["company", "saas", "b2b"],
"aka": ["TechFlow", "TFS"] # Can search by "TFS" to find this
}
)
# Returns: {"entity_id": 43, ...}
# Create infrastructure
server = execute_forgetful_tool(
"create_entity",
{
"name": "Cache Server 01",
"entity_type": "Device",
"description": "Redis cluster primary node - production",
"tags": ["infrastructure", "cache", "production", "redis"],
"aka": ["redis-primary", "cache-01"],
"metadata": {"ip": "10.0.1.50", "region": "us-west-2"}
}
)
# Returns: {"entity_id": 44, ...}
list_entities
List entities with optional filtering.
Parameters:
entity_type(optional): Filter by typetags(optional): Filter by tagsproject_id(optional): Filter by project
Returns:
- List of matching entities
Example:
# Find all team members
team = execute_forgetful_tool(
"list_entities",
{"entity_type": "Individual", "tags": ["engineering"]}
)
search_entities
Search entities by name or alternative names (aka). Case-insensitive text matching.
Parameters:
query(required): Search term (matches name or any aka, partial match supported)entity_type(optional): Filter by entity typetags(optional): Filter by tagslimit(optional): Maximum results (1-100, default 20)
Returns:
- List of entities matching the search term (via name or aka)
Example:
# Find entities with "Chen" in the name
results = execute_forgetful_tool(
"search_entities",
{"query": "Chen"}
)
# Returns: [{"entity_id": 42, "name": "Sarah Chen", "aka": ["Sarah", "S.C."], ...}, ...]
# Search by alias - finds "TechFlow Systems" via its "TFS" alias
results = execute_forgetful_tool(
"search_entities",
{"query": "TFS"}
)
# Returns: [{"entity_id": 43, "name": "TechFlow Systems", "aka": ["TechFlow", "TFS"], ...}]
get_entity
Retrieve complete entity details by ID.
Parameters:
entity_id(required): Entity ID
Returns:
- Complete entity object
Example:
entity = execute_forgetful_tool("get_entity", {"entity_id": 42})
update_entity
Update entity (PATCH semantics - only provided fields changed).
Parameters:
entity_id(required): Entity IDname,description,tags,aka,metadata(all optional)aka: Replaces existing aliases. Empty list[]clears all aliases.
Returns:
- Updated entity object
Example:
# Update description and add aliases
execute_forgetful_tool(
"update_entity",
{
"entity_id": 42,
"description": "Principal Backend Engineer, Tech Lead for distributed systems",
"aka": ["Sarah", "S.C.", "Chen"], # Replaces existing aka list
"metadata": {"promotion_date": "2025-01-01", "title": "Principal Engineer"}
}
)
delete_entity
Delete entity (cascade removes memory links and relationships).
Parameters:
entity_id(required): Entity ID
Returns:
- Confirmation of deletion
Example:
execute_forgetful_tool("delete_entity", {"entity_id": 42})
Entity-Memory Linking
link_entity_to_memory
Link an entity to a memory (establishes reference relationship).
Parameters:
entity_id(required): Entity IDmemory_id(required): Memory ID
Returns:
- Confirmation of link
Example:
# Link Sarah to a memory about an architecture decision she made
execute_forgetful_tool(
"link_entity_to_memory",
{
"entity_id": 42, # Sarah Chen
"memory_id": 156 # "API rate limiting decision"
}
)
unlink_entity_from_memory
Remove entity-memory link.
Parameters:
entity_id(required): Entity IDmemory_id(required): Memory ID
Returns:
- Confirmation of unlink
Example:
execute_forgetful_tool(
"unlink_entity_from_memory",
{"entity_id": 42, "memory_id": 156}
)
Entity-Project Linking
link_entity_to_project
Link an entity to a project for organizational grouping.
Parameters:
entity_id(required): Entity IDproject_id(required): Project ID
Returns:
{"success": true}on success
Example:
# Link Sarah to the API Gateway project
execute_forgetful_tool(
"link_entity_to_project",
{
"entity_id": 42, # Sarah Chen
"project_id": 12 # API Gateway project
}
)
unlink_entity_from_project
Remove entity-project link.
Parameters:
entity_id(required): Entity IDproject_id(required): Project ID
Returns:
{"success": true}if unlinked,{"success": false}if link didn't exist
Example:
execute_forgetful_tool(
"unlink_entity_from_project",
{"entity_id": 42, "project_id": 12}
)
Entity Relationships (Knowledge Graph)
Build directional knowledge graphs showing how entities relate to each other.
create_entity_relationship
Create a typed relationship between two entities.
Parameters:
from_entity_id(required): Source entity IDto_entity_id(required): Target entity IDrelationship_type(required): Relationship type (see list above, or custom)strength(optional): Relationship strength 0.0-1.0 (default: 1.0)confidence(optional): Confidence level 0.0-1.0 (default: 1.0)metadata(optional): Additional JSON metadata
Returns:
- Created relationship with
relationship_id
Example:
# Sarah works for TechFlow
relationship = execute_forgetful_tool(
"create_entity_relationship",
{
"from_entity_id": 42, # Sarah Chen
"to_entity_id": 43, # TechFlow Systems
"relationship_type": "works_for",
"strength": 1.0,
"metadata": {
"role": "Principal Backend Engineer",
"department": "Platform Engineering",
"start_date": "2024-03-15"
}
}
)
# Returns: {"relationship_id": 12, ...}
# Server owned by TechFlow
execute_forgetful_tool(
"create_entity_relationship",
{
"from_entity_id": 43, # TechFlow Systems
"to_entity_id": 44, # Cache Server 01
"relationship_type": "owns",
"metadata": {"purchased": "2024-06-01", "cost_center": "engineering"}
}
)
get_entity_relationships
Get relationships for an entity with optional filtering.
Parameters:
entity_id(required): Entity IDrelationship_type(optional): Filter by relationship typedirection(optional):outgoing,incoming, orboth(default:both)
Returns:
- List of relationships
Example:
# Get all of Sarah's relationships
relationships = execute_forgetful_tool(
"get_entity_relationships",
{"entity_id": 42}
)
# Get only employment relationships
employment = execute_forgetful_tool(
"get_entity_relationships",
{
"entity_id": 42,
"relationship_type": "works_for",
"direction": "outgoing"
}
)
update_entity_relationship
Update entity relationship (PATCH semantics).
Parameters:
relationship_id(required): Relationship IDrelationship_type,strength,confidence,metadata(all optional)
Returns:
- Updated relationship object
Example:
# Update Sarah's role after promotion
execute_forgetful_tool(
"update_entity_relationship",
{
"relationship_id": 12,
"metadata": {
"role": "Engineering Director",
"department": "Platform Engineering",
"promotion_date": "2025-01-01"
}
}
)
delete_entity_relationship
Delete entity relationship (removes knowledge graph edge).
Parameters:
relationship_id(required): Relationship ID
Returns:
- Confirmation of deletion
Example:
execute_forgetful_tool("delete_entity_relationship", {"relationship_id": 12})
Plan Tools
Create and manage plans within projects. Plans serve as containers for organizing tasks toward a specific goal.
Plan Statuses
draft,active,completed,archived
create_plan
Create a new plan within a project.
Parameters:
title(required): Plan titleproject_id(required): Parent project IDgoal(optional): High-level goal for the plancontext(optional): Additional context or backgroundstatus(optional): Plan status (default:draft)
Returns:
- Created plan with
plan_id
Example:
plan = execute_forgetful_tool(
"create_plan",
{
"title": "Migrate Authentication to OAuth2",
"project_id": 12,
"goal": "Replace legacy session-based auth with OAuth2 + JWT",
"context": "Current auth system has scaling issues and no SSO support",
"status": "draft"
}
)
# Returns: {"plan_id": 5, "title": "Migrate Authentication to OAuth2", ...}
update_plan
Update plan metadata (PATCH semantics - only provided fields changed).
Parameters:
plan_id(required): Plan IDtitle(optional): Updated titlegoal(optional): Updated goalcontext(optional): Updated contextstatus(optional): Updated status
Returns:
- Updated plan object
Example:
# Move plan from draft to active
execute_forgetful_tool(
"update_plan",
{
"plan_id": 5,
"status": "active",
"goal": "Replace legacy auth with OAuth2 + JWT by end of Q2"
}
)
get_plan
Retrieve complete plan details by ID.
Parameters:
plan_id(required): Plan ID
Returns:
- Complete plan object with all fields
Errors:
- Raises an error (not
null) whenplan_iddoes not exist or is not visible to the caller
Example:
plan = execute_forgetful_tool("get_plan", {"plan_id": 5})
list_plans
List plans with optional filtering.
Parameters:
project_id(optional): Filter by projectstatus(optional): Filter by status
Returns:
- List of matching plans
Example:
# Get all active plans for a project
active_plans = execute_forgetful_tool(
"list_plans",
{"project_id": 12, "status": "active"}
)
Task Tools
Manage tasks within plans, including acceptance criteria, dependencies, and agent assignment with optimistic locking.
Task States
Tasks follow a lifecycle defined by TaskState (see app/models/plan_models.py):
todo(default) — not starteddoing— in progresswaiting— blocked / awaiting external inputdone— completedcancelled— will not be completed
Valid transitions (enforced by VALID_TASK_TRANSITIONS):
| From → To | Allowed |
|---|---|
todo → | doing, waiting, cancelled |
doing → | done, waiting, todo, cancelled |
waiting → | todo, doing, cancelled |
done → | todo (reopen only) |
cancelled → | todo (reinstate only) |
Any other transition is rejected by transition_task with a validation error.
Task Priorities
P0- CriticalP1- HighP2- Medium (default)P3- Low
create_task
Create a task within a plan.
Parameters:
title(required): Task titleplan_id(required): Parent plan IDdescription(optional): Detailed task descriptionpriority(optional): Task priority (default:P2)assigned_agent(optional): Agent identifier to assign the task tocriteria(optional): Inline list of acceptance criterion descriptionsdependency_ids(optional): List of task IDs this task depends on
Returns:
- Created task with
task_id
Example:
task = execute_forgetful_tool(
"create_task",
{
"title": "Implement JWT token generation endpoint",
"plan_id": 5,
"description": "Create /auth/token endpoint that issues JWT tokens with refresh token rotation",
"priority": "P1",
"assigned_agent": "backend-agent",
"criteria": [
"Endpoint returns access + refresh token pair",
"Access tokens expire after 15 minutes",
"Refresh tokens support rotation"
],
"dependency_ids": [10, 12]
}
)
# Returns: {"task_id": 25, "title": "Implement JWT token generation endpoint", ...}
update_task
Update task metadata (not state - use transition_task for state changes).
Parameters:
task_id(required): Task IDtitle(optional): Updated titledescription(optional): Updated descriptionpriority(optional): Updated priority
Returns:
- Updated task object
Example:
execute_forgetful_tool(
"update_task",
{
"task_id": 25,
"priority": "P0",
"description": "Create /auth/token endpoint - now critical path for launch"
}
)
get_task
Get task with its acceptance criteria and dependency IDs.
Parameters:
task_id(required): Task ID
Returns:
- Complete task object including criteria and dependency_ids
Errors:
- Raises an error (not
null) whentask_iddoes not exist or is not visible to the caller
Example:
task = execute_forgetful_tool("get_task", {"task_id": 25})
# Returns: {"task_id": 25, "criteria": [...], "dependency_ids": [10, 12], ...}
query_tasks
Query tasks within a plan with optional filtering.
Parameters:
plan_id(required): Plan IDstate(optional): Filter by task statepriority(optional): Filter by priorityassigned_agent(optional): Filter by assigned agent
Returns:
- List of matching tasks
Example:
# Find all todo P0/P1 tasks assigned to an agent
critical_tasks = execute_forgetful_tool(
"query_tasks",
{
"plan_id": 5,
"state": "todo",
"priority": "P1",
"assigned_agent": "backend-agent"
}
)
claim_task
Claim a task for an agent. Uses optimistic locking to prevent concurrent claims.
Parameters:
task_id(required): Task IDagent_id(required): Agent identifier claiming the taskversion(required): Current task version (for optimistic locking)
Returns:
- Updated task object with new version
Example:
# First get the task to obtain current version
task = execute_forgetful_tool("get_task", {"task_id": 25})
# Claim with version check
claimed = execute_forgetful_tool(
"claim_task",
{
"task_id": 25,
"agent_id": "backend-agent-01",
"version": task["version"]
}
)
transition_task
Transition a task to a new state. Uses optimistic locking to prevent conflicting state changes.
Parameters:
task_id(required): Task IDstate(required): Target stateversion(required): Current task version (for optimistic locking)
Returns:
- Updated task object with new state and version
Example:
# Move task from todo to doing
task = execute_forgetful_tool("get_task", {"task_id": 25})
execute_forgetful_tool(
"transition_task",
{
"task_id": 25,
"state": "doing",
"version": task["version"]
}
)
# Later, mark as done
task = execute_forgetful_tool("get_task", {"task_id": 25})
execute_forgetful_tool(
"transition_task",
{
"task_id": 25,
"state": "done",
"version": task["version"]
}
)
add_criterion
Add an acceptance criterion to a task.
Parameters:
task_id(required): Task IDdescription(required): Criterion description
Returns:
- Created criterion with
criterion_id
Example:
criterion = execute_forgetful_tool(
"add_criterion",
{
"task_id": 25,
"description": "Token endpoint returns 401 for invalid credentials"
}
)
# Returns: {"criterion_id": 78, "description": "Token endpoint returns 401 for invalid credentials", ...}
verify_criterion
Mark an acceptance criterion as met or unmet.
Parameters:
criterion_id(required): Criterion IDmet(required): Whether the criterion is met (true/false)
Returns:
- Updated criterion object
Example:
# Mark criterion as satisfied
execute_forgetful_tool(
"verify_criterion",
{"criterion_id": 78, "met": true}
)
delete_criterion
Delete an acceptance criterion from a task.
Parameters:
criterion_id(required): Criterion ID
Returns:
- Confirmation of deletion
Example:
execute_forgetful_tool("delete_criterion", {"criterion_id": 78})
add_dependency
Add a dependency between tasks. The dependent task cannot proceed until the dependency is completed.
Parameters:
task_id(required): Task that depends on anotherdepends_on_task_id(required): Task that must be completed first
Returns:
- Confirmation of dependency creation
Example:
# Task 25 depends on task 20 being completed first
execute_forgetful_tool(
"add_dependency",
{
"task_id": 25,
"depends_on_task_id": 20
}
)
remove_dependency
Remove a dependency between tasks.
Parameters:
task_id(required): Task with the dependencydepends_on_task_id(required): Task to remove as dependency
Returns:
- Confirmation of dependency removal
Example:
execute_forgetful_tool(
"remove_dependency",
{
"task_id": 25,
"depends_on_task_id": 20
}
)
Cross-Category Workflows
Real-world scenarios demonstrating how tools work together.
Scenario 1: Documenting a Complete Feature
Context: You've implemented a new authentication system and want to capture all knowledge.
# 1. Create project
project = execute_forgetful_tool(
"create_project",
{
"name": "Authentication System V2",
"project_type": "development",
"status": "active"
}
)
project_id = project["id"]
# 2. Store architecture decision document
adr = execute_forgetful_tool(
"create_document",
{
"title": "ADR-001: OAuth2 + JWT Authentication Strategy",
"content": "[... full 3000-word architecture decision record ...]",
"document_type": "markdown",
"tags": ["adr", "authentication", "oauth2", "jwt"],
"project_id": project_id
}
)
# 3. Extract key decision as atomic memory
decision_memory = execute_forgetful_tool(
"create_memory",
{
"title": "Auth strategy: OAuth2 for third-party + JWT for sessions",
"content": "Use OAuth2 for social login and JWT for internal sessions.",
"context": "Capturing the authentication architecture decision",
"keywords": ["authentication", "oauth2", "jwt"],
"tags": ["authentication", "decision"],
"importance": 10,
"project_ids": [project_id],
"document_ids": [adr["id"]]
}
)
# 4. Store reusable JWT middleware
middleware = execute_forgetful_tool(
"create_code_artifact",
{
"title": "JWT Authentication Middleware",
"description": "FastAPI middleware that validates JWT bearer tokens",
"code": '''
from fastapi import Request, HTTPException
from jose import jwt, JWTError
async def verify_jwt(request: Request):
token = request.headers.get("Authorization", "").replace("Bearer ", "")
try:
payload = jwt.decode(token, settings.SECRET_KEY, algorithms=["HS256"])
return payload
except JWTError:
raise HTTPException(status_code=401, detail="Invalid token")
''',
"language": "python",
"tags": ["authentication", "jwt", "middleware"],
"project_id": project_id
}
)
# 5. Create entity for the engineer who implemented it
engineer = execute_forgetful_tool(
"create_entity",
{
"name": "Alex Kim",
"entity_type": "Individual",
"notes": "Senior Full-Stack Engineer",
"tags": ["engineering", "fullstack"],
"aka": ["Alex", "A.K."]
}
)
# 6. Link engineer to the decision memory
execute_forgetful_tool(
"link_entity_to_memory",
{
"entity_id": engineer["id"],
"memory_id": decision_memory["id"]
}
)
# 7. Later, query everything about auth
results = execute_forgetful_tool(
"query_memory",
{
"query": "authentication implementation",
"query_context": "Reviewing the authentication implementation",
"project_ids": [project_id]
}
)
# Returns decision_memory + auto-linked memories + linked document + code artifact + entity
Scenario 2: New Team Member Onboarding
Context: A new engineer joins, you want to capture their information and link relevant knowledge.
# 1. Create entity for new engineer
new_hire = execute_forgetful_tool(
"create_entity",
{
"name": "Jordan Taylor",
"entity_type": "Individual",
"notes": "Backend Engineer - Payments Team",
"tags": ["engineering", "backend", "payments"],
"aka": ["Jordan", "J.T."]
}
)
# 2. Get company entity (assuming it exists) - can search by name or alias
company = execute_forgetful_tool(
"search_entities",
{"query": "TechFlow"}
)
company_id = company["entities"][0]["id"]
# 3. Create employment relationship
execute_forgetful_tool(
"create_entity_relationship",
{
"from_entity_id": new_hire["id"],
"to_entity_id": company_id,
"relationship_type": "works_for",
"metadata": {
"role": "Backend Engineer II",
"department": "Payments",
"team": "Checkout"
}
}
)
# 4. Create onboarding memory
onboarding_memory = execute_forgetful_tool(
"create_memory",
{
"title": "Jordan Taylor joined - Payments team focus areas",
"content": "Jordan will focus on payment integrations and PCI compliance.",
"context": "New hire onboarding for the payments team",
"keywords": ["jordan", "payments", "stripe", "pci"],
"tags": ["team", "onboarding", "payments"],
"importance": 7
}
)
# 5. Link new hire to onboarding memory
execute_forgetful_tool(
"link_entity_to_memory",
{
"entity_id": new_hire["id"],
"memory_id": onboarding_memory["id"]
}
)
# 6. Query existing payment system memories and link relevant ones
payment_memories = execute_forgetful_tool(
"query_memory",
{
"query": "payment gateway stripe paypal",
"query_context": "Finding onboarding material for the payments team",
"k": 5
}
)
for memory in payment_memories["primary_memories"]:
execute_forgetful_tool(
"link_entity_to_memory",
{
"entity_id": new_hire["id"],
"memory_id": memory["id"]
}
)
Scenario 3: Infrastructure Incident Documentation
Context: Redis server failed, you resolved it and want to document for future reference.
# 1. Get the server entity (can also search by alias like "redis-primary")
server = execute_forgetful_tool(
"search_entities",
{"query": "Cache Server 01"}
)
server_id = server["entities"][0]["id"]
# 2. Create incident memory
incident = execute_forgetful_tool(
"create_memory",
{
"title": "Redis failover incident - memory exhaustion",
"content": "Cache Server 01 ran out of memory due to unbounded key growth. Implemented maxmemory-policy=allkeys-lru and set maxmemory=4gb. Also added monitoring alerts at 80% memory usage.",
"importance": 9,
"tags": ["incident", "redis", "infrastructure", "production"],
"context": "Production incident on 2025-01-18, resolved in 45 minutes",
"keywords": ["redis", "memory", "failover", "monitoring"]
}
)
# 3. Link incident to server
execute_forgetful_tool(
"link_entity_to_memory",
{
"entity_id": server_id,
"memory_id": incident["id"]
}
)
# 4. Update server metadata with fix
execute_forgetful_tool(
"update_entity",
{
"entity_id": server_id,
"notes": "4 GB maxmemory, allkeys-lru policy, monitoring enabled"
}
)
# 5. Create code artifact for monitoring script
monitoring_script = execute_forgetful_tool(
"create_code_artifact",
{
"title": "Redis Memory Monitoring Script",
"code": '''
import redis
import os
def check_redis_memory(threshold=0.8):
r = redis.Redis(host='cache-server-01', port=6379)
info = r.info('memory')
used = info['used_memory']
max_mem = info['maxmemory']
if max_mem > 0 and (used / max_mem) > threshold:
send_alert(f"Redis memory at {(used/max_mem)*100:.1f}%")
''',
"language": "python",
"tags": ["monitoring", "redis", "alerting"],
"description": "Alert when Redis memory usage exceeds threshold"
}
)
# 6. Link monitoring script to incident memory
execute_forgetful_tool(
"create_memory",
{
"title": "Implemented Redis memory monitoring",
"content": "Added an alert at 80% memory usage to prevent future incidents.",
"context": "Follow-up action from the Redis memory exhaustion incident",
"keywords": ["redis", "memory", "monitoring", "alert"],
"tags": ["monitoring", "prevention", "redis"],
"importance": 8,
"code_artifact_ids": [monitoring_script["id"]]
}
)
Scenario 4: Research and Decision Making
Context: Researching database options, documenting findings, and making a decision.
# 1. Create research project
research_project = execute_forgetful_tool(
"create_project",
{
"name": "Database Technology Evaluation 2025",
"project_type": "learning",
"status": "active"
}
)
project_id = research_project["id"]
# 2. Create comprehensive research document
research_doc = execute_forgetful_tool(
"create_document",
{
"title": "Vector Database Comparison: pgvector vs Qdrant vs Weaviate",
"description": "Comparison of vector database options",
"content": "[... 5000-word detailed comparison of features, performance, costs ...]",
"document_type": "markdown",
"tags": ["research", "database", "vector-db", "embeddings"],
"project_id": project_id
}
)
# 3. Extract atomic insights as memories
insight1 = execute_forgetful_tool(
"create_memory",
{
"title": "pgvector: Best for existing PostgreSQL setups",
"content": "pgvector avoids a separate vector database when PostgreSQL is in use.",
"context": "Capturing a conclusion from the vector database comparison",
"keywords": ["pgvector", "postgresql", "vector-database"],
"tags": ["database", "pgvector", "vectors"],
"importance": 8,
"project_ids": [project_id],
"document_ids": [research_doc["id"]]
}
)
insight2 = execute_forgetful_tool(
"create_memory",
{
"title": "Qdrant: Best performance for large-scale vector search",
"content": "Qdrant performs well at large scale but requires a separate service.",
"context": "Capturing a conclusion from the vector database comparison",
"keywords": ["qdrant", "vector-database", "performance"],
"tags": ["database", "qdrant", "vectors"],
"importance": 8,
"project_ids": [project_id],
"document_ids": [research_doc["id"]]
}
)
# 4. Make decision and create decision memory
decision = execute_forgetful_tool(
"create_memory",
{
"title": "Decision: pgvector for Forgetful project",
"content": "Selected pgvector because Forgetful already uses PostgreSQL.",
"context": "Final decision from the vector database evaluation",
"keywords": ["pgvector", "postgresql", "database-decision"],
"tags": ["decision", "database", "pgvector", "forgetful"],
"importance": 10,
"project_ids": [project_id],
"document_ids": [research_doc["id"]]
}
)
# 5. Manually link related insights to decision
execute_forgetful_tool(
"link_memories",
{"memory_id": decision["id"], "related_ids": [insight1["id"]]}
)
execute_forgetful_tool(
"link_memories",
{"memory_id": decision["id"], "related_ids": [insight2["id"]]}
)
# 6. Mark project as completed
execute_forgetful_tool(
"update_project",
{
"project_id": project_id,
"status": "completed",
"notes": "Selected pgvector; evaluation completed 2025-01-15"
}
)
Best Practices
Memory Creation
- One concept per memory - Follow atomic memory principle
- Title it first - If you can't easily title it, break it down further
- High importance for reusable knowledge - Use 8-10 for architectural decisions and patterns
- Always provide context - Future you will thank past you
- Tag consistently - Develop a tagging taxonomy for your knowledge domain
Project Organization
- Scope queries to projects - Dramatically improves search relevance
- Use project types consistently - Helps with filtering and organization
- Archive completed projects - Don't delete - preserve knowledge with context
- Link related projects - Create memories that reference multiple projects
Entity & Knowledge Graph
- Entities for concrete things, memories for concepts - "Sarah Chen" is an entity, "Sarah's API design preference" is a memory
- Build relationships as you learn - Don't wait to build complete graphs
- Use metadata liberally - Capture temporal and contextual information
- Link entities to relevant memories - Creates rich context for queries
Code Artifacts & Documents
- Code artifacts for reusable snippets (<200 lines) - Utilities, patterns, configs
- Documents for detailed content (>400 words) - ADRs, research, specifications
- Always extract atomic memories - Documents are storage, memories are searchable knowledge
- Link atoms to documents - Preserve connection to detailed source
Search & Retrieval
- Query early and often - Check existing knowledge before creating duplicates
- Use natural language - Semantic search works better than keyword matching
- Filter by project for focus - Especially in multi-project environments
- Check auto-linked memories - Often find related context you didn't know existed
Token Budget & Performance
Forgetful protects your LLM context window with configurable token budgets:
- Default: 8,000 tokens per query result
- Max 20 memories returned per query
- Prioritization: High importance (9-10) → Medium importance (7-8) → Recency (newest first)
- Graceful truncation: If over budget, lower-priority memories excluded
Configure via environment variables:
MEMORY_TOKEN_BUDGET=8000
MEMORY_MAX_QUERY_RESULTS=20
Additional Resources
- Configuration Guide - All environment variables
- Connectivity Guide - MCP client setup
- Search Documentation - Embedding pipeline details
- MCP Protocol - MCP specification
Last Updated: 2025-01-22 Forgetful Version: 0.1.x