Skip to main content
Glama

create_moc

Automatically generates a Map of Contents (MOC) note in Obsidian to organize and link related notes based on tags, folders, or patterns.

Instructions

Map of Contents(目次ノート)を自動生成します

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
titleYesMOCのタイトル
targetPathYesMOCの保存先パス(vault相対パス)
sourcePatternNo対象ノートのパターン(省略時は全て)
groupByNoグループ化方法none
includeDescriptionNo説明を含めるかどうか

Implementation Reference

  • The core handler function implementing the create_moc tool. It generates a Map of Contents (MOC) note by collecting source files, grouping them if specified, generating wiki links, and writing the MOC file to the target path.
    async createMoc(title: string, targetPath: string, sourcePattern?: string, groupBy: 'tag' | 'folder' | 'none' = 'none', includeDescription: boolean = false): Promise<string> { if (!FileUtils.validatePath(this.config.vaultPath, targetPath)) { throw new Error('無効な保存パスです'); } const vaultPath = this.config.vaultPath; const fullTargetPath = path.join(vaultPath, targetPath); // ディレクトリを作成 await FileUtils.ensureDir(path.dirname(fullTargetPath)); // ソースファイルを収集 const sourceFiles = await this.collectSourceFiles(sourcePattern); // グループ化 const groupedFiles = await this.groupFiles(sourceFiles, groupBy); // MOC内容を生成 let mocContent = `# ${title}\n\n`; mocContent += `*このMap of Contentsは自動生成されました - ${new Date().toISOString().split('T')[0]}*\n\n`; if (groupBy === 'none') { mocContent += '## 目次\n\n'; for (const file of sourceFiles) { const relativeFilePath = path.relative(vaultPath, file); const fileName = path.basename(file, '.md'); const linkText = `[[${relativeFilePath.replace(/\.md$/, '')}|${fileName}]]`; if (includeDescription) { const description = await this.extractDescription(file); mocContent += `- ${linkText}${description ? ` - ${description}` : ''}\n`; } else { mocContent += `- ${linkText}\n`; } } } else { for (const [groupName, files] of Object.entries(groupedFiles)) { mocContent += `## ${groupName}\n\n`; for (const file of files) { const relativeFilePath = path.relative(vaultPath, file); const fileName = path.basename(file, '.md'); const linkText = `[[${relativeFilePath.replace(/\.md$/, '')}|${fileName}]]`; if (includeDescription) { const description = await this.extractDescription(file); mocContent += `- ${linkText}${description ? ` - ${description}` : ''}\n`; } else { mocContent += `- ${linkText}\n`; } } mocContent += '\n'; } } // ファイルを書き込み await fs.writeFile(fullTargetPath, mocContent, 'utf-8'); return `Map of Contents '${title}' を '${targetPath}' に作成しました。${sourceFiles.length}個のファイルを含みます。`; }
  • The input schema definition for the create_moc tool, specifying parameters like title, targetPath, sourcePattern, groupBy, and includeDescription.
    name: 'create_moc', description: 'Map of Contents(目次ノート)を自動生成します', inputSchema: { type: 'object', properties: { title: { type: 'string', description: 'MOCのタイトル', }, targetPath: { type: 'string', description: 'MOCの保存先パス(vault相対パス)', }, sourcePattern: { type: 'string', description: '対象ノートのパターン(省略時は全て)', }, groupBy: { type: 'string', enum: ['tag', 'folder', 'none'], description: 'グループ化方法', default: 'none', }, includeDescription: { type: 'boolean', description: '説明を含めるかどうか', default: false, }, }, required: ['title', 'targetPath'], }, },
  • src/server.ts:365-376 (registration)
    The registration and dispatching logic in the CallToolRequest handler that invokes the createMoc method on ObsidianHandler for the 'create_moc' tool.
    case 'create_moc': const mocResult = await this.obsidianHandler.createMoc( args.title as string, args.targetPath as string, args.sourcePattern as string, (args.groupBy as 'tag' | 'folder' | 'none') || 'none', (args.includeDescription as boolean) || false ); return { content: [{ type: 'text', text: mocResult }], };
  • Helper method to collect source Markdown files matching the optional sourcePattern, used by createMoc.
    private async collectSourceFiles(sourcePattern?: string): Promise<string[]> { const vaultPath = this.config.vaultPath; const allMdFiles = await this.getAllMdFiles(vaultPath); if (!sourcePattern) { return allMdFiles; } // パターンマッチング(簡単な実装) return allMdFiles.filter(file => { const relativePath = path.relative(vaultPath, file); return relativePath.includes(sourcePattern) || path.basename(file).includes(sourcePattern); }); }
  • Helper method to group collected files by tag or folder for the MOC generation, used by createMoc.
    private async groupFiles(files: string[], groupBy: 'tag' | 'folder' | 'none'): Promise<Record<string, string[]>> { if (groupBy === 'none') { return { 'All Files': files }; } const groups: Record<string, string[]> = {}; for (const file of files) { if (groupBy === 'folder') { const dir = path.dirname(path.relative(this.config.vaultPath, file)); const folderName = dir === '.' ? 'ルート' : dir; if (!groups[folderName]) { groups[folderName] = []; } groups[folderName].push(file); } else if (groupBy === 'tag') { const tags = await this.extractFileTags(file); if (tags.length === 0) { if (!groups['タグなし']) { groups['タグなし'] = []; } groups['タグなし'].push(file); } else { for (const tag of tags) { if (!groups[tag]) { groups[tag] = []; } groups[tag].push(file); } } } } return groups; }

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/libra850/obsidian-mcp-server'

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