Skip to main content
Glama

workflow

Provides context-based workflow guidance and actionable suggestions to optimize tasks in the Obsidian Semantic MCP Server environment.

Instructions

Workflow guidance and suggestions based on current context

Input Schema

NameRequiredDescriptionDefault
actionYesThe specific action to perform
typeNoType of analysis or workflow

Input Schema (JSON Schema)

{ "properties": { "action": { "description": "The specific action to perform", "enum": [ "suggest" ], "type": "string" }, "type": { "description": "Type of analysis or workflow", "type": "string" } }, "required": [ "action" ], "type": "object" }

Implementation Reference

  • Primary MCP tool handler for the 'workflow' tool (shared with other semantic tools). Instantiates SemanticRouter and calls route() with operation='workflow', then formats response for MCP protocol including workflow hints.
    handler: async (api: ObsidianAPI, args: any) => { const router = new SemanticRouter(api); const request: SemanticRequest = { operation, action: args.action, params: args }; const response = await router.route(request); // Format for MCP if (response.error) { return { content: [{ type: 'text', text: JSON.stringify({ error: response.error, workflow: response.workflow, context: response.context }, null, 2) }], isError: true }; } // Check if the result is an image file for vault read operations if (operation === 'vault' && args.action === 'read' && response.result && isImageFile(response.result)) { // Return image content for MCP return { content: [{ type: 'image', data: response.result.base64Data, mimeType: response.result.mimeType }] }; } return { content: [{ type: 'text', text: JSON.stringify({ result: response.result, workflow: response.workflow, context: response.context, efficiency_hints: response.efficiency_hints }, null, 2) }] }; }
  • Schema definitions for 'workflow' tool: description, actions=['suggest'], parameters={type?: string}, integrated into inputSchema with required 'action'.
    function getOperationDescription(operation: string): string { const descriptions: Record<string, string> = { vault: 'File and folder operations - list, read, create, update, delete, search', edit: 'Smart editing operations - window (auto-buffers content), append, patch, at_line, from_buffer', view: 'Content viewing and navigation - file, window, active, open_in_obsidian', workflow: 'Workflow guidance and suggestions based on current context', system: 'System operations - info, commands, fetch_web' }; return descriptions[operation] || 'Unknown operation'; } function getActionsForOperation(operation: string): string[] { const actions: Record<string, string[]> = { vault: ['list', 'read', 'create', 'update', 'delete', 'search', 'fragments'], edit: ['window', 'append', 'patch', 'at_line', 'from_buffer'], view: ['file', 'window', 'active', 'open_in_obsidian'], workflow: ['suggest'], system: ['info', 'commands', 'fetch_web'] }; return actions[operation] || []; } function getParametersForOperation(operation: string): Record<string, any> { // Common parameters across operations const pathParam = { path: { type: 'string', description: 'Path to the file or directory' } }; const contentParam = { content: { type: 'string', description: 'Content to write or append' } }; // Operation-specific parameters const operationParams: Record<string, Record<string, any>> = { vault: { ...pathParam, directory: { type: 'string', description: 'Directory path for list operations' }, query: { type: 'string', description: 'Search query' }, page: { type: 'number', description: 'Page number for paginated results' }, pageSize: { type: 'number', description: 'Number of results per page' }, strategy: { type: 'string', enum: ['auto', 'adaptive', 'proximity', 'semantic'], description: 'Fragment retrieval strategy (default: auto)' }, maxFragments: { type: 'number', description: 'Maximum number of fragments to return (default: 5)' }, returnFullFile: { type: 'boolean', description: 'Return full file instead of fragments (WARNING: large files can consume significant context)' }, includeContent: { type: 'boolean', description: 'Include file content in search results (slower but more thorough)' }, ...contentParam }, edit: { ...pathParam, ...contentParam, oldText: { type: 'string', description: 'Text to search for (supports fuzzy matching)' }, newText: { type: 'string', description: 'Text to replace with' }, fuzzyThreshold: { type: 'number', description: 'Similarity threshold for fuzzy matching (0-1)', default: 0.7 }, lineNumber: { type: 'number', description: 'Line number for at_line action' }, mode: { type: 'string', enum: ['before', 'after', 'replace'], description: 'Insert mode for at_line action' }, operation: { type: 'string', enum: ['append', 'prepend', 'replace'], description: 'Patch operation: append (add after), prepend (add before), or replace' }, targetType: { type: 'string', enum: ['heading', 'block', 'frontmatter'], description: 'What to target: heading (by path like "H1::H2"), block (by ID), or frontmatter (field)' }, target: { type: 'string', description: 'Target identifier - e.g., "Daily Notes::Today" for heading, block ID, or frontmatter field name' } }, view: { ...pathParam, searchText: { type: 'string', description: 'Text to search for and highlight' }, lineNumber: { type: 'number', description: 'Line number to center view around' }, windowSize: { type: 'number', description: 'Number of lines to show', default: 20 } }, workflow: { type: { type: 'string', description: 'Type of analysis or workflow' } }, system: { url: { type: 'string', description: 'URL to fetch and convert to markdown' } } }; return operationParams[operation] || {}; }
  • src/index.ts:80-100 (registration)
    MCP server registration: sets handlers for ListToolsRequestSchema and CallToolRequestSchema using semanticTools array (includes 'workflow' tool).
    server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools: semanticTools.map(tool => ({ name: tool.name, description: tool.description, inputSchema: tool.inputSchema })) }; }); // Handle tool execution server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; const tool = semanticTools.find(t => t.name === name); if (!tool) { throw new Error(`Tool not found: ${name}`); } return await tool.handler(obsidianAPI, args); });
  • SemanticRouter.executeWorkflowOperation: routes 'suggest' action (only action) to generateWorkflowSuggestions().
    private async executeWorkflowOperation(action: string, params: any): Promise<any> { switch (action) { case 'suggest': return this.generateWorkflowSuggestions(); default: throw new Error(`Unknown workflow action: ${action}`); } }
  • Core implementation: generateWorkflowSuggestions provides context-aware suggestions (e.g., continue with last file, refine search) based on SemanticRouter state and context.
    private generateWorkflowSuggestions(): any { // Generate contextual workflow suggestions based on current state const suggestions: SuggestedAction[] = []; if (this.context.last_file) { suggestions.push({ description: 'Continue working with last file', command: `vault(action='read', path='${this.context.last_file}')`, reason: 'Return to previous work' }); } if (this.context.search_history?.length) { const lastSearch = this.context.search_history[this.context.search_history.length - 1]; suggestions.push({ description: 'Refine last search', command: `vault(action='search', query='${lastSearch} AND ...')`, reason: 'Narrow down results' }); } // Always include a default suggestion if no context-specific ones if (suggestions.length === 0) { suggestions.push({ description: 'Use workflow hints from other operations', command: 'vault(action="list") or vault(action="read", path="...") etc.', reason: 'Each operation provides contextual workflow suggestions' }); } return { current_context: this.getCurrentContext(), suggestions }; }

Other Tools

Related Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/aaronsb/obsidian-semantic-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server