mcpField
M
meeting-prep

meeting-prep

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

meeting-prep について

meeting-prepは、インバウンドリードの選別、商談前の準備、ディスカバリーやデモの計画を支援する営業向けスキルです。日付付きの根拠と透明性のある採点を使い、事実を作り足さずに要点をまとめます。

主な機能

  1. 01基準に沿ったインバウンドリード選別
  2. 021画面の商談前ブリーフ
  3. 03ディスカバリーとデモの通話計画
  4. 04日付付きの根拠と明示的な出典
  5. 05任意の読み取り専用CRM・メール情報

活用シーン

  1. 01新規リードをまとめて優先順位付け
  2. 02商談前に企業と担当者の背景を確認
  3. 03提示された顧客課題から質問案を作成

MCP 対応

Crustdata MCP サーバーの `execute` ツールを通じて Crustdata の呼び出しを行います。リード選別と商談準備で使うデータ取得やフィールド指定の方法を定めています。

インストール

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

$npx skills add https://github.com/crustdata/skills --skill meeting-prep

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

同梱ファイルevals/evals.jsonREADME.md

詳細

商談準備

やることは一つです。今日予定されている商談と見込み客への対応です。 営業担当者は商談の合間にこれを開くため、成果物はすべて1画面に収め、すべての情報に日付を付け、セクションを埋めるために何も捏造しません。

3つのモードがあります。

  1. インバウンドの優先度判定 — 誰かがフォームに入力したか、メールを送ってきました。この対応に時間をかける価値はありますか?
  2. 商談前のブリーフ — 日常的に使うモードです。商談の2分前に読める、1画面のブリーフを作成します。
  3. 商談プラン — ディスカバリー質問のプラン、または明示された課題だけに基づくデモの流れを作成します。

依頼からモードが明らかでなければ、どのモードか確認してください。「2時の商談の準備をして」はモード2です。「この見込み客を評価して」はモード1です。「ディスカバリープランを作って」はモード3です。


ステップ0 — コンテキスト(作業を妨げない)

  • 作業ディレクトリに config/gtm-config.md または config/persona-profile.md があれば、読んでください。ICP、販売内容、購買担当者の役職、顧客リスト、競合リスト、話し方などが記載されています。これらをもとに、評価基準と冒頭の話し方を決めます。
  • 存在しない場合は、その場で1〜2つ質問する(「どの業界・規模・地域の顧客に販売していますか? 購買担当者の役職は何ですか?」)か、設定を適切に作成するために icp-builder スキルを案内してください。設定がなくても作業は妨げません。
  • 任意の読み取り専用情報補完: CRM、通話録音ツール、またはメールが接続されている場合は、同じドメインとの過去のメール、メモ、通話を読み取り専用で確認すると、ブリーフの精度が上がります。過去に出た懸念、すでに話をした相手、前回の案件が停滞した理由などを確認できます。読み取り専用とし、書き込みは決して行わず、その情報を軸に成果物を作成しないでください。公開データだけでもブリーフが成り立つ必要があります。
  • カレンダーが接続されておらず「2時の商談の準備をして」と依頼された場合は、どの商談かを確認してください。会社名と、誰と会うのかを尋ねます。

Code Mode の基本ルール(一度読んで、すべての場面で適用)

Crustdata の呼び出しはすべて、Crustdata MCP サーバー(install.crustdata.com/mcp)の execute ツール内で、プレーンな JavaScript スクリプトとして実行します。

  • プレーンな JavaScript のみを使用します。 get_schema から得られる型付きインターフェースに沿って記述しますが、スクリプト本体には型注釈を一切含めません。: Type、as、ジェネリクスはパースエラーとなり、実行前に全体が失敗します。
  • 各スクリプトの先頭には、ソースを示すコメントを付けます。文字どおりの依頼には // user query: ...、そこから導いた手順には // model query: ... を使います。これがないスクリプトは実行前に拒否されます。
  • I/O プリミティブは1つだけです:const r = await callTool(name, params) → { ok: true, data } または { ok: false, status, errorType, message }。必ず r.ok で分岐してください。呼び出しに失敗してもスクリプトは中断されないため、失敗を確認しないと空のデータで処理が続き、「手がかりなし」のように見えてしまいます。
  • fields はレスポンスの許可リストです。 結果には指定したグループだけが含まれます。指定しなかったグループは後で undefined となり、データがないように見えます。読み取るグループはすべて指定してください。
  • 返すデータは必要最小限の射影にします。 スクリプトが返したものだけがモデルに渡されます。生のプロフィールではなく、コンパクトな行にマッピングしてください。
  • 独立した呼び出しは await parallelMap(items, fn) で並列化します。最初に chunk(list, 25) でバッチに分割してください。カーソルによるページネーションや依存する段階は並列化しないでください。identify → enrich は順番に実行し、各段階内で並列化します。
  • company_identify は無料ですが、結果は曖昧です。 1つのドメインまたは名前から複数の企業が一致する場合があります。confidence_score が最も高い候補を選んでください。identify では social_profiles を射影しないでください。プラン制限対象のため、呼び出し全体が 403 エラーになります。
  • プラン制限対象の射影を指定すると、フィールド名を示す 403 エラーとなり、呼び出し全体が失敗します。 person_search では professional_network.followers または metadata を、person_enrich では certifications/honors/updated_at を射影しないでください。
  • フィルターパスとレスポンスパスは異なります。 experience.employment_details.current.company_name でフィルターしますが、レスポンスキーは ...current[].name です。プロフィール URL は social_handles.professional_network_identifier.profile_url に返されます。profileUrl(p) アクセサーを使用してください。
  • カテゴリ値は固定された選択肢です。 もっともらしくても誤った値を指定すると、エラーにならずに結果が0件になります。業種、資金調達ラウンドの種類、役職のシニアリティでフィルターする前に、無料の company_autocomplete/person_autocomplete で値を確認してください。
  • 結果が0件でも、手がかりがないとは限りません。 アカウントに動きがないと営業担当者に伝える前に、execute のレスポンスにある trajectory を確認してください。

モード 1 — インバウンドのトリアージ

入力:フォームやメールで得られた情報(名前、仕事用メールアドレス、会社名またはドメイン、本人申告の役職、そして多くの場合、自由記述の「何をお探しですか」)。運がよければ LinkedIn URL も含まれます。

ステップ 1 — 企業属性を特定して取得する(低コストで、バッチ処理可能)

company_identify は無料です。まずすべてのリードを特定してから、解決した ID を対象に、1回の company_search でバッチ全体の規模、業種、資金調達、成長を取得します(1行あたり約 0.03 クレジット)。ここでは company_enrich を使わないでください。リード1件あたり2クレジットかかるため、トリアージには適しません。

// user query: triage today's inbound — 6 form fills
const leads = inputs.leads; // [{ email, name, title, domain }, ...]
const batches = chunk(leads.map(l => l.domain).filter(Boolean), 25);
const identified = await parallelMap(batches, async (batch) => {
  const r = await callTool("company_identify", {
    domains: batch, // ONE identifier type per call
    fields: ["crustdata_company_id", "basic_info"],
  });
  return r.ok ? r.data : batch.map(d => ({ matched_on: d, matches: [], error: r.message }));
});
const rows = identified.flat();
const unresolved = rows.filter(m => !m.matches?.length).map(m => m.matched_on);
const byDomain = {};
for (const m of rows) {
  const top = (m.matches ?? []).slice().sort((a, b) => (b.confidence_score ?? 0) - (a.confidence_score ?? 0))[0];
  const cd = top?.company_data;
  if (cd) byDomain[m.matched_on] = cd.basic_info?.crustdata_company_id ?? cd.crustdata_company_id;
}
const ids = Object.values(byDomain).filter(Boolean);
checkpoint({ ids, unresolved });

const r = await callTool("company_search", {
  filters: in_("crustdata_company_id", ids),
  fields: ["crustdata_company_id", "basic_info", "headcount", "funding", "locations"],
  limit: ids.length,
});
if (!r.ok) return { error: r.message, unresolved };
return {
  unresolved, // personal-email leads and dead domains — surfaced, never silently dropped
  companies: r.data.companies.map(c => ({
    id: c.crustdata_company_id,
    name: c.basic_info?.name,
    domain: c.basic_info?.primary_domain,
    industries: c.basic_info?.industries,
    hc: c.headcount?.total,
    growth12m: c.headcount?.growth_percent?.["12m"],
    lastRound: c.funding?.last_round_type,
    lastRaise: c.funding?.last_fundraise_date,
    country: c.locations?.country,
  })),
};

locations.country はフィルターとして ISO-3(USA)を受け付けますが、返される値は正規化された国名です。レスポンスの値を "USA" と比較しないでください。

ステップ 2 — タイミングのシグナルを低コストで確認する

limit: 0 を指定した job_search の集計を1回実行すると、特定済みのすべてのアカウントについて、募集中の職種数をまとめて取得できます。販売対象の職能の採用を進めている会社では、予算が動いています。

// model query: open-role counts per inbound account (timing signal, counts only)
const r = await callTool("job_search", {
  filters: in_("company.basic_info.company_id", inputs.ids),
  aggregations: [{ type: "group_by", field: "company.basic_info.crustdata_company_id", agg: "count", size: 100 }],
  limit: 0,
});
if (!r.ok) return { error: r.message };
return r.data.aggregations;
Step 3 — 担当者
  • LinkedIn URL が提示されている場合 → person_enrich(1 クレジット)を fields: ["basic_profile", "experience", "social_handles"] とともに使います。実際の役職、実際の在職期間、実際の勤務先がわかります。重要度の高い見込み客が 1 人なら利用する価値がありますが、ユーザーから求められていない限り、20 人の一括処理では省略します。
  • URL がない場合 → 自己申告の役職を使い、出力では自己申告と明記します。フォームの回答は、実態より高くも低くも申告されます。
  • 役職を、設定にある ICP の購買担当者の役職と照合します。標準化されたシニオリティ区分は、person_enrich と person_search のどちらもすでに返す experience グループに含まれています。検索で取得するのではなく、cur.seniority_level を確認してください。これをフィルタリングに使う場合、値の語彙は固定されており、オートコンプリートを前提としています。Entry Level、Entry Level Manager、Experienced Manager、Senior、Director、Vice President、CXO、Owner / Partner、In Training、Strategic です。
Step 4 — スコアを付け、根拠を示す

7 点満点の透明性のある評価基準を使います。受注実績の履歴がなければ確率を調整できないため、「受注確率 %」は決して出力しないでください。でっち上げたパーセンテージは、数値がないよりも悪い結果になります。

項目ポイント加点基準
企業属性の適合度0-3ICP に対する業種、規模区分、地域の適合度。それぞれ 1 点
購買担当者の役職との一致0-2指定された購買担当者の役職またはシニオリティ区分に一致 = 2 点、隣接する役職または影響力のある担当者 = 1 点、無関係または区分を大きく下回る = 0 点
タイミング0-2以下の条件ごとに 1 点、上限 2 点:6 か月以内の資金調達、12 か月間の従業員数の増加率が 20% 超、販売対象の部門で求人を募集中、60 日以内の関連ニュースまたは投稿

このモードは、今日あなたのもとに届いたリード向けです。自社の顧客リスト、担当テリトリー、または貼り付けたアカウント CSV の優先順位を付けるには、代わりに sales-prospecting の rank-my-accounts レシピを使ってください。

失格条件はスコアより常に優先されます。 次のいずれかに該当する場合は、ポイントにかかわらず見送ります。競合他社(設定に競合他社リストがあればそのリストを使います。ない場合は、失格条件を適用する前に、ICP と同じ一括質問で競合他社を尋ねてください)、既存顧客(アカウント担当者に引き継ぎます)、学生または求職者、会社を特定できない個人メールアドレス、対応できない地域、または設定した下限を下回る従業員数です。

判定区分(チャット出力の場合。レンダリングされた成果物では色付きのピル型ラベルとし、絵文字は使いません):

  • 🔥 今すぐ引き継ぐ — 適合度 ≥ 2、役職 ≥ 1、タイミングが少なくとも 1 点、かつ失格条件なし
  • 🟡 継続育成 — 実在する企業だが、タイミングまたは担当者が適切でない。判定が変わる条件を説明します
  • ⚪ 見送り — 適合しない、または失格条件に該当。該当する条件を明記します

すべての行に理由と証拠の日付を記載します(「Series B、2026-04-12」「求人 17 件、うち 4 件はデータエンジニアリング」)。日付のないシグナルは、営業担当者が活用できないシグナルです。

バッチモード

その日に届いたインバウンドリード全体を、次の列を持つ 1 つの表で順位付けします:リード — 企業 — 適合度 — 役職 — タイミング — スコア — 判定 — 今すぐの理由。スコア順に並べ、判定ごとにまとめます。解決できなかったドメインは、理由(個人メール、無効なドメイン、一致なし)を添えて末尾の短いリストにまとめ、何も見落とされないようにします。その後に、「今日折り返すべき 3 件はこちらです」と提示します。


Mode 2 — 通話前ブリーフ

日常的に使うモードです。入力:企業名(名称またはドメイン)と、面談相手(氏名、できれば LinkedIn URL)。

ブリーフ全体を1つのスクリプトに

まず識別します(無料、あいまい検索で、信頼度が最も高い候補を採用)。次に、互いに独立した4つのデータ取得を並行して実行します。人物情報の補完は企業情報に依存せず、人物の投稿履歴も企業情報に依存しないため、同じステージで実行します。

// user query: prep my 2pm with acme.com — meeting their VP Data
const idr = await callTool("company_identify", { domains: ["acme.com"] });
if (!idr.ok) return { error: idr.message };
const top = (idr.data[0]?.matches ?? [])
  .slice().sort((a, b) => (b.confidence_score ?? 0) - (a.confidence_score ?? 0))[0];
if (!top) return { error: "no company match for acme.com" };
const cd0 = top.company_data ?? {};
const companyId = cd0.basic_info?.crustdata_company_id ?? cd0.crustdata_company_id;
const logo = cd0.basic_info?.logo_permalink; // free, use it if the brief gets rendered

const calls = [
  { key: "company", name: "company_enrich", params: {
      crustdata_company_ids: [companyId], exact_match: true,
      fields: ["basic_info", "headcount", "funding", "news"] } },      // 2 cr, exactly one match
  { key: "jobs", name: "job_search", params: {
      filters: { op: "and", conditions: [
        { field: "company.basic_info.primary_domain", type: "=", value: "acme.com" } ]},
      sorts: [{ field: "metadata.date_added", order: "desc" }], limit: 15 } },
  { key: "person", name: "person_enrich", params: {
      professional_network_profile_urls: ["https://www.linkedin.com/in/example"],
      fields: ["basic_profile", "experience", "education", "social_handles"] } }, // 1 cr
  { key: "posts", name: "social_post_list_live", params: {
      professional_network_profile_url: "https://www.linkedin.com/in/example",
      limit: 5 } },                                                    // 1 cr PER POST — cap it
];
const out = await parallelMap(calls, async (c) => ({ key: c.key, r: await callTool(c.name, c.params) }));
checkpoint(out); // ~8-10 credits already spent — bank them before shaping, so a shaping error can't discard them
const get = (k) => out.find(x => x.key === k)?.r;

const ce = get("company");
const cd = ce?.ok ? (ce.data[0]?.matches?.[0]?.company_data ?? {}) : {};
const cutoff = new Date(Date.now() - 60 * 24 * 3600 * 1000).toISOString().slice(0, 10);
const news = (firstArray(cd.news) ?? [])
  .map(n => ({ title: n.article_title, url: n.article_url, date: n.article_publish_date }))
  .filter(n => n.date && n.date >= cutoff)
  .slice(0, 6);

const jr = get("jobs");
const pr = get("person");
const person = pr?.ok ? (pr.data[0]?.matches?.[0]?.person_data ?? {}) : {};
const cur = person.experience?.employment_details?.current?.[0] ?? {};
const posts = get("posts")?.ok
  ? (get("posts").data.posts ?? []).map(p => ({
      date: p.date_posted, text: (p.text ?? "").slice(0, 280),
      reactions: p.engagement?.total_reactions }))
  : [];

return {
  company: {
    name: cd.basic_info?.name,
    what: cd.basic_info?.description,
    hc: cd.headcount?.total,
    growth12m: cd.headcount?.growth_percent?.["12m"],
    lastRound: cd.funding?.last_round_type,
    lastRaise: cd.funding?.last_fundraise_date,
    logo,
  },
  news,
  openRoles: jr?.ok
    ? { total: jr.data.total_count,
        newest: jr.data.job_listings.map(j => ({ title: j.job_details?.title, added: j.metadata?.date_added })) }
    : { error: jr?.message },
  person: {
    name: person.basic_profile?.name,
    title: person.basic_profile?.current_title,
    company: cur.name,
    since: cur.start_date,
    past: (person.experience?.employment_details?.past ?? []).slice(0, 4).map(e => ({ company: e.name, title: e.title })),
    schools: (person.education?.schools ?? []).map(e => e.school).filter(Boolean).slice(0, 3),
    linkedin: profileUrl(person),
    photo: person.basic_profile?.profile_picture_permalink, // free
  },
  posts,
};

このスクリプトについての注意事項:

  • どちらの補完呼び出しでも、fields は許可リストです。news グループは指定しない限り返されず、人物の education は出身校が共通という接点を見つけるのに役立ちます。
  • social_post_list_live は投稿1件につき1クレジットかかります。5件あれば、相手が何について話しているかを把握するのに十分です。件数を増やす前に、コストを伝えてください。
  • 人物情報の取得で一致する情報が見つからない場合は、URLを確認し、企業情報のみのブリーフを作成してください。人物情報が少ないのは誠実ですが、でっち上げれば担当者の信頼を失います。
  • news グループでカバーできなかった過去60日間の情報が必要ですか?web_search_live で1件検索します(1クレジット)。検索は1件にとどめ、60日より古い情報は除外するか、その旨を明記してください。
成果物 — この順序で1画面にまとめる

企業ブロック 事業内容を1行で説明し、従業員数と過去12か月の成長率、直近の資金調達ラウンドとその日付、日付付きのシグナルを3~5件記載します(ニュース記事とそのURL、求人の状況、資金調達イベントなど)。採用状況はプレスリリースより多くを物語ります。データ関連の求人が20件あればデータに課題があり、初めてセキュリティ担当者を採用するなら、セキュリティ予算がまさに開かれようとしているということです。

人物ブロック 役職と在任期間、1行でまとめた職歴、直近の投稿と日付、話題にする価値のある共通点を記載します(同じ勤務先、同じ学校、同じ街、共通の知人など)。共通点は必須ではありません。無理に作るくらいなら、ないほうがましです。

担当者が実際に読む部分

  1. 話題のポイントを3つ。 それぞれ、根拠と日付を添えた1文にします。「急成長しています」ではなく、「過去12か月で従業員数が34%増え、データチームで6件の求人が出ているため、2024年に構築したパイプラインに負荷がかかっている可能性があります」のように記述します。
  2. 切り出しの一言を1つ。 そのまま口に出して言える文を1つだけ書き、実際にあった過去60日以内の日付付きの情報に触れます。最近の情報がなければ、その旨を伝え、役職の文脈に基づいた切り出しにします。話のきっかけを作るために最近の出来事を決してでっち上げないでください。
  3. ヒアリングの質問を2つ。 オープン形式で、この顧客に即した、上記のシグナルに基づく質問にします。
  4. 想定される反論と先回りの対処。 この役職、この企業規模で、この人物が最も口にしそうな反論を1つ挙げ、それを早い段階で解消する一文を記載します。

それ以外は記載しません。実際の情報がないセクションは省き、空である理由を伝えてください。

ブリーフの一括作成

今日は複数の電話がありますか?まずすべての識別ステージを実行し、その後、会議ごとに1つずつ、カレンダー順でブリーフを作成します。いずれも1画面に収めます。開始前にクレジットの合計を伝えてください。ブリーフ1件あたり約8~10クレジットかかるため、会議が5件なら約50クレジットです。


モード3 — 通話プラン

冒頭で、ディスカバリーかデモかを伝えてください。

ディスカバリープラン
  1. 根拠のある課題仮説を2つか3つ。 モード2のシグナル(募集中の職種、資金調達、成長率、投稿内容)をもとに仮説を立てます。質問を作る前に、手間をかけずに仮説を検証しましょう。職種名や説明文を対象に、[.] の完全一致演算子を使ったクエリの件数を数えます。
// model query: which pain themes show up in acme.com job posts
const themes = ["data quality", "observability", "migration"];
const brands = ["Snowflake", "dbt", "Airflow"];
const probes = [
  ...themes.map(t => ({ label: t, cond: { field: "content.description", type: "(.)", value: t } })),
  ...brands.map(b => ({ label: b, cond: exactToken("content.description", b) })), // [.] for brand names
];
const hits = await parallelMap(probes, async (p) => {
  const r = await callTool("job_search", {
    filters: { op: "and", conditions: [
      { field: "company.basic_info.primary_domain", type: "=", value: "acme.com" },
      p.cond,
    ]},
    limit: 1,
  });
  return { probe: p.label, postings: r.ok ? r.data.total_count : null, error: r.ok ? undefined : r.message };
});
return hits;

(.) はタイプミスに寛容で、似た単語にも一致するため、複数語からなる説明的なテーマには適していますが、ブランド名や製品名には適していません。そうした語には必ず [.](exactToken)を使ってください。

  1. 質問プランは、自由回答形式の質問を8〜12個。30個ではありません。 担当者が初回の通話で尋ねる質問は、おそらく8つほどです。それぞれを適格性評価フレームワークの項目に対応付けます。デフォルトではMEDDICCを使い、ユーザーがSPICEDに沿って進めている場合はそちらを使います。設定に記載がなければ、どちらを使うか尋ねてください。各質問には、満たすフレームワークの項目、検証する仮説、今それを尋ねる理由の3つを含めます。
項目質問検証する内容
指標「そのコストを現在どのように測定していますか?」課題仮説1が数値化されている
課題「午前2時にパイプラインが停止したとき、何が起きるか詳しく教えてください。」仮説1が思い込みではなく、実際の課題である
推進者「ほかに、毎週この課題を感じているのは誰ですか?」複数の関係者に働きかける道筋

質問のルール:誘導せず、自由回答形式にします。公開データですでにわかっていることは、決して尋ねません。従業員数が掲載されているのにVPにチームの規模を尋ねるのは、手元にある唯一の強みを無駄にすることになります。状況、課題、影響、プロセスの順に質問します。

  1. 具体的な次のステップ。 日付と名前を含めて、具体的な依頼を書きます。「来週の火曜日に、データ責任者にも参加してもらって30分の作業セッションを開くのはいかがでしょうか?」のほうが、「時間を見つけましょう」より効果的です。

  2. 網羅状況の確認。 このプランで1回の通話では扱わないフレームワークの項目を列挙します。予測の段階で初めて気づくのではなく、担当者が2回目の通話で何を確認すべきか把握できるようにします。

デモの流れ

見込み客が実際に述べた課題だけをもとに作成します。 「述べた」と見なす根拠は、ユーザーがディスカバリーメモを貼り付けること、同じセッション内でディスカバリーコールに続いてコールプランを作成すること、または接続された録音ツールやCRMにメモがあること(読み取り専用)です。公開情報から得られるのは仮説であり、述べられた課題ではありません。両者を区別し、それぞれ明示してください。

ディスカバリーが不十分なら、何かを作る前にそう伝えます。 「明らかになっている課題は1つで、仮説が2つあります。このデモは一般的な内容になります。最初に15分のディスカバリーの時間を設けますか?」と尋ねます。それでもユーザーが希望する場合は、短縮版を作成します。

構成:

  1. 冒頭の振り返り — 相手が述べた課題を、相手自身の言葉で読み上げます。何かを見せる前に確認します。
  2. 述べられた課題ごとに1つのパート。機能の順ではなく、相手の優先順位に沿って進めます。何を見せるのか、そして相手にとってなぜ重要なのかを伝え、実演してから、「チームでの使い方と合っていますか?」と確認します。根拠となる、述べられた課題がないパートは削除します。このモードで大切なのは、まさにこの姿勢です。
  3. クロージングプラン — 具体的な次のステップ、ほかに確認が必要な人、相手が決めるべきこと、その期限。

見せないものと、その理由を明示的に列挙します。 6つの機能をあえて省くデモは、自信の表れとして受け取られます。


ルール

  • 根拠のある情報のみ。 ブリーフのすべての主張は、Crustdata の検索結果、URL、またはユーザーから提供された情報にたどれる必要があります。不明確な場合は質問するか、省略してください。最近の出来事、共通の知人、課題を決してでっち上げないでください。
  • すべてに日付を付ける。 日付のないシグナルは使えません。60日を超える情報には、背景情報と明記してください。
  • 成果物は1画面に収める。 営業担当者は流し読みします。文章で水増しするのではなく、セクションを削ってください。
  • 作成するすべての文言に妥協しない。 書き出し、質問、要約のどれも、emダッシュを使わず、「delve」/「leverage」/「streamline」は避け、つなぎのためだけの文は入れないでください。下調べを済ませた同僚のように書いてください。
  • 自己申告と検証済みを区別する。 フォームのデータは Crustdata が確認するまでは自己申告です。明記してください。
  • まずは無料データを使う。 連絡先のエンリッチメントは、ユーザーが明示的に希望し、費用を確認した場合のみ行います。person_contact_enrich に基本料金はありませんが、マッチした人物ごとに返される連絡先の種類に応じて課金されます(仕事用メール1、個人用メール2、電話番号2)。1人あたり最大5クレジットです。fields を絞ると最悪の場合の見積もりはできますが、上限が保証されるわけではありません。単一ティアのリクエストでも、5クレジットの上限額が課金され、3つすべてのティアが返された事例があります。そのため、1人あたり5クレジットを上限として提示し、実際の消費量は credits_remaining で確認してください。実行前に上限を伝えてください(「12人分のリードのメールアドレス取得は最大約60クレジットです。実行してよいですか?」)。
  • 接続済みシステムでは読み取り専用。 CRM、レコーダー、メールが接続されている場合は、ブリーフを充実させるために読み取ってください。このスキルは、書き込み、記録、送信、スケジュール設定を一切行いません。
  • 成約確率をパーセンテージで出力しない。 代わりに、評価基準のスコアとその理由を示してください。
  • コンテンツに合わせてレイアウトを調整し、情報を隠さない。 ブランドシステムは固定ですが、レイアウトは固定ではありません。実際のコンテンツが収まらない場合は、レイアウトを変更してください。カードを伸ばす、切り詰めずに折り返す、1列にする、上限を上げる、または横幅の広い要素に専用のスクロールコンテナーを設けるなどの方法があります。カードを途中で切ったり、名前を省略記号で切り詰めたり、行を黙って削除したりしないでください。避けられない上限がある場合は、UI に「214件中、上位50件を表示」のように明記し、引き渡す前にレンダリング結果を確認してください。
  • レンダリング結果で使うアイコン:Lucide を SVG としてインライン化し、ストロークには currentColor を使ってください。成果物の UI で絵文字は使わないでください。🔥/🟡/⚪ の判定区分はチャットでのみ使用し、レンダリングされたブリーフでは色付きのピルに置き換えてください。
  • ロゴと写真は無料です。レンダリング結果で使ってください。 basic_info.logo_permalink は無料の company_identify から返されます。basic_profile.profile_picture_permalink は、person_enrich が返す basic_profile グループに含まれます。メディア CDN は binary/octet-stream として配信するため、リモートの <img src> は空白で表示されます。両方を data:image/jpeg;base64,... URI として Base64 インライン化してください。画像がない場合はモノグラムを代わりに表示してください。
  • 成果物のブランディング:ブリーフとトリアージ表は、デフォルトではチャット内で完結させてください。成果物を作ること自体を目的にレンダリングしないでください。ただし、ユーザーがブリーフまたはトリアージボードをレンダリングされたページやドキュメントとして求めた場合は、ヘッダーまたはフッターに Crustdata のブランドロックアップを含めてください。「Powered by」の小さな大文字表記と、crustdata.com へのリンクを含む公式 Crustdata ワードマークを配置します。ワードマーク一式はこのスキルの assets/ に含まれています。crustdata-logo-light.png(明るい背景用の暗色テキスト)と crustdata-logo-dark.png(暗い背景用の白色テキスト)です。テーマに合った方を約17pxの高さで Base64 インライン化してください。ホットリンクはしないでください。レンダリングされた成果物ではリモート画像を取得できません。ブランドアクセントカラーは #5547E2(暗い背景では #8387FF)です。埋め込み可能な場合は本文フォントに Geist を使い、それ以外はシステムフォントのスタックを使ってください。
  • 引き継ぎ先:詳細なアカウントプランが必要なホットなインバウンドリード → account-research、この企業に似た企業をさらに探す → sales-prospecting、ICP がまだ定義されていない → icp-builder、その企業ですでに知り合いの人物を確認する → warm-path-workspace、このブリーフをもとにアプローチ文を書く → sales-outreach。

エラー処理

  • すべてのスクリプトで r.ok に基づいて分岐してください。 失敗をチェックしないと「何も起きていない」ように見え、担当者がそれを信じたまま通話に臨んでしまいます。
  • company_identify で一致するものがない場合 → リードのドメインは個人用、パーキング中、または新規の可能性があります。理由を添えて未解決として示し、会社を推測しないでください。
  • フィールド名を示す 403 は、プランで制限された投影です。そのフィールドを削除して再実行してください。
  • person_enrich で一致するものがない場合 → URL を確認し、会社情報のみでブリーフを作成して、人物情報が限られていると伝えてください。
  • 投稿やニュースが空でもエラーではありません。「過去60日間に公開された活動はありません」と伝え、役職の情報をもとに導入文を作成してください。
  • すべての実行レスポンスには credits と credits_remaining が含まれます。無料の account_credits を使えば、必要に応じて残高を確認できます。

コスト早見表

呼び出しコスト
company_identify、autocomplete、get_schema、account_credits無料
company_search / person_search / job_search1件あたり約0.03クレジット
limit: 0 を指定した job_search の集計件数のみ、ほぼ無料
person_enrich(プロフィールグループのみ)1クレジット
exact_match: true を指定した ID による company_enrich1件の一致につき2クレジット
social_post_list_live投稿1件あたり1クレジット — 必ず limit を設定してください
web_search_liveクエリあたり1クレジット
person_contact_enrich(オプトイン)基本料金なし。1人あたり上限5クレジット — fields を絞っても上限が保証されるわけではありません

一般的な消費量:10件のリードをトリアージする場合、1クレジット未満です。通話前の完全なブリーフは約8~10クレジットです。

ツールの依存関係

このスキルには次のものが必要です。

  • Crustdata MCP サーバー (install.crustdata.com/mcp):list_tools、get_schema、execute を公開する単一の Code Mode MCP です。すべての Crustdata データツールは、await callTool(name, params) を介したプレーンな JavaScript スクリプト execute({ code }) 内で呼び出します。get_schema の型付きインターフェースに基づいて作成しますが、スクリプト本文には型注釈を含めません。ここで使用するツール:company_identify、company_search、company_enrich、person_search、person_enrich、job_search、social_post_list_live、web_search_live、company_autocomplete、person_autocomplete、person_contact_enrich(オプトイン)、account_credits
  • 任意のコネクター:ユーザーがすでに利用している可能性がある CRM、通話録音ツール、カレンダー、メールなど。いずれも読み取り専用かつ任意です。このスキルは、これらがなくても公開データだけで完全に動作します。

icp-builder(このスキルが読み込む設定を書き込みます)、sales-prospecting、account-research、warm-path-workspace とともに提供されます。

コメント