mcp-researchpowerpack 3.9.4 → 4.3.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.
- package/README.md +116 -208
- package/dist/index.js +280 -337
- package/dist/index.js.map +7 -1
- package/dist/mcp-use.json +7 -0
- package/dist/src/clients/reddit.js +278 -0
- package/dist/src/clients/reddit.js.map +7 -0
- package/dist/src/clients/scraper.js +326 -0
- package/dist/src/clients/scraper.js.map +7 -0
- package/dist/src/clients/search.js +217 -0
- package/dist/src/clients/search.js.map +7 -0
- package/dist/src/config/index.js +138 -0
- package/dist/src/config/index.js.map +7 -0
- package/dist/src/prompts/deep-research.js +41 -0
- package/dist/src/prompts/deep-research.js.map +7 -0
- package/dist/src/prompts/reddit-sentiment.js +47 -0
- package/dist/src/prompts/reddit-sentiment.js.map +7 -0
- package/dist/src/schemas/reddit.js +21 -0
- package/dist/src/schemas/reddit.js.map +7 -0
- package/dist/src/schemas/scrape-links.js +26 -0
- package/dist/src/schemas/scrape-links.js.map +7 -0
- package/dist/src/schemas/start-research.js +17 -0
- package/dist/src/schemas/start-research.js.map +7 -0
- package/dist/src/schemas/web-search.js +53 -0
- package/dist/src/schemas/web-search.js.map +7 -0
- package/dist/src/services/llm-processor.js +675 -0
- package/dist/src/services/llm-processor.js.map +7 -0
- package/dist/src/services/markdown-cleaner.js +62 -0
- package/dist/src/services/markdown-cleaner.js.map +7 -0
- package/dist/src/services/workflow-state.js +116 -0
- package/dist/src/services/workflow-state.js.map +7 -0
- package/dist/src/tools/mcp-helpers.js +50 -0
- package/dist/src/tools/mcp-helpers.js.map +7 -0
- package/dist/src/tools/reddit.js +277 -0
- package/dist/src/tools/reddit.js.map +7 -0
- package/dist/src/tools/registry.js +18 -0
- package/dist/src/tools/registry.js.map +7 -0
- package/dist/src/tools/scrape.js +334 -0
- package/dist/src/tools/scrape.js.map +7 -0
- package/dist/src/tools/search.js +423 -0
- package/dist/src/tools/search.js.map +7 -0
- package/dist/src/tools/start-research.js +199 -0
- package/dist/src/tools/start-research.js.map +7 -0
- package/dist/src/tools/utils.js +29 -0
- package/dist/src/tools/utils.js.map +7 -0
- package/dist/src/utils/bootstrap-guard.js +27 -0
- package/dist/src/utils/bootstrap-guard.js.map +7 -0
- package/dist/src/utils/concurrency.js +62 -0
- package/dist/src/utils/concurrency.js.map +7 -0
- package/dist/src/utils/content-extractor.js +61 -0
- package/dist/src/utils/content-extractor.js.map +7 -0
- package/dist/src/utils/errors.js +211 -0
- package/dist/src/utils/errors.js.map +7 -0
- package/dist/src/utils/logger.js +25 -0
- package/dist/src/utils/logger.js.map +7 -0
- package/dist/src/utils/markdown-formatter.js +15 -0
- package/dist/src/utils/markdown-formatter.js.map +7 -0
- package/dist/src/utils/reddit-keyword-guard.js +29 -0
- package/dist/src/utils/reddit-keyword-guard.js.map +7 -0
- package/dist/src/utils/response.js +81 -0
- package/dist/src/utils/response.js.map +7 -0
- package/dist/src/utils/retry.js +13 -0
- package/dist/src/utils/retry.js.map +7 -0
- package/dist/src/utils/sanitize.js +10 -0
- package/dist/src/utils/sanitize.js.map +7 -0
- package/dist/src/utils/source-type.js +41 -0
- package/dist/src/utils/source-type.js.map +7 -0
- package/dist/src/utils/url-aggregator.js +227 -0
- package/dist/src/utils/url-aggregator.js.map +7 -0
- package/dist/src/utils/workflow-key.js +14 -0
- package/dist/src/utils/workflow-key.js.map +7 -0
- package/dist/src/version.js +32 -0
- package/dist/src/version.js.map +7 -0
- package/package.json +33 -28
- package/dist/clients/reddit.d.ts +0 -69
- package/dist/clients/reddit.d.ts.map +0 -1
- package/dist/clients/reddit.js +0 -369
- package/dist/clients/reddit.js.map +0 -1
- package/dist/clients/research.d.ts +0 -67
- package/dist/clients/research.d.ts.map +0 -1
- package/dist/clients/research.js +0 -290
- package/dist/clients/research.js.map +0 -1
- package/dist/clients/scraper.d.ts +0 -72
- package/dist/clients/scraper.d.ts.map +0 -1
- package/dist/clients/scraper.js +0 -338
- package/dist/clients/scraper.js.map +0 -1
- package/dist/clients/search.d.ts +0 -57
- package/dist/clients/search.d.ts.map +0 -1
- package/dist/clients/search.js +0 -223
- package/dist/clients/search.js.map +0 -1
- package/dist/config/index.d.ts +0 -78
- package/dist/config/index.d.ts.map +0 -1
- package/dist/config/index.js +0 -201
- package/dist/config/index.js.map +0 -1
- package/dist/config/loader.d.ts +0 -40
- package/dist/config/loader.d.ts.map +0 -1
- package/dist/config/loader.js +0 -322
- package/dist/config/loader.js.map +0 -1
- package/dist/config/types.d.ts +0 -81
- package/dist/config/types.d.ts.map +0 -1
- package/dist/config/types.js +0 -6
- package/dist/config/types.js.map +0 -1
- package/dist/config/yaml/tools.yaml +0 -146
- package/dist/index.d.ts +0 -7
- package/dist/index.d.ts.map +0 -1
- package/dist/schemas/deep-research.d.ts +0 -64
- package/dist/schemas/deep-research.d.ts.map +0 -1
- package/dist/schemas/deep-research.js +0 -224
- package/dist/schemas/deep-research.js.map +0 -1
- package/dist/schemas/scrape-links.d.ts +0 -32
- package/dist/schemas/scrape-links.d.ts.map +0 -1
- package/dist/schemas/scrape-links.js +0 -34
- package/dist/schemas/scrape-links.js.map +0 -1
- package/dist/schemas/web-search.d.ts +0 -22
- package/dist/schemas/web-search.d.ts.map +0 -1
- package/dist/schemas/web-search.js +0 -21
- package/dist/schemas/web-search.js.map +0 -1
- package/dist/services/file-attachment.d.ts +0 -30
- package/dist/services/file-attachment.d.ts.map +0 -1
- package/dist/services/file-attachment.js +0 -207
- package/dist/services/file-attachment.js.map +0 -1
- package/dist/services/llm-processor.d.ts +0 -29
- package/dist/services/llm-processor.d.ts.map +0 -1
- package/dist/services/llm-processor.js +0 -244
- package/dist/services/llm-processor.js.map +0 -1
- package/dist/services/markdown-cleaner.d.ts +0 -8
- package/dist/services/markdown-cleaner.d.ts.map +0 -1
- package/dist/services/markdown-cleaner.js +0 -74
- package/dist/services/markdown-cleaner.js.map +0 -1
- package/dist/tools/definitions.d.ts +0 -16
- package/dist/tools/definitions.d.ts.map +0 -1
- package/dist/tools/definitions.js +0 -17
- package/dist/tools/definitions.js.map +0 -1
- package/dist/tools/reddit.d.ts +0 -14
- package/dist/tools/reddit.d.ts.map +0 -1
- package/dist/tools/reddit.js +0 -265
- package/dist/tools/reddit.js.map +0 -1
- package/dist/tools/registry.d.ts +0 -71
- package/dist/tools/registry.d.ts.map +0 -1
- package/dist/tools/registry.js +0 -252
- package/dist/tools/registry.js.map +0 -1
- package/dist/tools/research.d.ts +0 -14
- package/dist/tools/research.d.ts.map +0 -1
- package/dist/tools/research.js +0 -196
- package/dist/tools/research.js.map +0 -1
- package/dist/tools/scrape.d.ts +0 -14
- package/dist/tools/scrape.d.ts.map +0 -1
- package/dist/tools/scrape.js +0 -234
- package/dist/tools/scrape.js.map +0 -1
- package/dist/tools/search.d.ts +0 -10
- package/dist/tools/search.d.ts.map +0 -1
- package/dist/tools/search.js +0 -158
- package/dist/tools/search.js.map +0 -1
- package/dist/tools/utils.d.ts +0 -105
- package/dist/tools/utils.d.ts.map +0 -1
- package/dist/tools/utils.js +0 -159
- package/dist/tools/utils.js.map +0 -1
- package/dist/utils/concurrency.d.ts +0 -28
- package/dist/utils/concurrency.d.ts.map +0 -1
- package/dist/utils/concurrency.js +0 -92
- package/dist/utils/concurrency.js.map +0 -1
- package/dist/utils/errors.d.ts +0 -95
- package/dist/utils/errors.d.ts.map +0 -1
- package/dist/utils/errors.js +0 -390
- package/dist/utils/errors.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -39
- package/dist/utils/logger.d.ts.map +0 -1
- package/dist/utils/logger.js +0 -57
- package/dist/utils/logger.js.map +0 -1
- package/dist/utils/markdown-formatter.d.ts +0 -5
- package/dist/utils/markdown-formatter.d.ts.map +0 -1
- package/dist/utils/markdown-formatter.js +0 -15
- package/dist/utils/markdown-formatter.js.map +0 -1
- package/dist/utils/response.d.ts +0 -93
- package/dist/utils/response.d.ts.map +0 -1
- package/dist/utils/response.js +0 -170
- package/dist/utils/response.js.map +0 -1
- package/dist/utils/retry.d.ts +0 -43
- package/dist/utils/retry.d.ts.map +0 -1
- package/dist/utils/retry.js +0 -57
- package/dist/utils/retry.js.map +0 -1
- package/dist/utils/url-aggregator.d.ts +0 -90
- package/dist/utils/url-aggregator.d.ts.map +0 -1
- package/dist/utils/url-aggregator.js +0 -538
- package/dist/utils/url-aggregator.js.map +0 -1
- package/dist/version.d.ts +0 -29
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js +0 -55
- package/dist/version.js.map +0 -1
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getRedditPostParamsSchema,
|
|
3
|
+
getRedditPostOutputSchema
|
|
4
|
+
} from "../schemas/reddit.js";
|
|
5
|
+
import { RedditClient } from "../clients/reddit.js";
|
|
6
|
+
import { REDDIT, getCapabilities, getMissingEnvMessage, parseEnv } from "../config/index.js";
|
|
7
|
+
import { classifyError } from "../utils/errors.js";
|
|
8
|
+
import {
|
|
9
|
+
formatSuccess,
|
|
10
|
+
formatError,
|
|
11
|
+
formatBatchHeader
|
|
12
|
+
} from "./utils.js";
|
|
13
|
+
import {
|
|
14
|
+
createToolReporter,
|
|
15
|
+
NOOP_REPORTER,
|
|
16
|
+
toolFailure,
|
|
17
|
+
toolSuccess,
|
|
18
|
+
toToolResponse
|
|
19
|
+
} from "./mcp-helpers.js";
|
|
20
|
+
import { requireBootstrap } from "../utils/bootstrap-guard.js";
|
|
21
|
+
function countWords(text) {
|
|
22
|
+
const plain = text.replace(/[*_~`#>|[\]()!-]/g, "");
|
|
23
|
+
return plain.split(/\s+/).filter((w) => w.length > 0).length;
|
|
24
|
+
}
|
|
25
|
+
function formatComments(comments, maxWords) {
|
|
26
|
+
let md = "";
|
|
27
|
+
let wordsUsed = 0;
|
|
28
|
+
let shown = 0;
|
|
29
|
+
for (const c of comments) {
|
|
30
|
+
const indent = " ".repeat(c.depth);
|
|
31
|
+
const op = c.isOP ? " **[OP]**" : "";
|
|
32
|
+
const score = c.score >= 0 ? `+${c.score}` : `${c.score}`;
|
|
33
|
+
const authorLine = `${indent}- **u/${c.author}**${op} _(${score})_
|
|
34
|
+
`;
|
|
35
|
+
const bodyLines = c.body.split("\n").map((line) => `${indent} ${line}`).join("\n");
|
|
36
|
+
const commentMd = `${authorLine}${bodyLines}
|
|
37
|
+
|
|
38
|
+
`;
|
|
39
|
+
const commentWords = countWords(commentMd);
|
|
40
|
+
if (wordsUsed + commentWords > maxWords && shown > 0) break;
|
|
41
|
+
md += commentMd;
|
|
42
|
+
wordsUsed += commentWords;
|
|
43
|
+
shown++;
|
|
44
|
+
}
|
|
45
|
+
return { md, wordsUsed, shown, truncated: comments.length - shown };
|
|
46
|
+
}
|
|
47
|
+
function formatPost(result, fetchComments, maxWords) {
|
|
48
|
+
const { post, comments } = result;
|
|
49
|
+
let md = `## ${post.title}
|
|
50
|
+
|
|
51
|
+
`;
|
|
52
|
+
md += `**r/${post.subreddit}** \u2022 u/${post.author} \u2022 \u2B06\uFE0F ${post.score} \u2022 \u{1F4AC} ${post.commentCount} comments
|
|
53
|
+
`;
|
|
54
|
+
md += `\u{1F517} ${post.url}
|
|
55
|
+
|
|
56
|
+
`;
|
|
57
|
+
let wordsUsed = countWords(md);
|
|
58
|
+
if (post.body) {
|
|
59
|
+
const bodySection = `### Post Content
|
|
60
|
+
|
|
61
|
+
${post.body}
|
|
62
|
+
|
|
63
|
+
`;
|
|
64
|
+
wordsUsed += countWords(bodySection);
|
|
65
|
+
md += bodySection;
|
|
66
|
+
}
|
|
67
|
+
let commentsShown = 0;
|
|
68
|
+
let commentsTruncated = 0;
|
|
69
|
+
if (fetchComments && comments.length > 0) {
|
|
70
|
+
const remainingWords = Math.max(0, maxWords - wordsUsed);
|
|
71
|
+
const commentsResult = formatComments(comments, remainingWords);
|
|
72
|
+
commentsShown = commentsResult.shown;
|
|
73
|
+
commentsTruncated = commentsResult.truncated;
|
|
74
|
+
md += `### Top Comments (${commentsResult.shown}/${post.commentCount} shown, ${commentsResult.wordsUsed.toLocaleString()} words)
|
|
75
|
+
|
|
76
|
+
`;
|
|
77
|
+
md += commentsResult.md;
|
|
78
|
+
wordsUsed += commentsResult.wordsUsed;
|
|
79
|
+
if (commentsResult.truncated > 0) {
|
|
80
|
+
md += `
|
|
81
|
+
_${commentsResult.truncated} more comments not shown (word budget reached)._
|
|
82
|
+
|
|
83
|
+
`;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return { md, wordsUsed, commentsShown, commentsTruncated };
|
|
87
|
+
}
|
|
88
|
+
function validatePostCount(urlCount) {
|
|
89
|
+
if (urlCount < REDDIT.MIN_POSTS) {
|
|
90
|
+
return formatError({
|
|
91
|
+
code: "MIN_POSTS",
|
|
92
|
+
message: `Minimum ${REDDIT.MIN_POSTS} Reddit posts required. Received: ${urlCount}`,
|
|
93
|
+
toolName: "get-reddit-post",
|
|
94
|
+
howToFix: [`Add at least ${REDDIT.MIN_POSTS - urlCount} more Reddit URL(s)`],
|
|
95
|
+
alternatives: [
|
|
96
|
+
`web-search(queries=["topic discussion", "topic recommendations"], extract="...", scope: "reddit") \u2014 find more Reddit post permalinks first, then call get-reddit-post with ${REDDIT.MIN_POSTS}+ URLs`
|
|
97
|
+
]
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
if (urlCount > REDDIT.MAX_POSTS) {
|
|
101
|
+
return formatError({
|
|
102
|
+
code: "MAX_POSTS",
|
|
103
|
+
message: `Maximum ${REDDIT.MAX_POSTS} Reddit posts allowed. Received: ${urlCount}`,
|
|
104
|
+
toolName: "get-reddit-post",
|
|
105
|
+
howToFix: [`Remove ${urlCount - REDDIT.MAX_POSTS} URL(s) and retry`]
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
async function fetchAndProcessPosts(results) {
|
|
111
|
+
let failed = 0;
|
|
112
|
+
const failedContents = [];
|
|
113
|
+
const successContents = [];
|
|
114
|
+
let successful = 0;
|
|
115
|
+
let totalWordsUsed = 0;
|
|
116
|
+
const skippedUrls = [];
|
|
117
|
+
for (const [url, result] of results) {
|
|
118
|
+
if (result instanceof Error) {
|
|
119
|
+
failed++;
|
|
120
|
+
failedContents.push(`## \u274C Failed: ${url}
|
|
121
|
+
|
|
122
|
+
_${result.message}_`);
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
if (totalWordsUsed >= REDDIT.MAX_WORDS_TOTAL) {
|
|
126
|
+
skippedUrls.push(url);
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
const formatted = formatPost(result, true, REDDIT.MAX_WORDS_PER_POST);
|
|
130
|
+
totalWordsUsed += formatted.wordsUsed;
|
|
131
|
+
successContents.push(formatted.md);
|
|
132
|
+
successful++;
|
|
133
|
+
}
|
|
134
|
+
const contents = [...failedContents, ...successContents];
|
|
135
|
+
return { successful, failed, llmErrors: 0, llmAvailable: false, contents, totalWordsUsed, skippedUrls };
|
|
136
|
+
}
|
|
137
|
+
function buildRedditStatusExtras(rateLimitHits, llmAvailable, llmErrors) {
|
|
138
|
+
const extras = [];
|
|
139
|
+
if (rateLimitHits > 0) extras.push(`\u26A0\uFE0F ${rateLimitHits} rate limit retries`);
|
|
140
|
+
if (!llmAvailable) {
|
|
141
|
+
extras.push("\u26A0\uFE0F LLM unavailable (LLM_EXTRACTION_API_KEY not set) \u2014 raw content returned");
|
|
142
|
+
} else if (llmErrors > 0) {
|
|
143
|
+
extras.push(`\u26A0\uFE0F ${llmErrors} LLM extraction failures`);
|
|
144
|
+
}
|
|
145
|
+
return extras.length > 0 ? `
|
|
146
|
+
${extras.join(" | ")}` : "";
|
|
147
|
+
}
|
|
148
|
+
function formatRedditOutput(urls, processResult, fetchComments, totalBatches, tokensPerUrl, extraStatus) {
|
|
149
|
+
const batchHeader = formatBatchHeader({
|
|
150
|
+
title: `Reddit Posts`,
|
|
151
|
+
totalItems: urls.length,
|
|
152
|
+
successful: processResult.successful,
|
|
153
|
+
failed: processResult.failed,
|
|
154
|
+
...fetchComments ? { extras: { "Words used": processResult.totalWordsUsed.toLocaleString() } } : {},
|
|
155
|
+
tokensPerItem: tokensPerUrl,
|
|
156
|
+
batches: totalBatches
|
|
157
|
+
});
|
|
158
|
+
let data = processResult.contents.join("\n\n---\n\n");
|
|
159
|
+
if (processResult.skippedUrls.length > 0) {
|
|
160
|
+
data += "\n\n---\n\n";
|
|
161
|
+
data += `**Word limit reached (${REDDIT.MAX_WORDS_TOTAL.toLocaleString()} words).** The following posts were not included:
|
|
162
|
+
`;
|
|
163
|
+
for (const url of processResult.skippedUrls) {
|
|
164
|
+
data += `- ${url}
|
|
165
|
+
`;
|
|
166
|
+
}
|
|
167
|
+
data += `
|
|
168
|
+
Call get-reddit-post(urls=[...skipped URLs above...]) with just the skipped URLs.`;
|
|
169
|
+
}
|
|
170
|
+
return formatSuccess({
|
|
171
|
+
title: `Reddit Posts Fetched (${processResult.successful}/${urls.length})`,
|
|
172
|
+
summary: batchHeader + extraStatus,
|
|
173
|
+
data
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
function formatGetRedditPostsError(error) {
|
|
177
|
+
const structuredError = classifyError(error);
|
|
178
|
+
return formatError({
|
|
179
|
+
code: structuredError.code,
|
|
180
|
+
message: structuredError.message,
|
|
181
|
+
retryable: structuredError.retryable,
|
|
182
|
+
toolName: "get-reddit-post",
|
|
183
|
+
howToFix: ["Verify REDDIT_CLIENT_ID and REDDIT_CLIENT_SECRET are set"],
|
|
184
|
+
alternatives: [
|
|
185
|
+
'web-search(queries=["topic reddit discussion", "topic reddit recommendations"], extract="reddit discussions and recommendations") \u2014 search for Reddit content via web search instead',
|
|
186
|
+
'scrape-links(urls=[...the Reddit URLs...], extract="post content | top comments | recommendations") \u2014 scrape Reddit pages directly as a fallback'
|
|
187
|
+
]
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
async function handleGetRedditPosts(urls, clientId, clientSecret, reporter = NOOP_REPORTER) {
|
|
191
|
+
const startTime = Date.now();
|
|
192
|
+
try {
|
|
193
|
+
const validationError = validatePostCount(urls.length);
|
|
194
|
+
if (validationError) return toolFailure(validationError);
|
|
195
|
+
const totalBatches = Math.ceil(urls.length / REDDIT.BATCH_SIZE);
|
|
196
|
+
await reporter.log("info", `Fetching ${urls.length} Reddit post(s)`);
|
|
197
|
+
await reporter.progress(20, 100, "Fetching Reddit posts");
|
|
198
|
+
const client = new RedditClient(clientId, clientSecret);
|
|
199
|
+
const batchResult = await client.batchGetPosts(urls, true);
|
|
200
|
+
await reporter.progress(55, 100, "Formatting posts and comments");
|
|
201
|
+
const processResult = await fetchAndProcessPosts(batchResult.results);
|
|
202
|
+
await reporter.progress(85, 100, "Building output");
|
|
203
|
+
const extraStatus = buildRedditStatusExtras(
|
|
204
|
+
batchResult.rateLimitHits,
|
|
205
|
+
false,
|
|
206
|
+
0
|
|
207
|
+
);
|
|
208
|
+
const content = formatRedditOutput(
|
|
209
|
+
urls,
|
|
210
|
+
processResult,
|
|
211
|
+
true,
|
|
212
|
+
totalBatches,
|
|
213
|
+
0,
|
|
214
|
+
extraStatus
|
|
215
|
+
);
|
|
216
|
+
const executionTime = Date.now() - startTime;
|
|
217
|
+
if (processResult.successful === 0 && processResult.failed > 0) {
|
|
218
|
+
return toolFailure(content);
|
|
219
|
+
}
|
|
220
|
+
return toolSuccess(content, {
|
|
221
|
+
content,
|
|
222
|
+
metadata: {
|
|
223
|
+
total_items: urls.length,
|
|
224
|
+
successful: processResult.successful,
|
|
225
|
+
failed: processResult.failed,
|
|
226
|
+
execution_time_ms: executionTime,
|
|
227
|
+
rate_limit_hits: batchResult.rateLimitHits
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
} catch (error) {
|
|
231
|
+
return toolFailure(formatGetRedditPostsError(error));
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function registerGetRedditPostTool(server) {
|
|
235
|
+
server.tool(
|
|
236
|
+
{
|
|
237
|
+
name: "get-reddit-post",
|
|
238
|
+
title: "Get Reddit Post",
|
|
239
|
+
description: "Fetch up to 100 Reddit posts with full threaded comment trees. Returns the raw post content and all comments with author, score, and OP markers.",
|
|
240
|
+
schema: getRedditPostParamsSchema,
|
|
241
|
+
outputSchema: getRedditPostOutputSchema,
|
|
242
|
+
annotations: {
|
|
243
|
+
readOnlyHint: true,
|
|
244
|
+
idempotentHint: true,
|
|
245
|
+
destructiveHint: false,
|
|
246
|
+
openWorldHint: true,
|
|
247
|
+
// See contract-fixes/03 — non-standard precondition hint.
|
|
248
|
+
...{ experimental: { requires: ["start-research"] } }
|
|
249
|
+
},
|
|
250
|
+
_meta: { requires: ["start-research"] }
|
|
251
|
+
},
|
|
252
|
+
async ({ urls }, ctx) => {
|
|
253
|
+
if (!getCapabilities().reddit) {
|
|
254
|
+
return toToolResponse(toolFailure(getMissingEnvMessage("reddit")));
|
|
255
|
+
}
|
|
256
|
+
const guard = await requireBootstrap(ctx);
|
|
257
|
+
if (guard) {
|
|
258
|
+
return guard;
|
|
259
|
+
}
|
|
260
|
+
const env = parseEnv();
|
|
261
|
+
const reporter = createToolReporter(ctx, "get-reddit-post");
|
|
262
|
+
const result = await handleGetRedditPosts(
|
|
263
|
+
urls,
|
|
264
|
+
env.REDDIT_CLIENT_ID,
|
|
265
|
+
env.REDDIT_CLIENT_SECRET,
|
|
266
|
+
reporter
|
|
267
|
+
);
|
|
268
|
+
await reporter.progress(100, 100, result.isError ? "Reddit fetch failed" : "Reddit fetch complete");
|
|
269
|
+
return toToolResponse(result);
|
|
270
|
+
}
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
export {
|
|
274
|
+
handleGetRedditPosts,
|
|
275
|
+
registerGetRedditPostTool
|
|
276
|
+
};
|
|
277
|
+
//# sourceMappingURL=reddit.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/tools/reddit.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Reddit Tools \u2014 get-reddit-post\n *\n * NEVER throws - always returns structured response for graceful degradation.\n *\n * Note: search-reddit was deleted in mcp-revisions/tool-surface/01. Reddit\n * discovery now flows through `web-search` with `scope: \"reddit\"`. See\n * mcp-revisions/tool-surface/04 for the rationale on keeping\n * get-reddit-post separate (Reddit threads have a structurally different\n * response shape than HTML pages).\n */\n\nimport type { MCPServer } from 'mcp-use/server';\n\nimport {\n getRedditPostParamsSchema,\n getRedditPostOutputSchema,\n type GetRedditPostOutput,\n} from '../schemas/reddit.js';\nimport { RedditClient, type PostResult, type Comment } from '../clients/reddit.js';\nimport { REDDIT, getCapabilities, getMissingEnvMessage, parseEnv } from '../config/index.js';\nimport { classifyError } from '../utils/errors.js';\nimport {\n mcpLog,\n formatSuccess,\n formatError,\n formatBatchHeader,\n} from './utils.js';\nimport {\n createToolReporter,\n NOOP_REPORTER,\n toolFailure,\n toolSuccess,\n toToolResponse,\n type ToolExecutionResult,\n type ToolReporter,\n} from './mcp-helpers.js';\nimport { requireBootstrap } from '../utils/bootstrap-guard.js';\n\n// ============================================================================\n// Formatters\n// ============================================================================\n\nfunction countWords(text: string): number {\n const plain = text.replace(/[*_~`#>|[\\]()!-]/g, '');\n return plain.split(/\\s+/).filter(w => w.length > 0).length;\n}\n\ninterface FormattedCommentsResult {\n md: string;\n wordsUsed: number;\n shown: number;\n truncated: number;\n}\n\nfunction formatComments(comments: Comment[], maxWords: number): FormattedCommentsResult {\n let md = '';\n let wordsUsed = 0;\n let shown = 0;\n\n for (const c of comments) {\n const indent = ' '.repeat(c.depth);\n const op = c.isOP ? ' **[OP]**' : '';\n const score = c.score >= 0 ? `+${c.score}` : `${c.score}`;\n const authorLine = `${indent}- **u/${c.author}**${op} _(${score})_\\n`;\n const bodyLines = c.body.split('\\n').map(line => `${indent} ${line}`).join('\\n');\n const commentMd = `${authorLine}${bodyLines}\\n\\n`;\n const commentWords = countWords(commentMd);\n\n if (wordsUsed + commentWords > maxWords && shown > 0) break;\n\n md += commentMd;\n wordsUsed += commentWords;\n shown++;\n }\n\n return { md, wordsUsed, shown, truncated: comments.length - shown };\n}\n\ninterface FormattedPostResult {\n md: string;\n wordsUsed: number;\n commentsShown: number;\n commentsTruncated: number;\n}\n\nfunction formatPost(result: PostResult, fetchComments: boolean, maxWords: number): FormattedPostResult {\n const { post, comments } = result;\n let md = `## ${post.title}\\n\\n`;\n md += `**r/${post.subreddit}** \u2022 u/${post.author} \u2022 \u2B06\uFE0F ${post.score} \u2022 \uD83D\uDCAC ${post.commentCount} comments\\n`;\n md += `\uD83D\uDD17 ${post.url}\\n\\n`;\n\n let wordsUsed = countWords(md);\n\n if (post.body) {\n const bodySection = `### Post Content\\n\\n${post.body}\\n\\n`;\n wordsUsed += countWords(bodySection);\n md += bodySection;\n }\n\n let commentsShown = 0;\n let commentsTruncated = 0;\n\n if (fetchComments && comments.length > 0) {\n const remainingWords = Math.max(0, maxWords - wordsUsed);\n const commentsResult = formatComments(comments, remainingWords);\n commentsShown = commentsResult.shown;\n commentsTruncated = commentsResult.truncated;\n\n md += `### Top Comments (${commentsResult.shown}/${post.commentCount} shown, ${commentsResult.wordsUsed.toLocaleString()} words)\\n\\n`;\n md += commentsResult.md;\n wordsUsed += commentsResult.wordsUsed;\n\n if (commentsResult.truncated > 0) {\n md += `\\n_${commentsResult.truncated} more comments not shown (word budget reached)._\\n\\n`;\n }\n }\n\n return { md, wordsUsed, commentsShown, commentsTruncated };\n}\n\n// ============================================================================\n// Get Reddit Posts Handler\n// ============================================================================\n\n// get-reddit-post no longer uses LLM \u2014 returns raw posts + comments\n\n// --- Internal types ---\n\ninterface PostProcessResult {\n successful: number;\n failed: number;\n llmErrors: number;\n llmAvailable: boolean;\n contents: string[];\n totalWordsUsed: number;\n skippedUrls: string[];\n}\n\n// --- Helpers ---\n\nfunction validatePostCount(urlCount: number): string | null {\n if (urlCount < REDDIT.MIN_POSTS) {\n return formatError({\n code: 'MIN_POSTS',\n message: `Minimum ${REDDIT.MIN_POSTS} Reddit posts required. Received: ${urlCount}`,\n toolName: 'get-reddit-post',\n howToFix: [`Add at least ${REDDIT.MIN_POSTS - urlCount} more Reddit URL(s)`],\n alternatives: [\n `web-search(queries=[\"topic discussion\", \"topic recommendations\"], extract=\"...\", scope: \"reddit\") \u2014 find more Reddit post permalinks first, then call get-reddit-post with ${REDDIT.MIN_POSTS}+ URLs`,\n ],\n });\n }\n if (urlCount > REDDIT.MAX_POSTS) {\n return formatError({\n code: 'MAX_POSTS',\n message: `Maximum ${REDDIT.MAX_POSTS} Reddit posts allowed. Received: ${urlCount}`,\n toolName: 'get-reddit-post',\n howToFix: [`Remove ${urlCount - REDDIT.MAX_POSTS} URL(s) and retry`],\n });\n }\n return null;\n}\n\nasync function fetchAndProcessPosts(\n results: Map<string, PostResult | Error>,\n): Promise<PostProcessResult> {\n let failed = 0;\n const failedContents: string[] = [];\n const successContents: string[] = [];\n let successful = 0;\n let totalWordsUsed = 0;\n const skippedUrls: string[] = [];\n\n for (const [url, result] of results) {\n if (result instanceof Error) {\n failed++;\n failedContents.push(`## \u274C Failed: ${url}\\n\\n_${result.message}_`);\n continue;\n }\n\n if (totalWordsUsed >= REDDIT.MAX_WORDS_TOTAL) {\n skippedUrls.push(url);\n continue;\n }\n\n const formatted = formatPost(result, true, REDDIT.MAX_WORDS_PER_POST);\n totalWordsUsed += formatted.wordsUsed;\n successContents.push(formatted.md);\n successful++;\n }\n\n const contents = [...failedContents, ...successContents];\n return { successful, failed, llmErrors: 0, llmAvailable: false, contents, totalWordsUsed, skippedUrls };\n}\n\nfunction buildRedditStatusExtras(\n rateLimitHits: number,\n llmAvailable: boolean,\n llmErrors: number,\n): string {\n const extras: string[] = [];\n if (rateLimitHits > 0) extras.push(`\u26A0\uFE0F ${rateLimitHits} rate limit retries`);\n if (!llmAvailable) {\n extras.push('\u26A0\uFE0F LLM unavailable (LLM_EXTRACTION_API_KEY not set) \u2014 raw content returned');\n } else if (llmErrors > 0) {\n extras.push(`\u26A0\uFE0F ${llmErrors} LLM extraction failures`);\n }\n return extras.length > 0 ? `\\n${extras.join(' | ')}` : '';\n}\n\nfunction formatRedditOutput(\n urls: string[],\n processResult: PostProcessResult,\n fetchComments: boolean,\n totalBatches: number,\n tokensPerUrl: number,\n extraStatus: string,\n): string {\n const batchHeader = formatBatchHeader({\n title: `Reddit Posts`,\n totalItems: urls.length,\n successful: processResult.successful,\n failed: processResult.failed,\n ...(fetchComments ? { extras: { 'Words used': processResult.totalWordsUsed.toLocaleString() } } : {}),\n tokensPerItem: tokensPerUrl,\n batches: totalBatches,\n });\n\n let data = processResult.contents.join('\\n\\n---\\n\\n');\n\n if (processResult.skippedUrls.length > 0) {\n data += '\\n\\n---\\n\\n';\n data += `**Word limit reached (${REDDIT.MAX_WORDS_TOTAL.toLocaleString()} words).** The following posts were not included:\\n`;\n for (const url of processResult.skippedUrls) {\n data += `- ${url}\\n`;\n }\n data += `\\nCall get-reddit-post(urls=[...skipped URLs above...]) with just the skipped URLs.`;\n }\n\n // No cookie-cutter \"Next Steps\" with literal `[...]` placeholders here\n // either. See: docs/code-review/context/07-derailment-evidence.md\n // ([FOOTER-BAD]) and mcp-revisions/output-shaping/05.\n return formatSuccess({\n title: `Reddit Posts Fetched (${processResult.successful}/${urls.length})`,\n summary: batchHeader + extraStatus,\n data,\n });\n}\n\nfunction formatGetRedditPostsError(error: unknown): string {\n const structuredError = classifyError(error);\n return formatError({\n code: structuredError.code,\n message: structuredError.message,\n retryable: structuredError.retryable,\n toolName: 'get-reddit-post',\n howToFix: ['Verify REDDIT_CLIENT_ID and REDDIT_CLIENT_SECRET are set'],\n alternatives: [\n 'web-search(queries=[\"topic reddit discussion\", \"topic reddit recommendations\"], extract=\"reddit discussions and recommendations\") \u2014 search for Reddit content via web search instead',\n 'scrape-links(urls=[...the Reddit URLs...], extract=\"post content | top comments | recommendations\") \u2014 scrape Reddit pages directly as a fallback',\n ],\n });\n}\n\nexport async function handleGetRedditPosts(\n urls: string[],\n clientId: string,\n clientSecret: string,\n reporter: ToolReporter = NOOP_REPORTER,\n): Promise<ToolExecutionResult<GetRedditPostOutput>> {\n const startTime = Date.now();\n try {\n const validationError = validatePostCount(urls.length);\n if (validationError) return toolFailure(validationError);\n\n const totalBatches = Math.ceil(urls.length / REDDIT.BATCH_SIZE);\n\n await reporter.log('info', `Fetching ${urls.length} Reddit post(s)`);\n await reporter.progress(20, 100, 'Fetching Reddit posts');\n const client = new RedditClient(clientId, clientSecret);\n const batchResult = await client.batchGetPosts(urls, true);\n await reporter.progress(55, 100, 'Formatting posts and comments');\n\n const processResult = await fetchAndProcessPosts(batchResult.results);\n await reporter.progress(85, 100, 'Building output');\n\n const extraStatus = buildRedditStatusExtras(\n batchResult.rateLimitHits, false, 0,\n );\n const content = formatRedditOutput(\n urls, processResult, true, totalBatches, 0, extraStatus,\n );\n\n const executionTime = Date.now() - startTime;\n\n // Contract: zero successful posts in a non-empty batch \u2192 isError:true so\n // callers that check response.isError can short-circuit. Partial success\n // still resolves through toolSuccess so the agent sees both rows. See\n // docs/code-review/context/02-current-tool-surface.md (E6).\n if (processResult.successful === 0 && processResult.failed > 0) {\n return toolFailure(content);\n }\n\n return toolSuccess(content, {\n content,\n metadata: {\n total_items: urls.length,\n successful: processResult.successful,\n failed: processResult.failed,\n execution_time_ms: executionTime,\n rate_limit_hits: batchResult.rateLimitHits,\n },\n });\n } catch (error) {\n return toolFailure(formatGetRedditPostsError(error));\n }\n}\n\nexport function registerGetRedditPostTool(server: MCPServer): void {\n server.tool(\n {\n name: 'get-reddit-post',\n title: 'Get Reddit Post',\n description:\n 'Fetch up to 100 Reddit posts with full threaded comment trees. Returns the raw post content and all comments with author, score, and OP markers.',\n schema: getRedditPostParamsSchema,\n outputSchema: getRedditPostOutputSchema,\n annotations: {\n readOnlyHint: true,\n idempotentHint: true,\n destructiveHint: false,\n openWorldHint: true,\n // See contract-fixes/03 \u2014 non-standard precondition hint.\n ...({ experimental: { requires: ['start-research'] } } as Record<string, unknown>),\n },\n _meta: { requires: ['start-research'] },\n },\n async ({ urls }, ctx) => {\n if (!getCapabilities().reddit) {\n return toToolResponse(toolFailure(getMissingEnvMessage('reddit')));\n }\n\n const guard = await requireBootstrap(ctx);\n if (guard) {\n return guard;\n }\n\n const env = parseEnv();\n const reporter = createToolReporter(ctx, 'get-reddit-post');\n const result = await handleGetRedditPosts(\n urls,\n env.REDDIT_CLIENT_ID!,\n env.REDDIT_CLIENT_SECRET!,\n reporter,\n );\n\n await reporter.progress(100, 100, result.isError ? 'Reddit fetch failed' : 'Reddit fetch complete');\n return toToolResponse(result);\n },\n );\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { registerDeepResearchPrompt } from "../prompts/deep-research.js";
|
|
2
|
+
import { registerRedditSentimentPrompt } from "../prompts/reddit-sentiment.js";
|
|
3
|
+
import { registerGetRedditPostTool } from "./reddit.js";
|
|
4
|
+
import { registerScrapeLinksTool } from "./scrape.js";
|
|
5
|
+
import { registerWebSearchTool } from "./search.js";
|
|
6
|
+
import { registerStartResearchTool } from "./start-research.js";
|
|
7
|
+
function registerAllTools(server) {
|
|
8
|
+
registerStartResearchTool(server);
|
|
9
|
+
registerWebSearchTool(server);
|
|
10
|
+
registerGetRedditPostTool(server);
|
|
11
|
+
registerScrapeLinksTool(server);
|
|
12
|
+
registerDeepResearchPrompt(server);
|
|
13
|
+
registerRedditSentimentPrompt(server);
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
registerAllTools
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/tools/registry.ts"],
|
|
4
|
+
"sourcesContent": ["import type { MCPServer } from 'mcp-use/server';\n\nimport { registerDeepResearchPrompt } from '../prompts/deep-research.js';\nimport { registerRedditSentimentPrompt } from '../prompts/reddit-sentiment.js';\nimport { registerGetRedditPostTool } from './reddit.js';\nimport { registerScrapeLinksTool } from './scrape.js';\nimport { registerWebSearchTool } from './search.js';\nimport { registerStartResearchTool } from './start-research.js';\n\nexport function registerAllTools(server: MCPServer): void {\n // Tool count is intentionally 4 \u2014 search-reddit was deleted in favor of\n // web-search with `scope: \"reddit\"`. See:\n // docs/code-review/context/02-current-tool-surface.md\n // mcp-revisions/tool-surface/01-delete-search-reddit.md\n // mcp-revisions/tool-surface/02-extend-web-search-with-reddit-scope.md\n registerStartResearchTool(server);\n registerWebSearchTool(server);\n registerGetRedditPostTool(server);\n registerScrapeLinksTool(server);\n registerDeepResearchPrompt(server);\n registerRedditSentimentPrompt(server);\n}\n"],
|
|
5
|
+
"mappings": "AAEA,SAAS,kCAAkC;AAC3C,SAAS,qCAAqC;AAC9C,SAAS,iCAAiC;AAC1C,SAAS,+BAA+B;AACxC,SAAS,6BAA6B;AACtC,SAAS,iCAAiC;AAEnC,SAAS,iBAAiB,QAAyB;AAMxD,4BAA0B,MAAM;AAChC,wBAAsB,MAAM;AAC5B,4BAA0B,MAAM;AAChC,0BAAwB,MAAM;AAC9B,6BAA2B,MAAM;AACjC,gCAA8B,MAAM;AACtC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|