@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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.claude-plugin/skills/advanced-workflows/SKILL.md +692 -0
- package/.claude-plugin/skills/collaboration/SKILL.md +441 -0
- package/.claude-plugin/skills/documentation-writing/SKILL.md +541 -0
- package/.claude-plugin/{SKILL.md → skills/meldoc-overview/SKILL.md} +14 -6
- package/.claude-plugin/skills/onboarding/SKILL.md +832 -0
- package/.claude-plugin/skills/search-and-discovery/SKILL.md +382 -0
- package/package.json +1 -1
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"source": "github",
|
|
15
15
|
"repo": "meldoc-io/mcp-stdio-proxy"
|
|
16
16
|
},
|
|
17
|
-
"version": "1.0.
|
|
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.
|
|
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!
|