Skip to main content
Glama

Markdown MCP Server

by huntkil
simple-test.jsโ€ข11.9 kB
#!/usr/bin/env node import { MarkdownManager } from './src/MarkdownManager.js'; import { ObsidianManager } from './src/ObsidianManager.js'; import { promises as fs } from 'fs'; import { join } from 'path'; class SimpleTest { constructor() { this.markdownManager = new MarkdownManager('.'); this.obsidianManager = new ObsidianManager('.'); this.testDir = 'test-output'; } async setup() { console.log('๐Ÿš€ ๊ฐ„๋‹จํ•œ ๋กœ์ปฌ ํ…Œ์ŠคํŠธ ์‹œ์ž‘...\n'); // ํ…Œ์ŠคํŠธ ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ try { await fs.mkdir(this.testDir, { recursive: true }); console.log('โœ… ํ…Œ์ŠคํŠธ ๋””๋ ‰ํ† ๋ฆฌ ์ƒ์„ฑ๋จ'); } catch (error) { console.log('โš ๏ธ ํ…Œ์ŠคํŠธ ๋””๋ ‰ํ† ๋ฆฌ ์ด๋ฏธ ์กด์žฌํ•จ'); } } async testBasicOperations() { console.log('\n๐Ÿ“ ๊ธฐ๋ณธ CRUD ์ž‘์—… ํ…Œ์ŠคํŠธ...\n'); const testFile = join(this.testDir, 'test-basic.md'); const testContent = `# ๊ธฐ๋ณธ ํ…Œ์ŠคํŠธ ํŒŒ์ผ ์ด๊ฒƒ์€ ๊ธฐ๋ณธ ํ…Œ์ŠคํŠธ ํŒŒ์ผ์ž…๋‹ˆ๋‹ค. ## ์„น์…˜ 1 ๋‚ด์šฉ์ด ์—ฌ๊ธฐ์— ์žˆ์Šต๋‹ˆ๋‹ค. ## ์„น์…˜ 2 ๋‹ค๋ฅธ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค. #tag1 #tag2 #test`; // 1. ํŒŒ์ผ ์ƒ์„ฑ console.log('1. ํŒŒ์ผ ์ƒ์„ฑ ํ…Œ์ŠคํŠธ'); try { await this.markdownManager.createFile(testFile, testContent); console.log('โœ… ํŒŒ์ผ ์ƒ์„ฑ ์„ฑ๊ณต'); } catch (error) { console.log('โŒ ํŒŒ์ผ ์ƒ์„ฑ ์‹คํŒจ:', error.message); } // 2. ํŒŒ์ผ ์ฝ๊ธฐ console.log('\n2. ํŒŒ์ผ ์ฝ๊ธฐ ํ…Œ์ŠคํŠธ'); try { const content = await this.markdownManager.readFile(testFile); console.log('โœ… ํŒŒ์ผ ์ฝ๊ธฐ ์„ฑ๊ณต'); console.log(' ๋‚ด์šฉ ๋ฏธ๋ฆฌ๋ณด๊ธฐ:', content.substring(0, 100) + '...'); } catch (error) { console.log('โŒ ํŒŒ์ผ ์ฝ๊ธฐ ์‹คํŒจ:', error.message); } // 3. ํŒŒ์ผ ๋ชฉ๋ก ์กฐํšŒ console.log('\n3. ํŒŒ์ผ ๋ชฉ๋ก ์กฐํšŒ ํ…Œ์ŠคํŠธ'); try { const files = await this.markdownManager.listFiles(this.testDir); console.log('โœ… ํŒŒ์ผ ๋ชฉ๋ก ์กฐํšŒ ์„ฑ๊ณต:', files); } catch (error) { console.log('โŒ ํŒŒ์ผ ๋ชฉ๋ก ์กฐํšŒ ์‹คํŒจ:', error.message); } // 4. ๊ฒ€์ƒ‰ ํ…Œ์ŠคํŠธ console.log('\n4. ๊ฒ€์ƒ‰ ํ…Œ์ŠคํŠธ'); try { const results = await this.markdownManager.searchContent(this.testDir, { query: 'ํ…Œ์ŠคํŠธ' }); console.log('โœ… ๊ฒ€์ƒ‰ ์„ฑ๊ณต:', results.length, '๊ฐœ ๊ฒฐ๊ณผ'); if (results.length > 0) { console.log(' ์ฒซ ๋ฒˆ์งธ ๊ฒฐ๊ณผ:', results[0]); } } catch (error) { console.log('โŒ ๊ฒ€์ƒ‰ ์‹คํŒจ:', error.message); } // 5. ํŒŒ์ผ ์—…๋ฐ์ดํŠธ console.log('\n5. ํŒŒ์ผ ์—…๋ฐ์ดํŠธ ํ…Œ์ŠคํŠธ'); try { await this.markdownManager.updateFile(testFile, '\n\n## ์ƒˆ๋กœ์šด ์„น์…˜\n\n์—…๋ฐ์ดํŠธ๋œ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.\n\n#updated', true); console.log('โœ… ํŒŒ์ผ ์—…๋ฐ์ดํŠธ ์„ฑ๊ณต'); } catch (error) { console.log('โŒ ํŒŒ์ผ ์—…๋ฐ์ดํŠธ ์‹คํŒจ:', error.message); } // 6. Frontmatter ๊ด€๋ฆฌ console.log('\n6. Frontmatter ๊ด€๋ฆฌ ํ…Œ์ŠคํŠธ'); try { await this.markdownManager.manageFrontmatter(testFile, 'set', { title: 'ํ…Œ์ŠคํŠธ ํŒŒ์ผ', tags: ['test', 'markdown'], status: 'draft' }); console.log('โœ… Frontmatter ์„ค์ • ์„ฑ๊ณต'); } catch (error) { console.log('โŒ Frontmatter ์„ค์ • ์‹คํŒจ:', error.message); } // 7. Frontmatter ์ฝ๊ธฐ console.log('\n7. Frontmatter ์ฝ๊ธฐ ํ…Œ์ŠคํŠธ'); try { const frontmatter = await this.markdownManager.manageFrontmatter(testFile, 'get'); console.log('โœ… Frontmatter ์ฝ๊ธฐ ์„ฑ๊ณต:', frontmatter.metadata); } catch (error) { console.log('โŒ Frontmatter ์ฝ๊ธฐ ์‹คํŒจ:', error.message); } } async testObsidianFeatures() { console.log('\n๐Ÿ”ง Obsidian ํŠนํ™” ๊ธฐ๋Šฅ ํ…Œ์ŠคํŠธ...\n'); const testFile = join(this.testDir, 'test-obsidian.md'); const testContent = `# Obsidian ํ…Œ์ŠคํŠธ ํŒŒ์ผ ์ด๊ฒƒ์€ Obsidian ๊ธฐ๋Šฅ์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ํŒŒ์ผ์ž…๋‹ˆ๋‹ค. ## ๋งํฌ ํ…Œ์ŠคํŠธ - ๋‚ด๋ถ€ ๋งํฌ: [[another-file]] - ์™ธ๋ถ€ ๋งํฌ: [Google](https://google.com) - ์ž„๋ฒ ๋“œ: ![[image.png]] ## ํƒœ๊ทธ ํ…Œ์ŠคํŠธ #project #important #obsidian ## TODO ํ…Œ์ŠคํŠธ - [ ] ์ฒซ ๋ฒˆ์งธ ํ•  ์ผ - [x] ์™„๋ฃŒ๋œ ํ•  ์ผ - [ ] ๋‘ ๋ฒˆ์งธ ํ•  ์ผ ## ์„น์…˜ 1 ๋‚ด์šฉ์ด ์—ฌ๊ธฐ์— ์žˆ์Šต๋‹ˆ๋‹ค. ## ์„น์…˜ 2 ๋‹ค๋ฅธ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.`; // 1. ํ…Œ์ŠคํŠธ ํŒŒ์ผ ์ƒ์„ฑ console.log('1. Obsidian ํ…Œ์ŠคํŠธ ํŒŒ์ผ ์ƒ์„ฑ'); try { await this.markdownManager.createFile(testFile, testContent); console.log('โœ… Obsidian ํ…Œ์ŠคํŠธ ํŒŒ์ผ ์ƒ์„ฑ ์„ฑ๊ณต'); } catch (error) { console.log('โŒ Obsidian ํ…Œ์ŠคํŠธ ํŒŒ์ผ ์ƒ์„ฑ ์‹คํŒจ:', error.message); } // 2. ๋งํฌ ์ถ”์ถœ console.log('\n2. ๋งํฌ ์ถ”์ถœ ํ…Œ์ŠคํŠธ'); try { const links = await this.obsidianManager.extractLinks(testFile); console.log('โœ… ๋งํฌ ์ถ”์ถœ ์„ฑ๊ณต:'); console.log(' ๋‚ด๋ถ€ ๋งํฌ:', links.internal.length, '๊ฐœ'); console.log(' ์™ธ๋ถ€ ๋งํฌ:', links.external.length, '๊ฐœ'); console.log(' ์ž„๋ฒ ๋“œ:', links.embeds.length, '๊ฐœ'); console.log(' ํƒœ๊ทธ:', links.tags.length, '๊ฐœ'); } catch (error) { console.log('โŒ ๋งํฌ ์ถ”์ถœ ์‹คํŒจ:', error.message); } // 3. ํƒœ๊ทธ๋กœ ํŒŒ์ผ ๊ฒ€์ƒ‰ console.log('\n3. ํƒœ๊ทธ ๊ฒ€์ƒ‰ ํ…Œ์ŠคํŠธ'); try { const tagResults = await this.obsidianManager.findFilesByTag('project'); console.log('โœ… ํƒœ๊ทธ ๊ฒ€์ƒ‰ ์„ฑ๊ณต:', tagResults.length, '๊ฐœ ๊ฒฐ๊ณผ'); } catch (error) { console.log('โŒ ํƒœ๊ทธ ๊ฒ€์ƒ‰ ์‹คํŒจ:', error.message); } // 4. ๋ชจ๋“  ํƒœ๊ทธ ์กฐํšŒ console.log('\n4. ๋ชจ๋“  ํƒœ๊ทธ ์กฐํšŒ ํ…Œ์ŠคํŠธ'); try { const allTags = await this.obsidianManager.getAllTags(); console.log('โœ… ๋ชจ๋“  ํƒœ๊ทธ ์กฐํšŒ ์„ฑ๊ณต:', allTags); } catch (error) { console.log('โŒ ๋ชจ๋“  ํƒœ๊ทธ ์กฐํšŒ ์‹คํŒจ:', error.message); } // 5. ๊ทธ๋ž˜ํ”„ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ console.log('\n5. ๊ทธ๋ž˜ํ”„ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ ํ…Œ์ŠคํŠธ'); try { const graphData = await this.obsidianManager.generateGraphData(); console.log('โœ… ๊ทธ๋ž˜ํ”„ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ ์„ฑ๊ณต:'); console.log(' ๋…ธ๋“œ:', graphData.nodes.length, '๊ฐœ'); console.log(' ์—ฃ์ง€:', graphData.edges.length, '๊ฐœ'); } catch (error) { console.log('โŒ ๊ทธ๋ž˜ํ”„ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ ์‹คํŒจ:', error.message); } // 6. TODO ์ถ”์ถœ console.log('\n6. TODO ์ถ”์ถœ ํ…Œ์ŠคํŠธ'); try { const todos = await this.obsidianManager.extractTodos(testFile); console.log('โœ… TODO ์ถ”์ถœ ์„ฑ๊ณต:', todos.length, '๊ฐœ TODO'); todos.forEach(todo => { console.log(` - ${todo.completed ? '[x]' : '[ ]'} ${todo.task} (${todo.file}:${todo.line})`); }); } catch (error) { console.log('โŒ TODO ์ถ”์ถœ ์‹คํŒจ:', error.message); } // 7. Vault ํ†ต๊ณ„ console.log('\n7. Vault ํ†ต๊ณ„ ํ…Œ์ŠคํŠธ'); try { const stats = await this.obsidianManager.generateVaultStats(); console.log('โœ… Vault ํ†ต๊ณ„ ์ƒ์„ฑ ์„ฑ๊ณต:'); console.log(' ์ด ํŒŒ์ผ:', stats.totalFiles, '๊ฐœ'); console.log(' ์ด ๋‹จ์–ด:', stats.totalWords, '๊ฐœ'); console.log(' ์ด ๋งํฌ:', stats.totalLinks, '๊ฐœ'); console.log(' ์ด ํƒœ๊ทธ:', stats.totalTags, '๊ฐœ'); } catch (error) { console.log('โŒ Vault ํ†ต๊ณ„ ์ƒ์„ฑ ์‹คํŒจ:', error.message); } // 8. ์•„์›ƒ๋ผ์ธ ์ถ”์ถœ console.log('\n8. ์•„์›ƒ๋ผ์ธ ์ถ”์ถœ ํ…Œ์ŠคํŠธ'); try { const outline = await this.obsidianManager.extractOutline(testFile); console.log('โœ… ์•„์›ƒ๋ผ์ธ ์ถ”์ถœ ์„ฑ๊ณต:', outline.length, '๊ฐœ ์„น์…˜'); outline.forEach(item => { console.log(` ${' '.repeat(item.level)}${item.title} (๋ผ์ธ ${item.line})`); }); } catch (error) { console.log('โŒ ์•„์›ƒ๋ผ์ธ ์ถ”์ถœ ์‹คํŒจ:', error.message); } } async testAdvancedFeatures() { console.log('\n๐Ÿš€ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ ํ…Œ์ŠคํŠธ...\n'); // 1. ๋ฐ์ผ๋ฆฌ ๋…ธํŠธ ์ƒ์„ฑ console.log('1. ๋ฐ์ผ๋ฆฌ ๋…ธํŠธ ์ƒ์„ฑ ํ…Œ์ŠคํŠธ'); try { const dailyResult = await this.obsidianManager.createDailyNote('2024-01-15', '## ์˜ค๋Š˜์˜ ํ•  ์ผ\n\n- [ ] \n\n## ๋ฉ”๋ชจ\n\n', 'daily'); console.log('โœ… ๋ฐ์ผ๋ฆฌ ๋…ธํŠธ ์ƒ์„ฑ ์„ฑ๊ณต:', dailyResult.filePath); } catch (error) { console.log('โŒ ๋ฐ์ผ๋ฆฌ ๋…ธํŠธ ์ƒ์„ฑ ์‹คํŒจ:', error.message); } // 2. ํ…œํ”Œ๋ฆฟ ๊ด€๋ฆฌ console.log('\n2. ํ…œํ”Œ๋ฆฟ ๊ด€๋ฆฌ ํ…Œ์ŠคํŠธ'); try { const templateResult = await this.obsidianManager.manageTemplate('create', 'meeting', '# ํšŒ์˜๋ก\n\n## ์ฐธ์„์ž\n\n## ์•ˆ๊ฑด\n\n## ๊ฒฐ์ •์‚ฌํ•ญ\n\n## ๋‹ค์Œ ์•ก์…˜ ์•„์ดํ…œ\n\n'); console.log('โœ… ํ…œํ”Œ๋ฆฟ ์ƒ์„ฑ ์„ฑ๊ณต:', templateResult.templateName); } catch (error) { console.log('โŒ ํ…œํ”Œ๋ฆฟ ์ƒ์„ฑ ์‹คํŒจ:', error.message); } // 3. Zettel ID ์ƒ์„ฑ console.log('\n3. Zettel ID ์ƒ์„ฑ ํ…Œ์ŠคํŠธ'); try { const zettelId = this.obsidianManager.generateZettelId('TEST'); console.log('โœ… Zettel ID ์ƒ์„ฑ ์„ฑ๊ณต:', zettelId); } catch (error) { console.log('โŒ Zettel ID ์ƒ์„ฑ ์‹คํŒจ:', error.message); } // 4. ๋…ธํŠธ ์œ ์‚ฌ์„ฑ ๊ณ„์‚ฐ console.log('\n4. ๋…ธํŠธ ์œ ์‚ฌ์„ฑ ๊ณ„์‚ฐ ํ…Œ์ŠคํŠธ'); try { const testFile1 = join(this.testDir, 'similarity-test1.md'); const testFile2 = join(this.testDir, 'similarity-test2.md'); await this.markdownManager.createFile(testFile1, '# ํŒŒ์ผ 1\n\n์ด๊ฒƒ์€ ์ฒซ ๋ฒˆ์งธ ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.\n\n#test #similarity'); await this.markdownManager.createFile(testFile2, '# ํŒŒ์ผ 2\n\n์ด๊ฒƒ์€ ๋‘ ๋ฒˆ์งธ ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.\n\n#test #similarity'); const similarity = await this.obsidianManager.calculateSimilarity(testFile1, testFile2); console.log('โœ… ๋…ธํŠธ ์œ ์‚ฌ์„ฑ ๊ณ„์‚ฐ ์„ฑ๊ณต:', similarity); } catch (error) { console.log('โŒ ๋…ธํŠธ ์œ ์‚ฌ์„ฑ ๊ณ„์‚ฐ ์‹คํŒจ:', error.message); } } async cleanup() { console.log('\n๐Ÿงน ์ •๋ฆฌ ์ž‘์—…...\n'); try { // ํ…Œ์ŠคํŠธ ๋””๋ ‰ํ† ๋ฆฌ ์‚ญ์ œ await fs.rm(this.testDir, { recursive: true, force: true }); console.log('โœ… ํ…Œ์ŠคํŠธ ๋””๋ ‰ํ† ๋ฆฌ ์ •๋ฆฌ ์™„๋ฃŒ'); } catch (error) { console.log('โš ๏ธ ์ •๋ฆฌ ์ค‘ ์˜ค๋ฅ˜:', error.message); } } async run() { try { await this.setup(); await this.testBasicOperations(); await this.testObsidianFeatures(); await this.testAdvancedFeatures(); console.log('\n๐ŸŽ‰ ๋ชจ๋“  ํ…Œ์ŠคํŠธ ์™„๋ฃŒ!'); } catch (error) { console.error('โŒ ํ…Œ์ŠคํŠธ ์ค‘ ์˜ค๋ฅ˜ ๋ฐœ์ƒ:', error); } finally { await this.cleanup(); } } } // ํ…Œ์ŠคํŠธ ์‹คํ–‰ const simpleTest = new SimpleTest(); simpleTest.run();

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/huntkil/mcp_js'

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