Skip to main content
Glama
libra850
by libra850

create_moc

Generate a Map of Contents 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

  • Core handler function for the 'create_moc' tool. Collects Markdown files matching a source pattern (or all), groups them by tag, folder, or none, generates a Markdown MOC file with wiki links to the files (with optional descriptions), and saves it to the target path in the Obsidian vault.
    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}個のファイルを含みます。`; }
  • src/server.ts:214-246 (registration)
    Registration of the 'create_moc' tool in the MCP server's listTools handler, including name, description, and full input schema definition.
    { 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'], }, },
  • Dispatch handler in the MCP server's CallToolRequestSchema that maps the tool call to the ObsidianHandler.createMoc method with argument casting.
    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 all Markdown files in the vault or filter by sourcePattern for inclusion in the MOC.
    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 folder path or tags extracted from each file for structured MOC generation.
    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