reddit-mcp-server 1.6.1 → 1.6.3

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/dist/bin.js CHANGED
@@ -3,12 +3,12 @@
3
3
  process.env.TRANSPORT_TYPE ??= "stdio";
4
4
  const args = process.argv.slice(2);
5
5
  if (args.includes("--version") || args.includes("-v")) {
6
- console.log("1.6.1");
6
+ console.log("1.6.3");
7
7
  process.exit(0);
8
8
  }
9
9
  if (args.includes("--help") || args.includes("-h")) {
10
10
  console.log(`
11
- Reddit MCP Server v1.6.1
11
+ Reddit MCP Server v1.6.3
12
12
 
13
13
  Usage: reddit-mcp-server [options]
14
14
 
@@ -16,6 +16,11 @@ Options:
16
16
  -v, --version Show version number
17
17
  -h, --help Show help
18
18
 
19
+ This is an MCP server, not an interactive CLI. In stdio mode (the default here) it
20
+ expects an MCP client such as Claude Desktop or Claude Code on stdin/stdout.
21
+ Test interactively: npx @modelcontextprotocol/inspector npx reddit-mcp-server
22
+ Run as HTTP: TRANSPORT_TYPE=httpStream npx reddit-mcp-server
23
+
19
24
  Environment Variables:
20
25
  REDDIT_CLIENT_ID Reddit API client ID (optional, for OAuth)
21
26
  REDDIT_CLIENT_SECRET Reddit API client secret (optional, for OAuth)
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.js","names":[],"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\n\ndeclare const __VERSION__: string\n\n// Force stdio mode for CLI/npx usage (unless explicitly overridden)\nprocess.env.TRANSPORT_TYPE ??= \"stdio\"\n\n// Handle command line arguments BEFORE any other imports\nconst args = process.argv.slice(2)\n\nif (args.includes(\"--version\") || args.includes(\"-v\")) {\n console.log(__VERSION__)\n process.exit(0)\n}\n\nif (args.includes(\"--help\") || args.includes(\"-h\")) {\n console.log(`\nReddit MCP Server v${__VERSION__}\n\nUsage: reddit-mcp-server [options]\n\nOptions:\n -v, --version Show version number\n -h, --help Show help\n\nEnvironment Variables:\n REDDIT_CLIENT_ID Reddit API client ID (optional, for OAuth)\n REDDIT_CLIENT_SECRET Reddit API client secret (optional, for OAuth)\n REDDIT_USERNAME Reddit username (optional, for write operations)\n REDDIT_PASSWORD Reddit password (optional, for write operations)\n REDDIT_USER_AGENT Custom user agent (optional)\n REDDIT_AUTH_MODE Authentication mode: auto, authenticated, anonymous (default: auto)\n REDDIT_SAFE_MODE Spam protection: off, standard, strict (default: standard)\n REDDIT_BOT_DISCLOSURE Bot disclosure footer: auto, off (default: off)\n REDDIT_BOT_FOOTER Custom bot footer text (optional, used with REDDIT_BOT_DISCLOSURE=auto)\n\nFor more information, visit: https://github.com/jordanburke/reddit-mcp-server\n`)\n process.exit(0)\n}\n\n// Import and start server if not showing version/help\nasync function main() {\n await import(\"./index.js\")\n}\n\nvoid main().catch(console.error)\n"],"mappings":";;AAKA,QAAQ,IAAI,mBAAmB;AAG/B,MAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AAEjC,IAAI,KAAK,SAAS,WAAW,KAAK,KAAK,SAAS,IAAI,GAAG;CACrD,QAAQ,IAAA,OAAe;CACvB,QAAQ,KAAK,CAAC;AAChB;AAEA,IAAI,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,IAAI,GAAG;CAClD,QAAQ,IAAI;;;;;;;;;;;;;;;;;;;;;CAqBb;CACC,QAAQ,KAAK,CAAC;AAChB;AAGA,eAAe,OAAO;CACpB,MAAM,OAAO;AACf;AAEK,KAAK,CAAC,CAAC,MAAM,QAAQ,KAAK"}
1
+ {"version":3,"file":"bin.js","names":[],"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\n\ndeclare const __VERSION__: string\n\n// Force stdio mode for CLI/npx usage (unless explicitly overridden)\nprocess.env.TRANSPORT_TYPE ??= \"stdio\"\n\n// Handle command line arguments BEFORE any other imports\nconst args = process.argv.slice(2)\n\nif (args.includes(\"--version\") || args.includes(\"-v\")) {\n console.log(__VERSION__)\n process.exit(0)\n}\n\nif (args.includes(\"--help\") || args.includes(\"-h\")) {\n console.log(`\nReddit MCP Server v${__VERSION__}\n\nUsage: reddit-mcp-server [options]\n\nOptions:\n -v, --version Show version number\n -h, --help Show help\n\nThis is an MCP server, not an interactive CLI. In stdio mode (the default here) it\nexpects an MCP client such as Claude Desktop or Claude Code on stdin/stdout.\n Test interactively: npx @modelcontextprotocol/inspector npx reddit-mcp-server\n Run as HTTP: TRANSPORT_TYPE=httpStream npx reddit-mcp-server\n\nEnvironment Variables:\n REDDIT_CLIENT_ID Reddit API client ID (optional, for OAuth)\n REDDIT_CLIENT_SECRET Reddit API client secret (optional, for OAuth)\n REDDIT_USERNAME Reddit username (optional, for write operations)\n REDDIT_PASSWORD Reddit password (optional, for write operations)\n REDDIT_USER_AGENT Custom user agent (optional)\n REDDIT_AUTH_MODE Authentication mode: auto, authenticated, anonymous (default: auto)\n REDDIT_SAFE_MODE Spam protection: off, standard, strict (default: standard)\n REDDIT_BOT_DISCLOSURE Bot disclosure footer: auto, off (default: off)\n REDDIT_BOT_FOOTER Custom bot footer text (optional, used with REDDIT_BOT_DISCLOSURE=auto)\n\nFor more information, visit: https://github.com/jordanburke/reddit-mcp-server\n`)\n process.exit(0)\n}\n\n// Import and start server if not showing version/help\nasync function main() {\n await import(\"./index.js\")\n}\n\nvoid main().catch(console.error)\n"],"mappings":";;AAKA,QAAQ,IAAI,mBAAmB;AAG/B,MAAM,OAAO,QAAQ,KAAK,MAAM,CAAC;AAEjC,IAAI,KAAK,SAAS,WAAW,KAAK,KAAK,SAAS,IAAI,GAAG;CACrD,QAAQ,IAAA,OAAe;CACvB,QAAQ,KAAK,CAAC;AAChB;AAEA,IAAI,KAAK,SAAS,QAAQ,KAAK,KAAK,SAAS,IAAI,GAAG;CAClD,QAAQ,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;CA0Bb;CACC,QAAQ,KAAK,CAAC;AAChB;AAGA,eAAe,OAAO;CACpB,MAAM,OAAO;AACf;AAEK,KAAK,CAAC,CAAC,MAAM,QAAQ,KAAK"}
package/dist/index.js CHANGED
@@ -1161,6 +1161,14 @@ function getSubredditEngagementTips(subreddit) {
1161
1161
  const allTips = [...sizeTips, ...activityTips];
1162
1162
  return allTips.length > 0 ? allTips.join("\n - ") : "Regular engagement recommended to maintain community presence";
1163
1163
  }
1164
+ function analyzeCommentImpact(score, isEdited, isOp) {
1165
+ const insights = [
1166
+ ...score > 100 ? ["Highly upvoted comment with significant community agreement"] : score < 0 ? ["Controversial or contested viewpoint"] : [],
1167
+ ...isEdited ? ["Refined for clarity or accuracy"] : [],
1168
+ ...isOp ? ["Author's perspective adds context to original post"] : []
1169
+ ];
1170
+ return insights.length > 0 ? insights.join("\n - ") : "Standard engagement with discussion";
1171
+ }
1164
1172
  function formatUserInfo(user) {
1165
1173
  const accountAgeDays = (Date.now() / 1e3 - user.createdUtc) / 86400;
1166
1174
  const karmaRatio = user.commentKarma / (user.linkKarma === 0 ? 1 : user.linkKarma);
@@ -1183,9 +1191,18 @@ function formatUserInfo(user) {
1183
1191
  recommendations: getUserRecommendations(karmaRatio, user.isMod, accountAgeDays)
1184
1192
  };
1185
1193
  }
1194
+ const POST_CONTENT_MAX_LENGTH = 1e4;
1195
+ const COMMENT_CONTENT_MAX_LENGTH = 5e3;
1196
+ function truncateText(text, maxLength) {
1197
+ return text.length > maxLength ? `${text.substring(0, maxLength - 3)}...` : text;
1198
+ }
1199
+ function postContent(post) {
1200
+ const body = truncateText(post.selftext ?? "", POST_CONTENT_MAX_LENGTH);
1201
+ if (post.isSelf) return body;
1202
+ return [body, post.url ?? ""].filter((part) => part.length > 0).join("\n\n");
1203
+ }
1186
1204
  function formatPostInfo(post) {
1187
1205
  const contentType = post.isSelf ? "Text Post" : "Link Post";
1188
- const content = post.isSelf ? post.selftext ?? "" : post.url ?? "";
1189
1206
  const flags = [
1190
1207
  ...post.over18 ? ["NSFW"] : [],
1191
1208
  ...post.spoiler === true ? ["Spoiler"] : [],
@@ -1194,7 +1211,7 @@ function formatPostInfo(post) {
1194
1211
  return {
1195
1212
  title: post.title,
1196
1213
  type: contentType,
1197
- content: content.length > 300 ? `${content.substring(0, 297)}...` : content,
1214
+ content: postContent(post),
1198
1215
  author: post.author,
1199
1216
  subreddit: post.subreddit,
1200
1217
  stats: {
@@ -1241,10 +1258,31 @@ function formatSubredditInfo(subreddit) {
1241
1258
  engagementTips: getSubredditEngagementTips(subreddit)
1242
1259
  };
1243
1260
  }
1261
+ function formatCommentInfo(comment, maxLength = COMMENT_CONTENT_MAX_LENGTH) {
1262
+ const flags = [...comment.edited ? ["Edited"] : [], ...comment.isSubmitter ? ["OP"] : []];
1263
+ return {
1264
+ author: comment.author,
1265
+ content: truncateText(comment.body, maxLength),
1266
+ stats: {
1267
+ score: comment.score,
1268
+ controversiality: comment.controversiality
1269
+ },
1270
+ context: {
1271
+ subreddit: comment.subreddit,
1272
+ thread: comment.submissionTitle
1273
+ },
1274
+ metadata: {
1275
+ posted: formatTimestamp(comment.createdUtc),
1276
+ flags: flags.length > 0 ? flags : ["None"]
1277
+ },
1278
+ link: `https://reddit.com${comment.permalink}`,
1279
+ commentAnalysis: analyzeCommentImpact(comment.score, comment.edited, comment.isSubmitter)
1280
+ };
1281
+ }
1244
1282
  //#endregion
1245
1283
  //#region src/index.ts
1246
1284
  dotenv.config({ quiet: true });
1247
- const VERSION = "1.6.1";
1285
+ const VERSION = "1.6.3";
1248
1286
  function validateUserAgent(userAgent, username) {
1249
1287
  if (!/^[\w-]+:[\w-]+:[\d.]+ \(by \/u\/\w+\)$/.test(userAgent)) {
1250
1288
  console.error("[Warning] User-Agent does not follow Reddit's recommended format");
@@ -1313,8 +1351,8 @@ function nextPageHint(after) {
1313
1351
  }
1314
1352
  function formatUserContent(heading, content) {
1315
1353
  return `# ${heading}\n\n${content.posts.length === 0 ? "" : `## Posts (${content.posts.length})\n${content.posts.map((post, index) => `${index + 1}. ${post.title} — r/${post.subreddit}, score ${post.score.toLocaleString()} — https://reddit.com${post.permalink}`).join("\n")}\n\n`}${content.comments.length === 0 ? "" : `## Comments (${content.comments.length})\n${content.comments.map((comment, index) => {
1316
- const body = comment.body.length > 200 ? `${comment.body.substring(0, 200)}...` : comment.body;
1317
- return `${index + 1}. in r/${comment.subreddit}: ${body} — https://reddit.com${comment.permalink}`;
1354
+ const formatted = formatCommentInfo(comment, 200);
1355
+ return `${index + 1}. in r/${comment.subreddit}: ${formatted.content} — ${formatted.link}`;
1318
1356
  }).join("\n")}\n\n`}${content.posts.length === 0 && content.comments.length === 0 ? "No items found.\n\n" : ""}`.trimEnd() + nextPageHint(content.after);
1319
1357
  }
1320
1358
  async function setupRedditClient() {
@@ -1676,16 +1714,16 @@ server.addTool({
1676
1714
  const comments = page.items;
1677
1715
  if (comments.length === 0) return `No comments found for u/${args.username} with the specified filters.`;
1678
1716
  const commentSummaries = comments.map((comment, index) => {
1679
- const truncatedBody = comment.body.length > 300 ? `${comment.body.substring(0, 300)}...` : comment.body;
1717
+ const formatted = formatCommentInfo(comment, 300);
1680
1718
  const flags = [...comment.edited ? ["*(edited)*"] : [], ...comment.isSubmitter ? ["**OP**"] : []];
1681
1719
  return `### ${index + 1}. Comment ${flags.join(" ")}
1682
1720
  In r/${comment.subreddit} on "${comment.submissionTitle}"
1683
1721
 
1684
- > ${truncatedBody}
1722
+ > ${formatted.content}
1685
1723
 
1686
1724
  - Score: ${comment.score.toLocaleString()}
1687
1725
  - Posted: ${(/* @__PURE__ */ new Date(comment.createdUtc * 1e3)).toLocaleString()}
1688
- - Link: https://reddit.com${comment.permalink}`;
1726
+ - Link: ${formatted.link}`;
1689
1727
  }).join("\n\n");
1690
1728
  return `# Comments by u/${args.username} (${args.sort} - ${args.time_filter})
1691
1729
 
@@ -2287,13 +2325,13 @@ server.addTool({
2287
2325
  }, (comments) => {
2288
2326
  if (comments.length === 0) return "No additional comments were returned for those ids.";
2289
2327
  const commentList = comments.map((comment, index) => {
2290
- const truncated = comment.body.length > 300 ? `${comment.body.substring(0, 300)}...` : comment.body;
2328
+ const formatted = formatCommentInfo(comment, 300);
2291
2329
  const flags = [...comment.edited ? ["*(edited)*"] : [], ...comment.isSubmitter ? ["**OP**"] : []];
2292
2330
  return `### ${index + 1}. u/${comment.author} ${flags.join(" ")}
2293
- > ${truncated}
2331
+ > ${formatted.content}
2294
2332
 
2295
2333
  - Score: ${comment.score.toLocaleString()}
2296
- - Link: https://reddit.com${comment.permalink}`;
2334
+ - Link: ${formatted.link}`;
2297
2335
  }).join("\n\n");
2298
2336
  return `# Expanded Comments (${comments.length})
2299
2337
 
@@ -2320,6 +2358,11 @@ async function main() {
2320
2358
  console.error(`[Setup] SSE endpoint available at http://${host}:${port}/sse`);
2321
2359
  } else {
2322
2360
  console.error("[Setup] Starting in stdio mode");
2361
+ if (process.stdin.isTTY) {
2362
+ console.error("[Setup] ⚠ stdin is a terminal. This server speaks MCP JSON-RPC over stdio and expects an MCP client (Claude Desktop, Claude Code, MCP Inspector) on the other end — typed input will cause JSON parse errors.");
2363
+ console.error("[Setup] Test interactively: npx @modelcontextprotocol/inspector npx reddit-mcp-server");
2364
+ console.error("[Setup] Or run as HTTP: TRANSPORT_TYPE=httpStream npx reddit-mcp-server");
2365
+ }
2323
2366
  await server.start({ transportType: "stdio" });
2324
2367
  }
2325
2368
  }