@redpanda-data/docs-extensions-and-macros 4.12.6 → 4.13.0

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.
Files changed (61) hide show
  1. package/README.adoc +33 -1064
  2. package/bin/doc-tools-mcp.js +720 -0
  3. package/bin/doc-tools.js +1050 -50
  4. package/bin/mcp-tools/antora.js +153 -0
  5. package/bin/mcp-tools/cache.js +89 -0
  6. package/bin/mcp-tools/cloud-regions.js +127 -0
  7. package/bin/mcp-tools/content-review.js +196 -0
  8. package/bin/mcp-tools/crd-docs.js +153 -0
  9. package/bin/mcp-tools/frontmatter.js +138 -0
  10. package/bin/mcp-tools/generated-docs-review.js +887 -0
  11. package/bin/mcp-tools/helm-docs.js +152 -0
  12. package/bin/mcp-tools/index.js +245 -0
  13. package/bin/mcp-tools/job-queue.js +468 -0
  14. package/bin/mcp-tools/mcp-validation.js +266 -0
  15. package/bin/mcp-tools/metrics-docs.js +146 -0
  16. package/bin/mcp-tools/openapi.js +174 -0
  17. package/bin/mcp-tools/prompt-discovery.js +283 -0
  18. package/bin/mcp-tools/property-docs.js +157 -0
  19. package/bin/mcp-tools/rpcn-docs.js +113 -0
  20. package/bin/mcp-tools/rpk-docs.js +141 -0
  21. package/bin/mcp-tools/telemetry.js +211 -0
  22. package/bin/mcp-tools/utils.js +131 -0
  23. package/bin/mcp-tools/versions.js +168 -0
  24. package/cli-utils/convert-doc-links.js +1 -1
  25. package/cli-utils/github-token.js +58 -0
  26. package/cli-utils/self-managed-docs-branch.js +2 -2
  27. package/cli-utils/setup-mcp.js +313 -0
  28. package/docker-compose/25.1/transactions.md +1 -1
  29. package/docker-compose/transactions.md +1 -1
  30. package/extensions/DEVELOPMENT.adoc +464 -0
  31. package/extensions/README.adoc +124 -0
  32. package/extensions/REFERENCE.adoc +768 -0
  33. package/extensions/USER_GUIDE.adoc +339 -0
  34. package/extensions/generate-rp-connect-info.js +3 -4
  35. package/extensions/version-fetcher/get-latest-console-version.js +38 -27
  36. package/extensions/version-fetcher/get-latest-redpanda-version.js +65 -54
  37. package/extensions/version-fetcher/retry-util.js +88 -0
  38. package/extensions/version-fetcher/set-latest-version.js +6 -3
  39. package/macros/DEVELOPMENT.adoc +377 -0
  40. package/macros/README.adoc +105 -0
  41. package/macros/REFERENCE.adoc +222 -0
  42. package/macros/USER_GUIDE.adoc +220 -0
  43. package/macros/rp-connect-components.js +6 -6
  44. package/package.json +12 -3
  45. package/tools/bundle-openapi.js +20 -10
  46. package/tools/cloud-regions/generate-cloud-regions.js +1 -1
  47. package/tools/fetch-from-github.js +18 -4
  48. package/tools/gen-rpk-ascii.py +3 -1
  49. package/tools/generate-cli-docs.js +325 -0
  50. package/tools/get-console-version.js +4 -2
  51. package/tools/get-redpanda-version.js +4 -2
  52. package/tools/metrics/metrics.py +19 -7
  53. package/tools/property-extractor/Makefile +7 -1
  54. package/tools/property-extractor/cloud_config.py +4 -4
  55. package/tools/property-extractor/constant_resolver.py +11 -11
  56. package/tools/property-extractor/property_extractor.py +18 -16
  57. package/tools/property-extractor/topic_property_extractor.py +2 -2
  58. package/tools/property-extractor/transformers.py +7 -7
  59. package/tools/property-extractor/type_definition_extractor.py +4 -4
  60. package/tools/redpanda-connect/README.adoc +1 -1
  61. package/tools/redpanda-connect/generate-rpcn-connector-docs.js +5 -3
@@ -0,0 +1,720 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * MCP Server for Redpanda Documentation Tools
5
+ *
6
+ * This server exposes domain-specific documentation tools to Claude Code
7
+ * via the Model Context Protocol.
8
+ *
9
+ * Features:
10
+ * - Context-aware: Works from any repository based on cwd
11
+ * - Antora intelligence: Understands component/module structure
12
+ * - Automation: Run doc-tools generate commands
13
+ * - Auto-discovery: Prompts loaded automatically from mcp/prompts/
14
+ * - Validation: Startup checks ensure all resources are accessible
15
+ * - Telemetry: Usage tracking for adoption metrics
16
+ */
17
+
18
+ const fs = require('fs');
19
+ const path = require('path');
20
+ const { Server } = require('@modelcontextprotocol/sdk/server/index.js');
21
+ const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
22
+ const {
23
+ CallToolRequestSchema,
24
+ ListToolsRequestSchema,
25
+ ListPromptsRequestSchema,
26
+ GetPromptRequestSchema,
27
+ ListResourcesRequestSchema,
28
+ ReadResourceRequestSchema,
29
+ } = require('@modelcontextprotocol/sdk/types.js');
30
+ const { findRepoRoot, executeTool } = require('./mcp-tools');
31
+ const { initializeJobQueue, getJob, listJobs } = require('./mcp-tools/job-queue');
32
+
33
+ // New modules for improved architecture
34
+ const {
35
+ PromptCache,
36
+ loadAllPrompts,
37
+ watchPrompts,
38
+ buildPromptWithArguments,
39
+ promptsToMcpFormat
40
+ } = require('./mcp-tools/prompt-discovery');
41
+ const {
42
+ validatePromptArguments,
43
+ validateMcpConfiguration
44
+ } = require('./mcp-tools/mcp-validation');
45
+ const {
46
+ UsageStats,
47
+ createPeriodicReporter,
48
+ createShutdownHandler
49
+ } = require('./mcp-tools/telemetry');
50
+
51
+ // Get version from package.json
52
+ const packageJson = require('../package.json');
53
+
54
+ // Base directory
55
+ const baseDir = path.join(__dirname, '..');
56
+
57
+ // Initialize prompt cache and usage stats
58
+ const promptCache = new PromptCache();
59
+ const usageStats = new UsageStats();
60
+
61
+ // Create the MCP server
62
+ const server = new Server(
63
+ {
64
+ name: 'redpanda-doc-tools-assistant',
65
+ version: packageJson.version,
66
+ },
67
+ {
68
+ capabilities: {
69
+ tools: {},
70
+ prompts: {},
71
+ resources: {},
72
+ },
73
+ }
74
+ );
75
+
76
+ // Tool definitions - Writer-friendly documentation tools
77
+ const tools = [
78
+ {
79
+ name: 'get_antora_structure',
80
+ description: 'Get information about the Antora documentation structure in the current repository, including components, modules, and available directories. Use this to understand the docs organization.',
81
+ inputSchema: {
82
+ type: 'object',
83
+ properties: {},
84
+ required: []
85
+ }
86
+ },
87
+ {
88
+ name: 'get_redpanda_version',
89
+ description: 'Get the latest Redpanda version information including version number, Docker tag, and release notes URL. Writers use this to find out what version to document.',
90
+ inputSchema: {
91
+ type: 'object',
92
+ properties: {
93
+ beta: {
94
+ type: 'boolean',
95
+ description: 'Whether to get the latest beta/RC version instead of stable (optional, defaults to false)'
96
+ }
97
+ },
98
+ required: []
99
+ }
100
+ },
101
+ {
102
+ name: 'get_console_version',
103
+ description: 'Get the latest Redpanda Console version information including version number, Docker tag, and release notes URL.',
104
+ inputSchema: {
105
+ type: 'object',
106
+ properties: {},
107
+ required: []
108
+ }
109
+ },
110
+ {
111
+ name: 'generate_property_docs',
112
+ description: 'Generate Redpanda configuration property documentation for a specific version. Creates JSON and optionally AsciiDoc partials with all configuration properties. Writers use this when updating docs for a new Redpanda release. Can run in background with progress streaming.',
113
+ inputSchema: {
114
+ type: 'object',
115
+ properties: {
116
+ tag: {
117
+ type: 'string',
118
+ description: 'Git tag for released content (for example "25.3.1", "v25.3.1", or "latest"). Auto-prepends "v" if not present. Use tags for GA or beta releases.'
119
+ },
120
+ branch: {
121
+ type: 'string',
122
+ description: 'Branch name for in-progress content (for example "dev", "main"). Use branches for documentation under development.'
123
+ },
124
+ generate_partials: {
125
+ type: 'boolean',
126
+ description: 'Whether to generate AsciiDoc partials (cluster-properties.adoc, topic-properties.adoc, etc.). Default: false (only generates JSON)'
127
+ },
128
+ background: {
129
+ type: 'boolean',
130
+ description: 'Run as background job with progress updates. Returns job ID immediately instead of waiting. Default: false (run synchronously)'
131
+ }
132
+ },
133
+ required: []
134
+ }
135
+ },
136
+ {
137
+ name: 'generate_metrics_docs',
138
+ description: 'Generate Redpanda metrics documentation for a specific version. Creates the public metrics reference page. Writers use this when updating metrics docs for a new release. Can run in background with progress streaming.',
139
+ inputSchema: {
140
+ type: 'object',
141
+ properties: {
142
+ tag: {
143
+ type: 'string',
144
+ description: 'Git tag for released content (for example "25.3.1" or "v25.3.1"). Auto-prepends "v" if not present. Use tags for GA or beta releases.'
145
+ },
146
+ branch: {
147
+ type: 'string',
148
+ description: 'Branch name for in-progress content (for example "dev", "main"). Use branches for documentation under development.'
149
+ },
150
+ background: {
151
+ type: 'boolean',
152
+ description: 'Run as background job with progress updates. Returns job ID immediately instead of waiting. Default: false (run synchronously)'
153
+ }
154
+ },
155
+ required: []
156
+ }
157
+ },
158
+ {
159
+ name: 'generate_rpk_docs',
160
+ description: 'Generate RPK command-line documentation for a specific version. Creates AsciiDoc files for all rpk commands. Writers use this when updating CLI docs for a new release. Can run in background with progress streaming.',
161
+ inputSchema: {
162
+ type: 'object',
163
+ properties: {
164
+ tag: {
165
+ type: 'string',
166
+ description: 'Git tag for released content (for example "25.3.1" or "v25.3.1"). Auto-prepends "v" if not present. Use tags for GA or beta releases.'
167
+ },
168
+ branch: {
169
+ type: 'string',
170
+ description: 'Branch name for in-progress content (for example "dev", "main"). Use branches for documentation under development.'
171
+ },
172
+ background: {
173
+ type: 'boolean',
174
+ description: 'Run as background job with progress updates. Returns job ID immediately instead of waiting. Default: false (run synchronously)'
175
+ }
176
+ },
177
+ required: []
178
+ }
179
+ },
180
+ {
181
+ name: 'generate_rpcn_connector_docs',
182
+ description: 'Generate Redpanda Connect connector documentation. Creates component documentation for all connectors. Writers use this when updating connector reference docs.',
183
+ inputSchema: {
184
+ type: 'object',
185
+ properties: {
186
+ fetch_connectors: {
187
+ type: 'boolean',
188
+ description: 'Fetch latest connector data using rpk (optional, defaults to false)'
189
+ },
190
+ draft_missing: {
191
+ type: 'boolean',
192
+ description: 'Generate full-doc drafts for connectors missing in output (optional, defaults to false)'
193
+ },
194
+ update_whats_new: {
195
+ type: 'boolean',
196
+ description: 'Update whats-new.adoc with new section from diff JSON (optional, defaults to false)'
197
+ },
198
+ include_bloblang: {
199
+ type: 'boolean',
200
+ description: 'Include Bloblang functions and methods in generation (optional, defaults to false)'
201
+ },
202
+ data_dir: {
203
+ type: 'string',
204
+ description: 'Directory where versioned connect JSON files live (optional)'
205
+ },
206
+ old_data: {
207
+ type: 'string',
208
+ description: 'Optional override for old data file (for diff)'
209
+ },
210
+ csv: {
211
+ type: 'string',
212
+ description: 'Path to connector metadata CSV file (optional)'
213
+ },
214
+ overrides: {
215
+ type: 'string',
216
+ description: 'Path to optional JSON file with overrides'
217
+ }
218
+ },
219
+ required: []
220
+ }
221
+ },
222
+ {
223
+ name: 'generate_helm_docs',
224
+ description: 'Generate Helm chart documentation. Creates AsciiDoc documentation for Helm charts from local directories or GitHub repositories. Writers use this when updating Helm chart reference docs.',
225
+ inputSchema: {
226
+ type: 'object',
227
+ properties: {
228
+ chart_dir: {
229
+ type: 'string',
230
+ description: 'Chart directory (contains Chart.yaml) or root containing multiple charts, or a GitHub URL (optional, defaults to Redpanda operator charts)'
231
+ },
232
+ tag: {
233
+ type: 'string',
234
+ description: 'Git tag for released content when using GitHub URL (for example "25.1.2" or "v25.1.2"). Auto-prepends "v" if not present. For redpanda-operator repository, also auto-prepends "operator/".'
235
+ },
236
+ branch: {
237
+ type: 'string',
238
+ description: 'Branch name for in-progress content when using GitHub URL (for example "dev", "main").'
239
+ },
240
+ readme: {
241
+ type: 'string',
242
+ description: 'Relative README.md path inside each chart dir (optional, defaults to "README.md")'
243
+ },
244
+ output_dir: {
245
+ type: 'string',
246
+ description: 'Where to write all generated AsciiDoc files (optional, defaults to "modules/reference/pages")'
247
+ },
248
+ output_suffix: {
249
+ type: 'string',
250
+ description: 'Suffix to append to each chart name including extension (optional, defaults to "-helm-spec.adoc")'
251
+ }
252
+ },
253
+ required: []
254
+ }
255
+ },
256
+ {
257
+ name: 'generate_cloud_regions',
258
+ description: 'Generate cloud regions table documentation. Creates a Markdown or AsciiDoc table of cloud regions and tiers from GitHub YAML data. Writers use this when updating cloud region documentation.',
259
+ inputSchema: {
260
+ type: 'object',
261
+ properties: {
262
+ output: {
263
+ type: 'string',
264
+ description: 'Output file path relative to repo root (optional, defaults to "cloud-controlplane/x-topics/cloud-regions.md")'
265
+ },
266
+ format: {
267
+ type: 'string',
268
+ description: 'Output format: "md" (Markdown) or "adoc" (AsciiDoc) (optional, defaults to "md")',
269
+ enum: ['md', 'adoc']
270
+ },
271
+ owner: {
272
+ type: 'string',
273
+ description: 'GitHub repository owner (optional, defaults to "redpanda-data")'
274
+ },
275
+ repo: {
276
+ type: 'string',
277
+ description: 'GitHub repository name (optional, defaults to "cloudv2-infra")'
278
+ },
279
+ path: {
280
+ type: 'string',
281
+ description: 'Path to YAML file in repository (optional)'
282
+ },
283
+ ref: {
284
+ type: 'string',
285
+ description: 'Git reference - branch, tag, or commit SHA (optional, defaults to "integration")'
286
+ },
287
+ template: {
288
+ type: 'string',
289
+ description: 'Path to custom Handlebars template relative to repo root (optional)'
290
+ },
291
+ dry_run: {
292
+ type: 'boolean',
293
+ description: 'Print output to stdout instead of writing file (optional, defaults to false)'
294
+ }
295
+ },
296
+ required: []
297
+ }
298
+ },
299
+ {
300
+ name: 'generate_crd_docs',
301
+ description: 'Generate Kubernetes CRD (Custom Resource Definition) documentation. Creates AsciiDoc documentation for Kubernetes operator CRDs. Writers use this when updating operator reference docs.',
302
+ inputSchema: {
303
+ type: 'object',
304
+ properties: {
305
+ tag: {
306
+ type: 'string',
307
+ description: 'Operator release tag (for example "operator/v25.1.2", "25.1.2", or "v25.1.2"). Auto-prepends "operator/" for redpanda-operator repository.'
308
+ },
309
+ branch: {
310
+ type: 'string',
311
+ description: 'Branch name for in-progress content (for example "dev", "main").'
312
+ },
313
+ source_path: {
314
+ type: 'string',
315
+ description: 'CRD Go types directory or GitHub URL (optional, defaults to Redpanda operator repo)'
316
+ },
317
+ depth: {
318
+ type: 'number',
319
+ description: 'How many levels deep to generate (optional, defaults to 10)'
320
+ },
321
+ templates_dir: {
322
+ type: 'string',
323
+ description: 'Asciidoctor templates directory (optional)'
324
+ },
325
+ output: {
326
+ type: 'string',
327
+ description: 'Where to write the generated AsciiDoc file (optional, defaults to "modules/reference/pages/k-crd.adoc")'
328
+ }
329
+ },
330
+ required: []
331
+ }
332
+ },
333
+ {
334
+ name: 'generate_bundle_openapi',
335
+ description: 'Bundle Redpanda OpenAPI fragments. Creates complete OpenAPI 3.1 documents for admin and/or connect APIs by bundling fragments from the Redpanda repository. Writers use this when updating API reference docs.',
336
+ inputSchema: {
337
+ type: 'object',
338
+ properties: {
339
+ tag: {
340
+ type: 'string',
341
+ description: 'Git tag for released content (for example "v24.3.2" or "24.3.2"). Use tags for GA or beta releases.'
342
+ },
343
+ branch: {
344
+ type: 'string',
345
+ description: 'Branch name for in-progress content (for example "dev", "main"). Use branches for documentation under development.'
346
+ },
347
+ repo: {
348
+ type: 'string',
349
+ description: 'Repository URL (optional, defaults to Redpanda repo)'
350
+ },
351
+ surface: {
352
+ type: 'string',
353
+ description: 'Which API surface(s) to bundle (optional, defaults to "both")',
354
+ enum: ['admin', 'connect', 'both']
355
+ },
356
+ out_admin: {
357
+ type: 'string',
358
+ description: 'Output path for admin API (optional, defaults to "admin/redpanda-admin-api.yaml")'
359
+ },
360
+ out_connect: {
361
+ type: 'string',
362
+ description: 'Output path for connect API (optional, defaults to "connect/redpanda-connect-api.yaml")'
363
+ },
364
+ admin_major: {
365
+ type: 'string',
366
+ description: 'Admin API major version (optional, defaults to "v2.0.0")'
367
+ },
368
+ use_admin_major_version: {
369
+ type: 'boolean',
370
+ description: 'Use admin major version for info.version instead of git tag (optional, defaults to false)'
371
+ },
372
+ quiet: {
373
+ type: 'boolean',
374
+ description: 'Suppress logs (optional, defaults to false)'
375
+ }
376
+ },
377
+ required: []
378
+ }
379
+ },
380
+ {
381
+ name: 'review_generated_docs',
382
+ description: 'Review recently generated documentation for quality issues. Checks for missing descriptions, invalid formatting, DRY violations, and other quality problems. Uses the quality criteria from the property-docs-guide and rpcn-connector-docs-guide prompts. Can generate a formatted markdown report for easy review.',
383
+ inputSchema: {
384
+ type: 'object',
385
+ properties: {
386
+ doc_type: {
387
+ type: 'string',
388
+ description: 'Type of documentation to review',
389
+ enum: ['properties', 'metrics', 'rpk', 'rpcn_connectors']
390
+ },
391
+ version: {
392
+ type: 'string',
393
+ description: 'Version of the docs to review (required for properties, metrics, rpk; for example "25.3.1" or "v25.3.1")'
394
+ },
395
+ generate_report: {
396
+ type: 'boolean',
397
+ description: 'Generate a formatted markdown report file for easy review (default: true)'
398
+ }
399
+ },
400
+ required: ['doc_type']
401
+ }
402
+ },
403
+ {
404
+ name: 'review_content',
405
+ description: 'Review documentation content with automatic style guide context. This tool bundles the style guide and review instructions in a single call, ensuring the LLM has all necessary context. Use this instead of manually fetching resources when you need a quick, comprehensive review.',
406
+ inputSchema: {
407
+ type: 'object',
408
+ properties: {
409
+ content: {
410
+ type: 'string',
411
+ description: 'The documentation content to review (can be a file path or raw content)'
412
+ },
413
+ focus: {
414
+ type: 'string',
415
+ description: 'What aspect to focus on (optional, defaults to comprehensive)',
416
+ enum: ['comprehensive', 'style', 'terminology', 'clarity']
417
+ }
418
+ },
419
+ required: ['content']
420
+ }
421
+ },
422
+ {
423
+ name: 'run_doc_tools_command',
424
+ description: 'Advanced: Run a raw doc-tools command. Only use this if none of the specific tools above fit your needs. Requires knowledge of doc-tools CLI syntax.',
425
+ inputSchema: {
426
+ type: 'object',
427
+ properties: {
428
+ command: {
429
+ type: 'string',
430
+ description: 'The doc-tools command to run (without "npx doc-tools" prefix)'
431
+ }
432
+ },
433
+ required: ['command']
434
+ }
435
+ },
436
+ {
437
+ name: 'get_job_status',
438
+ description: 'Get the status and progress of a background job. Use this to check on long-running documentation generation tasks.',
439
+ inputSchema: {
440
+ type: 'object',
441
+ properties: {
442
+ job_id: {
443
+ type: 'string',
444
+ description: 'Job ID returned when the job was created'
445
+ }
446
+ },
447
+ required: ['job_id']
448
+ }
449
+ },
450
+ {
451
+ name: 'list_jobs',
452
+ description: 'List all background jobs with optional filtering. Use this to see recent documentation generation jobs and their status.',
453
+ inputSchema: {
454
+ type: 'object',
455
+ properties: {
456
+ status: {
457
+ type: 'string',
458
+ description: 'Filter by job status (optional)',
459
+ enum: ['pending', 'running', 'completed', 'failed']
460
+ },
461
+ tool: {
462
+ type: 'string',
463
+ description: 'Filter by tool name (optional)'
464
+ }
465
+ },
466
+ required: []
467
+ }
468
+ }
469
+ ];
470
+
471
+ // Resource definitions - Team standards and guidelines
472
+ const resources = [
473
+ {
474
+ uri: 'redpanda://style-guide',
475
+ name: 'Redpanda Documentation Style Guide',
476
+ description: 'Complete style guide based on Google Developer Documentation Style Guide with Redpanda-specific guidelines, voice/tone standards, and formatting preferences. Includes references to official glossary sources.',
477
+ mimeType: 'text/markdown',
478
+ version: '1.0.0',
479
+ lastUpdated: '2025-12-11'
480
+ }
481
+ ];
482
+
483
+ // Resource file mappings
484
+ const resourceMap = {
485
+ 'redpanda://style-guide': { file: 'style-guide.md', mimeType: 'text/markdown' }
486
+ };
487
+
488
+ /**
489
+ * Load resource content from team-standards directory
490
+ * @param {string} uri - Resource URI (such as 'redpanda://style-guide')
491
+ * @returns {Object} Resource content
492
+ */
493
+ function getResourceContent(uri) {
494
+ const resource = resourceMap[uri];
495
+ if (!resource) {
496
+ throw new Error(`Unknown resource: ${uri}`);
497
+ }
498
+
499
+ const resourcePath = path.join(baseDir, 'mcp', 'team-standards', resource.file);
500
+ try {
501
+ const content = fs.readFileSync(resourcePath, 'utf8');
502
+ return {
503
+ contents: [{
504
+ uri,
505
+ mimeType: resource.mimeType,
506
+ text: content
507
+ }]
508
+ };
509
+ } catch (err) {
510
+ console.error(`Error loading resource ${uri}: ${err.message}`);
511
+ throw new Error(`Resource not found: ${uri}`);
512
+ }
513
+ }
514
+
515
+ // Handle list tools request
516
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
517
+ return { tools };
518
+ });
519
+
520
+ // Handle list prompts request
521
+ server.setRequestHandler(ListPromptsRequestSchema, async () => {
522
+ const allPrompts = promptCache.getAll();
523
+ return { prompts: promptsToMcpFormat(allPrompts) };
524
+ });
525
+
526
+ // Handle list resources request
527
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
528
+ return { resources };
529
+ });
530
+
531
+ // Handle read resource request
532
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
533
+ const { uri } = request.params;
534
+
535
+ // Record usage
536
+ usageStats.recordResource(uri);
537
+
538
+ return getResourceContent(uri);
539
+ });
540
+
541
+ // Handle get prompt request
542
+ server.setRequestHandler(GetPromptRequestSchema, async (request) => {
543
+ const { name, arguments: args } = request.params;
544
+
545
+ // Record usage
546
+ usageStats.recordPrompt(name);
547
+
548
+ // Get prompt from cache
549
+ const prompt = promptCache.get(name);
550
+ if (!prompt) {
551
+ throw new Error(`Unknown prompt: ${name}`);
552
+ }
553
+
554
+ // Validate arguments if schema exists
555
+ if (prompt.arguments && prompt.arguments.length > 0) {
556
+ try {
557
+ validatePromptArguments(name, args, prompt.arguments);
558
+ } catch (err) {
559
+ return {
560
+ messages: [{
561
+ role: 'user',
562
+ content: {
563
+ type: 'text',
564
+ text: `Error: ${err.message}`
565
+ }
566
+ }]
567
+ };
568
+ }
569
+ }
570
+
571
+ // Build prompt with arguments
572
+ const promptText = buildPromptWithArguments(prompt, args);
573
+
574
+ return {
575
+ messages: [{
576
+ role: 'user',
577
+ content: {
578
+ type: 'text',
579
+ text: promptText
580
+ }
581
+ }]
582
+ };
583
+ });
584
+
585
+ // Handle tool execution
586
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
587
+ const { name, arguments: args } = request.params;
588
+
589
+ // Record usage
590
+ usageStats.recordTool(name);
591
+
592
+ // Handle job management tools
593
+ if (name === 'get_job_status') {
594
+ const job = getJob(args.job_id);
595
+ if (!job) {
596
+ return {
597
+ content: [
598
+ {
599
+ type: 'text',
600
+ text: JSON.stringify({
601
+ success: false,
602
+ error: `Job not found: ${args.job_id}`,
603
+ suggestion: 'Check the job ID or use list_jobs to see available jobs'
604
+ }, null, 2)
605
+ }
606
+ ]
607
+ };
608
+ }
609
+
610
+ return {
611
+ content: [
612
+ {
613
+ type: 'text',
614
+ text: JSON.stringify({
615
+ success: true,
616
+ job
617
+ }, null, 2)
618
+ }
619
+ ]
620
+ };
621
+ }
622
+
623
+ if (name === 'list_jobs') {
624
+ const jobs = listJobs(args || {});
625
+ return {
626
+ content: [
627
+ {
628
+ type: 'text',
629
+ text: JSON.stringify({
630
+ success: true,
631
+ jobs,
632
+ total: jobs.length
633
+ }, null, 2)
634
+ }
635
+ ]
636
+ };
637
+ }
638
+
639
+ // Handle regular tools
640
+ const result = executeTool(name, args || {});
641
+
642
+ return {
643
+ content: [
644
+ {
645
+ type: 'text',
646
+ text: JSON.stringify(result, null, 2)
647
+ }
648
+ ]
649
+ };
650
+ });
651
+
652
+ // Start the server
653
+ async function main() {
654
+ // Load and validate prompts
655
+ console.error('Loading prompts...');
656
+ const prompts = loadAllPrompts(baseDir, promptCache);
657
+ console.error(`Loaded ${prompts.length} prompts`);
658
+
659
+ // Validate configuration at startup
660
+ console.error('Validating MCP configuration...');
661
+ const validation = validateMcpConfiguration({
662
+ resources,
663
+ resourceMap,
664
+ prompts,
665
+ baseDir
666
+ });
667
+
668
+ if (!validation.valid) {
669
+ console.error('\nMCP Configuration validation FAILED:');
670
+ validation.errors.forEach(err => console.error(` ${err}`));
671
+ console.error('\nServer cannot start with invalid configuration.');
672
+ process.exit(1);
673
+ }
674
+
675
+ if (validation.warnings.length > 0) {
676
+ console.error('\nWarnings:');
677
+ validation.warnings.forEach(warn => console.error(` ⚠ ${warn}`));
678
+ }
679
+
680
+ console.error('Configuration valid');
681
+
682
+ // Enable file watching in dev mode
683
+ if (process.env.MCP_DEV_MODE === 'true') {
684
+ watchPrompts(baseDir, promptCache, (reloadedPrompts) => {
685
+ console.error(`Prompts reloaded: ${reloadedPrompts.length} available`);
686
+ });
687
+ }
688
+
689
+ // Initialize usage tracking
690
+ createShutdownHandler(usageStats, baseDir);
691
+
692
+ // Periodic reporting (every hour)
693
+ if (process.env.MCP_TELEMETRY_REPORTING === 'true') {
694
+ createPeriodicReporter(usageStats, 3600000);
695
+ }
696
+
697
+ // Connect MCP server
698
+ const transport = new StdioServerTransport();
699
+ await server.connect(transport);
700
+
701
+ // Initialize job queue with server instance for progress notifications
702
+ initializeJobQueue(server);
703
+
704
+ // Log to stderr so it doesn't interfere with MCP protocol on stdout
705
+ const repoInfo = findRepoRoot();
706
+ console.error('Redpanda Doc Tools MCP Server running');
707
+ console.error(`Server version: ${packageJson.version}`);
708
+ console.error(`Working directory: ${process.cwd()}`);
709
+ console.error(`Repository root: ${repoInfo.root} (${repoInfo.detected ? repoInfo.type : 'not detected'})`);
710
+ console.error('Background job queue: enabled');
711
+ console.error('Command timeout: 10 minutes');
712
+ console.error('Auto-discovery: enabled');
713
+ console.error('Startup validation: enabled');
714
+ console.error('Usage telemetry: enabled');
715
+ }
716
+
717
+ main().catch((error) => {
718
+ console.error('Server error:', error);
719
+ process.exit(1);
720
+ });