obsidian_periodic_notes
Retrieve current periodic notes (daily, weekly, monthly, quarterly, yearly) from Obsidian vaults with comprehensive metadata and content for structured journaling and planning.
Instructions
Get current periodic note for the specified period. Returns both comprehensive metadata (tags, links, titles, etc.) and note content using the enhanced API approach.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| period | Yes | The period type (daily, weekly, monthly, quarterly, yearly) |
Implementation Reference
- PeriodicNotesToolHandler class implements the tool 'obsidian_periodic_notes'. The run_tool method fetches the current periodic note for the given period (daily/weekly/etc.), retrieves metadata and content using Obsidian API, enhances with note info (tags, links, frontmatter), and returns formatted TextContent.class PeriodicNotesToolHandler(ToolHandler): def __init__(self): super().__init__(TOOL_PERIODIC_NOTES) def get_tool_description(self): return Tool( name=self.name, description="Get current periodic note for the specified period. Returns both comprehensive metadata (tags, links, titles, etc.) and note content using the enhanced API approach.", inputSchema={ "type": "object", "properties": { "period": { "type": "string", "description": "The period type (daily, weekly, monthly, quarterly, yearly)", "enum": ["daily", "weekly", "monthly", "quarterly", "yearly"] } }, "required": ["period"] } ) def run_tool(self, args: dict) -> Sequence[TextContent | ImageContent | EmbeddedResource]: if "period" not in args: raise RuntimeError("period argument missing in arguments") period = args["period"] valid_periods = ["daily", "weekly", "monthly", "quarterly", "yearly"] if period not in valid_periods: raise RuntimeError(f"Invalid period: {period}. Must be one of: {', '.join(valid_periods)}") try: # Get the periodic note metadata to extract the file path metadata_response = api.get_periodic_note(period, "metadata") # Parse the JSON response to extract the file path import json try: metadata_json = json.loads(metadata_response) filepath = metadata_json.get('path', '') except (json.JSONDecodeError, AttributeError): # Fallback: try to get content directly if metadata parsing fails content = api.get_periodic_note(period, "content") return [ TextContent( type="text", text=f"## Periodic Note ({period})\n\n### Content Below:\n\n{content}" ) ] if not filepath: return [ TextContent( type="text", text=f"No {period} periodic note found." ) ] # Use the enhanced API approach to get comprehensive metadata and content # Get content using the existing method content = api.get_file_contents(filepath) # Get enhanced metadata using REST API url = f"{api.get_base_url()}/vault/{filepath}" headers = api._get_headers() | {'Accept': 'application/vnd.olrapi.note+json'} def call_fn(): response = requests.get(url, headers=headers, verify=api.verify_ssl, timeout=api.timeout) response.raise_for_status() return response.json() file_data = api._safe_call(call_fn) # Extract data from the API response api_frontmatter = file_data.get('frontmatter', {}) api_stat = file_data.get('stat', {}) api_tags = file_data.get('tags', []) # Get additional note info using obsidiantools for connections/links try: note_info = api.get_note_info(filepath) # Replace the tags from get_note_info with the more accurate API tags note_info['metadata']['tags'] = api_tags # Also update frontmatter with API data for accuracy note_info['metadata']['front_matter'] = api_frontmatter # Update file info with API stat data note_info['metadata']['file_info'].update({ 'ctime': api_stat.get('ctime'), 'mtime': api_stat.get('mtime'), 'size': api_stat.get('size') }) except Exception as note_info_error: # Fallback: create basic note info from API data note_info = { 'metadata': { 'tags': api_tags, 'front_matter': api_frontmatter, 'file_info': { 'rel_filepath': filepath, 'ctime': api_stat.get('ctime'), 'mtime': api_stat.get('mtime'), 'size': api_stat.get('size') }, 'counts': { 'n_backlinks': 0, 'n_wikilinks': 0, 'n_embedded_files': 0, 'n_tags': len(api_tags) } }, 'connections': { 'direct_links': [], 'backlinks': [], 'non_existent_links': [] } } # Create metadata JSON following BatchGetFilesToolHandler pattern metadata_json = { "filepath": filepath, "note_info": note_info } return [ TextContent( type="text", text=f"## Periodic Note ({period}): {filepath}\n\n### Metadata & Info\n```json\n{json.dumps(metadata_json, indent=2)}\n```" ), TextContent( type="text", text=f"### Content Below:\n\n{content}" ) ] except Exception as e: return [ TextContent( type="text", text=f"Error getting {period} periodic note: {str(e)}" ) ]
- Input schema definition for the 'obsidian_periodic_notes' tool, specifying the required 'period' parameter with valid enum values.def get_tool_description(self): return Tool( name=self.name, description="Get current periodic note for the specified period. Returns both comprehensive metadata (tags, links, titles, etc.) and note content using the enhanced API approach.", inputSchema={ "type": "object", "properties": { "period": { "type": "string", "description": "The period type (daily, weekly, monthly, quarterly, yearly)", "enum": ["daily", "weekly", "monthly", "quarterly", "yearly"] } }, "required": ["period"] } )
- src/mcp_obsidian_advanced/server.py:25-43 (registration)TOOL_MAPPING dictionary maps the tool name 'obsidian_periodic_notes' (TOOL_PERIODIC_NOTES) to its handler class PeriodicNotesToolHandler, used for registration.# Tool mapping between tool constants and their handler classes TOOL_MAPPING = { tools.TOOL_LIST_FILES_IN_DIR: tools.ListFilesInDirToolHandler, tools.TOOL_SIMPLE_SEARCH: tools.SearchToolHandler, tools.TOOL_PATCH_CONTENT: tools.PatchContentToolHandler, tools.TOOL_PUT_CONTENT: tools.PutContentToolHandler, tools.TOOL_APPEND_CONTENT: tools.AppendContentToolHandler, tools.TOOL_DELETE_FILE: tools.DeleteFileToolHandler, tools.TOOL_COMPLEX_SEARCH: tools.ComplexSearchToolHandler, tools.TOOL_BATCH_GET_FILES: tools.BatchGetFilesToolHandler, tools.TOOL_PERIODIC_NOTES: tools.PeriodicNotesToolHandler, tools.TOOL_RECENT_PERIODIC_NOTES: tools.RecentPeriodicNotesToolHandler, tools.TOOL_RECENT_CHANGES: tools.RecentChangesToolHandler, tools.TOOL_UNDERSTAND_VAULT: tools.UnderstandVaultToolHandler, tools.TOOL_GET_ACTIVE_NOTE: tools.GetActiveNoteToolHandler, tools.TOOL_OPEN_FILES: tools.OpenFilesToolHandler, tools.TOOL_LIST_COMMANDS: tools.ListCommandsToolHandler, tools.TOOL_EXECUTE_COMMANDS: tools.ExecuteCommandsToolHandler, }
- src/mcp_obsidian_advanced/server.py:95-108 (registration)register_tools function instantiates handler classes from TOOL_MAPPING (including PeriodicNotesToolHandler) and adds them to tool_handlers dictionary for MCP server registration.def register_tools(): """Register the selected tools with the server.""" tools_to_include = parse_include_tools() registered_count = 0 for tool_name in tools_to_include: if tool_name in TOOL_MAPPING: handler_class = TOOL_MAPPING[tool_name] handler_instance = handler_class() add_tool_handler(handler_instance) registered_count += 1 logger.debug(f"Registered tool: {tool_name}") logger.info(f"Successfully registered {registered_count} tools")