more tools, append endpoint, doc updates
This commit is contained in:
parent
50b7d08bb2
commit
eab16aafff
|
|
@ -1078,6 +1078,62 @@ async def create_or_update_note(request: Request, note_path: str, content: dict)
|
||||||
raise HTTPException(status_code=500, detail=safe_error_message(e, "Failed to save note"))
|
raise HTTPException(status_code=500, detail=safe_error_message(e, "Failed to save note"))
|
||||||
|
|
||||||
|
|
||||||
|
@api_router.patch("/notes/{note_path:path}", tags=["Notes"])
|
||||||
|
@limiter.limit("60/minute")
|
||||||
|
async def append_to_note(request: Request, note_path: str, data: dict):
|
||||||
|
"""
|
||||||
|
Append content to an existing note without overwriting.
|
||||||
|
|
||||||
|
Perfect for journals, logs, or collecting ideas incrementally.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
note_path: Path to the note
|
||||||
|
data: Dictionary with 'content' to append and optional 'add_timestamp' boolean
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
content_to_append = data.get('content', '')
|
||||||
|
add_timestamp = data.get('add_timestamp', False)
|
||||||
|
|
||||||
|
if not content_to_append:
|
||||||
|
raise HTTPException(status_code=400, detail="Content to append is required")
|
||||||
|
|
||||||
|
# Get existing content
|
||||||
|
existing_content = get_note_content(config['storage']['notes_dir'], note_path)
|
||||||
|
|
||||||
|
if existing_content is None:
|
||||||
|
raise HTTPException(status_code=404, detail="Note not found")
|
||||||
|
|
||||||
|
# Build the appended content
|
||||||
|
if add_timestamp:
|
||||||
|
from datetime import datetime
|
||||||
|
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M")
|
||||||
|
content_to_append = f"\n\n---\n\n**{timestamp}**\n\n{content_to_append}"
|
||||||
|
else:
|
||||||
|
content_to_append = f"\n\n{content_to_append}"
|
||||||
|
|
||||||
|
new_content = existing_content + content_to_append
|
||||||
|
|
||||||
|
# Run on_note_save hook
|
||||||
|
transformed_content = plugin_manager.run_hook('on_note_save', note_path=note_path, content=new_content)
|
||||||
|
if transformed_content is None:
|
||||||
|
transformed_content = new_content
|
||||||
|
|
||||||
|
success = save_note(config['storage']['notes_dir'], note_path, transformed_content)
|
||||||
|
|
||||||
|
if not success:
|
||||||
|
raise HTTPException(status_code=500, detail="Failed to append to note")
|
||||||
|
|
||||||
|
return {
|
||||||
|
"success": True,
|
||||||
|
"path": note_path,
|
||||||
|
"message": "Content appended successfully"
|
||||||
|
}
|
||||||
|
except HTTPException:
|
||||||
|
raise
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(status_code=500, detail=safe_error_message(e, "Failed to append to note"))
|
||||||
|
|
||||||
|
|
||||||
@api_router.delete("/notes/{note_path:path}", tags=["Notes"])
|
@api_router.delete("/notes/{note_path:path}", tags=["Notes"])
|
||||||
@limiter.limit("30/minute")
|
@limiter.limit("30/minute")
|
||||||
async def remove_note(request: Request, note_path: str):
|
async def remove_note(request: Request, note_path: str):
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,56 @@ DELETE /api/notes/{note_path}
|
||||||
curl -X DELETE http://localhost:8000/api/notes/test.md
|
curl -X DELETE http://localhost:8000/api/notes/test.md
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Append to Note
|
||||||
|
```http
|
||||||
|
PATCH /api/notes/{note_path}
|
||||||
|
Content-Type: application/json
|
||||||
|
|
||||||
|
{
|
||||||
|
"content": "Content to append...",
|
||||||
|
"add_timestamp": true
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Append content to an existing note without overwriting. Perfect for journals, logs, or collecting ideas incrementally.
|
||||||
|
|
||||||
|
**Parameters:**
|
||||||
|
| Parameter | Type | Required | Description |
|
||||||
|
|-----------|------|----------|-------------|
|
||||||
|
| `content` | string | Yes | Content to append to the note |
|
||||||
|
| `add_timestamp` | boolean | No | If `true`, prepends a timestamp header (default: `false`) |
|
||||||
|
|
||||||
|
**Response:**
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"success": true,
|
||||||
|
"path": "daily-journal.md",
|
||||||
|
"message": "Content appended successfully"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
**Example with timestamp:**
|
||||||
|
```bash
|
||||||
|
curl -X PATCH http://localhost:8000/api/notes/daily-journal.md \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '{"content": "Had a productive meeting about the roadmap.", "add_timestamp": true}'
|
||||||
|
```
|
||||||
|
|
||||||
|
This will append:
|
||||||
|
```markdown
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**2024-03-13 14:30**
|
||||||
|
|
||||||
|
Had a productive meeting about the roadmap.
|
||||||
|
```
|
||||||
|
|
||||||
|
**Windows PowerShell:**
|
||||||
|
```powershell
|
||||||
|
curl.exe -X PATCH http://localhost:8000/api/notes/daily-journal.md -H "Content-Type: application/json" -d "{\"content\": \"New entry here\", \"add_timestamp\": true}"
|
||||||
|
```
|
||||||
|
|
||||||
### Move Note
|
### Move Note
|
||||||
```http
|
```http
|
||||||
POST /api/notes/move
|
POST /api/notes/move
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,9 @@ MCP (Model Context Protocol) is an open standard that allows AI assistants to se
|
||||||
- 📖 **Read** note contents
|
- 📖 **Read** note contents
|
||||||
- 🏷️ **Browse** by tags
|
- 🏷️ **Browse** by tags
|
||||||
- 📝 **Create** new notes
|
- 📝 **Create** new notes
|
||||||
|
- ✏️ **Append** to existing notes (journals, logs)
|
||||||
|
- 📂 **Organize** notes (move, rename, folders)
|
||||||
|
- 📋 **Use templates** to create structured notes
|
||||||
- 🔗 **Explore** the knowledge graph
|
- 🔗 **Explore** the knowledge graph
|
||||||
|
|
||||||
## Quick Setup
|
## Quick Setup
|
||||||
|
|
@ -114,6 +117,7 @@ The MCP server provides these tools to AI assistants:
|
||||||
| `search_notes` | Full-text search across all notes |
|
| `search_notes` | Full-text search across all notes |
|
||||||
| `list_notes` | List all notes with metadata |
|
| `list_notes` | List all notes with metadata |
|
||||||
| `get_note` | Read a specific note's content |
|
| `get_note` | Read a specific note's content |
|
||||||
|
| `get_recent_notes` | Get recently modified notes (last N days) |
|
||||||
|
|
||||||
### Organization
|
### Organization
|
||||||
|
|
||||||
|
|
@ -128,6 +132,8 @@ The MCP server provides these tools to AI assistants:
|
||||||
| Tool | Description |
|
| Tool | Description |
|
||||||
|------|-------------|
|
|------|-------------|
|
||||||
| `create_note` | Create or update a note |
|
| `create_note` | Create or update a note |
|
||||||
|
| `append_to_note` | Append content to an existing note (great for journals/logs) |
|
||||||
|
| `move_note` | Move or rename a note |
|
||||||
| `delete_note` | Delete a note |
|
| `delete_note` | Delete a note |
|
||||||
| `create_folder` | Create a new folder |
|
| `create_folder` | Create a new folder |
|
||||||
|
|
||||||
|
|
@ -137,6 +143,7 @@ The MCP server provides these tools to AI assistants:
|
||||||
|------|-------------|
|
|------|-------------|
|
||||||
| `list_templates` | List available templates |
|
| `list_templates` | List available templates |
|
||||||
| `get_template` | Get template content |
|
| `get_template` | Get template content |
|
||||||
|
| `create_note_from_template` | Create a note from a template with variable substitution |
|
||||||
|
|
||||||
### System
|
### System
|
||||||
|
|
||||||
|
|
@ -144,6 +151,62 @@ The MCP server provides these tools to AI assistants:
|
||||||
|------|-------------|
|
|------|-------------|
|
||||||
| `health_check` | Verify server connectivity |
|
| `health_check` | Verify server connectivity |
|
||||||
|
|
||||||
|
## Tool Details
|
||||||
|
|
||||||
|
### `append_to_note`
|
||||||
|
|
||||||
|
Append content to an existing note without overwriting. Perfect for journals, logs, or collecting ideas.
|
||||||
|
|
||||||
|
| Parameter | Type | Required | Description |
|
||||||
|
|-----------|------|----------|-------------|
|
||||||
|
| `path` | string | Yes | Path to existing note |
|
||||||
|
| `content` | string | Yes | Content to append |
|
||||||
|
| `add_timestamp` | boolean | No | Add timestamp header before content |
|
||||||
|
|
||||||
|
**Example prompt:** "Add this meeting summary to my daily-journal.md with a timestamp"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `move_note`
|
||||||
|
|
||||||
|
Move or rename a note to a different location.
|
||||||
|
|
||||||
|
| Parameter | Type | Required | Description |
|
||||||
|
|-----------|------|----------|-------------|
|
||||||
|
| `old_path` | string | Yes | Current note path |
|
||||||
|
| `new_path` | string | Yes | New path (can include folder) |
|
||||||
|
|
||||||
|
**Example prompt:** "Move draft.md to published/final-article.md"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `get_recent_notes`
|
||||||
|
|
||||||
|
Get recently modified notes. Useful for context about what you've been working on.
|
||||||
|
|
||||||
|
| Parameter | Type | Required | Default | Description |
|
||||||
|
|-----------|------|----------|---------|-------------|
|
||||||
|
| `days` | integer | No | 7 | Notes modified in last N days |
|
||||||
|
| `limit` | integer | No | 10 | Max notes to return |
|
||||||
|
|
||||||
|
**Example prompt:** "What was I working on this week?"
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### `create_note_from_template`
|
||||||
|
|
||||||
|
Create a new note from a template with variable substitution.
|
||||||
|
|
||||||
|
| Parameter | Type | Required | Description |
|
||||||
|
|-----------|------|----------|-------------|
|
||||||
|
| `template_name` | string | Yes | Template name (e.g., "meeting-notes") |
|
||||||
|
| `note_path` | string | Yes | Path for the new note |
|
||||||
|
| `variables` | object | No | Variables to substitute (e.g., `{"project": "Alpha"}`) |
|
||||||
|
|
||||||
|
**Built-in placeholders:** `{{date}}`, `{{time}}`, `{{datetime}}`, `{{title}}`, `{{folder}}`
|
||||||
|
|
||||||
|
**Example prompt:** "Create a new meeting note for Project Alpha using the meeting-notes template"
|
||||||
|
|
||||||
## Usage Examples
|
## Usage Examples
|
||||||
|
|
||||||
Once configured, you can interact with your notes naturally:
|
Once configured, you can interact with your notes naturally:
|
||||||
|
|
@ -166,6 +229,24 @@ Once configured, you can interact with your notes naturally:
|
||||||
>
|
>
|
||||||
> "You have 7 notes with the #project tag..."
|
> "You have 7 notes with the #project tag..."
|
||||||
|
|
||||||
|
> **User:** "Add this to my daily journal with a timestamp"
|
||||||
|
>
|
||||||
|
> **AI:** *Uses `append_to_note` with `add_timestamp: true`*
|
||||||
|
>
|
||||||
|
> "Done! I've appended your entry to 'daily-journal.md' with today's timestamp."
|
||||||
|
|
||||||
|
> **User:** "What was I working on last week?"
|
||||||
|
>
|
||||||
|
> **AI:** *Uses `get_recent_notes` with `days: 7`*
|
||||||
|
>
|
||||||
|
> "You modified 5 notes in the last week: project-roadmap.md, meeting-notes.md..."
|
||||||
|
|
||||||
|
> **User:** "Create a meeting note for the design review using my template"
|
||||||
|
>
|
||||||
|
> **AI:** *Uses `create_note_from_template` with the meeting-notes template*
|
||||||
|
>
|
||||||
|
> "Created 'meetings/design-review-2024-03-13.md' from your meeting-notes template."
|
||||||
|
|
||||||
## Authentication
|
## Authentication
|
||||||
|
|
||||||
If you have authentication enabled in NoteDiscovery:
|
If you have authentication enabled in NoteDiscovery:
|
||||||
|
|
|
||||||
|
|
@ -189,6 +189,68 @@ class NoteDiscoveryClient:
|
||||||
encoded_path = urllib.parse.quote(path, safe="")
|
encoded_path = urllib.parse.quote(path, safe="")
|
||||||
return self._request("DELETE", f"/api/notes/{encoded_path}")
|
return self._request("DELETE", f"/api/notes/{encoded_path}")
|
||||||
|
|
||||||
|
def append_to_note(self, path: str, content: str, add_timestamp: bool = False) -> APIResponse:
|
||||||
|
"""
|
||||||
|
Append content to an existing note.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
path: Note path
|
||||||
|
content: Content to append
|
||||||
|
add_timestamp: Whether to add a timestamp header
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
APIResponse with append result
|
||||||
|
"""
|
||||||
|
encoded_path = urllib.parse.quote(path, safe="")
|
||||||
|
return self._request(
|
||||||
|
"PATCH",
|
||||||
|
f"/api/notes/{encoded_path}",
|
||||||
|
data={"content": content, "add_timestamp": add_timestamp}
|
||||||
|
)
|
||||||
|
|
||||||
|
def move_note(self, old_path: str, new_path: str) -> APIResponse:
|
||||||
|
"""
|
||||||
|
Move or rename a note.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
old_path: Current note path
|
||||||
|
new_path: New note path
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
APIResponse with move result
|
||||||
|
"""
|
||||||
|
return self._request(
|
||||||
|
"POST",
|
||||||
|
"/api/notes/move",
|
||||||
|
data={"oldPath": old_path, "newPath": new_path}
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_note_from_template(
|
||||||
|
self,
|
||||||
|
template_name: str,
|
||||||
|
note_path: str,
|
||||||
|
variables: dict | None = None
|
||||||
|
) -> APIResponse:
|
||||||
|
"""
|
||||||
|
Create a note from a template.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
template_name: Name of the template
|
||||||
|
note_path: Path for the new note
|
||||||
|
variables: Variables to substitute in the template
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
APIResponse with creation result
|
||||||
|
"""
|
||||||
|
data = {
|
||||||
|
"template": template_name,
|
||||||
|
"path": note_path,
|
||||||
|
}
|
||||||
|
if variables:
|
||||||
|
data["variables"] = variables
|
||||||
|
|
||||||
|
return self._request("POST", "/api/templates/create-note", data=data)
|
||||||
|
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
# Search API
|
# Search API
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
|
|
|
||||||
|
|
@ -450,6 +450,113 @@ class MCPServer:
|
||||||
|
|
||||||
return f"Template: {name}\n---\n{content}"
|
return f"Template: {name}\n---\n{content}"
|
||||||
|
|
||||||
|
def _tool_append_to_note(self, args: dict) -> str:
|
||||||
|
"""Append content to an existing note."""
|
||||||
|
path = args.get("path", "")
|
||||||
|
content = args.get("content", "")
|
||||||
|
add_timestamp = args.get("add_timestamp", False)
|
||||||
|
|
||||||
|
is_valid, error = self._validate_path(path)
|
||||||
|
if not is_valid:
|
||||||
|
return f"Error: {error}"
|
||||||
|
if not content:
|
||||||
|
return "Error: content is required"
|
||||||
|
|
||||||
|
response = self.client.append_to_note(path, content, add_timestamp)
|
||||||
|
|
||||||
|
if not response.success:
|
||||||
|
return f"Failed to append to note: {response.error}"
|
||||||
|
|
||||||
|
return f"✅ Content appended to: {path}"
|
||||||
|
|
||||||
|
def _tool_move_note(self, args: dict) -> str:
|
||||||
|
"""Move or rename a note."""
|
||||||
|
old_path = args.get("old_path", "")
|
||||||
|
new_path = args.get("new_path", "")
|
||||||
|
|
||||||
|
is_valid, error = self._validate_path(old_path)
|
||||||
|
if not is_valid:
|
||||||
|
return f"Error: old_path - {error}"
|
||||||
|
|
||||||
|
is_valid, error = self._validate_path(new_path)
|
||||||
|
if not is_valid:
|
||||||
|
return f"Error: new_path - {error}"
|
||||||
|
|
||||||
|
response = self.client.move_note(old_path, new_path)
|
||||||
|
|
||||||
|
if not response.success:
|
||||||
|
return f"Failed to move note: {response.error}"
|
||||||
|
|
||||||
|
return f"✅ Note moved: {old_path} → {new_path}"
|
||||||
|
|
||||||
|
def _tool_get_recent_notes(self, args: dict) -> str:
|
||||||
|
"""Get recently modified notes."""
|
||||||
|
days = args.get("days", 7)
|
||||||
|
limit = args.get("limit", 10)
|
||||||
|
|
||||||
|
# Get all notes
|
||||||
|
response = self.client.list_notes()
|
||||||
|
|
||||||
|
if not response.success:
|
||||||
|
return f"Failed to get notes: {response.error}"
|
||||||
|
|
||||||
|
data = response.data or {}
|
||||||
|
notes = data.get("notes", [])
|
||||||
|
|
||||||
|
if not notes:
|
||||||
|
return "No notes found."
|
||||||
|
|
||||||
|
# Filter by date
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
cutoff = datetime.now() - timedelta(days=days)
|
||||||
|
|
||||||
|
recent_notes = []
|
||||||
|
for note in notes:
|
||||||
|
modified_str = note.get("modified", "")
|
||||||
|
if modified_str:
|
||||||
|
try:
|
||||||
|
# Parse ISO format datetime
|
||||||
|
modified = datetime.fromisoformat(modified_str.replace("Z", "+00:00"))
|
||||||
|
if modified.replace(tzinfo=None) >= cutoff:
|
||||||
|
recent_notes.append(note)
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Sort by modified date (most recent first) and limit
|
||||||
|
recent_notes.sort(key=lambda x: x.get("modified", ""), reverse=True)
|
||||||
|
recent_notes = recent_notes[:limit]
|
||||||
|
|
||||||
|
if not recent_notes:
|
||||||
|
return f"No notes modified in the last {days} day(s)."
|
||||||
|
|
||||||
|
output = [f"📅 Notes modified in the last {days} day(s) (showing {len(recent_notes)}):\n"]
|
||||||
|
for note in recent_notes:
|
||||||
|
path = note.get("path", "unknown")
|
||||||
|
modified = note.get("modified", "")[:10] # Just the date part
|
||||||
|
output.append(f" 📝 {path} (modified: {modified})")
|
||||||
|
|
||||||
|
return "\n".join(output)
|
||||||
|
|
||||||
|
def _tool_create_note_from_template(self, args: dict) -> str:
|
||||||
|
"""Create a note from a template."""
|
||||||
|
template_name = args.get("template_name", "")
|
||||||
|
note_path = args.get("note_path", "")
|
||||||
|
variables = args.get("variables", {})
|
||||||
|
|
||||||
|
if not template_name:
|
||||||
|
return "Error: template_name is required"
|
||||||
|
|
||||||
|
is_valid, error = self._validate_path(note_path)
|
||||||
|
if not is_valid:
|
||||||
|
return f"Error: note_path - {error}"
|
||||||
|
|
||||||
|
response = self.client.create_note_from_template(template_name, note_path, variables)
|
||||||
|
|
||||||
|
if not response.success:
|
||||||
|
return f"Failed to create note from template: {response.error}"
|
||||||
|
|
||||||
|
return f"✅ Note created from template '{template_name}': {note_path}"
|
||||||
|
|
||||||
def _tool_health_check(self, args: dict) -> str:
|
def _tool_health_check(self, args: dict) -> str:
|
||||||
"""Check server health."""
|
"""Check server health."""
|
||||||
response = self.client.health_check()
|
response = self.client.health_check()
|
||||||
|
|
|
||||||
|
|
@ -139,6 +139,86 @@ TOOLS: list[dict[str, Any]] = [
|
||||||
"required": ["path"]
|
"required": ["path"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "append_to_note",
|
||||||
|
"description": "Append content to an existing note without overwriting. Perfect for journals, logs, meeting notes, or collecting ideas incrementally.",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"path": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Path to the existing note"
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Content to append to the note"
|
||||||
|
},
|
||||||
|
"add_timestamp": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to add a timestamp header before the appended content (default: false)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["path", "content"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "move_note",
|
||||||
|
"description": "Move or rename a note to a different path. Use this to reorganize notes or rename them.",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"old_path": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Current path of the note"
|
||||||
|
},
|
||||||
|
"new_path": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "New path for the note (can be in a different folder)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["old_path", "new_path"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "get_recent_notes",
|
||||||
|
"description": "Get recently modified notes. Useful for finding what you were working on recently.",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"days": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Get notes modified in the last N days (default: 7)"
|
||||||
|
},
|
||||||
|
"limit": {
|
||||||
|
"type": "integer",
|
||||||
|
"description": "Maximum number of notes to return (default: 10)"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "create_note_from_template",
|
||||||
|
"description": "Create a new note from a template with variable substitution. Variables in the template like {{variable_name}} will be replaced.",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"template_name": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Name of the template to use (e.g., 'meeting-notes', 'daily-journal')"
|
||||||
|
},
|
||||||
|
"note_path": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Path for the new note (e.g., 'meetings/2024-03-13.md')"
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Variables to substitute in the template (e.g., {\"project\": \"Alpha\", \"date\": \"2024-03-13\"})"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["template_name", "note_path"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
# =========================================================================
|
# =========================================================================
|
||||||
# Templates
|
# Templates
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue