@meldocio/mcp-stdio-proxy 1.0.26 → 1.0.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -14,7 +14,7 @@
14
14
  "source": "github",
15
15
  "repo": "meldoc-io/mcp-stdio-proxy"
16
16
  },
17
- "version": "1.0.26",
17
+ "version": "1.0.27",
18
18
  "description": "Connect Claude Desktop, Claude Code, and other MCP clients to your Meldoc documentation workspace. Read, search, create, and update your documentation directly from AI conversations.",
19
19
  "author": {
20
20
  "name": "Meldoc",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "meldoc-mcp",
3
- "version": "1.0.26",
3
+ "version": "1.0.27",
4
4
  "description": "Connect Claude Desktop, Claude Code, and other MCP clients to your Meldoc documentation workspace. Read, search, create, and update your documentation directly from AI conversations through the Model Context Protocol.",
5
5
  "author": {
6
6
  "name": "Meldoc",
@@ -0,0 +1,697 @@
1
+ # Meldoc Advanced Workflows
2
+
3
+ Master-level patterns for power users and complex documentation scenarios.
4
+
5
+ ## When to Use This Skill
6
+
7
+ Use this skill for:
8
+ - Complex documentation refactoring
9
+ - Large-scale migrations
10
+ - Automated documentation workflows
11
+ - Integration with development pipelines
12
+ - Custom documentation structures
13
+
14
+ ## Advanced Patterns
15
+
16
+ ### Pattern: Documentation as Code
17
+
18
+ Treat documentation like code:
19
+
20
+ ```javascript
21
+ // 1. Plan structure programmatically
22
+ const structure = {
23
+ "api-docs": {
24
+ children: ["endpoints", "authentication", "errors"]
25
+ },
26
+ "guides": {
27
+ children: ["quickstart", "tutorials", "advanced"]
28
+ }
29
+ };
30
+
31
+ // 2. Create hierarchy
32
+ for (const [parent, config] of Object.entries(structure)) {
33
+ // Create parent with proper frontmatter
34
+ await docs_create({
35
+ title: parent,
36
+ alias: parent.replace(/\s+/g, '-').toLowerCase(),
37
+ contentMd: `---
38
+ alias: ${parent.replace(/\s+/g, '-').toLowerCase()}
39
+ title: ${parent}
40
+ ---
41
+
42
+ ## Overview
43
+
44
+ Overview...
45
+ `
46
+ });
47
+
48
+ // Create children
49
+ for (const child of config.children) {
50
+ const childAlias = child.replace(/\s+/g, '-').toLowerCase();
51
+ await docs_create({
52
+ title: child,
53
+ alias: childAlias,
54
+ contentMd: `---
55
+ alias: ${childAlias}
56
+ title: ${child}
57
+ parentAlias: ${parent.replace(/\s+/g, '-').toLowerCase()}
58
+ ---
59
+
60
+ ## ${child}
61
+
62
+ Content...
63
+ `,
64
+ parentAlias: parent.replace(/\s+/g, '-').toLowerCase()
65
+ });
66
+ }
67
+ }
68
+ ```
69
+
70
+ ### Pattern: Bulk Operations
71
+
72
+ When updating many documents:
73
+
74
+ ```javascript
75
+ // 1. Get all documents in project
76
+ const allDocs = await docs_list({ projectId: "..." });
77
+
78
+ // 2. Filter by criteria
79
+ const needsUpdate = allDocs.filter(doc =>
80
+ doc.title.includes("[OLD]") ||
81
+ !doc.content.includes("## Prerequisites")
82
+ );
83
+
84
+ // 3. Update each with proper frontmatter
85
+ for (const doc of needsUpdate) {
86
+ const current = await docs_get({ docId: doc.id });
87
+
88
+ // Parse existing frontmatter
89
+ const frontmatterMatch = current.contentMd.match(/^---\n([\s\S]*?)\n---/);
90
+ const frontmatter = frontmatterMatch ? frontmatterMatch[1] : '';
91
+
92
+ // Add prerequisites section if missing
93
+ const updated = addPrerequisitesSection(current.contentMd);
94
+
95
+ await docs_update({
96
+ docId: doc.id,
97
+ contentMd: updated,
98
+ expectedUpdatedAt: current.updatedAt
99
+ });
100
+ }
101
+ ```
102
+
103
+ ### Pattern: Documentation Validation
104
+
105
+ Automated quality checks:
106
+
107
+ ```javascript
108
+ async function validateDocumentation(projectId) {
109
+ const docs = await docs_list({ projectId });
110
+ const issues = [];
111
+
112
+ for (const doc of docs) {
113
+ const content = await docs_get({ docId: doc.id });
114
+
115
+ // Check for frontmatter
116
+ if (!content.contentMd.startsWith('---')) {
117
+ issues.push(`${doc.title}: Missing YAML frontmatter`);
118
+ }
119
+
120
+ // Check for alias
121
+ if (!content.contentMd.includes('alias:')) {
122
+ issues.push(`${doc.title}: Missing alias in frontmatter`);
123
+ }
124
+
125
+ // Check for H2 (content should start with H2, not H1)
126
+ if (!content.contentMd.match(/^---[\s\S]*?---\s*\n## /)) {
127
+ issues.push(`${doc.title}: Content should start with H2, not H1`);
128
+ }
129
+
130
+ if (content.contentMd.length < 100) {
131
+ issues.push(`${doc.title}: Very short content`);
132
+ }
133
+
134
+ // Check links (should use [[alias]] format)
135
+ const links = await docs_links({ docId: doc.id });
136
+ const contentLinks = content.contentMd.match(/\[\[([^\]]+)\]\]/g);
137
+ if (links.length > 0 && !contentLinks) {
138
+ issues.push(`${doc.title}: Links should use [[alias]] format`);
139
+ }
140
+
141
+ // Check backlinks
142
+ const backlinks = await docs_backlinks({ docId: doc.id });
143
+ if (backlinks.length === 0 && !doc.parentAlias) {
144
+ issues.push(`${doc.title}: Orphaned document`);
145
+ }
146
+ }
147
+
148
+ return issues;
149
+ }
150
+ ```
151
+
152
+ ### Pattern: Cross-Reference Analysis
153
+
154
+ Find documentation gaps:
155
+
156
+ ```javascript
157
+ async function analyzeConnections(projectId) {
158
+ const docs = await docs_list({ projectId });
159
+ const graph = {};
160
+
161
+ // Build connection graph
162
+ for (const doc of docs) {
163
+ const links = await docs_links({ docId: doc.id });
164
+ graph[doc.id] = {
165
+ title: doc.title,
166
+ alias: doc.alias,
167
+ outgoing: links.length,
168
+ incoming: 0
169
+ };
170
+ }
171
+
172
+ // Count incoming links
173
+ for (const doc of docs) {
174
+ const backlinks = await docs_backlinks({ docId: doc.id });
175
+ if (graph[doc.id]) {
176
+ graph[doc.id].incoming = backlinks.length;
177
+ }
178
+ }
179
+
180
+ // Identify hubs (many links)
181
+ const hubs = Object.entries(graph)
182
+ .filter(([_, data]) => data.incoming > 10)
183
+ .map(([id, data]) => ({ id, ...data }));
184
+
185
+ // Identify orphans (no links)
186
+ const orphans = Object.entries(graph)
187
+ .filter(([_, data]) => data.incoming === 0 && data.outgoing === 0)
188
+ .map(([id, data]) => ({ id, ...data }));
189
+
190
+ return { hubs, orphans, graph };
191
+ }
192
+ ```
193
+
194
+ ### Pattern: Smart Content Migration
195
+
196
+ Migrate from another platform:
197
+
198
+ ```javascript
199
+ async function migrateFromMarkdown(files, projectId) {
200
+ // 1. Parse all files to build structure
201
+ const structure = parseMarkdownFiles(files);
202
+
203
+ // 2. Create documents in order (parents first) with frontmatter
204
+ const created = {};
205
+
206
+ for (const file of structure.sorted) {
207
+ const parent = file.parent ? created[file.parent] : null;
208
+ const alias = generateAlias(file.title);
209
+
210
+ // Convert H1 to title, H2+ remain
211
+ const content = convertMarkdown(file.content);
212
+ const contentMd = `---
213
+ alias: ${alias}
214
+ title: ${file.title}
215
+ ${parent ? `parentAlias: ${parent.alias}` : ''}
216
+ ---
217
+
218
+ ${content}`;
219
+
220
+ const doc = await docs_create({
221
+ title: file.title,
222
+ alias: alias,
223
+ contentMd: contentMd,
224
+ projectId,
225
+ parentAlias: parent?.alias
226
+ });
227
+
228
+ created[file.path] = doc;
229
+ }
230
+
231
+ // 3. Update internal links to [[alias]] format
232
+ for (const [path, doc] of Object.entries(created)) {
233
+ const content = await docs_get({ docId: doc.id });
234
+ const updated = updateLinksToMagicFormat(content.contentMd, created);
235
+
236
+ await docs_update({
237
+ docId: doc.id,
238
+ contentMd: updated
239
+ });
240
+ }
241
+
242
+ return created;
243
+ }
244
+
245
+ function generateAlias(title) {
246
+ return title
247
+ .toLowerCase()
248
+ .replace(/[^a-z0-9]+/g, '-')
249
+ .replace(/^-+|-+$/g, '');
250
+ }
251
+ ```
252
+
253
+ ### Pattern: Documentation Search Index
254
+
255
+ Build custom search index:
256
+
257
+ ```javascript
258
+ async function buildSearchIndex(projectId) {
259
+ const docs = await docs_list({ projectId });
260
+ const index = {};
261
+
262
+ for (const doc of docs) {
263
+ const content = await docs_get({ docId: doc.id });
264
+
265
+ // Extract keywords from content (skip frontmatter)
266
+ const contentBody = content.contentMd.replace(/^---[\s\S]*?---\s*\n/, '');
267
+ const keywords = extractKeywords(contentBody);
268
+
269
+ // Build reverse index
270
+ for (const keyword of keywords) {
271
+ if (!index[keyword]) {
272
+ index[keyword] = [];
273
+ }
274
+ index[keyword].push({
275
+ docId: doc.id,
276
+ alias: doc.alias,
277
+ title: doc.title,
278
+ relevance: calculateRelevance(keyword, contentBody)
279
+ });
280
+ }
281
+ }
282
+
283
+ // Sort by relevance
284
+ for (const keyword in index) {
285
+ index[keyword].sort((a, b) => b.relevance - a.relevance);
286
+ }
287
+
288
+ return index;
289
+ }
290
+ ```
291
+
292
+ ## Integration Patterns
293
+
294
+ ### CI/CD Documentation
295
+
296
+ Update docs automatically:
297
+
298
+ ```javascript
299
+ // In your CI/CD pipeline
300
+ async function updateDocsFromCodegen(apiSpec) {
301
+ // 1. Generate markdown from OpenAPI spec
302
+ const markdown = generateApiDocs(apiSpec);
303
+
304
+ // 2. Find or create API docs
305
+ const results = await docs_search({
306
+ query: "API Reference",
307
+ projectId: "docs-project"
308
+ });
309
+
310
+ let docId;
311
+ if (results.length > 0) {
312
+ docId = results[0].id;
313
+ } else {
314
+ const doc = await docs_create({
315
+ title: "API Reference",
316
+ alias: "api-reference",
317
+ contentMd: `---
318
+ alias: api-reference
319
+ title: API Reference
320
+ ---
321
+
322
+ ${markdown}`,
323
+ projectId: "docs-project"
324
+ });
325
+ docId = doc.id;
326
+ }
327
+
328
+ // 3. Update with proper frontmatter
329
+ const current = await docs_get({ docId });
330
+ const updated = `---
331
+ alias: api-reference
332
+ title: API Reference
333
+ ---
334
+
335
+ ${markdown}`;
336
+
337
+ await docs_update({
338
+ docId,
339
+ contentMd: updated,
340
+ expectedUpdatedAt: current.updatedAt
341
+ });
342
+ }
343
+ ```
344
+
345
+ ### Monitoring & Alerts
346
+
347
+ Track documentation health:
348
+
349
+ ```javascript
350
+ async function checkDocumentationHealth() {
351
+ const alerts = [];
352
+
353
+ // Check for stale docs (not updated in 6 months)
354
+ const docs = await docs_list({ projectId: "..." });
355
+ const sixMonthsAgo = new Date();
356
+ sixMonthsAgo.setMonth(sixMonthsAgo.getMonth() - 6);
357
+
358
+ for (const doc of docs) {
359
+ const updated = new Date(doc.updatedAt);
360
+ if (updated < sixMonthsAgo) {
361
+ alerts.push({
362
+ type: "stale",
363
+ docId: doc.id,
364
+ alias: doc.alias,
365
+ title: doc.title,
366
+ lastUpdated: doc.updatedAt
367
+ });
368
+ }
369
+
370
+ // Check for missing frontmatter
371
+ const content = await docs_get({ docId: doc.id });
372
+ if (!content.contentMd.startsWith('---')) {
373
+ alerts.push({
374
+ type: "missing_frontmatter",
375
+ docId: doc.id,
376
+ title: doc.title
377
+ });
378
+ }
379
+ }
380
+
381
+ return alerts;
382
+ }
383
+ ```
384
+
385
+ ### Multi-Workspace Operations
386
+
387
+ Work across workspaces:
388
+
389
+ ```javascript
390
+ async function syncAcrossWorkspaces(sourceWs, targetWs, docId) {
391
+ // 1. Get document from source
392
+ set_workspace({ workspace: sourceWs });
393
+ const sourceDoc = await docs_get({ docId });
394
+
395
+ // 2. Extract frontmatter and content
396
+ const frontmatterMatch = sourceDoc.contentMd.match(/^---\n([\s\S]*?)\n---/);
397
+ const contentBody = sourceDoc.contentMd.replace(/^---[\s\S]*?---\s*\n/, '');
398
+
399
+ // 3. Create in target with new alias
400
+ set_workspace({ workspace: targetWs });
401
+ const newAlias = `${sourceDoc.alias}-imported`;
402
+ const targetDoc = await docs_create({
403
+ title: `[From ${sourceWs}] ${sourceDoc.title}`,
404
+ alias: newAlias,
405
+ contentMd: `---
406
+ alias: ${newAlias}
407
+ title: [From ${sourceWs}] ${sourceDoc.title}
408
+ ---
409
+
410
+ ${contentBody}`,
411
+ projectId: "imported-docs"
412
+ });
413
+
414
+ return targetDoc;
415
+ }
416
+ ```
417
+
418
+ ## Optimization Techniques
419
+
420
+ ### Batch Processing
421
+
422
+ Process multiple documents efficiently:
423
+
424
+ ```javascript
425
+ // Instead of this (slow):
426
+ for (const docId of docIds) {
427
+ const doc = await docs_get({ docId });
428
+ process(doc);
429
+ }
430
+
431
+ // Do this (faster):
432
+ const docs = await Promise.all(
433
+ docIds.map(docId => docs_get({ docId }))
434
+ );
435
+ docs.forEach(process);
436
+ ```
437
+
438
+ ### Caching Strategy
439
+
440
+ Cache frequently accessed docs:
441
+
442
+ ```javascript
443
+ const cache = new Map();
444
+
445
+ async function getCachedDoc(docId, maxAge = 5 * 60 * 1000) {
446
+ const cached = cache.get(docId);
447
+
448
+ if (cached && Date.now() - cached.timestamp < maxAge) {
449
+ return cached.doc;
450
+ }
451
+
452
+ const doc = await docs_get({ docId });
453
+ cache.set(docId, { doc, timestamp: Date.now() });
454
+
455
+ return doc;
456
+ }
457
+ ```
458
+
459
+ ### Smart Polling
460
+
461
+ Monitor for changes:
462
+
463
+ ```javascript
464
+ async function watchForChanges(projectId, callback) {
465
+ let lastCheck = new Date();
466
+
467
+ setInterval(async () => {
468
+ const docs = await docs_list({ projectId });
469
+
470
+ const updated = docs.filter(doc =>
471
+ new Date(doc.updatedAt) > lastCheck
472
+ );
473
+
474
+ if (updated.length > 0) {
475
+ callback(updated);
476
+ }
477
+
478
+ lastCheck = new Date();
479
+ }, 60000); // Check every minute
480
+ }
481
+ ```
482
+
483
+ ## Complex Scenarios
484
+
485
+ ### Scenario: Multi-Language Documentation
486
+
487
+ Maintain docs in multiple languages:
488
+
489
+ ```javascript
490
+ const languages = ['en', 'es', 'fr', 'de'];
491
+
492
+ async function createMultiLangDoc(content, projectId) {
493
+ const docs = {};
494
+
495
+ // Create parent (language selector) with frontmatter
496
+ const parent = await docs_create({
497
+ title: content.title,
498
+ alias: generateAlias(content.title),
499
+ contentMd: `---
500
+ alias: ${generateAlias(content.title)}
501
+ title: ${content.title}
502
+ ---
503
+
504
+ ## Select Language
505
+
506
+ ${languages.map(lang => `- [[${generateAlias(content.title)}-${lang}]]`).join('\n')}
507
+ `,
508
+ projectId
509
+ });
510
+
511
+ // Create version for each language
512
+ for (const lang of languages) {
513
+ const translated = await translate(content.body, lang);
514
+ const alias = `${generateAlias(content.title)}-${lang}`;
515
+
516
+ docs[lang] = await docs_create({
517
+ title: `${content.title} (${lang.toUpperCase()})`,
518
+ alias: alias,
519
+ contentMd: `---
520
+ alias: ${alias}
521
+ title: ${content.title} (${lang.toUpperCase()})
522
+ parentAlias: ${parent.alias}
523
+ ---
524
+
525
+ ${translated}`,
526
+ parentAlias: parent.alias,
527
+ projectId
528
+ });
529
+ }
530
+
531
+ return { parent, docs };
532
+ }
533
+ ```
534
+
535
+ ### Scenario: Version-Specific Documentation
536
+
537
+ Maintain docs for different versions:
538
+
539
+ ```javascript
540
+ async function createVersionedDocs(feature, versions, projectId) {
541
+ // Create feature overview with frontmatter
542
+ const overviewAlias = generateAlias(feature.name);
543
+ const overview = await docs_create({
544
+ title: feature.name,
545
+ alias: overviewAlias,
546
+ contentMd: `---
547
+ alias: ${overviewAlias}
548
+ title: ${feature.name}
549
+ ---
550
+
551
+ ## Overview
552
+
553
+ ${feature.overview}
554
+ `,
555
+ projectId
556
+ });
557
+
558
+ // Create version-specific docs
559
+ for (const version of versions) {
560
+ const alias = `${overviewAlias}-v${version}`;
561
+ await docs_create({
562
+ title: `${feature.name} (v${version})`,
563
+ alias: alias,
564
+ contentMd: `---
565
+ alias: ${alias}
566
+ title: ${feature.name} (v${version})
567
+ parentAlias: ${overviewAlias}
568
+ ---
569
+
570
+ ${feature.versionContent[version]}
571
+ `,
572
+ parentAlias: overviewAlias,
573
+ projectId
574
+ });
575
+ }
576
+ }
577
+ ```
578
+
579
+ ### Scenario: Auto-Generated Examples
580
+
581
+ Generate code examples:
582
+
583
+ ```javascript
584
+ async function generateExamplesDoc(apiEndpoint, projectId) {
585
+ const examples = [];
586
+
587
+ // Generate examples in multiple languages
588
+ for (const lang of ['curl', 'javascript', 'python']) {
589
+ examples.push({
590
+ language: lang,
591
+ code: generateCodeExample(apiEndpoint, lang)
592
+ });
593
+ }
594
+
595
+ const alias = generateAlias(`${apiEndpoint.name} Examples`);
596
+ const markdown = examples.map(ex => `
597
+ ### ${ex.language}
598
+
599
+ \`\`\`${ex.language}
600
+ ${ex.code}
601
+ \`\`\`
602
+ `).join('\n');
603
+
604
+ await docs_create({
605
+ title: `${apiEndpoint.name} Examples`,
606
+ alias: alias,
607
+ contentMd: `---
608
+ alias: ${alias}
609
+ title: ${apiEndpoint.name} Examples
610
+ ---
611
+
612
+ ## Description
613
+ ${apiEndpoint.description}
614
+
615
+ ${markdown}
616
+ `,
617
+ projectId
618
+ });
619
+ }
620
+ ```
621
+
622
+ ## Power User Tips
623
+
624
+ 1. **Use docs_tree first** - Understand structure before bulk operations
625
+ 2. **Batch operations** - Process multiple docs in parallel when possible
626
+ 3. **Cache aggressively** - Reduce API calls for frequently accessed docs
627
+ 4. **Validate before updating** - Check `expectedUpdatedAt` to avoid conflicts
628
+ 5. **Always include frontmatter** - Every document needs YAML frontmatter with `title` and `alias`
629
+ 6. **Use magic links** - Prefer `[[alias]]` format for internal links
630
+ 7. **Build tooling** - Create scripts for repetitive tasks
631
+ 8. **Monitor metrics** - Track documentation health over time
632
+ 9. **Automate quality** - Run validation checks regularly
633
+ 10. **Version control** - Keep external backups of critical docs
634
+ 11. **Test migrations** - Try on small subset before bulk operations
635
+ 12. **Document your automations** - Others will need to maintain them
636
+
637
+ ## API Best Practices
638
+
639
+ ### Error Handling
640
+
641
+ ```javascript
642
+ async function robustDocUpdate(docId, newContent) {
643
+ const maxRetries = 3;
644
+ let attempt = 0;
645
+
646
+ while (attempt < maxRetries) {
647
+ try {
648
+ const current = await docs_get({ docId });
649
+
650
+ // Preserve frontmatter
651
+ const frontmatterMatch = current.contentMd.match(/^---\n([\s\S]*?)\n---/);
652
+ const frontmatter = frontmatterMatch ? frontmatterMatch[1] : '';
653
+
654
+ await docs_update({
655
+ docId,
656
+ contentMd: `---\n${frontmatter}\n---\n\n${newContent}`,
657
+ expectedUpdatedAt: current.updatedAt
658
+ });
659
+
660
+ return true;
661
+ } catch (error) {
662
+ if (error.code === 'CONFLICT' && attempt < maxRetries - 1) {
663
+ attempt++;
664
+ await sleep(1000 * attempt); // Exponential backoff
665
+ continue;
666
+ }
667
+ throw error;
668
+ }
669
+ }
670
+ }
671
+ ```
672
+
673
+ ### Rate Limiting
674
+
675
+ ```javascript
676
+ async function processWithRateLimit(items, processor, rateLimit = 10) {
677
+ const chunks = chunkArray(items, rateLimit);
678
+
679
+ for (const chunk of chunks) {
680
+ await Promise.all(chunk.map(processor));
681
+ await sleep(1000); // Wait 1 second between chunks
682
+ }
683
+ }
684
+ ```
685
+
686
+ ## Advanced Use Cases
687
+
688
+ - **Documentation Analytics** - Track views, searches, popular docs
689
+ - **Custom Workflows** - Approval processes, review cycles
690
+ - **Integration Bridges** - Sync with other systems
691
+ - **Automated Testing** - Validate links, code examples, frontmatter
692
+ - **Content Generation** - AI-assisted documentation
693
+ - **Search Enhancement** - Custom ranking, filters
694
+ - **Access Control** - Additional permission layers
695
+ - **Audit Logging** - Track all changes for compliance
696
+
697
+ Each pattern can be customized for your specific needs!