mcpField
C
cold-email-outreach

cold-email-outreach

github.com/nikiandrマーケティング・グロース1116 回インストール31 週間前に更新
リポジトリ

cold-email-outreach について

Supabaseの条件に合うリードをコールドメールキャンペーンへつなげるスキルです。対象選定、メールシーケンス作成、キャンペーン設定、記録までを扱い、SmartleadではMCPで自動化し、ほかのツールではCSVとインポート手順を用います。

主な機能

  1. 01Supabaseからリードを絞り込み
  2. 0284日間の連絡クールダウンを適用
  3. 03メールシーケンスの計画とレビュー
  4. 04Smartleadキャンペーン設定の自動化
  5. 05各ツール向けCSVのエクスポート
  6. 06アウトリーチ記録のSupabaseへの保存

活用シーン

  1. 01レビュー済みのSmartleadキャンペーンを開始
  2. 02Instantly、Lemlist、Apollo向けCSVの準備
  3. 03キャンペーンの連絡履歴とクールダウンの追跡

MCP 対応

SmartleadではMCPツールを使い、メールアカウントの一覧、キャンペーン作成、シーケンスや設定の構成、リードの登録、承認後の開始を行います。それ以外のアウトリーチツールではCSVをエクスポートします。

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/nikiandr/goose-skills --skill cold-email-outreach

インストール後、Claude Code で/cold-email-outreachを入力して読み込まれたか確認します。

同梱ファイルskill.meta.json

詳細

コールドメールのアウトリーチ

アウトバウンドパイプラインの最終段階です。Supabase から条件を満たすリードを取得し、email-drafting スキルを使ってメールシーケンスを作成し、ユーザーが選択したアウトリーチツールにキャンペーンを読み込み、すべての情報を Supabase に記録します。

ツールに依存しません: ユーザーが使用しているアウトリーチプラットフォームを尋ねます。MCP ツールが設定されている場合は、Smartlead をデフォルトとして使用します。それ以外のツールや手動のワークフローでは、CSV エクスポートに切り替えます。

自動読み込みのタイミング

次の場合にこのスキルを読み込みます。

  • ユーザーが「キャンペーンを開始して」「アウトリーチを送信して」「これらのリードにメールして」「コールドメールを設定して」と言った場合
  • 上流のスキルが「メールキャンペーンを作成して」と連携する場合、または「passes: supabase-eligible-leads」を渡す場合
  • ユーザーが lead-qualification を完了し、その結果に基づいて行動したい場合

対応するアウトリーチツール

このスキルは特定のツールを前提としません。まずユーザーに尋ね、その後、選択に応じて対応します。

ツール統合動作
Smartlead(デフォルト)MCP ツール(mcp__smartlead__*)全自動:キャンペーンの作成、シーケンスの追加、リードのインポート、スケジュールの設定、開始
InstantlyCSV インポートInstantly のインポート形式に合わせた CSV を生成し、ユーザーが手動でアップロード
LemlistCSV インポートLemlist 互換の列を含む CSV を生成
ApolloCSV インポートApollo のシーケンスインポート形式に合わせた CSV を生成
手動/その他CSV +手順リードとメールを汎用 CSV としてエクスポートし、設定手順を提供

ツールの選択ロジック:

  1. フェーズ 0 でユーザーに「どのアウトリーチツールを使っていますか?」と尋ねます。
  2. Smartlead の場合 → MCP ツールを使って全自動で処理します
  3. Instantly/Lemlist/Apollo の場合 → 各ツール専用のインポート CSV を生成します
  4. その他または不明 の場合 → 汎用 CSV(各タッチにつき email、first_name、last_name、company、title、subject、body)を生成し、使用するツールのインポート要件をユーザーに尋ねます

前提条件

Supabase

tools/supabase/schema.sql のスキーマに従って、人物データが Supabase に保存されている必要があります。people テーブルと outreach_log テーブルが存在している必要があります。新規にセットアップする場合は、python3 tools/supabase/setup_database.py を実行してください。

.env 内の環境変数:

SUPABASE_URL=https://xxx.supabase.co
SUPABASE_SERVICE_ROLE_KEY=eyJ...
アウトリーチツール
  • Smartlead: mcp__smartlead__* 経由で MCP ツールを利用できます。追加のセットアップは不要です。
  • その他すべて: CSV エクスポートのみが必要です。API キーは不要です。

フェーズ 0:情報収集

すべての質問をまとめて尋ねます。カテゴリ別に整理します。上流のスキルですでに回答済みの質問は省略します。

キャンペーンの目標
  1. 目的は何ですか?(ミーティングの予約、デモのリクエスト獲得、返信の獲得、関係構築)
  2. アウトリーチの切り口やフックは何ですか?(採用の兆候、競合からの乗り換え、イベントに基づくもの、課題に基づくもの、コールドデータベース)
  3. このキャンペーンの名前は何にしますか?
アウトリーチツール
  1. どのアウトリーチツールを使っていますか?(Smartlead/Instantly/Lemlist/Apollo/その他/CSV だけでよい)
リードの選定
  1. どのリードを対象にしますか?選択肢:
    • 特定の client_name のすべてのリード
    • 特定の icp_segment
    • 役職のパターン(例:「VP Operations」「Director of Sales」)
    • 業界または所在地のフィルター
    • しきい値を超える qualification_score
    • 特定の source(crustdata、apollo、linkedin など)
    • カスタムフィルター(条件を説明してください)
  2. 除外する対象はありますか?(特定の企業、最近連絡したリード、特定の役職)
  3. キャンペーンの最大規模は?(デフォルト:200)
シーケンスの設計
  1. タッチ数はいくつですか?(デフォルト:3)
  2. タッチの間隔は?(デフォルト:1 日目/5 日目/12 日目)
  3. パーソナライズのレベルは?(レベル 1:差し込みフィールドのみ/レベル 2:セグメント別/レベル 3:リードごとに個別作成)
送信設定(CSV エクスポートの場合は省略)
  1. どのメールアカウントから送信しますか?(アカウントの一覧、または「利用可能なすべてを使う」)
  2. 送信スケジュールは?(デフォルト:受信者のタイムゾーンで月曜~金曜の午前 8 時~午後 5 時)
  3. アカウントごとの 1 日あたりの送信上限は?(デフォルト:1 日 30 件)
  4. 開封とクリックを追跡しますか?(デフォルト:開封は追跡、クリックは追跡しない)

フェーズ 1:Supabase からのリード選定

接続

共有 Supabase クライアントを使用します。

import sys, os
sys.path.insert(0, os.path.join("tools", "supabase"))
from supabase_client import SupabaseClient

client = SupabaseClient(os.environ["SUPABASE_URL"], os.environ["SUPABASE_SERVICE_ROLE_KEY"])
フィルターの構築

ユーザーの条件を、people テーブルの PostgREST クエリパラメーターに変換します:

ユーザーの条件PostgREST フィルター
「VP Operations」title=ilike.*VP Operations*
クライアント「happy-robot」client_name=eq.happy-robot
スコア > 7qualification_score=gte.7
メールアドレスが確認済みemail_verified=eq.true
業界「logistics」industry=ilike.*logistics*
所在地「San Francisco」location=ilike.*San Francisco*
ソース「crustdata」source=eq.crustdata
84日間連絡していないor=(last_contacted.is.null,last_contacted.lt.{84_days_ago})
クールダウンフィルター(必須)

必ず、84日以内(12週間以内)に連絡した人を除外してください。これは任意ではありません。

共有クライアントの check_cooldown() メソッドを使用します:

in_cooldown = client.check_cooldown(client_name="happy-robot", cooldown_days=84)
# Returns set of person_id strings still in cooldown

または、直接クエリします:

  1. outreach_log をクエリして、過去84日以内の sent_date を持つ person_id を取得します:
    GET /rest/v1/outreach_log?select=person_id&sent_date=gte.{84_days_ago}&status=neq.bounced&client_name=eq.{client}
    
  2. それらの person_id を除外セットにまとめます
  3. people クエリに id=not.in.({excluded_ids}) を追加します
提示して確認

サンプルテーブル(10~15件のリード)を表示します。以下を含めてください:

  • 名前、役職、会社、業界、スコア、メールアドレス、最終連絡日

ユーザーに、対象となるリードの合計数、クールダウンにより除外された数、メールアドレスが確認済みの数を伝えます。

続行する前に、フィルターの確認または調整をユーザーに求めます。

フェーズ 2:シーケンスの設計

コピーを作成する前に、シーケンス案を表形式で提示します:

タッチ日メールの種類フレームワークCTA
11コールドイントロSignal-Proof-Ask15分の通話
25新しい切り口/資料PASリソースの案内
312ソーシャルプルーフBABお話しできますか?

フェーズ 3 でコピーを生成する前に、構成についてユーザーの承認を得ます。

フェーズ 3:メールの生成

email-drafting スキルを読み込み、次の情報を渡します:

  • キャンペーンの背景(目標、切り口、製品、実績を示す要素)
  • フェーズ 2 で決定したシーケンス構成
  • 選択したリストからのサンプルリード 3~5 件
  • パーソナライズのレベル
  • 希望するトーン
パーソナライズのレベル別

レベル 1(汎用): 各タッチにつき、差し込みフィールド({first_name}、{company}、{title})を含むテンプレートを 1 つ生成します。すべてのリードに同じテンプレートを使用します。

レベル 2(セグメント): セグメントごと、タッチごとにテンプレートを 1 つ生成します。セグメントは役職、業界、シグナルの種類で定義します。セグメント間で課題と実績を示す要素を切り替えます。

レベル 3(詳細): リードごと、タッチごとに個別のメールを生成します。上限は 50 件です。それを超える場合は、レベル 2 を推奨します。

レビューループ
  1. まず 3~5 件のリード向けにサンプルメールを生成します
  2. ユーザーに提示してレビューしてもらいます
  3. 承認されるまで反復します(最大 3 回)
  4. 承認後、残りのメールを生成します

フェーズ 4:キャンペーンの設定

Smartlead の場合(MCP による自動化)

MCP ツールを使用して、完全に自動化します。次の順序で実行します:

ステップ 1:メールアカウントの一覧表示

mcp__smartlead__get_email_accounts

利用可能なアカウントを提示します。ユーザーに使用するアカウントを選択してもらいます。

ステップ 2:キャンペーンの作成

mcp__smartlead__create_campaign
  name: {campaign_name}

返された campaign_id を保存します。

ステップ 3:シーケンスのステップを追加

mcp__smartlead__save_campaign_sequences
  campaign_id: {campaign_id}
  sequences: [
    { seq_number: 1, subject: "...", email_body: "...", seq_delay_details: { delay_in_days: 0 } },
    { seq_number: 2, subject: "...", email_body: "...", seq_delay_details: { delay_in_days: 4 } },
    { seq_number: 3, subject: "...", email_body: "...", seq_delay_details: { delay_in_days: 7 } }
  ]

マージ変数のマッピング: {first_name} → {{first_name}}、{company} → {{company}} に変換します(Smartlead では二重波括弧の構文を使用します)。

ステップ 4:リードのインポート(1 回につき 100 件)

mcp__smartlead__add_leads_to_campaign
  campaign_id: {campaign_id}
  lead_list: [{ email: "...", first_name: "...", last_name: "...", company_name: "...", ... }]

リードが 100 件を超える場合は、100 件ずつのグループに分けます。

ステップ 5:送信アカウントの割り当て

mcp__smartlead__add_email_accounts_to_campaign
  campaign_id: {campaign_id}
  email_account_ids: [...]

ステップ 6:スケジュールの設定

mcp__smartlead__update_campaign_schedule
  campaign_id: {campaign_id}
  schedule: { ... }

ステップ 7:設定の構成

mcp__smartlead__update_campaign_settings
  campaign_id: {campaign_id}
  settings: { track_opens: true, track_clicks: false, stop_on_reply: true }
CSV ベースのツールの場合(Instantly、Lemlist、Apollo、その他)

ステップ 1:CSV を生成する

列はパーソナライズのレベルによって異なります。

レベル 1(全員に同じテンプレートを使用):

  • CSV の列:email、first_name、last_name、company、title、custom_field_1(シグナル/フック)
  • シーケンステンプレート(件名+差し込みフィールドを含む本文)は別ファイルにします

レベル 2/3(セグメント別またはリード別のメール):

  • CSV の列:email、first_name、last_name、company、title、touch_1_subject、touch_1_body、touch_2_subject、touch_2_body、touch_3_subject、touch_3_body

ステップ 2:ファイルを保存する

skills/cold-email-outreach/output/{campaign-name}-{YYYY-MM-DD}.csv

ステップ 3:ツール固有のインポート手順を提示する

Instantly:

  • CSV をアップロード → Sequences → Create new sequence
  • 列を対応付けます:Email → email、First Name → first_name など
  • 各ステップにシーケンステンプレートを貼り付けます
  • ステップ間の遅延を設定します

Lemlist:

  • People → Import → Upload CSV
  • カスタム変数を列に対応付けます
  • キャンペーンを作成 → メールのステップを追加 → 変数を挿入します

Apollo:

  • Sequences → Create Sequence → メールのステップを追加
  • Contacts → Import → Upload CSV
  • インポートした連絡先をシーケンスに追加します

その他/手動:

  • CSV のパスを提示し、列の構成を説明します
  • ツールで必要な形式をユーザーに確認し、必要に応じて調整します

フェーズ 5:確認と開始

キャンペーンの概要を提示します。

Campaign: {name}
Leads: {count}
Sequence: {touches} touches over {days} days
Sending: {accounts} accounts × {daily_limit}/day = {daily_volume} emails/day
Estimated completion: {date}
Tool: {smartlead/instantly/etc.}
開始前の必須承認

ユーザーの明示的な確認なしにキャンペーンを有効化してはいけません。 概要を提示してから、次のように尋ねます:「開始してよろしいですか? 有効化するには「yes」と入力してください。」

  • Smartlead: mcp__smartlead__update_campaign_status → ステータスを active に設定
  • CSV ツール: ファイルをインポートできる状態であることをユーザーに伝え、ファイルのパスを提示します

フェーズ 6:追跡とログ記録

データベース書き込みポリシー

このフェーズでデータベースに書き込むには、すべてフェーズ 5 の開始ゲートでユーザーから事前承認を得る必要があります。 フェーズ 5 の承認(「開始してよろしいですか?」)は、キャンペーンの有効化とその後のログ記録の両方を対象とします。ただし、キャンペーンを CSV としてエクスポートした場合(Smartlead で開始していない場合)は、ログを記録する前にユーザーに確認してください。まだインポートまたは送信していない可能性があります。

Supabase にログを記録する

開始後(またはエクスポート後)、outreach_log にレコードを挿入します。

POST /rest/v1/outreach_log
Prefer: return=minimal

[
  {
    "person_id": "{person_uuid}",
    "campaign_name": "{campaign_name}",
    "external_campaign_id": "{smartlead_campaign_id or null}",
    "channel": "email",
    "tool": "{smartlead/instantly/lemlist/apollo/manual}",
    "sent_date": "{ISO timestamp}",
    "status": "sent",
    "client_name": "{client_name}"
  },
  ...
]

または、共有クライアントを使用します。

client.log_outreach(entries)

CSV ベースのツールの場合: status = "exported" として記録します。ユーザーがツールでキャンペーンを開始したと確認した時点で "sent" に変更します。

People レコードを更新する

このキャンペーンに含まれるすべての人物について、people テーブルの last_contacted を更新します。

PATCH /rest/v1/people?id=in.({person_ids})
{ "last_contacted": "{ISO timestamp}" }
概要を提示する
{count} people logged to outreach_log
last_contacted updated for {count} people
Campaign ID: {id}
Cooldown active until: {date + 84 days}
Next eligible re-contact: {date}

クールダウンの適用ルール

このスキル全体で使用するクールダウンロジックの参照セクションです。

ルール詳細
デフォルトのクールダウンsent_date から 84 日(12 週間)
バウンスしたリードクールダウンの対象外です。メールが届いていないためです。クールダウンを確認する際のフィルター:status=neq.bounced
実施中のキャンペーンのリード常に対象外です。リードが実施中のキャンペーンに含まれている場合(ステータス = "sent" で、返信またはバウンスがない場合)、別のキャンペーンに追加できません
ユーザーによる上書きユーザーは特定のリードについてクールダウンを明示的に上書きできます。許可する前に確認してください
last_contacted が null の場合これまで連絡していないリードは常に対象となります

出力ディレクトリ

キャンペーンのエクスポートは次の場所に保存します。

skills/cold-email-outreach/output/

このディレクトリが存在しない場合は作成します。ファイル名は {campaign-name}-{YYYY-MM-DD}.csv です。

コメント