@meldocio/mcp-stdio-proxy 1.0.26 → 1.0.28

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