S'more for coding agents

Give your agent a growth job

Use Codex, Cursor, Claude Code, or another MCP client to score X posts, find qualified conversations and X posts worth joining now, post your approved X replies and quotes, and work with approved outreach for X, LinkedIn, and Reddit

Connect your agent
1
Score an X post

Jev evaluates nine X-algorithm-informed engagement signals and flags reply bait.

2
Run a lead-finding agent

S'more searches X, judges each post against your brief, and drafts replies in your voice.

3
Send approved outreach

X and LinkedIn approved sending are live. Reddit campaigns await rollout.

4
Join a conversation while it is moving

Find fresh X posts worth joining and breaking-wave signals, then post your own reply, quote, or original post after you approve its exact preview.

Connect in minutes

Connect your client

Add the hosted server to your MCP client. S'more opens in your browser so you can sign in, choose a workspace, and approve only Viral Score access.

One command takes you straight into secure browser approval, then returns you to your AI ready to score a draft.

https://app.makesmores.com/api/v1/mcp

1 Add the server

Codex opens the S'more approval page in your browser.

codex mcp add smore --url https://app.makesmores.com/api/v1/mcp

2 Sign in

Use your S'more email, then choose the workspace this connection can access.

3 Approve access

Review the exact viral:score permission before granting it.

4 Score a draft

Ask your client to call predict_viral_score. Browser OAuth handles the credential securely.

Choose your platform permissions

Request outreach access separately for the workspace that owns your sending account. Existing grants keep their original permissions. Clients with explicit OAuth scope support can request X outreach with this command; the platform references list LinkedIn and Reddit scopes.

codex mcp login smore --scopes outreach:read,outreach:send,outreach:cancel

S'more CLI v0.15.134 supports the opt-ins below. Choose the flags you need and combine them for access to multiple platforms; --reddit-posts requests post drafts for review.

smore auth login --outreach
smore auth login --linkedin-outreach
smore auth login --reddit-outreach --reddit-posts
smore mcp-proxy

Review every requested permission in the browser. These flags also request the existing agent, run, lead, and scoring scopes. Credentials stay in your OS keychain. Approving access does not enable a platform whose rollout is pending.

Enable X signals and posting

Request the X signal and posting permissions explicitly and approve them for the workspace that owns your X account. Existing grants gain nothing.

codex mcp login smore --scopes x:signals:read,x:signals:write,x:post:send,outreach:read,outreach:cancel

With the CLI bridge, use S'more CLI v0.15.148 or newer, run smore auth login --x-signals --x-post, then smore mcp-proxy. --x-signals requests x:signals:read and x:signals:write; --x-post requests x:post:send, outreach:read, and outreach:cancel, without outreach:send. A connection that only reads signals needs just x:signals:read.

Need the full agent toolkit

Request the additional agent, run, and lead permissions explicitly. S'more shows every permission before approval.

codex mcp login smore --scopes agents:read,agents:write,runs:start,runs:read,leads:read

Agent-readable facts

A focused, permissioned surface

Access is scoped to one workspace and revocable. Each platform's sending requires separate outreach approval, current workspace membership, paid access, and a verified user-owned account. Reddit post generation has separate review-only permissions. X posting requires its own separately approved permission, and every X post also needs your approval of its exact preview.

Protocol
Streamable HTTP MCP
Hosted endpoint
https://app.makesmores.com/api/v1/mcp
Authentication
Browser OAuth with PKCE, scoped to one workspace and revocable in Settings.
Permissions
viral:score by default; agent, run, lead, platform outreach, X signal, X posting, and Reddit post-draft permissions require explicit approval

MCP tools

What your agent can do

smore_create_agent

Create a focused lead-finding agent in the approved workspace.

smore_list_agents

See the agents available to the approved workspace.

smore_run_agent

Start a search and qualification run for one agent.

smore_get_run

Check run progress and its current state.

smore_list_leads

Retrieve qualified conversations and drafted replies for review.

smore_watch_x_keywords

Add, remove, or list up to 10 X keywords your workspace tracks. S'more keeps hourly post counts for each and can poll fresh posts inside a daily window. Watching never posts. Requires x:signals:write and paid access.

smore_find_x_posts

Read fresh X posts worth joining now for your watched keywords and S'more's seed searches, ranked by how fast they are gaining views. Reads S'more's cache with provisional ranking rules. Requires x:signals:read.

smore_get_x_waves

Read breaking-wave signals for S'more's term panel and your watched keywords: how likely posting volume is to keep rising over the next 24 hours, with stage and recent volume. Requires x:signals:read.

smore_upload_x_media

Stage one PNG, JPEG, or WebP image with required alt text for a later post. S'more removes image metadata and never fetches URLs. Requires x:post:send.

smore_post_x

Prepare one reply, quote, or original post from your connected X account with your exact text and up to four images. Returns the exact preview and a single-use approval token; nothing is queued yet. Requires x:post:send.

smore_approve_x_post

Queue the previewed post only after you approve that exact preview in your agent. The token is single-use and expires after 10 minutes. Requires x:post:send.

Each platform reference below lists its exact tools, scopes, request fields, and receipts. X and LinkedIn approved sending are live. Reddit sending and post generation are pending rollout.

Want to try the scorer first?

Paste your own post into the public Viral Score. You get five free scores before connecting an account.

Score a post

Approved X outreach

Hand over the finished list

Prepare the outreach, choose your connected sending account, and tell your assistant when to start. S'more queues the approved public replies and one-to-one DMs, sends the exact text, and keeps a delivery record for every row.

  1. Connect your X account

    Ask your assistant to call smore_list_x_connections and open its secure connect_url. Sign in to S'more with your email and PIN if needed, select the intended workspace, and connect X in Settings. An owner or administrator completes any X verification there. Login runs in the background while Settings shows progress.

  2. Give your assistant the approved CSV

    Use the columns row_id,action,handle,reply_url,message. Choose reply or dm, use handles without @, and supply a post link for each public reply. Your assistant converts the CSV to structured rows; S'more receives those rows through MCP.

  3. Submit the batch

    Identify the sender and approve the destinations and final text before submission. smore_submit_x_outreach authorizes automatic sending in row order, without another approval for every message. S'more preserves your text, including spaces and line breaks.

  4. Check delivery or stop remaining work

    Keep the returned batch_id. Ask your assistant for progress, a row's receipt, or cancellation. Confirmed replies have an X post link; confirmed DMs have a provider message ID. These are delivery outcomes, not incoming-response or read tracking.

Start time
Start when the batch is eligible, or choose a one-time local date and time with an explicit IANA zone, such as 7 am in America/Los_Angeles.
Default pacing
A persisted random delay of 45 to 240 seconds between attempted writes, shared across batches using the same X identity in that workspace. Provider waits can make the interval longer.
Selected sender
One verified, user-owned X account per batch. Your assistant must choose it explicitly.
Delivery records
Every row retains its status, attempt count, and confirmed provider ID when available. A completed batch can still contain failed or uncertain rows.

The scheduled time is the earliest eligible start. Account availability, provider limits, or reconnection can delay it. A batch expires seven days after its resolved start, including time spent paused.

This feature sends finished outreach. It does not draft or enrich your CSV, read your X inbox or DMs, track incoming replies or read receipts, create follow-up sequences, or run recurring schedules. Lead-finding and Viral Score remain separate tools.

X outreach reference

The data your assistant sends

Use stable row IDs to match results to your CSV. These examples contain placeholders; replace the account, destinations, messages, and date with the values you have approved.

Tools and permissions
X MCP tools
ToolArguments and purposeRequired permission
smore_list_x_connections{} lists workspace-owned accounts and returns a secure connection link, even when none are connected.outreach:read
smore_submit_x_outreachOne sender, approved rows, a submission key, and optional start time and pacing. Authorizes automatic sending.outreach:send
smore_get_x_outreachbatch_id, optional cursor and limit. Reads progress, confirmed reply and post links, and DM message IDs.outreach:read
smore_cancel_x_outreachbatch_id stops messages and posts that have not started. Already dispatched writes may finish.outreach:cancel
CSV format and submission example

The CSV stays with your assistant or MCP client. There is no separate server-side CSV upload endpoint. Quote CSV fields that contain commas, quotation marks, or line breaks. Leave reply_url empty for a DM, then omit that field from its JSON row.

row_id,action,handle,reply_url,message
reply-001,reply,example_handle,https://x.com/example_handle/status/1234567890123456789,"Your approved public reply goes here."
dm-001,dm,example_handle,,"Your approved direct message goes here."

Arguments for smore_submit_x_outreach

Get the real connection_id from smore_list_x_connections. Omit schedule for immediate eligibility and omit pacing to use the default 45 to 240 second range.

{
  "connection_id": "11111111-1111-4111-8111-111111111111",
  "idempotency_key": "approved-outreach-2026-10-08-v1",
  "schedule": {
    "local_start_at": "2026-10-08T07:00:00",
    "time_zone": "America/Los_Angeles"
  },
  "pacing": {
    "min_delay_seconds": 45,
    "max_delay_seconds": 240
  },
  "rows": [
    {
      "row_id": "reply-001",
      "action": "reply",
      "handle": "example_handle",
      "reply_url": "https://x.com/example_handle/status/1234567890123456789",
      "message": "Your approved public reply goes here."
    },
    {
      "row_id": "dm-001",
      "action": "dm",
      "handle": "example_handle",
      "message": "Your approved direct message goes here."
    }
  ]
}
Submission fields
FieldContract
connection_idRequired UUID of the selected workspace's verified user-owned X connection.
idempotency_keyRequired nonblank submission key, up to 128 bytes. Reuse it only for the identical approved batch.
rows1 to 500 rows, within the server's limits and a 1 MiB request size.
row_idRequired nonblank ID, up to 128 bytes, unique within this batch.
actionreply or dm.
handle1 to 15 letters, digits, or underscores, with no leading @.
reply_urlRequired HTTPS X or Twitter post URL for a reply; forbidden for a DM. S'more verifies that the post belongs to the supplied handle before sending.
messageRequired final text, preserved exactly. Public replies use X's weighted 280-character limit; DMs allow up to 4,000 Unicode code points.
scheduleOptional local_start_at in YYYY-MM-DDTHH:mm:ss without an offset, plus an explicit IANA time_zone. Choose a future time within the default 30-day horizon. Missing or repeated daylight-saving times are rejected.
pacingOptional integer min_delay_seconds and max_delay_seconds. Defaults are 45 and 240; default supported bounds are 15 to 300 seconds, with minimum no greater than maximum. Server policy can tighten limits.

Invalid rows, unknown fields, duplicate keys or row IDs, and malformed destinations reject the whole submission before anything is queued. DM handles resolve to their current numeric X identity at dispatch, which is saved before sending.

Progress, receipts, retries, and cancellation

Submission returns batch_id, status, sender, resolved UTC start, pacing, expiry, progress counts, and next_send_at when applicable. Use smore_get_x_outreach with {"batch_id":"…","limit":50} to read row results. The maximum page size is 100; pass the returned next_cursor back as cursor unchanged.

Row outcomes
StatusMeaning
queuedWaiting for dispatch or a safe retry after a definite rejection.
sendingAn attempt is reserved and the provider write may be in progress.
sentA confirmed provider ID is recorded. Replies include receipt_url; DMs retain a message ID without a public receipt URL.
failedA definite rejection, invalid destination, expiry, or lost authority stopped the row.
send_unknownThe write may have succeeded but its result is uncertain. S'more will not automatically send it again.
cancelledThe row was stopped before dispatch.

Batch states are scheduled, queued, running, paused, completed, cancelled, or failed. Inspect the per-row outcomes and progress counts; completed does not mean every message was sent successfully. Rows retain your original ID, destination and message, plus attempts, error code, and dispatch/finish times when available. Receipts prove provider acceptance, not that someone read or answered.

Submitting the same key with identical input returns the original batch. Changing the sender, text, destination, schedule, or pacing under that key produces idempotency_conflict. A timeout or lost provider response becomes send_unknown; do not create a new batch to repeat an unresolved write. A late confirmed receipt can update the existing outcome.

Call smore_cancel_x_outreach with {"batch_id":"…"} to stop remaining queued messages. Cancellation cannot retract a sent message or guarantee stopping one already dispatched. Grant revocation or expiry, membership removal, or account/workspace closure stops remaining unauthorized work while preserving known outcomes.

MCP errors use isError: true with a safe code and message. Relevant codes include invalid_request, idempotency_conflict, paid_required, connection_required, insufficient_scope, invalid_token, not_found, and outreach_disabled.

If the sending account disconnects

The accepted batch pauses and returns a reconnect action through smore_get_x_outreach. This is a batch status, rather than a failed submission. An example of the relevant return fields:

{
  "status": "paused",
  "code": "account_disconnected",
  "next_send_at": null,
  "next_action": {
    "type": "reconnect_x",
    "url": "https://app.makesmores.com/app/settings?outreach_batch_id=22222222-2222-4222-8222-222222222222&workspace_id=33333333-3333-4333-8333-333333333333",
    "requires_role": "owner_or_admin"
  },
  "resume_policy": "automatic_after_same_account_reconnect"
}

Your assistant should say: "Outreach is paused because the sending X account disconnected. Open the reconnect link, select the batch's workspace, and connect the same account. Pending rows will resume automatically."

An owner or administrator reconnects in the secure Settings form, including any provider challenge. S'more verifies the original numeric X identity; matching the handle alone is insufficient. A different account cannot take over the approved batch. After verification, pending rows resume within the batch's expiry. Sent and uncertain rows are not repeated.

X signals and posting

Find posts worth joining now

Your assistant can find fresh X posts worth joining, read breaking-wave signals for S'more's term panel and the keywords you track, and post your reply, quote, or original post, with images, from your own connected X account. Each post is queued only after you approve its exact preview in your agent.

  1. Track your keywords

    Optionally ask your assistant to watch up to 10 keywords with smore_watch_x_keywords. S'more backfills 30 days of hourly post counts, keeps them fresh, and can poll fresh posts for each keyword inside a daily window.

  2. Find a post or a wave

    smore_find_x_posts returns fresh posts ranked by how fast they are gaining views, and marks the ones under an hour old, in the top tier, and below a reply count you can set. smore_get_x_waves returns keywords that are breaking. Both read S'more's cache; post text from X is untrusted third-party content.

  3. Write it and review the preview

    You choose the target and write the final text. Stage up to four images with alt text using smore_upload_x_media. smore_post_x returns the exact preview and a single-use token valid for 10 minutes. Nothing is queued yet.

  4. Approve, then track

    Only after you approve that exact preview in the chat does your assistant call smore_approve_x_post, which queues the post. Read its receipt link with smore_get_x_outreach or stop it with smore_cancel_x_outreach.

Your text, your account
S'more never drafts, rewrites, or selects post text in this flow. Posts go out only from the verified user-owned X account your assistant selects.
One approval, one post
Each approval queues exactly one reply, quote, or original post. An unsent post expires 30 minutes after approval, so a reply is never sent long after its target was read.
Posting limits
Server policy sets the limits. Defaults are 5 posts per account per UTC day, one reply or quote per target post per account, 15 minutes between posts, and found targets read within the last 90 minutes.
Account protection
If X reports automated behavior (error 226), a challenge, or the daily post limit, S'more pauses every write from that account for 24 hours. An uncertain write is never repeated automatically.
Access
Finding posts and reading waves work for any workspace with x:signals:read. Watching keywords, uploading images, and posting need paid access.
Signal quality
Post rankings use provisional rules. Wave scores come from a model whose live performance is still provisional; scores for terms outside its AI-topic training set are marked as such.

Posts that mention sensitive topics such as tragedies, war, politics, crypto promotion, adult content, or sports are left out of results, unless your own keyword names that topic, and are refused as reply or quote targets. Images are PNG, JPEG, or WebP up to 700 KiB each, with alt text; rotate them before upload, because S'more removes orientation metadata along with the rest.

S'more never posts on a keyword, watch, wave, or schedule trigger; watching only refreshes counts and polls fresh posts. There is no recurring or automatic posting, no X inbox or DM reading, no reply tracking, and no editing or deleting of posts. Managed or pooled X accounts never post.

X signals and posting reference

The data your assistant sends

Successful results return structuredContent with schema_version: 1. The six tools appear only for grants that hold their permission.

Tool inputs, permissions, and errors
X signal and posting tools
ToolMain inputsPermission
smore_watch_x_keywordsadd (keyword, counts, hot_posts, window), remove (watch IDs), idempotency_key; a call with neither lists the watchesx:signals:write, paid
smore_find_x_postswatch_ids, include_seed_pool, max_age_min, worth_reply_only, max_replies, limitx:signals:read
smore_get_x_wavessource (watched, panel, or all), flagged_only, since_cursor, limitx:signals:read
smore_upload_x_mediamime, data_base64, alt_textx:post:send, paid
smore_post_xconnection_id, mode (reply, quote, or post), target_ref or target_post_url for replies and quotes, text, media_refs, possibly_sensitive, idempotency_keyx:post:send, paid
smore_approve_x_postpost_request_id, preview_sha256, approval_tokenx:post:send, paid

A target_ref comes from find or waves and stays valid for 90 minutes after the post was read. With a target_post_url, S'more reads the post's author and link when it sends. Text is at most 280 X-weighted characters and is never trimmed. Receipts are X post links for all three modes.

Errors use isError: true with a safe code and message. Relevant codes include paid_required, watch_limit_reached, keyword_invalid, target_ref_expired, target_blocked, target_limit_reached, account_day_limit_reached, account_paused, media_too_large, approval_expired, approval_mismatch, approval_used, text_too_long, connection_required, idempotency_conflict, and rate_limited.

Approved LinkedIn outreach

Use your connected LinkedIn account

Give your assistant finished profile links, post links, and approved messages. LinkedIn outreach supports DMs to first-degree connections, public comments, replies to comments, and connection invitations with an exact note.

LinkedIn account connection and approved sending are live. Complete any provider verification in Settings, then choose the verified account for your batch.

  1. Approve LinkedIn access

    Approve the required LinkedIn permissions for the workspace that owns your sending account. Existing X permissions do not include LinkedIn. Sending requires paid access, current workspace membership, and an active grant.

  2. Connect in Settings

    Ask your assistant to call smore_list_linkedin_connections with {}, then open its connect_url. Sign in to S'more with your email and PIN if needed. In the intended workspace, an owner or administrator enters the LinkedIn account nickname, email, and password. Settings shows progress and any provider PIN request, including its masked destination and expiry. Enter the code there; account credentials and codes stay out of MCP.

  3. Submit your approved list

    Your assistant converts the CSV into JSON rows, preserving their order and exact text. Choose one verified, user-owned sender and approve the destinations, messages, and optional start time. Calling smore_submit_linkedin_outreach authorizes automatic sending.

  4. Read outcomes or stop the batch

    Keep the returned batch_id. Use the get tool to check progress and receipts, or the cancel tool to stop rows that have not started. If the account disconnects, an owner or administrator reconnects the same LinkedIn member in the same workspace.

You can send an invitation alone: submit one row with action: "connect" through smore_submit_linkedin_outreach. There is no dedicated invitation-only tool. Connecting your own sending account happens separately in Settings.

Invitations depend on the account's allowance for notes. Existing connections, pending invitations, exhausted allowances, or missing required information produce explicit outcomes. S'more does not drop the approved note or send a blank invitation instead. A DM to someone outside your first-degree connections fails; it does not trigger an invitation and follow-up sequence.

LinkedIn outreach reference

The data your assistant sends

These examples use placeholders. Replace the sender, destinations, messages, and date with your approved values before submitting.

Tools and permissions
LinkedIn MCP tools
ToolArguments and purposeRequired permission
smore_list_linkedin_connections{} returns the workspace's user-owned accounts, status, can_send, and a connect_url, including when the list is empty.linkedin:outreach:read
smore_submit_linkedin_outreachOne connection_id, an idempotency_key, approved rows, and optional schedule and pacing.linkedin:outreach:send
smore_get_linkedin_outreach{"batch_id":"…","limit":50} reads progress and rows. Maximum page size is 100; pass next_cursor back as cursor unchanged.linkedin:outreach:read
smore_cancel_linkedin_outreach{"batch_id":"…"} stops remaining unstarted rows.linkedin:outreach:cancel

For clients that accept explicit OAuth scopes, request linkedin:outreach:read,linkedin:outreach:send,linkedin:outreach:cancel. S'more CLI v0.15.134 supports smore auth login --linkedin-outreach. This flag also requests the existing agent, run, lead, and scoring scopes; review every permission in the browser before approving it.

CSV rows and a standalone invitation

The CSV stays with your assistant or client, which parses it into MCP arguments. Quote fields containing commas or line breaks. Omit empty destination fields from each JSON row.

row_id,action,profile_url,reply_url,parent_comment_urn,message
dm-001,dm,https://www.linkedin.com/in/first-degree-recipient/,,,"Your approved DM."
comment-001,reply,,https://www.linkedin.com/feed/update/urn:li:activity:1234567890123456789/,,"Your approved comment."
nested-001,reply,,https://www.linkedin.com/feed/update/urn:li:activity:1234567890123456789/,"urn:li:comment:(urn:li:activity:1234567890123456789,1234567890123456790)","Your approved nested reply."
invite-001,connect,https://www.linkedin.com/in/example-recipient/,,,"Your approved invitation note."

Arguments for one invitation

Get the actual sender's connection_id from the list tool. This one-row request uses smore_submit_linkedin_outreach and does not schedule a later DM.

{
  "connection_id": "11111111-1111-4111-8111-111111111111",
  "idempotency_key": "approved-linkedin-invitation-2026-10-08-v1",
  "schedule": {
    "local_start_at": "2026-10-08T07:00:00",
    "time_zone": "America/Los_Angeles"
  },
  "pacing": {"min_delay_seconds": 45, "max_delay_seconds": 240},
  "rows": [{
    "row_id": "invite-001",
    "action": "connect",
    "profile_url": "https://www.linkedin.com/in/example-recipient/",
    "message": "Your approved invitation note."
  }]
}
Row fields and limits
FieldContract
connection_idRequired UUID of one verified, user-owned LinkedIn account in the approved workspace.
idempotency_key, row_idRequired nonblank values, each up to 128 bytes. Row IDs must be unique within the batch. Reuse a submission key only for identical approved input.
rows1 to 500 rows within a 1 MiB request and current server policy.
actiondm, reply, or connect. A reply without a parent creates a public comment on the post.
profile_urlRequired for DM or invitation; forbidden for reply. Use an HTTPS linkedin.com/in/… or www.linkedin.com/in/… personal profile link.
reply_urlRequired for reply; forbidden for DM or invitation. Supported post links use /feed/update/urn:li:activity:… or /posts/…-activity-… on those LinkedIn hosts.
parent_comment_urnOptional for a nested reply only. Supply the real parent comment URN; a comment URL alone is not supported. S'more verifies that exact comment belongs to the approved post. An unverifiable parent fails before sending.
messageNonblank exact approved text, up to 1,000 UTF-16 code units for DM/comment/reply or 200 for an invitation note. Some emoji count as two units. These S'more limits do not override LinkedIn account restrictions.

S'more preserves spaces, line breaks, and the full note. Invalid fields, duplicate keys or row IDs, malformed text, and unsupported destinations reject submission before it queues anything. Use canonical links without URL credentials, explicit ports, or fragments.

Start time and pacing

Omit schedule for immediate eligibility. A one-time schedule uses local YYYY-MM-DDTHH:mm:ss without an offset and an explicit IANA zone. Default spacing is a persisted random 45 to 240 seconds, shared across batches using the same LinkedIn member in that workspace. It survives restarts; provider waits can extend it.

The shared scheduling and result rules apply: a default 30-day scheduling horizon, rejection of ambiguous or nonexistent daylight-saving times, expiry seven days after the resolved start including pauses, and optional pacing bounds of 15 to 300 seconds with minimum no greater than maximum. The start time is the earliest eligible time.

Receipts, cancellation, and reconnecting

Submission returns the batch ID, sender, resolved start, expiry, pacing, progress, and next_send_at. Get returns row IDs, exact messages, destinations, attempts, safe error codes, timestamps, and confirmed external_id values when available. A verified public comment URL may appear as receipt_url; DMs and invitations have no invented public links.

The shared row statuses, replay, and cancellation rules apply. A sent receipt records provider acceptance, not reading, response, or invitation acceptance. A completed batch can contain failures. A send_unknown write may have succeeded and is never automatically repeated; later writes from that account pause. Do not submit a new batch to repeat an unresolved write.

Cancellation stops unstarted rows and leaves earlier or already dispatched work intact. It does not withdraw invitations or remove comments or DMs. Identical input under the same key returns the original batch; changing the sender, rows, text, destinations, schedule, or pacing produces idempotency_conflict.

If the sender disconnects, the batch pauses. Relevant return fields:

{
  "status": "paused",
  "code": "account_disconnected",
  "next_send_at": null,
  "next_action": {
    "type": "reconnect_linkedin",
    "url": "https://app.makesmores.com/app/settings?platform=linkedin&outreach_batch_id=22222222-2222-4222-8222-222222222222&workspace_id=33333333-3333-4333-8333-333333333333",
    "requires_role": "owner_or_admin"
  },
  "resume_policy": "automatic_after_same_account_reconnect"
}

Your assistant should prompt: "LinkedIn outreach is paused because the sending account disconnected. Open the reconnect link, select this batch's workspace, and reconnect the same LinkedIn account. Pending rows will resume within the batch's expiry."

S'more verifies the original member identity; a matching nickname, email, or profile URL is insufficient. A different account cannot take over the batch. Sent and uncertain rows remain unchanged.

What this feature covers

This feature sends finished outreach. It excludes discovery, drafting, inbox reads, incoming-response tracking, invitation-acceptance polling, recurring schedules, and follow-up sequences. InMail, Open Profile messages, message requests, page senders, group DMs, and attachments are also outside this flow.

Approved Reddit campaigns

Review the content, then submit the campaign

Prepare comments, nested replies, text or link posts, and one-to-one chat messages for one connected Reddit account. Your assistant submits the approved rows, and S'more records the outcome of each delivery attempt.

  1. Approve Reddit permissions

    Approve the Reddit outreach scopes for the workspace that owns your sending account. Post generation has separate permissions. Existing grants keep their original scopes; X access does not grant Reddit access. Sending requires paid access, current workspace membership, and an active grant.

  2. Connect and check the community

    Call smore_list_reddit_connections and open its connect_url. Sign in to S'more with your email and PIN if needed, select the intended workspace, and have an owner or administrator connect Reddit in Settings. Complete any Reddit verification in the browser, then read the selected account's subreddit rules, requirements, and flair with smore_get_reddit_posting_context.

  3. Review every destination and message

    Give your assistant finished rows, or use smore_generate_reddit_posts to prepare posts for review. Edit and approve the exact content in chat. Generated drafts are never sent automatically; sending requires a separate batch submission with the final title, body or link, flags, destination, and sender.

  4. Submit and follow the results

    smore_submit_reddit_outreach authorizes automatic sending of the approved rows in order. Keep the returned batch_id to retrieve progress and receipts, or cancel work that has not started. A confirmed conversation creation still needs a separate message delivery before a DM is sent.

Reddit uses the same one-time scheduling, expiry, and status rules described in the outreach reference. Default spacing is 45 to 240 seconds between attempted writes, shared across Reddit batches using the same account in that workspace. Creating a new chat and sending its message are separate writes. Provider limits can extend the wait.

These tools support text and link posts, comments, nested replies, and one-to-one chat. They do not support images or video, polls, crossposts, inbox or response tracking, follow-ups, recurring schedules, or editing and deleting published content.

Reddit campaign reference

The rows and drafts your assistant works with

These examples use placeholders. Replace the connection, community, post and comment IDs, recipient, and content with values you have reviewed before submitting.

Seven tools and their permissions
ToolInput and purposeScope
smore_list_reddit_connections{} lists user-owned accounts and returns a secure connect_url, including when none are connected.reddit:outreach:read
smore_get_reddit_posting_contextconnection_id and subreddit; optional post_fullname and parent_comment_fullname check the reply target. Returns current account-visible rules, requirements, and flair.reddit:outreach:read
smore_generate_reddit_postsConnection, request key, count, target, and brief/voice or agent. Saves posts for review.reddit:posts:write
smore_get_reddit_postsExactly one of request_id or idempotency_key. Retrieves the saved generation request and drafts.reddit:posts:read
smore_submit_reddit_outreachconnection_id, idempotency_key, approved rows, and optional schedule/pacing. Authorizes sending.reddit:outreach:send
smore_get_reddit_outreachbatch_id, optional cursor and limit. Reads progress and delivery results.reddit:outreach:read
smore_cancel_reddit_outreachbatch_id. Stops remaining unstarted work.reddit:outreach:cancel

After rollout, clients with explicit OAuth scope support can request the scopes in this table. The CLI provides separate opt-ins; combine them when you need both sending and post drafts:

smore auth login --reddit-outreach --reddit-posts
smore mcp-proxy

Review all requested permissions in the browser. CLI login also requests the existing agent, run, lead, and scoring scopes, and keeps credentials in your OS keychain. S'more CLI v0.15.134 supports both flags; Reddit sending and generation remain pending rollout.

Choose the returned connection_id explicitly. Connection metadata includes account_key, reddit_user_id, username, status, and can_send. The server verifies the account again before dispatch. Managed discovery accounts cannot send. Optional thread context checks subreddit, ancestry, and locked, archived, or removed targets. If a required source is unavailable, the read returns an error.

Approved CSV and JSON rows

The CSV stays with your assistant, which converts it to JSON rows. There is no separate CSV upload endpoint. Quote values containing commas, quotation marks, or line breaks. Empty cells for another action must be omitted from that JSON row.

row_id,action,subreddit,post_fullname,parent_comment_fullname,kind,title,body,link_url,recipient_username,message
comment-001,reply,example,t3_abc123,,,,,,,"Your approved comment."
nested-001,reply,example,t3_abc123,t1_def456,,,,,,"Your approved nested reply."
self-001,post,example,,,self,"Your approved title","Your approved body.",,,
link-001,post,example,,,link,"Your approved link title",,https://example.com/guide,,
dm-001,dm,,,,,,,,example_user,"Your approved chat message."

Arguments for smore_submit_reddit_outreach

{
  "connection_id": "11111111-1111-4111-8111-111111111111",
  "idempotency_key": "approved-reddit-campaign-v1",
  "rows": [
    {"row_id":"comment-001","action":"reply","subreddit":"example","post_fullname":"t3_abc123","message":"Your approved comment."},
    {"row_id":"nested-001","action":"reply","subreddit":"example","post_fullname":"t3_abc123","parent_comment_fullname":"t1_def456","message":"Your approved nested reply."},
    {"row_id":"self-001","action":"post","kind":"self","subreddit":"example","title":"Your approved title","body":"Your approved body."},
    {"row_id":"link-001","action":"post","kind":"link","subreddit":"example","title":"Your approved link title","link_url":"https://example.com/guide"},
    {"row_id":"dm-001","action":"dm","recipient_username":"example_user","message":"Your approved chat message."}
  ]
}
RowContent and targetOptional fields
Commentaction: reply, subreddit, root post_fullname, and messageAdd parent_comment_fullname for a nested reply. Both IDs must belong to the same root post and subreddit.
Text postaction: post, kind: self, subreddit, title, and nonblank bodyflair_id, nsfw, spoiler, send_replies, source_draft_id
Link postaction: post, kind: link, subreddit, title, and link_url; omit bodyThe same optional post fields
One-to-one chataction: dm, recipient_username, and messageconversation_id selects an existing direct conversation. S'more verifies its two participants; multiple matching conversations require an explicit selection.

Validation limits

Every row needs a unique, nonblank row_id. Row IDs and the batch key allow up to 128 bytes. Batches accept 1 to 500 rows within a 1 MiB request, subject to server policy. Unknown fields, duplicate JSON keys or row IDs, and fields from another action reject the submission before enqueue.

Subreddit names use 2 to 21 letters, digits, or underscores without r/. Recipient usernames use 3 to 20 letters, digits, underscores, or hyphens without u/. Post IDs are t3_ plus 1 to 32 lowercase letters or digits; comment IDs use t1_ with the same suffix rule. Comments allow 10,000 Unicode code points, titles 300, text bodies 40,000, and DMs 4,000. Content must be nonblank; titles cannot contain line breaks.

Batch link URLs must be HTTP(S), at most 2,048 bytes, with no embedded credentials, whitespace, or control characters. Flair IDs allow up to 128 bytes without whitespace or control characters. Post flags default to nsfw: false, spoiler: false, and send_replies: true. An optional source_draft_id is the UUID of a saved draft in this workspace; it records lineage while your submitted content remains the approved content.

Optional conversation_id is a Reddit room ID such as !approved_room:reddit.com, with 1 to 255 letters, digits, periods, underscores, equals signs, or hyphens between ! and :reddit.com. Use a real returned room ID. The server resolves the approved username to its native Reddit identity before a write.

Omit schedule for immediate eligibility and pacing for defaults. The shared outreach reference gives the exact local-time and pacing objects, the default 30-day scheduling horizon, seven-day expiry, and 15 to 300 second pacing bounds. Reuse a key only for identical explicit input; changing any approved field returns idempotency_conflict.

Generate posts for review

smore_generate_reddit_posts produces 1 to 5 drafts. Supply either an existing workspace Reddit agent_id, or both an inline brief and voice. This example asks for one text post:

{
  "connection_id": "11111111-1111-4111-8111-111111111111",
  "idempotency_key": "reddit-post-review-v1",
  "count": 1,
  "subreddit": "example",
  "kind": "self",
  "brief": {
    "who": "Independent software founders",
    "signals": "Discuss how founders find their first customers",
    "never": "Invent results or promote an unrelated product",
    "goal": "Start a useful discussion about what worked"
  },
  "voice": "Plain language, short paragraphs, and a natural question"
}

For a link draft, use kind: link and supply the exact HTTPS link_url. Generation requires HTTPS even though an approved batch accepts HTTP(S). Optional flair_id must be available in the account's posting context. Optional source_link_ids accepts up to 32 unique workspace proof-link UUIDs that are enabled for drafting. Each brief field and the voice allow up to 20,000 Unicode code points.

The response includes request_id, status, model and prompt provenance, review_only: true, and saved posts with draft IDs. Questions and Markdown are supported. Retrieve a lost response with smore_get_reddit_posts: supply only the returned request_id, or use {"idempotency_key":"reddit-post-review-v1"}. Identical input keeps the original request and context; changed input under the same key conflicts. An interrupted generation call can repeat model work.

Review and edit each returned post, then copy its exact approved content into a post row for smore_submit_reddit_outreach. Including its source_draft_id does not substitute the generated text or approve sending.

Receipts, DM phases, and reconnecting

Read results with smore_get_reddit_outreach and the returned batch_id, for example {"batch_id":"22222222-2222-4222-8222-222222222222","limit":50}. The default page has 50 rows; the maximum is 100. Pass a returned next_cursor unchanged as cursor. The shared batch and row states apply here: completed can include failed or uncertain rows. Results retain the exact approved content, attempt counts, safe error codes, timestamps, and receipts.

Confirmed comments have a t1_ receipt, posts a t3_ receipt, and chat messages an associated event ID. Receipts establish provider acceptance; they do not establish public visibility, reading, or a response.

A DM can pass through stage: dm_create and stage: dm_send. A confirmed room creation retains create_external_id and conversation_id; the row stays queued for its message. Check message_dispatched and the message receipt before reporting it as sent. Cancellation between the two steps preserves the room and stops the message.

If either write is uncertain, send_unknown and unknown_operation identify the unresolved step. S'more does not automatically repeat it, and later writes from that Reddit identity in the workspace wait. Do not create a replacement batch to repeat an unresolved operation. A matching late receipt can settle the original result.

Cancel remaining work with smore_cancel_reddit_outreach and {"batch_id":"22222222-2222-4222-8222-222222222222"}, replacing that placeholder with the returned ID. Already dispatched writes can finish, and cancellation does not retract published content. Grant expiry or revocation, membership removal, or account/workspace closure removes authority for remaining work.

If the sender needs renewal, the batch pauses and returns next_action.type: reconnect_reddit, a Settings link, and resume_policy: automatic_after_same_account_reconnect. An owner or administrator opens that link, selects the batch's workspace, and reconnects the same verified t2_ Reddit identity. The username alone is insufficient. Pending rows resume within expiry; sent and uncertain writes are not repeated.

Approve access in the browser

Add S'more to your MCP client, sign in, and approve a workspace-scoped connection through OAuth.

Connect Viral Score