0) Prerequisites (10–30 min once)
Accounts & API keys: Reddit (script app), Substack (export/API), Gmail/Google Cloud (OAuth), Slack (bot), HubSpot (Private App), Smartlead (API), Clay (API).
Machine: Any Linux/Mac/Windows box (4 GB RAM+).
Secrets management:
.env
locally or a secret store (Doppler/1Password/Vault).Optional brokers: Redis/RabbitMQ for queues if you expect >5k ops/day.
1) Quick Install & Boot (≈14 minutes)
A. Directory scaffold
mcp/
.env
mcp.config.yaml
policies/
default.policy.yaml
workflows/
reddit_to_crm.yaml
substack_to_sheet.yaml
warm_email_funnel.yaml
slack_qa.yaml
content_distribution.yaml
logs/
data/
B. Environment variables (.env
) — rename values
# Reddit
REDDIT_CLIENT_ID=xxxx
REDDIT_CLIENT_SECRET=xxxx
REDDIT_USER_AGENT=growth-exe-mcp/1.0
# Substack (token or app password if enabled)
SUBSTACK_TOKEN=xxxx
# Google
GOOGLE_CLIENT_ID=xxxx
GOOGLE_CLIENT_SECRET=xxxx
GOOGLE_REFRESH_TOKEN=xxxx
# Slack
SLACK_BOT_TOKEN=xoxb-xxxx
SLACK_APP_TOKEN=xapp-xxxx
# HubSpot
HUBSPOT_TOKEN=pat-xxxx
# Smartlead
SMARTLEAD_API_KEY=xxxx
# Clay
CLAY_API_KEY=xxxx
C. MCP Server config (mcp.config.yaml
) — template
server:
port: 8787
log_level: info
auth:
mode: token
tokens:
- name: ops-console
value: REPLACE_ME_CONSOLE_TOKEN
- name: daily-sweep-agent
value: REPLACE_ME_SWEEP_TOKEN
namespaces:
- name: sales
resources:
- type: reddit
alias: reddit_public
creds:
client_id: ${REDDIT_CLIENT_ID}
client_secret: ${REDDIT_CLIENT_SECRET}
user_agent: ${REDDIT_USER_AGENT}
- type: hubspot
alias: hubspot_crm
creds:
token: ${HUBSPOT_TOKEN}
- type: smartlead
alias: smartlead_mail
creds:
api_key: ${SMARTLEAD_API_KEY}
- name: marketing
resources:
- type: substack
alias: substack_list
creds:
token: ${SUBSTACK_TOKEN}
- type: google_sheets
alias: sheets_ops
creds:
client_id: ${GOOGLE_CLIENT_ID}
client_secret: ${GOOGLE_CLIENT_SECRET}
refresh_token: ${GOOGLE_REFRESH_TOKEN}
- type: slack
alias: slack_connect
creds:
bot_token: ${SLACK_BOT_TOKEN}
app_token: ${SLACK_APP_TOKEN}
agents:
- id: lead_scout
allowed:
namespaces: [sales, marketing]
tools: [reddit.search, reddit.fetch_comments, clay.enrich, hubspot.upsert_contact, sheets.append_rows]
- id: warmoutreach
allowed:
namespaces: [sales]
tools: [smartlead.create_campaign, smartlead.send_email, hubspot.attach_engagement]
- id: support_bot
allowed:
namespaces: [marketing]
tools: [slack.listen, slack.reply, sheets.lookup_faq]
observability:
request_log: ./logs/requests.ndjson
event_log: ./logs/events.ndjson
queueing:
type: memory # switch to redis for scale
concurrency: 4
rate_limits:
reddit:
rpm: 50
hubspot:
rpm: 80
smartlead:
rpm: 60
D. Policies (least privilege) policies/default.policy.yaml
rules:
- subject: agent:lead_scout
allow:
- tool: reddit.search
- tool: reddit.fetch_comments
- tool: clay.enrich
- tool: sheets.append_rows
- tool: hubspot.upsert_contact
deny:
- tool: smartlead.send_email
- subject: agent:warmoutreach
allow:
- tool: smartlead.create_campaign
- tool: smartlead.send_email
- tool: hubspot.attach_engagement
deny:
- tool: reddit.*
- tool: sheets.append_rows
- subject: agent:support_bot
allow:
- tool: slack.listen
- tool: slack.reply
- tool: sheets.lookup_faq
E. Start the server
Binary/CLI:
agentpass-mcp serve --config ./mcp.config.yaml --env ./.env
Docker (template):
docker run -d --name mcp \
-p 8787:8787 \
--env-file .env \
-v $(pwd)/mcp.config.yaml:/app/mcp.config.yaml \
-v $(pwd)/policies:/app/policies \
-v $(pwd)/logs:/app/logs \
agentpass/mcp-server:latest serve --config /app/mcp.config.yaml
Adjust binary/image names to your local setup; the snippet is a template.
F. Sanity tests (pick any)
Auth test: call
GET /health
with theops-console
token.Tool list:
GET /tools
→ confirm namespaces/tools are visible.Dry-run: run
reddit.search
with a safe subreddit (e.g.,r/Entrepreneur
) and limit=3.
2) Register & Verify Each API (once per connector)
Create a script app; set redirect
http://localhost
if asked.
Save
client_id
,client_secret
,user_agent
.Test: search
site:substack.com "newsletter"
, ensure 200 OK.
Substack
Generate token (if enabled) or use export endpoint.
Test: list subscribers; compare count to dashboard.
Google Sheets/Gmail
Create OAuth client (Desktop).
Capture
client_id
,client_secret
,refresh_token
.Test: create a “Prospects (MCP)” sheet; append 1 row.
Slack
Create bot, add
chat:write
,channels:history
,app_mentions:read
.Install to workspace; note bot and app tokens.
Test: post a message to a test channel.
HubSpot
Private App → scopes:
crm.objects.contacts.read/write
, engagements.Test: upsert one dummy contact by email; verify in UI.
Smartlead
Create API key.
Test: list sender accounts; verify the correct pool appears.
3) Build the 5 Core Workflows (copy-paste templates)
Convention: Each workflow YAML declares: trigger → sources → filters → enrich → actions → log.
3.1 Reddit → CRM (workflows/reddit_to_crm.yaml
)
name: reddit_to_crm
schedule: "cron(*/20 * * * *)" # every 20 min
trigger:
type: timer
params:
subreddits: ["Entrepreneur", "SaaS"]
query: ["lead gen", "outbound", "tool recommendations"]
steps:
- id: fetch_posts
use: reddit.search
with:
subreddits: ${params.subreddits}
query: ${params.query}
limit: 25
- id: fetch_comments
use: reddit.fetch_comments
with:
post_ids: ${steps.fetch_posts.ids}
limit_per_post: 20
- id: pick_prospects
use: filter.expression
with:
input: ${steps.fetch_comments.items}
where: |
(score >= 1) and not is_op and not contains(text, "hire me")
- id: enrich
use: clay.enrich
with:
input: ${steps.pick_prospects.items}
fields: [name, company, email, linkedin_url, role]
- id: upsert_hubspot
use: hubspot.upsert_contact
with:
contacts: ${steps.enrich.results}
unique_key: email
- id: log
use: sheets.append_rows
with:
sheet: "Prospects (MCP)!A:F"
rows: ${steps.enrich.results}
3.2 Substack → Lead Sheet (workflows/substack_to_sheet.yaml
)
name: substack_to_sheet
schedule: "cron(5 6 * * *)" # 06:05 UTC daily ≈ 11:35 IST
steps:
- id: pull
use: substack.list_subscribers
with:
since_days: 2
- id: dedupe
use: sheets.dedupe
with:
sheet: "Subscribers (MCP)!A:D"
key: email
incoming: ${steps.pull.items}
- id: write
use: sheets.append_rows
with:
sheet: "Subscribers (MCP)!A:D"
rows: ${steps.dedupe.unique}
3.3 Warm Email Funnel (workflows/warm_email_funnel.yaml
)
name: warm_email_funnel
schedule: "cron(0 7,13 * * 1-6)" # 07:00 & 13:00 UTC Mon–Sat
steps:
- id: signals
use: aggregator.join
with:
reddit: reddit.engagers_last_48h
linkedin: sheets.read_range # maintained by separate job
substack: substack.opens_last_48h
- id: score
use: scorecard.linear
with:
weights:
reddit_comment: 3
linkedin_profile_view: 2
substack_open: 1
threshold: 3
- id: prep_email
use: template.render
with:
template: |
Subject: Quick idea for {{company}}
Body:
Hey {{firstName}} — noticed {{signal}}.
Built a tiny workflow that {{benefit}}.
Worth a 7-line note? If yes, I’ll send.
variables: ${steps.score.passed}
- id: send
use: smartlead.send_email
with:
messages: ${steps.prep_email.messages}
campaign: "Warm MCP Intros"
- id: attach
use: hubspot.attach_engagement
with:
items: ${steps.prep_email.messages}
3.4 Slack Q&A Agent (workflows/slack_qa.yaml
)
name: slack_qa
trigger:
type: event
source: slack_connect
event: app_mention
steps:
- id: lookup
use: sheets.lookup_faq
with:
sheet: "FAQ (MCP)!A:B"
key: ${event.text}
- id: reply
use: slack.reply
with:
channel: ${event.channel}
thread_ts: ${event.ts}
text: ${steps.lookup.answer or "I’ll DM you the doc in a sec."}
3.5 Content Distribution (workflows/content_distribution.yaml
)
name: content_distribution
trigger:
type: filewatch
path: ./data/drafts/
steps:
- id: parse
use: content.parse_frontmatter
- id: schedule_posts
use: publisher.multi
with:
linkedin: { when: "best_time_today", text: ${steps.parse.linkedin_copy} }
twitter: { when: "best_time_today", text: ${steps.parse.twitter_copy} }
substack: { when: "immediate", title: ${steps.parse.title}, body: ${steps.parse.body} }
- id: log
use: sheets.append_rows
with:
sheet: "Content Log (MCP)!A:E"
rows: ${steps.schedule_posts.summary}
4) Access Control & Safety (copy these patterns)
Least privilege by agent: All sends go through
warmoutreach
; scraping goes throughlead_scout
.Scoped tokens: one token per agent (
daily-sweep-agent
,ops-console
).Namespace isolation: sales vs. marketing separated to prevent tool bleed.
Rate limits: set explicit RPM caps per API (see config).
Audit & immutability: log all requests/events to append-only NDJSON.
Outbound approvals (optional): require
ops-console
approval for large send batches (>50).
5) The Daily Lead Sweep (IST-aware)
Target windows (IST):
01:00–03:00 scrape (low API contention)
05:00 enrich + dedupe
11:00 & 18:30 outreach windows (human-like timing)
Checklist
Run
reddit_to_crm
(pull + enrich + HubSpot + sheets log)Run
substack_to_sheet
(append + dedupe)Score signals → queue warm emails (reviewable batch)
Send via Smartlead with throttling (e.g., 12/min per sender)
Post summary to
#mcp-daily
Slack channel (new contacts, emails queued/sent, errors)
One-liner status (ops):
agentpass-mcp status --since 24h --workflows reddit_to_crm,substack_to_sheet,warm_email_funnel
6) Scaling Without Headaches
Queues: switch
queueing.type
toredis
and setconcurrency: 16+
.Idempotency: dedupe on
(source, external_id)
before upserts/sends.Backoff: exponential retry on 429/5xx; circuit break after 5 fails.
Shard by market: run separate MCP instances by geo or business unit.
Observability:
Errors: <1% per 24h
Time-to-lead: <10 min from capture → CRM
Outreach latency: <30 min from signal → first touch
7) Troubleshooting Quick Guide
401/403: token mismatch or policy deny → check
default.policy.yaml
.429 (rate limit): lower
rpm
, add jitter, widen cron intervals.HubSpot upsert fails: missing email or invalid property → validate schema before send.
Smartlead bounce spike: pause sender, warm IP/domain, verify DNS (SPF/DKIM/DMARC).
Slack bot silent: missing scope or wrong channel ID → reinstall + reauth.
8) QA Checklist Before “Go”
Secrets present (
.env
), no placeholders left.GET /tools
shows only needed tools per agent.Dry-run on each workflow with 1–3 records.
Rate limits tested using a burst (no bans).
Logs streaming to
logs/
and retained for 30 days.Emergency stop:
agentpass-mcp pause warm_email_funnel
.
9) Metrics & Review Cadence
Daily (Slack digest): new leads, sends, replies, errors.
Weekly: conversion to meeting (%), list health (open/click), bounce rate.
Monthly: SQL/Sheets audit of dedupe hits, domains, persona coverage.
10) Copy Blocks (use in UI/Docs)
Warm intro template
Subject: Quick idea for {{company}}
Hey {{firstName}} — I noticed {{signal}}.
We built a tiny workflow that {{benefit in 1 line}}.
If relevant, I’ll send a 7-line breakdown and leave it there.
Slack auto-reply (fallback)
Got it. I’m pulling the doc now and will drop it in this thread.
(If you need a human: @Divyanshi.)
11) Security Notes (non-negotiable)
Rotate all tokens every 90 days.
Separate senders for prospecting vs. customer comms.
Restrict ops token to VPN/office IPs.
Keep PII in CRM + Sheets only; avoid logs beyond email/name.