Skip to main content
Glama

view

Navigate and view content in Obsidian by specifying actions like opening files, managing windows, highlighting text, or focusing on specific line numbers for efficient document interaction.

Instructions

Content viewing and navigation - file, window, active, open_in_obsidian

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
actionYesThe specific action to perform
lineNumberNoLine number to center view around
pathNoPath to the file or directory
searchTextNoText to search for and highlight
windowSizeNoNumber of lines to show

Implementation Reference

  • Registers the 'view' tool by including createSemanticTool('view') in the semanticTools array, which is used by the MCP server.
    export const semanticTools = [ createSemanticTool('vault'), createSemanticTool('edit'), createSemanticTool('view'), createSemanticTool('workflow'), createSemanticTool('system') ];
  • Defines the input schema parameters specific to the 'view' operation.
    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 } },
  • The generic handler for all semantic tools including 'view', which instantiates SemanticRouter and routes the request.
    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) }] }; }
  • Core implementation of view operations: handles subactions 'file' (full file), 'window' (line window with search centering), 'active' (current Obsidian file), 'open_in_obsidian' (open file in app).
    private async executeViewOperation(action: string, params: any): Promise<any> { switch (action) { case 'file': return await this.api.getFile(params.path); case 'window': // View a portion of a file const file = await this.api.getFile(params.path); if (isImageFile(file)) { throw new Error('Cannot view window of image files'); } const content = typeof file === 'string' ? file : file.content; const lines = content.split('\n'); let centerLine = params.lineNumber || 1; // If search text provided, find it if (params.searchText && !params.lineNumber) { const { findFuzzyMatches } = await import('../utils/fuzzy-match.js'); const matches = findFuzzyMatches(content, params.searchText, 0.6); if (matches.length > 0) { centerLine = matches[0].lineNumber; } } // Calculate window const windowSize = params.windowSize || 20; const halfWindow = Math.floor(windowSize / 2); const startLine = Math.max(1, centerLine - halfWindow); const endLine = Math.min(lines.length, centerLine + halfWindow); return { path: params.path, lines: lines.slice(startLine - 1, endLine), startLine, endLine, totalLines: lines.length, centerLine, searchText: params.searchText }; case 'active': // Add timeout to prevent hanging when no file is active try { const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout: No active file in Obsidian. Please open a file first.')), 5000) ); const result = await Promise.race([ this.api.getActiveFile(), timeoutPromise ]); return result; } catch (error: any) { if (error.message.includes('Timeout')) { throw error; } // Re-throw original error if not timeout throw error; } case 'open_in_obsidian': return await this.api.openFile(params.path); default: throw new Error(`Unknown view action: ${action}`); } }
  • src/index.ts:80-100 (registration)
    Registers all semantic tools including 'view' with the MCP server by setting request handlers for listing and calling tools.
    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); });

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