<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Harsh Maur</title>
    <description>The latest articles on DEV Community by Harsh Maur (@harshmaur).</description>
    <link>https://dev.to/harshmaur</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F988089%2F3148a155-ea7d-48ec-abe0-4da70e9fa33f.jpeg</url>
      <title>DEV Community: Harsh Maur</title>
      <link>https://dev.to/harshmaur</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/harshmaur"/>
    <language>en</language>
    <item>
      <title>How to build a Reddit lead generation monitor with Apify MCP connectors</title>
      <dc:creator>Harsh Maur</dc:creator>
      <pubDate>Tue, 01 Sep 2026 06:09:32 +0000</pubDate>
      <link>https://dev.to/apify/how-to-build-a-reddit-lead-generation-monitor-with-apify-mcp-connectors-12j</link>
      <guid>https://dev.to/apify/how-to-build-a-reddit-lead-generation-monitor-with-apify-mcp-connectors-12j</guid>
      <description>&lt;p&gt;People do not always announce buying intent on a landing page. They ask for recommendations in a subreddit, complain about a workflow, or look for an alternative to a tool they already use.&lt;/p&gt;

&lt;p&gt;I saw that pattern while building and testing my &lt;a href="https://apify.com/harshmaur/reddit-scraper" rel="noopener noreferrer"&gt;Reddit Scraper&lt;/a&gt; Actor. I kept repeating the same keywords and communities across runs. These were no longer one-off research jobs; they were monitors. The missing piece was delivery. A useful post could sit in an Apify dataset until someone remembered to check it.&lt;/p&gt;

&lt;p&gt;I added optional Model Context Protocol (MCP) delivery so the Actor can send completed results to another service. This Reddit lead generation workflow uses Slack's official MCP server. For this guide, I configured the server, discovered its live tool schema, ran a one-result test, and verified the message in a private Slack channel. The first attempt failed for a non-obvious Slack setting, which is included below because it is exactly the kind of integration detail that polished examples tend to hide.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we are building
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Apify schedule -&amp;gt; Reddit Scraper -&amp;gt; structured Reddit posts and comments
  -&amp;gt; Apify MCP connector -&amp;gt; Slack MCP server -&amp;gt; private lead-alert channel -&amp;gt; human review
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Actor searches recent Reddit discussions, stores the complete results in its dataset, and sends selected posts through an Apify MCP connector. A Slack alert can contain the post title, subreddit, score, comment count, link, and selected comments.&lt;/p&gt;

&lt;p&gt;A person still decides whether to respond. This workflow surfaces relevant public conversations; it does not automate unsolicited Reddit replies.&lt;/p&gt;

&lt;p&gt;Two Apify features have similar names but opposite directions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;An Apify MCP connector lets an Actor call an external MCP server.&lt;/strong&gt; That is what sends the alerts in this tutorial.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The Apify MCP server lets an external AI client call Apify Actors and tools.&lt;/strong&gt; It is useful for Claude, ChatGPT, or Cursor, but it is not the delivery path here.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;You will need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an Apify account;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://apify.com/harshmaur/reddit-scraper" rel="noopener noreferrer"&gt;Reddit Scraper&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;permission to create a Slack app and a private destination channel;&lt;/li&gt;
&lt;li&gt;permission to create Apify tasks and schedules; and&lt;/li&gt;
&lt;li&gt;a small list of brand, competitor, and problem-related searches.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Slack exposes its official Streamable HTTP MCP endpoint at &lt;code&gt;https://mcp.slack.com/mcp&lt;/code&gt;. It requires a registered internal or Marketplace Slack app with a confidential OAuth client. Slack does not support Dynamic Client Registration for this endpoint, so the one-click OAuth option is not enough; use Apify's &lt;strong&gt;Own OAuth client&lt;/strong&gt; flow. Some Console versions label the same option &lt;strong&gt;Your own OAuth client&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Start with high-intent Reddit searches
&lt;/h2&gt;

&lt;p&gt;A broad category keyword creates noise. A phrase describing a decision or painful workflow creates better alerts.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Broad query&lt;/th&gt;
&lt;th&gt;Higher-intent query&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;scheduling software&lt;/td&gt;
&lt;td&gt;alternative to calendly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;appointment tools&lt;/td&gt;
&lt;td&gt;keep missing client calls&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;booking app&lt;/td&gt;
&lt;td&gt;double booked&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;CRM&lt;/td&gt;
&lt;td&gt;looking for a simple CRM&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A useful starter set contains your brand and common misspellings, two or three competitor names, a few problem phrases, and buying-intent language such as looking for, alternative to, or would pay for.&lt;/p&gt;

&lt;p&gt;Reddit Scraper has four controls that matter for monitoring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;searchSort: "new"&lt;/code&gt; orders results chronologically;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;searchTime: "day"&lt;/code&gt; limits the search window;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;withinCommunity&lt;/code&gt; limits a run to one subreddit; and&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;maxPostsCount&lt;/code&gt; caps the posts collected.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sorting by new does not remove old results, so use a time window as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foqoc9ha11karbjteukf1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Foqoc9ha11karbjteukf1.png" alt="Reddit Scraper configured to search for a recent high-intent phrase" width="800" height="815"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1: Search for a problem or buying-intent phrase, sort by New, and use a recent time window.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Start with 10 to 20 posts. It is easier to improve five weak alerts than to clean up a Slack channel after sending hundreds.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Configure Slack for Reddit lead generation alerts
&lt;/h2&gt;

&lt;p&gt;Create the private destination first: in Slack, select &lt;strong&gt;Add channels -&amp;gt; Create a new channel&lt;/strong&gt;, give it a clear test name, and make it private. The Slack user who authorizes the app must be a member of that channel and able to post there.&lt;/p&gt;

&lt;p&gt;Next open &lt;a href="https://api.slack.com/apps" rel="noopener noreferrer"&gt;Slack app management&lt;/a&gt;, select &lt;strong&gt;Create New App -&amp;gt; From scratch&lt;/strong&gt;, name the app, and choose the receiving workspace. In the new app, open &lt;strong&gt;OAuth &amp;amp; Permissions&lt;/strong&gt; and add this redirect URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://console.apify.com/oauth/mcp-proxy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Add &lt;code&gt;chat:write&lt;/code&gt; as a &lt;strong&gt;User Token Scope&lt;/strong&gt;. Then open the app's &lt;strong&gt;Agents&lt;/strong&gt; page and enable &lt;strong&gt;Slack Model Context Protocol (MCP) Server&lt;/strong&gt;. This toggle is separate from the app's OAuth scopes and is easy to miss. Open &lt;strong&gt;Basic Information -&amp;gt; App Credentials&lt;/strong&gt; to find the client ID and client secret required by Apify.&lt;/p&gt;

&lt;p&gt;In Apify Console, open &lt;strong&gt;Settings -&amp;gt; API &amp;amp; Integrations -&amp;gt; MCP connectors&lt;/strong&gt;, select &lt;strong&gt;Add connector&lt;/strong&gt;, and enter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;Name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Slack lead alerts&lt;/span&gt;
&lt;span class="na"&gt;Server URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://mcp.slack.com/mcp&lt;/span&gt;
&lt;span class="na"&gt;Authentication&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Own OAuth client (or Your own OAuth client)&lt;/span&gt;
&lt;span class="na"&gt;Authorization URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://slack.com/oauth/v2_user/authorize&lt;/span&gt;
&lt;span class="na"&gt;Token URL&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://slack.com/api/oauth.v2.user.access&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Supply the Slack app's client ID and client secret in Apify's secure fields. They should never appear in Actor input, datasets, source code, screenshots, or logs.&lt;/p&gt;

&lt;p&gt;Review the Slack consent page instead of approving it mechanically. The workflow needs &lt;code&gt;chat:write&lt;/code&gt;, not workspace-wide search, file, user, and channel-management permissions. In my August 2026 test, Apify generated the authorization popup with Slack's much broader advertised scope set. This was observed Apify behavior, not a Slack-supported scope picker. I completed the least-privilege flow as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In the same OAuth popup, focus the address bar without closing or duplicating the window.&lt;/li&gt;
&lt;li&gt;Change only the &lt;code&gt;scope&lt;/code&gt; query parameter to &lt;code&gt;chat:write&lt;/code&gt; and remove the empty &lt;code&gt;user_scope&lt;/code&gt; parameter.&lt;/li&gt;
&lt;li&gt;Preserve &lt;code&gt;client_id&lt;/code&gt;, &lt;code&gt;redirect_uri&lt;/code&gt;, &lt;code&gt;state&lt;/code&gt;, &lt;code&gt;code_challenge&lt;/code&gt;, &lt;code&gt;code_challenge_method&lt;/code&gt;, and &lt;code&gt;response_type&lt;/code&gt; exactly as Apify generated them.&lt;/li&gt;
&lt;li&gt;Reload that edited URL in the same popup and verify that the consent screen requests only permission to send messages as the authorizing user.&lt;/li&gt;
&lt;li&gt;Approve the request and return to Apify, where the connector should show the discovered tools.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;That URL edit is a workaround for the current connector flow. Do not alter, share, or reuse the OAuth state or Proof Key for Code Exchange (PKCE) values. If your administrator does not approve this workaround, stop rather than granting the broader scopes and use an administrator-managed least-privilege integration instead. Re-check Apify's connector UI before following this step because native scope selection may replace the workaround.&lt;/p&gt;

&lt;p&gt;After successful authorization, the live server exposed three tools with this scope:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;slack_send_message&lt;/code&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;slack_schedule_message&lt;/code&gt;; and&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;slack_send_message_draft&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;code&gt;slack_send_message&lt;/code&gt; input schema required exactly two values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"channel_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Optional fields included &lt;code&gt;thread_ts&lt;/code&gt;, &lt;code&gt;reply_broadcast&lt;/code&gt;, &lt;code&gt;draft_id&lt;/code&gt;, and &lt;code&gt;unfurl_app_links&lt;/code&gt;. I disabled &lt;strong&gt;Allow all&lt;/strong&gt; in the connector and permitted only &lt;code&gt;slack_send_message&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsp2qavabd1omyntq3ir1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fsp2qavabd1omyntq3ir1.png" alt="Slack connector restricted to the slack_send_message tool" width="800" height="920"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 2: OAuth scope and connector tool allowlists are separate controls. This connector can call only the immediate-send operation.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Apify stores the Slack credential server-side. The Actor receives a connector ID and authenticates to Apify's MCP proxy with its run token; it never receives the Slack OAuth token.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Configure Reddit Scraper delivery
&lt;/h2&gt;

&lt;p&gt;Open Reddit Scraper and expand &lt;strong&gt;Send to your apps (MCP integration, optional)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Copy the Slack channel ID before filling &lt;code&gt;mcpTarget&lt;/code&gt;: open the destination channel, select its name to open channel details, and copy the &lt;strong&gt;Channel ID&lt;/strong&gt; shown on the &lt;strong&gt;About&lt;/strong&gt; tab. You can also copy the channel link and use the segment beginning with C. Do not use the human-readable #channel-name in &lt;code&gt;mcpTarget&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feoqoxohtetrgfe4yhxb9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Feoqoxohtetrgfe4yhxb9.png" alt="Reddit Scraper configured for recent results and an eligible Slack MCP connector" width="800" height="661"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 3: The final configuration uses New, Last day, the authorized Slack connector, and one message per post.&lt;/em&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;What it controls&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mcpConnector&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Managed connector selected in Apify Console&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mcpMode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;One message per post (&lt;code&gt;perPost&lt;/code&gt;) or one digest (&lt;code&gt;summary&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mcpTarget&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Destination expected by the tool; for Slack, a channel ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mcpComments&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Ignore comments, bundle them, or send separate follow-ups&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mcpCommentsPerPost&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Highest-scoring comments included per post&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mcpMessage&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Deterministic &lt;code&gt;{{field}}&lt;/code&gt; template&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mcpTool&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Exact tool-name override&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mcpArguments&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Extra rendered arguments merged over inferred values&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;mcpMaxItems&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Maximum posts dispatched in &lt;code&gt;perPost&lt;/code&gt; mode&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For Slack lead alerts, use &lt;code&gt;perPost&lt;/code&gt;. Each opportunity becomes a message that can be discussed or assigned independently.&lt;/p&gt;

&lt;p&gt;A useful template is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight handlebars"&gt;&lt;code&gt;**&lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;title&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;**
&lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;communityName&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt; | score &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;score&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt; | &lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;commentsCount&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt; comments
&lt;span class="k"&gt;{{&lt;/span&gt;&lt;span class="nv"&gt;postUrl&lt;/span&gt;&lt;span class="k"&gt;}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Templates are deterministic substitutions, not AI prompts. Missing values render as empty strings, and nested dataset paths are supported.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fme6ar8lc42wxrbq5jk9g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fme6ar8lc42wxrbq5jk9g.png" alt="MCP message, comment, tool override, and dispatch cap settings" width="800" height="641"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 4: Control formatting, comment delivery, the exact MCP tool, and the dispatch cap.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here is the schema-validated smoke-test input used for the final screenshots. Replace the two placeholders with values from your account:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"searchTerms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"AI"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"searchPosts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"searchComments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"searchCommunities"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"searchSort"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"new"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"searchTime"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"day"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"crawlCommentsPerPost"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"maxPostsCount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpConnector"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"REPLACE_WITH_APIFY_CONNECTOR_ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpMode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"perPost"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpTarget"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"REPLACE_WITH_SLACK_CHANNEL_ID"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpComments"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ignore"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpTool"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"slack_send_message"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpMessage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"**{{title}}**&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;{{communityName}} | score {{score}} | {{commentsCount}} comments&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;{{postUrl}}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpMaxItems"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The broad, harmless AI query makes a one-result transport test more reliable than a narrow lead phrase. If it returns no post for day, widen &lt;code&gt;searchTime&lt;/code&gt; to &lt;code&gt;week&lt;/code&gt; and rerun before changing any connector settings. Once delivery works, replace AI with the high-intent phrases from step 1, optionally set &lt;code&gt;withinCommunity&lt;/code&gt;, and raise both caps gradually.&lt;/p&gt;

&lt;p&gt;The live Slack schema uses &lt;code&gt;channel_id&lt;/code&gt; and &lt;code&gt;message&lt;/code&gt;. Reddit Scraper maps &lt;code&gt;mcpTarget&lt;/code&gt; to the first destination-like string field and maps the rendered template to the first message-like string field, so no provider-specific request body is required.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Test the Reddit lead generation workflow
&lt;/h2&gt;

&lt;p&gt;Run the Actor manually before creating a task or schedule. Use &lt;code&gt;maxPostsCount: 1&lt;/code&gt; and &lt;code&gt;mcpMaxItems: 1&lt;/code&gt; for the first end-to-end test.&lt;/p&gt;

&lt;p&gt;My first run scraped one post but recorded &lt;code&gt;mcp_failed&lt;/code&gt;. The proxy surfaced an upstream HTTP 400 as a Server-Sent Events (SSE) connection error. That message initially suggested a transport incompatibility, because Slack explicitly supports Streamable HTTP and not SSE.&lt;/p&gt;

&lt;p&gt;A direct authenticated initialize request to Slack's MCP endpoint returned the actual cause: the Slack app was not enabled for Slack MCP server access. After I enabled &lt;strong&gt;Agents -&amp;gt; Slack Model Context Protocol (MCP) Server&lt;/strong&gt;, I recreated and reauthorized the Apify connector so it could rediscover tools. No Actor transport or argument-mapping change was needed.&lt;/p&gt;

&lt;p&gt;The second run discovered the three Slack tools, called &lt;code&gt;slack_send_message&lt;/code&gt;, and finished successfully. After restricting the connector to that one allowed tool, I repeated the one-item run; it dispatched one call and produced a second message in the private channel.&lt;/p&gt;

&lt;p&gt;That success exposed one small code issue. The existing default used Slack's legacy single-asterisk formatting, but the official MCP tool accepts standard Markdown, so the title rendered in italics. I changed the Actor's default and schema prefill from &lt;code&gt;*{{title}}*&lt;/code&gt; to &lt;code&gt;**{{title}}**&lt;/code&gt;, reran the test, and confirmed that both the alert heading and post title rendered bold.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F51wqplzqiz2rd0ux45x8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F51wqplzqiz2rd0ux45x8.png" alt="Successful Apify run log showing one Slack MCP dispatch" width="800" height="109"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 5: The test extracted one post, dispatched one MCP call through slack_send_message, and preserved a successful crawl result.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The private destination channel then contained the rendered Reddit alert and source link:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhqg28pe1960kpg3s5rq8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fhqg28pe1960kpg3s5rq8.png" alt="Reddit lead alert received in a private Slack channel" width="800" height="46"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 6: The external result confirms that connector authorization, schema mapping, and the Slack write all worked.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Check a manual run in this order:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verify the expected Reddit rows in the dataset.&lt;/li&gt;
&lt;li&gt;Confirm deliverable rows have &lt;code&gt;dataType: "post"&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Inspect the log for the selected MCP tool and dispatched-call count.&lt;/li&gt;
&lt;li&gt;Open Slack and verify the channel, formatting, and links.&lt;/li&gt;
&lt;li&gt;Compare the number of delivered posts with Slack messages.&lt;/li&gt;
&lt;li&gt;Tighten searches before raising the caps.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For diagnostics, the implementation supports &lt;code&gt;MCP_DEBUG_LIST_TOOLS&lt;/code&gt;. It logs tool names and schemas and exits without sending messages. An invalid explicit &lt;code&gt;mcpTool&lt;/code&gt; does not fall back to automatic selection.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Turn the working input into a monitor
&lt;/h2&gt;

&lt;p&gt;Once the manual run is clean:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Return to the Actor's &lt;strong&gt;Input&lt;/strong&gt; tab, open &lt;strong&gt;Actions&lt;/strong&gt;, and choose &lt;strong&gt;Save as a new task&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Name the task, save it, and open &lt;strong&gt;Schedules -&amp;gt; Create schedule&lt;/strong&gt; in Apify Console.&lt;/li&gt;
&lt;li&gt;Choose the saved task as the action, set an hourly or two-hour interval, and save the schedule.&lt;/li&gt;
&lt;li&gt;Use &lt;strong&gt;Run now&lt;/strong&gt; once and confirm the new run, dataset row, dispatch log, and Slack message before leaving the schedule enabled.&lt;/li&gt;
&lt;li&gt;Review alert quality for several days and remove noisy searches before increasing volume.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Reddit Scraper does not currently keep a cross-run set of posts delivered through MCP. Overlapping search windows can therefore repeat a post. Reduce duplicates with a shorter &lt;code&gt;searchTime&lt;/code&gt;, fewer overlapping queries, a slower schedule, or downstream deduplication on the Reddit post id.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the Actor maps Reddit data to Slack's MCP schema
&lt;/h2&gt;

&lt;p&gt;In the Actor source, the Reddit-specific code builds an ordered message list after the crawl:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Excerpt: products/reddit/src/utils/mcp.ts&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;allItems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nx"&gt;dataType&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;post&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;maxItems&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mcpMaxItems&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="nx"&gt;DEFAULT_MAX_ITEMS&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;maxItems&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;renderTemplate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;template&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;commentMode&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;bundle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;text&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="s2"&gt;`\n\n&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;renderCommentDigest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;top&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;postFields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;post&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="na"&gt;item&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;post&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The shared dispatcher then connects to Apify's managed proxy, discovers tools, reads the chosen tool's schema, and sends serially:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Excerpt: packages/core/src/mcp.ts&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tools&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;listTools&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toolName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;selectWriteTool&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tools&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;McpTool&lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mcpTool&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toolSchema&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;tools&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;McpTool&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;tool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;toolName&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nx"&gt;inputSchema&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mcpTarget&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;overrideArgs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mcpArguments&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;callTool&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;toolName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;arguments&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;buildToolArgs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toolSchema&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;...(&lt;/span&gt;&lt;span class="nf"&gt;interpolateDeep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;overrideArgs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;Record&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;unknown&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the observed Slack tool, schema inspection maps the alert to &lt;code&gt;message&lt;/code&gt; and the destination to &lt;code&gt;channel_id&lt;/code&gt;. The same dispatcher can adapt to other MCP servers whose schemas use fields such as &lt;code&gt;text&lt;/code&gt;, &lt;code&gt;content&lt;/code&gt;, &lt;code&gt;rows&lt;/code&gt;, or &lt;code&gt;properties&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reddit lead generation failure modes
&lt;/h2&gt;

&lt;p&gt;Scraping finishes before MCP delivery. A connector failure normally leaves the collected dataset intact, but partial delivery is possible.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Failure&lt;/th&gt;
&lt;th&gt;Observed or expected behavior&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Slack MCP Server toggle is disabled&lt;/td&gt;
&lt;td&gt;Upstream initialization returns HTTP 400; enable it, then reauthorize&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Managed proxy variables are unavailable locally&lt;/td&gt;
&lt;td&gt;Delivery records &lt;code&gt;mcp_unavailable&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dataset read fails&lt;/td&gt;
&lt;td&gt;Delivery records &lt;code&gt;dataset_read_failed&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Explicit tool is missing&lt;/td&gt;
&lt;td&gt;Delivery records &lt;code&gt;no_write_tool&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No write-like tool is exposed&lt;/td&gt;
&lt;td&gt;Delivery records &lt;code&gt;no_write_tool&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connection, discovery, or tool call throws&lt;/td&gt;
&lt;td&gt;Delivery records &lt;code&gt;dispatch_failed&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connector is empty&lt;/td&gt;
&lt;td&gt;MCP delivery is a silent no-op&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;No post messages are built&lt;/td&gt;
&lt;td&gt;The Actor does not connect to the server&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;There is no retry loop around individual tool calls. Calls are serial, and one failed call stops the remaining loop. Earlier Slack messages may already exist even when the run records &lt;code&gt;dispatch_failed&lt;/code&gt;; check Slack before rerunning to avoid duplicates.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;mcpMaxItems&lt;/code&gt; caps posts, not total calls. In separate-comment mode, one post can generate one post message plus several comment messages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Security, Reddit policies, and human review
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Give the Slack app only the scopes required by the permitted MCP tool.&lt;/li&gt;
&lt;li&gt;Disable &lt;strong&gt;Allow all&lt;/strong&gt; and allow only &lt;code&gt;slack_send_message&lt;/code&gt; for this connector.&lt;/li&gt;
&lt;li&gt;Send test alerts to a designated private channel.&lt;/li&gt;
&lt;li&gt;Keep &lt;code&gt;mcpMaxItems&lt;/code&gt; low until the query quality is proven.&lt;/li&gt;
&lt;li&gt;Prefer a managed connector over placing a bearer token in Actor input.&lt;/li&gt;
&lt;li&gt;Never put OAuth credentials in datasets, templates, screenshots, or logs.&lt;/li&gt;
&lt;li&gt;Treat public Reddit content as context, not consent for automated outreach.&lt;/li&gt;
&lt;li&gt;Keep a person responsible for deciding whether and how to respond.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use this workflow in accordance with Reddit's &lt;a href="https://www.redditinc.com/policies/user-agreement" rel="noopener noreferrer"&gt;User Agreement&lt;/a&gt;, &lt;a href="https://support.reddithelp.com/hc/en-us/articles/26410290525844-Public-Content-Policy" rel="noopener noreferrer"&gt;Public Content Policy&lt;/a&gt;, privacy requirements, and applicable law. Do not use it to profile sensitive traits, harass users, or automate spam.&lt;/p&gt;

&lt;p&gt;Slack also warns about mixing data across several MCP servers. Review every endpoint that can receive workspace context, and avoid sending workspace data through an MCP service you do not trust.&lt;/p&gt;

&lt;p&gt;After a temporary proof-of-concept, pause or delete the Apify schedule and task, remove the MCP connector from Apify, revoke the Slack app's OAuth grant, and archive the test channel. Delete the Slack app only if no other connector or workflow uses it.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I would improve next
&lt;/h2&gt;

&lt;p&gt;The useful first version is working: scheduled discovery, deterministic formatting, live tool discovery, least-privilege connector controls, comments, and safety caps.&lt;/p&gt;

&lt;p&gt;The next improvements are persistent delivered-post IDs, retry policies for transient MCP errors, explicit partial-success counts, and destination-specific templates. The main lesson, however, is that query quality matters more than scrape volume. Start with three phrases indicating a real problem or decision, send a tiny sample to Slack, review it with a human, and improve the searches before scheduling more runs.&lt;/p&gt;

&lt;p&gt;That turns Reddit Scraper from a dataset generator into a monitor a team can actually use.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://apify.com/harshmaur/reddit-scraper" rel="noopener noreferrer"&gt;Reddit Scraper on Apify&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.apify.com/platform/integrations/mcp-connectors" rel="noopener noreferrer"&gt;Apify MCP connectors overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.apify.com/integrations/mcp-connectors/use-in-actors" rel="noopener noreferrer"&gt;Build Actors with MCP connectors&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.apify.com/platform/schedules" rel="noopener noreferrer"&gt;Apify schedules&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.slack.dev/ai/slack-mcp-server/" rel="noopener noreferrer"&gt;Slack MCP server overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://modelcontextprotocol.io/" rel="noopener noreferrer"&gt;Model Context Protocol&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
  </channel>
</rss>
