crm-integration について
販売自動化向けの CRM 連携スキルです。Close CRM、HubSpot、Salesforce の各エンティティ操作、Webhook、パイプライン自動化、CRM 間の同期パターンを扱います。
主な機能
- 01CRM API の認証設定
- 02リード、連絡先、取引、活動の管理
- 03リアルタイム Webhook の処理
- 04販売パイプラインとレポートの自動化
- 05CRM 間の双方向同期と競合解決
活用シーン
- 01HubSpot または Salesforce の販売 API 設定
- 02複数の CRM 間で連絡先や取引を同期
- 03Webhook に応じた CRM データの更新
- 04販売パイプラインの自動化
MCP 対応
README では、Epiphan CRM MCP ツールによる HubSpot の直接検索と、Clay MCP を使ったデータ補完ワークフローが説明されています。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ scientiacapital/ skills --skill crm-integrationインストール後、Claude Code で/crm-integrationを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
config.jsonreference/clay-enrichment-patterns.mdclose-crm-examples.mdclose-deep-dive.mdwebhook-handlers.md詳細
- Close CRM - SMB の営業活動で日常的に使用(最もシンプルな API、最高のコストパフォーマンス)
- HubSpot - 豊富なエコシステムによるマーケティングと営業の連携
- Salesforce - エンタープライズ要件と複雑なワークフロー
- CRM 間の同期 - コンフリクト解決機能を備えた双方向同期
主な成果物:
- 適切な認証を備えた API クライアントのセットアップ
- リード、コンタクト、案件、アクティビティの CRUD 操作
- リアルタイム同期用の Webhook ハンドラー
- パイプラインの自動化とレポート作成
<quick_start> Close CRM(API キー認証):
import httpx
class CloseClient:
BASE_URL = "https://api.close.com/api/v1"
def __init__(self, api_key: str):
self.client = httpx.Client(
base_url=self.BASE_URL,
auth=(api_key, ""), # Basic auth, password empty
timeout=30.0,
)
def create_lead(self, data: dict) -> dict:
response = self.client.post("/lead/", json=data)
response.raise_for_status()
return response.json()
def search_leads(self, query: str) -> list:
response = self.client.post("/data/search/", json={
"query": {"type": "query_string", "value": query},
"results_limit": 100
})
return response.json()["data"]
# Usage
close = CloseClient(os.environ["CLOSE_API_KEY"])
leads = close.search_leads("company:Coperniq")
HubSpot(Python SDK):
from hubspot import HubSpot
from hubspot.crm.contacts import SimplePublicObjectInputForCreate
client = HubSpot(access_token=os.environ["HUBSPOT_ACCESS_TOKEN"])
# Create contact
contact = client.crm.contacts.basic_api.create(
SimplePublicObjectInputForCreate(properties={
"email": "[email protected]",
"firstname": "Jane",
"lastname": "Smith"
})
)
print(f"Created: {contact.id}")
Salesforce(JWT Bearer):
import jwt
from datetime import datetime, timedelta
class SalesforceClient:
def __init__(self, client_id: str, username: str, private_key: str):
self.auth_url = "https://login.salesforce.com"
self._authenticate(client_id, username, private_key)
def _authenticate(self, client_id, username, private_key):
payload = {
"iss": client_id,
"sub": username,
"aud": self.auth_url,
"exp": int((datetime.utcnow() + timedelta(minutes=3)).timestamp())
}
assertion = jwt.encode(payload, private_key, algorithm="RS256")
response = httpx.post(f"{self.auth_url}/services/oauth2/token", data={
"grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
"assertion": assertion
})
self.access_token = response.json()["access_token"]
self.instance_url = response.json()["instance_url"]
</quick_start>
<success_criteria> CRM 連携が成功したと判断できる条件:
- API 認証がエラーなく動作する
- すべてのエンティティタイプで CRUD 操作が完了する
- レート制限が遵守されている(Close:100 req/10s、HubSpot:プランによって異なります)
- Webhook が正しく発火し、処理される
- 重複なくデータが双方向に同期される </success_criteria>
<crm_comparison>
プラットフォームの比較
| 機能 | Close | HubSpot | Salesforce |
|---|---|---|---|
| 認証 | API Key | OAuth 2.0 / Private App | JWT Bearer |
| レート制限 | 100 req/10s | プランにより100-200 req/10s | 100k req/day |
| 最適な用途 | SMB の営業活動、シンプルさ | Tim の主要 CRM(Epiphan CRM MCP 経由) | エンタープライズ |
| 開始価格 | $49/user/mo | 無料(制限あり) | $25/user/mo |
| API アクセス | 全プラン | Starter+($45+) | 全プラン |
| Webhook | 全プラン | Pro+($800+) | 全プラン |
エンティティのマッピング
| 概念 | Close | HubSpot | Salesforce |
|---|---|---|---|
| 会社 | lead | company | Account |
| 人物 | contact | contact | Contact / Lead |
| 案件 | opportunity | deal | Opportunity |
| アクティビティ | activity | engagement | Task / Event |
| カスタムフィールド | custom.cf_xxx | properties | Field__c |
パイプラインステージのマッピング
| ステージ | Close | HubSpot | Salesforce |
|---|---|---|---|
| 新規 | Lead | appointmentscheduled | Prospecting |
| 適格 | Contacted | qualifiedtobuy | Qualification |
| デモ | Opportunity | presentationscheduled | Needs Analysis |
| 提案 | Proposal | decisionmakerboughtin | Proposal/Price Quote |
| 受注 | Won | closedwon | Closed Won |
| 失注 | Lost | closedlost | Closed Lost |
| </crm_comparison> |
<close_patterns>
Close CRM(日常的に使用)
注: Tim の主要 CRM は、Epiphan CRM MCP 経由で利用する HubSpot です。Close CRM のパターンは参考用に残されていますが、現在のワークフローでは使用していません。
クエリ言語の例、主要な操作(リード、案件、アクティビティ)、レート制限ヘッダーについては、
reference/close-crm-examples.mdを参照してください。
クエリ言語、Smart Views、シーケンス、レポートについては、
reference/close-deep-dive.mdを参照してください。 </close_patterns>
<hubspot_patterns>
HubSpot 連携
Python SDK パターン
from hubspot import HubSpot
from hubspot.crm.deals import SimplePublicObjectInputForCreate
from hubspot.crm.contacts import PublicObjectSearchRequest
client = HubSpot(access_token=os.environ["HUBSPOT_ACCESS_TOKEN"])
# Create deal with association
deal = client.crm.deals.basic_api.create(
SimplePublicObjectInputForCreate(properties={
"dealname": "Enterprise Deal",
"amount": "50000",
"dealstage": "appointmentscheduled",
"pipeline": "default"
})
)
# Search contacts by email domain
search = PublicObjectSearchRequest(
filter_groups=[{
"filters": [{
"propertyName": "email",
"operator": "CONTAINS",
"value": "@example.com"
}]
}],
properties=["email", "firstname", "lastname"],
limit=50
)
results = client.crm.contacts.search_api.do_search(search)
関連付けタイプ
| 関連元 | 関連先 | タイプ ID |
|---|---|---|
| コンタクト | 会社 | 1 |
| コンタクト | 案件 | 4 |
| 会社 | 案件 | 6 |
| 案件 | コンタクト | 3 |
バッチ操作、カスタムプロパティ、ワークフローについては、
reference/hubspot-patterns.mdを参照してください。 </hubspot_patterns>
<salesforce_patterns>
Salesforce 連携
SOQL クエリパターン
-- Parent-child relationship (Contacts of Account)
SELECT Id, Name, (SELECT LastName, Email FROM Contacts)
FROM Account WHERE Industry = 'Technology'
-- Child-parent relationship
SELECT Id, FirstName, Account.Name, Account.Industry
FROM Contact WHERE Account.Industry = 'Technology'
-- Semi-join (Accounts with open Opportunities)
SELECT Id, Name FROM Account
WHERE Id IN (SELECT AccountId FROM Opportunity WHERE IsClosed = false)
REST API v59.0
def create_opportunity(self, data: dict) -> dict:
"""Required: Name, StageName, CloseDate."""
response = self.client.post(
f"{self.instance_url}/services/data/v59.0/sobjects/Opportunity/",
headers={"Authorization": f"Bearer {self.access_token}"},
json=data
)
return response.json()
# Composite API (batch up to 200 records)
def composite_create(self, records: list) -> dict:
return self.client.post(
f"{self.instance_url}/services/data/v59.0/composite/sobjects",
json={"allOrNone": False, "records": records}
)
JWT のセットアップ、Platform Events、Bulk API については、
reference/salesforce-patterns.mdを参照してください。 </salesforce_patterns>
<webhook_patterns>
Webhook ハンドラー
署名検証機能を備えた Close の FastAPI Webhook ハンドラーと、Webhook イベントの全リストについては、
reference/webhook-handlers.mdを参照してください。 </webhook_patterns>
<sync_architecture>
CRM 間の同期
アーキテクチャ
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Close │────▶│ Sync Layer │◀────│ HubSpot │
│ (Primary) │◀────│ (Postgres) │────▶│ (Marketing)│
└─────────────┘ └──────────────┘ └─────────────┘
同期レコードのスキーマ
CREATE TABLE crm_sync_records (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
entity_type VARCHAR(50) NOT NULL,
close_id VARCHAR(100) UNIQUE,
hubspot_id VARCHAR(100) UNIQUE,
salesforce_id VARCHAR(100) UNIQUE,
email VARCHAR(255),
company_name VARCHAR(255),
last_synced_at TIMESTAMPTZ,
sync_source VARCHAR(50),
sync_hash VARCHAR(64)
);
CREATE INDEX idx_sync_email ON crm_sync_records(email);
コンフリクト解決
from enum import Enum
class ConflictStrategy(Enum):
CLOSE_WINS = "close" # Close is source of truth
LAST_WRITE_WINS = "lww" # Most recent update wins
def resolve_conflict(close_record, hubspot_record, strategy):
if strategy == ConflictStrategy.CLOSE_WINS:
merged = close_record.copy()
for key, value in hubspot_record.items():
if key not in merged or not merged[key]:
merged[key] = value
return merged
重複排除、移行スクリプト、一括同期については、
reference/sync-patterns.mdを参照してください。 </sync_architecture>
<integration_points>
連携ポイント(利用可能な MCP ツール)
HubSpot / Epiphan CRM
| ツール | 用途 |
|---|---|
hubspot_search_companies | 名前またはドメインで企業を検索 |
hubspot_search_contacts | メールアドレスまたは名前で連絡先を検索 |
hubspot_search_deals | 名前または PO 番号で取引を検索 |
hubspot_get_company | HubSpot ID で企業の詳細を取得 |
hubspot_get_contact | HubSpot ID で連絡先の詳細を取得 |
hubspot_get_deal | HubSpot ID で取引の詳細を取得 |
crm_search_customers | 顧客を検索(企業名のあいまい一致) |
crm_get_customer | CRM ID で顧客の詳細を取得 |
crm_search_customers | 企業名またはメールアドレスで顧客を検索 |
crm_get_order | 注文 ID で注文の詳細を取得 |
crm_get_customer_orders | 顧客の最近の注文を取得 |
analytics_get_device | シリアル番号でデバイスの詳細を取得 |
analytics_search_by_email | メールアドレスで登録済みのデバイスを検索 |
Clay MCP Enrichment (mcp__claude_ai_Clay__)
パターン:HubSpot → Apollo → Clay → HubSpot 同期
| ツール | 用途 |
|---|---|
find-and-enrich-company | ドメインまたは LinkedIn URL で企業を検索して情報を補完 |
find-and-enrich-contacts-at-company | 企業の役職・肩書き・所在地で連絡先を検索 |
find-and-enrich-list-of-contacts | 各企業に所属する、名前が指定された連絡先を検索 |
add-contact-data-points | 連絡先情報の補完をキューに追加(メールアドレス、電話番号、職歴、ソートリーダーシップ) |
add-company-data-points | 企業情報の補完をキューに追加(技術スタック、資金調達、従業員数、競合他社など) |
get-task | 情報補完の結果をポーリング(state: completed を確認) |
ask-question-about-accounts | Salesforce のアカウントデータを AI で分析 |
get-my-accounts | フィルターで Salesforce アカウントを検索 |
get-task | taskId でタスクのステータスと結果を取得 |
コストモデル:
- Apollo:無料(ただし、レート制限あり)
- Clay:クレジット制(BDR チームの一般的な利用で月額約 $150~300)
- ウォーターフォール戦略:まず Apollo を試し(高速かつ無料)、不足しているデータ(電話番号、メールアドレス、職歴)は Clay で補完します
通話データとインテリジェンス
| ツール | 用途 |
|---|---|
ask_agent | 複雑な CRM/分析クエリに対応する AI エージェント — アクティビティ履歴、エンゲージメントのタイムライン、取引インテリジェンス |
</integration_points>
<file_locations>
参照ファイル
CRM 固有:
reference/close-deep-dive.md- クエリ言語、Smart Views、シーケンス、レポートreference/close-crm-examples.md- Close クエリ言語、主要な操作、レート制限ヘッダーreference/webhook-handlers.md- Close の Webhook FastAPI ハンドラーとイベント一覧reference/hubspot-patterns.md- SDK パターン、一括操作、ワークフローreference/salesforce-patterns.md- JWT 認証、SOQL、Platform Events、一括 API
運用:
reference/sync-patterns.md- CRM 間の同期、重複排除、移行reference/automation.md- Webhook の設定、シーケンス、ワークフロー
テンプレート:
templates/close-client.py- Close API クライアント全体templates/hubspot-client.py- HubSpot SDK ラッパーtemplates/sync-service.py- CRM 間の同期サービス </file_locations>
ユーザーが CRM との連携を希望している場合: → Tim の BDR ワークフローには、デフォルトで HubSpot(Epiphan CRM MCP)を使用します → 認証のセットアップと基本的な CRUD を提供します
ユーザーがエンリッチメント/連絡先データを希望している場合:
→ Clay MCP のウォーターフォールパターンを使用します(ウォーターフォールに推奨。クレジットの利用は問題ありません)
→ ワークフロー:find-and-enrich-contacts-at-company → add-contact-data-points → 結果が出るまで get-task をポーリングします
→ フォールバック:手早く無料でエンリッチメントするには Apollo MCP を使用します(ポーリングは不要です)
→ 参考:「上記の連携ポイント」にある「Clay MCP Enrichment」を参照してください
→ コスト:Apollo は無料、Clay は月額 150~300 ドルの見込みです
ユーザーが Close CRM を希望している場合:
→ API キーのセットアップとクエリ言語を提供します
→ 参考:reference/close-deep-dive.md
ユーザーが HubSpot を希望している場合:
→ 直接連携には Epiphan CRM MCP ツールを使用します
→ 利用可能なツール:hubspot_search_companies、hubspot_search_contacts、hubspot_search_deals、hubspot_get_company、hubspot_get_contact、hubspot_get_deal
→ 企業の特定:crm_search_customers(あいまい検索)
→ アクティビティデータ:ask_agent(CRM/分析に関する AI クエリ)
→ エンリッチメント:HubSpot への書き戻し前のウォーターフォールエンリッチメントには Clay MCP を使用します
→ 参考:reference/hubspot-patterns.md
ユーザーが Salesforce を希望している場合:
→ JWT 認証と SOQL のパターンを提供します
→ 参考:reference/salesforce-patterns.md
ユーザーが CRM 間の同期を希望している場合:
→ 同期アーキテクチャと競合解決を提供します
→ 参考:reference/sync-patterns.md
ユーザーが Webhook を希望している場合: → 指定された CRM のハンドラーパターンを提供します → 署名検証を含めます
ユーザーが電話番号の検証/ウォーターフォールエンリッチメントを希望している場合:
→ Apollo の後に Clay MCP を使用します:find-and-enrich-contacts-at-company → Email/Phone のための add-contact-data-points → 結果をポーリングします
→ Clay は 50 以上のプロバイダーを集約し、電話番号とメールアドレスの高い一致率を実現します
→ 実装の全容については phone-verification-waterfall-skill を参照してください
<clay_mcp_pattern>
Clay MCP のウォーターフォールエンリッチメントワークフロー、ツールのプレフィックスの参照、コストに関する考慮事項、環境のセットアップ、セッションの例については、reference/clay-enrichment-patterns.md を参照してください。
</clay_mcp_pattern>
結果のサイドカーを出力する
~/.claude/skill-analytics/last-outcome-crm-integration.json に書き込みます:
{"ts":"[UTC ISO8601]","skill":"crm-integration","version":"1.0.0","variant":"default","status":"[success|partial|error]","runtime_ms":[ms],"metrics":{"integrations_configured":[n],"records_synced":[n]},"error":null,"session_id":"[YYYY-MM-DD]"}