mcp-researchpowerpack 3.6.9

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 (119) hide show
  1. package/README.md +635 -0
  2. package/dist/clients/reddit.d.ts +74 -0
  3. package/dist/clients/reddit.d.ts.map +1 -0
  4. package/dist/clients/reddit.js +305 -0
  5. package/dist/clients/reddit.js.map +1 -0
  6. package/dist/clients/research.d.ts +67 -0
  7. package/dist/clients/research.d.ts.map +1 -0
  8. package/dist/clients/research.js +252 -0
  9. package/dist/clients/research.js.map +1 -0
  10. package/dist/clients/scraper.d.ts +71 -0
  11. package/dist/clients/scraper.d.ts.map +1 -0
  12. package/dist/clients/scraper.js +321 -0
  13. package/dist/clients/scraper.js.map +1 -0
  14. package/dist/clients/search.d.ts +62 -0
  15. package/dist/clients/search.d.ts.map +1 -0
  16. package/dist/clients/search.js +219 -0
  17. package/dist/clients/search.js.map +1 -0
  18. package/dist/config/index.d.ts +62 -0
  19. package/dist/config/index.d.ts.map +1 -0
  20. package/dist/config/index.js +142 -0
  21. package/dist/config/index.js.map +1 -0
  22. package/dist/config/loader.d.ts +40 -0
  23. package/dist/config/loader.d.ts.map +1 -0
  24. package/dist/config/loader.js +305 -0
  25. package/dist/config/loader.js.map +1 -0
  26. package/dist/config/types.d.ts +81 -0
  27. package/dist/config/types.d.ts.map +1 -0
  28. package/dist/config/types.js +6 -0
  29. package/dist/config/types.js.map +1 -0
  30. package/dist/config/yaml/tools.yaml +130 -0
  31. package/dist/index.d.ts +7 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +271 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/schemas/deep-research.d.ts +64 -0
  36. package/dist/schemas/deep-research.d.ts.map +1 -0
  37. package/dist/schemas/deep-research.js +224 -0
  38. package/dist/schemas/deep-research.js.map +1 -0
  39. package/dist/schemas/scrape-links.d.ts +32 -0
  40. package/dist/schemas/scrape-links.d.ts.map +1 -0
  41. package/dist/schemas/scrape-links.js +34 -0
  42. package/dist/schemas/scrape-links.js.map +1 -0
  43. package/dist/schemas/web-search.d.ts +22 -0
  44. package/dist/schemas/web-search.d.ts.map +1 -0
  45. package/dist/schemas/web-search.js +21 -0
  46. package/dist/schemas/web-search.js.map +1 -0
  47. package/dist/services/file-attachment.d.ts +30 -0
  48. package/dist/services/file-attachment.d.ts.map +1 -0
  49. package/dist/services/file-attachment.js +199 -0
  50. package/dist/services/file-attachment.js.map +1 -0
  51. package/dist/services/llm-processor.d.ts +27 -0
  52. package/dist/services/llm-processor.d.ts.map +1 -0
  53. package/dist/services/llm-processor.js +179 -0
  54. package/dist/services/llm-processor.js.map +1 -0
  55. package/dist/services/markdown-cleaner.d.ts +8 -0
  56. package/dist/services/markdown-cleaner.d.ts.map +1 -0
  57. package/dist/services/markdown-cleaner.js +44 -0
  58. package/dist/services/markdown-cleaner.js.map +1 -0
  59. package/dist/tools/definitions.d.ts +16 -0
  60. package/dist/tools/definitions.d.ts.map +1 -0
  61. package/dist/tools/definitions.js +17 -0
  62. package/dist/tools/definitions.js.map +1 -0
  63. package/dist/tools/reddit.d.ts +14 -0
  64. package/dist/tools/reddit.d.ts.map +1 -0
  65. package/dist/tools/reddit.js +213 -0
  66. package/dist/tools/reddit.js.map +1 -0
  67. package/dist/tools/registry.d.ts +71 -0
  68. package/dist/tools/registry.d.ts.map +1 -0
  69. package/dist/tools/registry.js +242 -0
  70. package/dist/tools/registry.js.map +1 -0
  71. package/dist/tools/research.d.ts +14 -0
  72. package/dist/tools/research.d.ts.map +1 -0
  73. package/dist/tools/research.js +194 -0
  74. package/dist/tools/research.js.map +1 -0
  75. package/dist/tools/scrape.d.ts +14 -0
  76. package/dist/tools/scrape.d.ts.map +1 -0
  77. package/dist/tools/scrape.js +201 -0
  78. package/dist/tools/scrape.js.map +1 -0
  79. package/dist/tools/search.d.ts +10 -0
  80. package/dist/tools/search.d.ts.map +1 -0
  81. package/dist/tools/search.js +137 -0
  82. package/dist/tools/search.js.map +1 -0
  83. package/dist/tools/utils.d.ts +105 -0
  84. package/dist/tools/utils.d.ts.map +1 -0
  85. package/dist/tools/utils.js +159 -0
  86. package/dist/tools/utils.js.map +1 -0
  87. package/dist/utils/concurrency.d.ts +29 -0
  88. package/dist/utils/concurrency.d.ts.map +1 -0
  89. package/dist/utils/concurrency.js +73 -0
  90. package/dist/utils/concurrency.js.map +1 -0
  91. package/dist/utils/errors.d.ts +77 -0
  92. package/dist/utils/errors.d.ts.map +1 -0
  93. package/dist/utils/errors.js +335 -0
  94. package/dist/utils/errors.js.map +1 -0
  95. package/dist/utils/logger.d.ts +39 -0
  96. package/dist/utils/logger.d.ts.map +1 -0
  97. package/dist/utils/logger.js +57 -0
  98. package/dist/utils/logger.js.map +1 -0
  99. package/dist/utils/markdown-formatter.d.ts +5 -0
  100. package/dist/utils/markdown-formatter.d.ts.map +1 -0
  101. package/dist/utils/markdown-formatter.js +15 -0
  102. package/dist/utils/markdown-formatter.js.map +1 -0
  103. package/dist/utils/response.d.ts +88 -0
  104. package/dist/utils/response.d.ts.map +1 -0
  105. package/dist/utils/response.js +151 -0
  106. package/dist/utils/response.js.map +1 -0
  107. package/dist/utils/url-aggregator.d.ts +90 -0
  108. package/dist/utils/url-aggregator.d.ts.map +1 -0
  109. package/dist/utils/url-aggregator.js +502 -0
  110. package/dist/utils/url-aggregator.js.map +1 -0
  111. package/dist/version.d.ts +30 -0
  112. package/dist/version.d.ts.map +1 -0
  113. package/dist/version.js +60 -0
  114. package/dist/version.js.map +1 -0
  115. package/dist/worker.d.ts +17 -0
  116. package/dist/worker.d.ts.map +1 -0
  117. package/dist/worker.js +53 -0
  118. package/dist/worker.js.map +1 -0
  119. package/package.json +73 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reddit.d.ts","sourceRoot":"","sources":["../../src/tools/reddit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA0DH,wBAAsB,kBAAkB,CACtC,OAAO,EAAE,MAAM,EAAE,EACjB,MAAM,EAAE,MAAM,EACd,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,CA6CjB;AAMD,UAAU,qBAAqB;IAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAyBD,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EAAE,EACd,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,WAAW,SAAM,EACjB,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,MAAM,CAAC,CAmHjB"}
@@ -0,0 +1,213 @@
1
+ /**
2
+ * Reddit Tools - Search and Fetch
3
+ * NEVER throws - always returns structured response for graceful degradation
4
+ */
5
+ import { SearchClient } from '../clients/search.js';
6
+ import { RedditClient, calculateCommentAllocation } from '../clients/reddit.js';
7
+ import { aggregateAndRankReddit, generateRedditEnhancedOutput } from '../utils/url-aggregator.js';
8
+ import { REDDIT } from '../config/index.js';
9
+ import { classifyError } from '../utils/errors.js';
10
+ import { createLLMProcessor, processContentWithLLM } from '../services/llm-processor.js';
11
+ import { getToolConfig } from '../config/loader.js';
12
+ import { mcpLog, formatSuccess, formatError, formatBatchHeader, TOKEN_BUDGETS, } from './utils.js';
13
+ // ============================================================================
14
+ // Formatters
15
+ // ============================================================================
16
+ function formatComments(comments) {
17
+ let md = '';
18
+ for (const c of comments) {
19
+ const indent = ' '.repeat(c.depth);
20
+ const op = c.isOP ? ' **[OP]**' : '';
21
+ const score = c.score >= 0 ? `+${c.score}` : `${c.score}`;
22
+ md += `${indent}- **u/${c.author}**${op} _(${score})_\n`;
23
+ const bodyLines = c.body.split('\n').map(line => `${indent} ${line}`).join('\n');
24
+ md += `${bodyLines}\n\n`;
25
+ }
26
+ return md;
27
+ }
28
+ function formatPost(result, fetchComments) {
29
+ const { post, comments, allocatedComments } = result;
30
+ let md = `## ${post.title}\n\n`;
31
+ md += `**r/${post.subreddit}** • u/${post.author} • ⬆️ ${post.score} • 💬 ${post.commentCount} comments\n`;
32
+ md += `🔗 ${post.url}\n\n`;
33
+ if (post.body) {
34
+ md += `### Post Content\n\n${post.body}\n\n`;
35
+ }
36
+ if (fetchComments && comments.length > 0) {
37
+ md += `### Top Comments (${comments.length}/${post.commentCount} shown, allocated: ${allocatedComments})\n\n`;
38
+ md += formatComments(comments);
39
+ }
40
+ else if (!fetchComments) {
41
+ md += `_Comments not fetched (fetch_comments=false)_\n\n`;
42
+ }
43
+ return md;
44
+ }
45
+ // ============================================================================
46
+ // Search Reddit Handler
47
+ // ============================================================================
48
+ export async function handleSearchReddit(queries, apiKey, dateAfter) {
49
+ try {
50
+ const limited = queries.slice(0, 50);
51
+ const client = new SearchClient(apiKey);
52
+ const results = await client.searchRedditMultiple(limited, dateAfter);
53
+ // Check if any results were found
54
+ let totalResults = 0;
55
+ for (const items of results.values()) {
56
+ totalResults += items.length;
57
+ }
58
+ if (totalResults === 0) {
59
+ return formatError({
60
+ code: 'NO_RESULTS',
61
+ message: `No results found for any of the ${limited.length} queries`,
62
+ toolName: 'search_reddit',
63
+ howToFix: [
64
+ 'Try broader or simpler search terms',
65
+ 'Check spelling of technical terms',
66
+ 'Remove date filters if using them',
67
+ ],
68
+ alternatives: [
69
+ 'web_search(keywords=[...]) for general web results',
70
+ 'deep_research(questions=[...]) for synthesized analysis',
71
+ ],
72
+ });
73
+ }
74
+ // Aggregate and rank results by CTR
75
+ const aggregation = aggregateAndRankReddit(results, 3);
76
+ // Generate enhanced output with consensus highlighting AND per-query raw results
77
+ return generateRedditEnhancedOutput(aggregation, limited, results);
78
+ }
79
+ catch (error) {
80
+ const structuredError = classifyError(error);
81
+ return formatError({
82
+ code: structuredError.code,
83
+ message: structuredError.message,
84
+ retryable: structuredError.retryable,
85
+ toolName: 'search_reddit',
86
+ howToFix: ['Verify SERPER_API_KEY is set correctly'],
87
+ alternatives: ['web_search(keywords=[...]) as backup'],
88
+ });
89
+ }
90
+ }
91
+ // Get extraction suffix from YAML config (fallback to hardcoded if not found)
92
+ function getExtractionSuffix() {
93
+ const config = getToolConfig('get_reddit_post');
94
+ return config?.limits?.extraction_suffix || `
95
+ ---
96
+
97
+ ⚠️ IMPORTANT: Extract and synthesize the key insights, opinions, and recommendations from these Reddit discussions. Focus on:
98
+ - Common themes and consensus across posts
99
+ - Specific recommendations with context
100
+ - Contrasting viewpoints and debates
101
+ - Real-world experiences and lessons learned
102
+ - Technical details and implementation tips
103
+
104
+ Be comprehensive but concise. Prioritize actionable insights.
105
+
106
+ ---`;
107
+ }
108
+ function enhanceExtractionInstruction(instruction) {
109
+ const base = instruction || 'Extract key insights, recommendations, and community consensus from these Reddit discussions.';
110
+ return `${base}\n\n${getExtractionSuffix()}`;
111
+ }
112
+ export async function handleGetRedditPosts(urls, clientId, clientSecret, maxComments = 100, options = {}) {
113
+ try {
114
+ const { fetchComments = true, maxCommentsOverride, use_llm = false, what_to_extract } = options;
115
+ if (urls.length < REDDIT.MIN_POSTS) {
116
+ return formatError({
117
+ code: 'MIN_POSTS',
118
+ message: `Minimum ${REDDIT.MIN_POSTS} Reddit posts required. Received: ${urls.length}`,
119
+ toolName: 'get_reddit_post',
120
+ howToFix: [`Add at least ${REDDIT.MIN_POSTS - urls.length} more Reddit URL(s)`],
121
+ });
122
+ }
123
+ if (urls.length > REDDIT.MAX_POSTS) {
124
+ return formatError({
125
+ code: 'MAX_POSTS',
126
+ message: `Maximum ${REDDIT.MAX_POSTS} Reddit posts allowed. Received: ${urls.length}`,
127
+ toolName: 'get_reddit_post',
128
+ howToFix: [`Remove ${urls.length - REDDIT.MAX_POSTS} URL(s) and retry`],
129
+ });
130
+ }
131
+ const allocation = calculateCommentAllocation(urls.length);
132
+ const commentsPerPost = fetchComments ? (maxCommentsOverride || allocation.perPostCapped) : 0;
133
+ const totalBatches = Math.ceil(urls.length / REDDIT.BATCH_SIZE);
134
+ const client = new RedditClient(clientId, clientSecret);
135
+ const batchResult = await client.batchGetPosts(urls, commentsPerPost, fetchComments);
136
+ const results = batchResult.results;
137
+ // Initialize LLM processor if needed
138
+ const llmProcessor = use_llm ? createLLMProcessor() : null;
139
+ const tokensPerUrl = use_llm ? Math.floor(TOKEN_BUDGETS.RESEARCH / urls.length) : 0;
140
+ const enhancedInstruction = use_llm ? enhanceExtractionInstruction(what_to_extract) : undefined;
141
+ let successful = 0;
142
+ let failed = 0;
143
+ let llmErrors = 0;
144
+ const contents = [];
145
+ for (const [url, result] of results) {
146
+ if (result instanceof Error) {
147
+ failed++;
148
+ contents.push(`## ❌ Failed: ${url}\n\n_${result.message}_`);
149
+ }
150
+ else {
151
+ successful++;
152
+ let postContent = formatPost(result, fetchComments);
153
+ // Apply LLM extraction per-URL if enabled
154
+ if (use_llm && llmProcessor) {
155
+ mcpLog('info', `[${successful}/${urls.length}] Applying LLM extraction to ${url}`, 'reddit');
156
+ const llmResult = await processContentWithLLM(postContent, { use_llm: true, what_to_extract: enhancedInstruction, max_tokens: tokensPerUrl }, llmProcessor);
157
+ if (llmResult.processed) {
158
+ postContent = `## LLM Analysis: ${result.post.title}\n\n**r/${result.post.subreddit}** • u/${result.post.author} • ⬆️ ${result.post.score} • 💬 ${result.post.commentCount} comments\n🔗 ${result.post.url}\n\n${llmResult.content}`;
159
+ mcpLog('debug', `[${successful}/${urls.length}] LLM extraction complete`, 'reddit');
160
+ }
161
+ else {
162
+ llmErrors++;
163
+ mcpLog('warning', `[${successful}/${urls.length}] LLM extraction failed: ${llmResult.error || 'unknown'}`, 'reddit');
164
+ }
165
+ }
166
+ contents.push(postContent);
167
+ }
168
+ }
169
+ // Build 70/20/10 response
170
+ const batchHeader = formatBatchHeader({
171
+ title: `Reddit Posts`,
172
+ totalItems: urls.length,
173
+ successful,
174
+ failed,
175
+ ...(fetchComments ? { extras: { 'Comments/post': commentsPerPost } } : {}),
176
+ ...(use_llm ? { tokensPerItem: tokensPerUrl } : {}),
177
+ batches: totalBatches,
178
+ });
179
+ const statusExtras = [];
180
+ if (batchResult.rateLimitHits > 0) {
181
+ statusExtras.push(`⚠️ ${batchResult.rateLimitHits} rate limit retries`);
182
+ }
183
+ if (use_llm && !llmProcessor) {
184
+ statusExtras.push('⚠️ LLM unavailable (OPENROUTER_API_KEY not set)');
185
+ }
186
+ else if (llmErrors > 0) {
187
+ statusExtras.push(`⚠️ ${llmErrors} LLM extraction failures`);
188
+ }
189
+ const nextSteps = [
190
+ successful > 0 ? 'Research further: deep_research(questions=[{question: "Based on Reddit discussion..."}])' : null,
191
+ failed > 0 ? 'Retry failed URLs individually' : null,
192
+ 'Search related topics: search_reddit(queries=[...related terms...])',
193
+ ].filter(Boolean);
194
+ const extraStatus = statusExtras.length > 0 ? `\n${statusExtras.join(' | ')}` : '';
195
+ return formatSuccess({
196
+ title: `Reddit Posts Fetched (${successful}/${urls.length})`,
197
+ summary: batchHeader + extraStatus,
198
+ data: contents.join('\n\n---\n\n'),
199
+ nextSteps,
200
+ });
201
+ }
202
+ catch (error) {
203
+ const structuredError = classifyError(error);
204
+ return formatError({
205
+ code: structuredError.code,
206
+ message: structuredError.message,
207
+ retryable: structuredError.retryable,
208
+ toolName: 'get_reddit_post',
209
+ howToFix: ['Verify REDDIT_CLIENT_ID and REDDIT_CLIENT_SECRET are set'],
210
+ });
211
+ }
212
+ }
213
+ //# sourceMappingURL=reddit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reddit.js","sourceRoot":"","sources":["../../src/tools/reddit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,0BAA0B,EAAiC,MAAM,sBAAsB,CAAC;AAC/G,OAAO,EAAE,sBAAsB,EAAE,4BAA4B,EAAE,MAAM,4BAA4B,CAAC;AAClG,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EACL,MAAM,EACN,aAAa,EACb,WAAW,EACX,iBAAiB,EACjB,aAAa,GACd,MAAM,YAAY,CAAC;AAEpB,+EAA+E;AAC/E,aAAa;AACb,+EAA+E;AAE/E,SAAS,cAAc,CAAC,QAAmB;IACzC,IAAI,EAAE,GAAG,EAAE,CAAC;IACZ,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC;QAC1D,EAAE,IAAI,GAAG,MAAM,SAAS,CAAC,CAAC,MAAM,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;QACzD,MAAM,SAAS,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClF,EAAE,IAAI,GAAG,SAAS,MAAM,CAAC;IAC3B,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,SAAS,UAAU,CAAC,MAAkB,EAAE,aAAsB;IAC5D,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,iBAAiB,EAAE,GAAG,MAAM,CAAC;IACrD,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,MAAM,CAAC;IAChC,EAAE,IAAI,OAAO,IAAI,CAAC,SAAS,UAAU,IAAI,CAAC,MAAM,SAAS,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,YAAY,aAAa,CAAC;IAC3G,EAAE,IAAI,MAAM,IAAI,CAAC,GAAG,MAAM,CAAC;IAE3B,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,EAAE,IAAI,uBAAuB,IAAI,CAAC,IAAI,MAAM,CAAC;IAC/C,CAAC;IAED,IAAI,aAAa,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzC,EAAE,IAAI,qBAAqB,QAAQ,CAAC,MAAM,IAAI,IAAI,CAAC,YAAY,sBAAsB,iBAAiB,OAAO,CAAC;QAC9G,EAAE,IAAI,cAAc,CAAC,QAAQ,CAAC,CAAC;IACjC,CAAC;SAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QAC1B,EAAE,IAAI,mDAAmD,CAAC;IAC5D,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,+EAA+E;AAC/E,wBAAwB;AACxB,+EAA+E;AAE/E,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,OAAiB,EACjB,MAAc,EACd,SAAkB;IAElB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,oBAAoB,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC;QAEtE,kCAAkC;QAClC,IAAI,YAAY,GAAG,CAAC,CAAC;QACrB,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC;YACrC,YAAY,IAAI,KAAK,CAAC,MAAM,CAAC;QAC/B,CAAC;QAED,IAAI,YAAY,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,WAAW,CAAC;gBACjB,IAAI,EAAE,YAAY;gBAClB,OAAO,EAAE,mCAAmC,OAAO,CAAC,MAAM,UAAU;gBACpE,QAAQ,EAAE,eAAe;gBACzB,QAAQ,EAAE;oBACR,qCAAqC;oBACrC,mCAAmC;oBACnC,mCAAmC;iBACpC;gBACD,YAAY,EAAE;oBACZ,oDAAoD;oBACpD,yDAAyD;iBAC1D;aACF,CAAC,CAAC;QACL,CAAC;QAED,oCAAoC;QACpC,MAAM,WAAW,GAAG,sBAAsB,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QAEvD,iFAAiF;QACjF,OAAO,4BAA4B,CAAC,WAAW,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IACrE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,eAAe,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;QAC7C,OAAO,WAAW,CAAC;YACjB,IAAI,EAAE,eAAe,CAAC,IAAI;YAC1B,OAAO,EAAE,eAAe,CAAC,OAAO;YAChC,SAAS,EAAE,eAAe,CAAC,SAAS;YACpC,QAAQ,EAAE,eAAe;YACzB,QAAQ,EAAE,CAAC,wCAAwC,CAAC;YACpD,YAAY,EAAE,CAAC,sCAAsC,CAAC;SACvD,CAAC,CAAC;IACL,CAAC;AACH,CAAC;AAaD,8EAA8E;AAC9E,SAAS,mBAAmB;IAC1B,MAAM,MAAM,GAAG,aAAa,CAAC,iBAAiB,CAAC,CAAC;IAChD,OAAO,MAAM,EAAE,MAAM,EAAE,iBAA2B,IAAI;;;;;;;;;;;;IAYpD,CAAC;AACL,CAAC;AAED,SAAS,4BAA4B,CAAC,WAA+B;IACnE,MAAM,IAAI,GAAG,WAAW,IAAI,+FAA+F,CAAC;IAC5H,OAAO,GAAG,IAAI,OAAO,mBAAmB,EAAE,EAAE,CAAC;AAC/C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,IAAc,EACd,QAAgB,EAChB,YAAoB,EACpB,WAAW,GAAG,GAAG,EACjB,UAAiC,EAAE;IAEnC,IAAI,CAAC;QACH,MAAM,EAAE,aAAa,GAAG,IAAI,EAAE,mBAAmB,EAAE,OAAO,GAAG,KAAK,EAAE,eAAe,EAAE,GAAG,OAAO,CAAC;QAEhG,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;YACnC,OAAO,WAAW,CAAC;gBACjB,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,WAAW,MAAM,CAAC,SAAS,qCAAqC,IAAI,CAAC,MAAM,EAAE;gBACtF,QAAQ,EAAE,iBAAiB;gBAC3B,QAAQ,EAAE,CAAC,gBAAgB,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,qBAAqB,CAAC;aAChF,CAAC,CAAC;QACL,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC;YACnC,OAAO,WAAW,CAAC;gBACjB,IAAI,EAAE,WAAW;gBACjB,OAAO,EAAE,WAAW,MAAM,CAAC,SAAS,oCAAoC,IAAI,CAAC,MAAM,EAAE;gBACrF,QAAQ,EAAE,iBAAiB;gBAC3B,QAAQ,EAAE,CAAC,UAAU,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,SAAS,mBAAmB,CAAC;aACxE,CAAC,CAAC;QACL,CAAC;QAED,MAAM,UAAU,GAAG,0BAA0B,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3D,MAAM,eAAe,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,mBAAmB,IAAI,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9F,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;QAEhE,MAAM,MAAM,GAAG,IAAI,YAAY,CAAC,QAAQ,EAAE,YAAY,CAAC,CAAC;QACxD,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,eAAe,EAAE,aAAa,CAAC,CAAC;QACrF,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAC;QAEpC,qCAAqC;QACrC,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;QAC3D,MAAM,YAAY,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpF,MAAM,mBAAmB,GAAG,OAAO,CAAC,CAAC,CAAC,4BAA4B,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAEhG,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,MAAM,GAAG,CAAC,CAAC;QACf,IAAI,SAAS,GAAG,CAAC,CAAC;QAClB,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,KAAK,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACpC,IAAI,MAAM,YAAY,KAAK,EAAE,CAAC;gBAC5B,MAAM,EAAE,CAAC;gBACT,QAAQ,CAAC,IAAI,CAAC,gBAAgB,GAAG,QAAQ,MAAM,CAAC,OAAO,GAAG,CAAC,CAAC;YAC9D,CAAC;iBAAM,CAAC;gBACN,UAAU,EAAE,CAAC;gBACb,IAAI,WAAW,GAAG,UAAU,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;gBAEpD,0CAA0C;gBAC1C,IAAI,OAAO,IAAI,YAAY,EAAE,CAAC;oBAC5B,MAAM,CAAC,MAAM,EAAE,IAAI,UAAU,IAAI,IAAI,CAAC,MAAM,gCAAgC,GAAG,EAAE,EAAE,QAAQ,CAAC,CAAC;oBAE7F,MAAM,SAAS,GAAG,MAAM,qBAAqB,CAC3C,WAAW,EACX,EAAE,OAAO,EAAE,IAAI,EAAE,eAAe,EAAE,mBAAmB,EAAE,UAAU,EAAE,YAAY,EAAE,EACjF,YAAY,CACb,CAAC;oBAEF,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC;wBACxB,WAAW,GAAG,oBAAoB,MAAM,CAAC,IAAI,CAAC,KAAK,WAAW,MAAM,CAAC,IAAI,CAAC,SAAS,UAAU,MAAM,CAAC,IAAI,CAAC,MAAM,SAAS,MAAM,CAAC,IAAI,CAAC,KAAK,SAAS,MAAM,CAAC,IAAI,CAAC,YAAY,iBAAiB,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,SAAS,CAAC,OAAO,EAAE,CAAC;wBACrO,MAAM,CAAC,OAAO,EAAE,IAAI,UAAU,IAAI,IAAI,CAAC,MAAM,2BAA2B,EAAE,QAAQ,CAAC,CAAC;oBACtF,CAAC;yBAAM,CAAC;wBACN,SAAS,EAAE,CAAC;wBACZ,MAAM,CAAC,SAAS,EAAE,IAAI,UAAU,IAAI,IAAI,CAAC,MAAM,4BAA4B,SAAS,CAAC,KAAK,IAAI,SAAS,EAAE,EAAE,QAAQ,CAAC,CAAC;oBACvH,CAAC;gBACH,CAAC;gBAED,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;YAC7B,CAAC;QACH,CAAC;QAED,0BAA0B;QAC1B,MAAM,WAAW,GAAG,iBAAiB,CAAC;YACpC,KAAK,EAAE,cAAc;YACrB,UAAU,EAAE,IAAI,CAAC,MAAM;YACvB,UAAU;YACV,MAAM;YACN,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,eAAe,EAAE,eAAe,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1E,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnD,OAAO,EAAE,YAAY;SACtB,CAAC,CAAC;QAEH,MAAM,YAAY,GAAa,EAAE,CAAC;QAClC,IAAI,WAAW,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;YAClC,YAAY,CAAC,IAAI,CAAC,MAAM,WAAW,CAAC,aAAa,qBAAqB,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,OAAO,IAAI,CAAC,YAAY,EAAE,CAAC;YAC7B,YAAY,CAAC,IAAI,CAAC,iDAAiD,CAAC,CAAC;QACvE,CAAC;aAAM,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;YACzB,YAAY,CAAC,IAAI,CAAC,MAAM,SAAS,0BAA0B,CAAC,CAAC;QAC/D,CAAC;QAED,MAAM,SAAS,GAAG;YAChB,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,0FAA0F,CAAC,CAAC,CAAC,IAAI;YAClH,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,gCAAgC,CAAC,CAAC,CAAC,IAAI;YACpD,qEAAqE;SACtE,CAAC,MAAM,CAAC,OAAO,CAAa,CAAC;QAE9B,MAAM,WAAW,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAEnF,OAAO,aAAa,CAAC;YACnB,KAAK,EAAE,yBAAyB,UAAU,IAAI,IAAI,CAAC,MAAM,GAAG;YAC5D,OAAO,EAAE,WAAW,GAAG,WAAW;YAClC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,aAAa,CAAC;YAClC,SAAS;SACV,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,eAAe,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC;QAC7C,OAAO,WAAW,CAAC;YACjB,IAAI,EAAE,eAAe,CAAC,IAAI;YAC1B,OAAO,EAAE,eAAe,CAAC,OAAO;YAChC,SAAS,EAAE,eAAe,CAAC,SAAS;YACpC,QAAQ,EAAE,iBAAiB;YAC3B,QAAQ,EAAE,CAAC,0DAA0D,CAAC;SACvE,CAAC,CAAC;IACL,CAAC;AACH,CAAC"}
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Handler Registry - Central tool registration and execution
3
+ * Eliminates repetitive if/else routing with declarative registration
4
+ */
5
+ import { z } from 'zod';
6
+ import { type Capabilities } from '../config/index.js';
7
+ /**
8
+ * MCP-compliant tool result with index signature for SDK compatibility
9
+ */
10
+ export interface CallToolResult {
11
+ content: Array<{
12
+ type: 'text';
13
+ text: string;
14
+ }>;
15
+ isError?: boolean;
16
+ [key: string]: unknown;
17
+ }
18
+ /**
19
+ * Configuration for a registered tool
20
+ */
21
+ export interface ToolRegistration {
22
+ name: string;
23
+ capability?: keyof Capabilities;
24
+ schema: z.ZodSchema;
25
+ handler: (params: unknown) => Promise<string>;
26
+ postValidate?: (params: unknown) => string | undefined;
27
+ transformResponse?: (result: string) => {
28
+ content: string;
29
+ isError?: boolean;
30
+ };
31
+ }
32
+ /**
33
+ * Registry type
34
+ */
35
+ export type ToolRegistry = Record<string, ToolRegistration>;
36
+ /**
37
+ * Central registry of all MCP tools
38
+ */
39
+ export declare const toolRegistry: ToolRegistry;
40
+ /**
41
+ * Execute a tool by name with full middleware chain
42
+ *
43
+ * Middleware steps:
44
+ * 1. Lookup tool in registry (throw McpError if not found)
45
+ * 2. Check capability (return error response if missing)
46
+ * 3. Validate params with Zod (return error response if invalid)
47
+ * 4. Execute handler (catch and format any errors)
48
+ * 5. Transform response if needed
49
+ *
50
+ * @param name - Tool name from request
51
+ * @param args - Raw arguments from request
52
+ * @param capabilities - Current capabilities from getCapabilities()
53
+ * @returns MCP-compliant tool result
54
+ */
55
+ export declare function executeTool(name: string, args: unknown, capabilities: Capabilities): Promise<CallToolResult>;
56
+ /**
57
+ * Get list of all registered tool names
58
+ */
59
+ export declare function getRegisteredToolNames(): string[];
60
+ /**
61
+ * Check if a tool is registered
62
+ */
63
+ export declare function isToolRegistered(name: string): boolean;
64
+ /**
65
+ * Get tool capabilities for logging
66
+ */
67
+ export declare function getToolCapabilities(): {
68
+ enabled: string[];
69
+ disabled: string[];
70
+ };
71
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,CAAC,EAAY,MAAM,KAAK,CAAC;AAGlC,OAAO,EAAmD,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAkBxG;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,YAAY,CAAC;IAChC,MAAM,EAAE,CAAC,CAAC,SAAS,CAAC;IACpB,OAAO,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9C,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC;IACvD,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;CAChF;AAED;;GAEG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;AAgF5D;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,YA+C1B,CAAC;AAMF;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,OAAO,EACb,YAAY,EAAE,YAAY,GACzB,OAAO,CAAC,cAAc,CAAC,CAuEzB;AAMD;;GAEG;AACH,wBAAgB,sBAAsB,IAAI,MAAM,EAAE,CAEjD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,IAAI;IAAE,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAe/E"}
@@ -0,0 +1,242 @@
1
+ /**
2
+ * Handler Registry - Central tool registration and execution
3
+ * Eliminates repetitive if/else routing with declarative registration
4
+ */
5
+ import { z, ZodError } from 'zod';
6
+ import { McpError, ErrorCode as McpErrorCode } from '@modelcontextprotocol/sdk/types.js';
7
+ import { parseEnv, getCapabilities, getMissingEnvMessage } from '../config/index.js';
8
+ import { classifyError, createToolErrorFromStructured } from '../utils/errors.js';
9
+ // Import schemas
10
+ import { deepResearchParamsSchema } from '../schemas/deep-research.js';
11
+ import { scrapeLinksParamsSchema } from '../schemas/scrape-links.js';
12
+ import { webSearchParamsSchema } from '../schemas/web-search.js';
13
+ // Import handlers
14
+ import { handleSearchReddit, handleGetRedditPosts } from './reddit.js';
15
+ import { handleDeepResearch } from './research.js';
16
+ import { handleScrapeLinks } from './scrape.js';
17
+ import { handleWebSearch } from './search.js';
18
+ // ============================================================================
19
+ // Schemas for Simple Tools (inline definitions)
20
+ // ============================================================================
21
+ const searchRedditParamsSchema = z.object({
22
+ queries: z.array(z.string()).min(10).max(50),
23
+ date_after: z.string().optional(),
24
+ });
25
+ const getRedditPostParamsSchema = z.object({
26
+ urls: z.array(z.string()).min(2).max(50),
27
+ fetch_comments: z.boolean().default(true),
28
+ max_comments: z.number().default(100),
29
+ use_llm: z.boolean().default(false),
30
+ what_to_extract: z.string().optional(),
31
+ });
32
+ // ============================================================================
33
+ // Handler Wrappers
34
+ // ============================================================================
35
+ const env = parseEnv();
36
+ /**
37
+ * Wrapper for search_reddit handler
38
+ */
39
+ async function searchRedditHandler(params) {
40
+ const p = params;
41
+ return handleSearchReddit(p.queries, env.SEARCH_API_KEY || '', p.date_after);
42
+ }
43
+ /**
44
+ * Wrapper for get_reddit_post handler
45
+ */
46
+ async function getRedditPostHandler(params) {
47
+ const p = params;
48
+ return handleGetRedditPosts(p.urls, env.REDDIT_CLIENT_ID || '', env.REDDIT_CLIENT_SECRET || '', p.max_comments, {
49
+ fetchComments: p.fetch_comments,
50
+ maxCommentsOverride: p.max_comments !== 100 ? p.max_comments : undefined,
51
+ use_llm: p.use_llm,
52
+ what_to_extract: p.what_to_extract,
53
+ });
54
+ }
55
+ /**
56
+ * Wrapper for deep_research handler
57
+ */
58
+ async function deepResearchHandler(params) {
59
+ const { content } = await handleDeepResearch(params);
60
+ return content;
61
+ }
62
+ /**
63
+ * Wrapper for scrape_links handler
64
+ */
65
+ async function scrapeLinksHandler(params) {
66
+ const { content } = await handleScrapeLinks(params);
67
+ return content;
68
+ }
69
+ /**
70
+ * Wrapper for web_search handler
71
+ */
72
+ async function webSearchHandler(params) {
73
+ const { content } = await handleWebSearch(params);
74
+ return content;
75
+ }
76
+ // ============================================================================
77
+ // Tool Registry
78
+ // ============================================================================
79
+ /**
80
+ * Central registry of all MCP tools
81
+ */
82
+ export const toolRegistry = {
83
+ search_reddit: {
84
+ name: 'search_reddit',
85
+ capability: 'search',
86
+ schema: searchRedditParamsSchema,
87
+ handler: searchRedditHandler,
88
+ },
89
+ get_reddit_post: {
90
+ name: 'get_reddit_post',
91
+ capability: 'reddit',
92
+ schema: getRedditPostParamsSchema,
93
+ handler: getRedditPostHandler,
94
+ },
95
+ deep_research: {
96
+ name: 'deep_research',
97
+ capability: 'deepResearch',
98
+ schema: deepResearchParamsSchema,
99
+ handler: deepResearchHandler,
100
+ transformResponse: (result) => ({
101
+ content: result,
102
+ isError: result.includes('# ❌ Error'),
103
+ }),
104
+ },
105
+ scrape_links: {
106
+ name: 'scrape_links',
107
+ capability: 'scraping',
108
+ schema: scrapeLinksParamsSchema,
109
+ handler: scrapeLinksHandler,
110
+ transformResponse: (result) => ({
111
+ content: result,
112
+ isError: result.includes('# ❌ Scraping Failed'),
113
+ }),
114
+ },
115
+ web_search: {
116
+ name: 'web_search',
117
+ capability: 'search',
118
+ schema: webSearchParamsSchema,
119
+ handler: webSearchHandler,
120
+ transformResponse: (result) => ({
121
+ content: result,
122
+ isError: result.includes('# ❌ web_search'),
123
+ }),
124
+ },
125
+ };
126
+ // ============================================================================
127
+ // Execute Tool (Main Entry Point)
128
+ // ============================================================================
129
+ /**
130
+ * Execute a tool by name with full middleware chain
131
+ *
132
+ * Middleware steps:
133
+ * 1. Lookup tool in registry (throw McpError if not found)
134
+ * 2. Check capability (return error response if missing)
135
+ * 3. Validate params with Zod (return error response if invalid)
136
+ * 4. Execute handler (catch and format any errors)
137
+ * 5. Transform response if needed
138
+ *
139
+ * @param name - Tool name from request
140
+ * @param args - Raw arguments from request
141
+ * @param capabilities - Current capabilities from getCapabilities()
142
+ * @returns MCP-compliant tool result
143
+ */
144
+ export async function executeTool(name, args, capabilities) {
145
+ // Step 1: Lookup tool
146
+ const tool = toolRegistry[name];
147
+ if (!tool) {
148
+ throw new McpError(McpErrorCode.MethodNotFound, `Method not found: ${name}. Available tools: ${Object.keys(toolRegistry).join(', ')}`);
149
+ }
150
+ // Step 2: Check capability
151
+ if (tool.capability && !capabilities[tool.capability]) {
152
+ return {
153
+ content: [{ type: 'text', text: getMissingEnvMessage(tool.capability) }],
154
+ isError: true,
155
+ };
156
+ }
157
+ // Step 3: Validate params with Zod
158
+ let validatedParams;
159
+ try {
160
+ validatedParams = tool.schema.parse(args);
161
+ }
162
+ catch (error) {
163
+ if (error instanceof ZodError) {
164
+ const issues = error.issues
165
+ .map((i) => `- **${i.path.join('.') || 'root'}**: ${i.message}`)
166
+ .join('\n');
167
+ return {
168
+ content: [{ type: 'text', text: `# ❌ Validation Error\n\n${issues}` }],
169
+ isError: true,
170
+ };
171
+ }
172
+ // Non-Zod validation error
173
+ const structured = classifyError(error);
174
+ return createToolErrorFromStructured(structured);
175
+ }
176
+ // Step 3.5: Optional post-validation
177
+ if (tool.postValidate) {
178
+ const postError = tool.postValidate(validatedParams);
179
+ if (postError) {
180
+ return {
181
+ content: [{ type: 'text', text: `# ❌ Validation Error\n\n${postError}` }],
182
+ isError: true,
183
+ };
184
+ }
185
+ }
186
+ // Step 4: Execute handler
187
+ let result;
188
+ try {
189
+ result = await tool.handler(validatedParams);
190
+ }
191
+ catch (error) {
192
+ // Handler threw (shouldn't happen if handlers follow "never throw" pattern)
193
+ const structured = classifyError(error);
194
+ return createToolErrorFromStructured(structured);
195
+ }
196
+ // Step 5: Transform response
197
+ if (tool.transformResponse) {
198
+ const transformed = tool.transformResponse(result);
199
+ return {
200
+ content: [{ type: 'text', text: transformed.content }],
201
+ isError: transformed.isError,
202
+ };
203
+ }
204
+ // Default: success response
205
+ return {
206
+ content: [{ type: 'text', text: result }],
207
+ };
208
+ }
209
+ // ============================================================================
210
+ // Utility Functions
211
+ // ============================================================================
212
+ /**
213
+ * Get list of all registered tool names
214
+ */
215
+ export function getRegisteredToolNames() {
216
+ return Object.keys(toolRegistry);
217
+ }
218
+ /**
219
+ * Check if a tool is registered
220
+ */
221
+ export function isToolRegistered(name) {
222
+ return name in toolRegistry;
223
+ }
224
+ /**
225
+ * Get tool capabilities for logging
226
+ */
227
+ export function getToolCapabilities() {
228
+ const caps = getCapabilities();
229
+ const enabled = [];
230
+ const disabled = [];
231
+ for (const [name, tool] of Object.entries(toolRegistry)) {
232
+ const capKey = tool.capability;
233
+ if (!capKey || caps[capKey]) {
234
+ enabled.push(name);
235
+ }
236
+ else {
237
+ disabled.push(name);
238
+ }
239
+ }
240
+ return { enabled, disabled };
241
+ }
242
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/tools/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Deep Research Tool Handler - Batch processing with dynamic token allocation
3
+ * Implements robust error handling that NEVER crashes
4
+ */
5
+ import type { DeepResearchParams } from '../schemas/deep-research.js';
6
+ /**
7
+ * Handle deep research request
8
+ * NEVER throws - always returns a valid response
9
+ */
10
+ export declare function handleDeepResearch(params: DeepResearchParams): Promise<{
11
+ content: string;
12
+ structuredContent: object;
13
+ }>;
14
+ //# sourceMappingURL=research.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"research.d.ts","sourceRoot":"","sources":["../../src/tools/research.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AA8CtE;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,MAAM,EAAE,kBAAkB,GACzB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CAAC,CA6KzD"}