mcpField
C
Creatif Space

Creatif Space

リモート
creatif.spaceソーシャルメディア0今日更新
リポジトリ公式サイト

Creatif Space について

Creatif Spaceは、AIクライアントからソーシャルコンテンツを管理するリモートMCPサーバーです。下書き、承認、公開、レポートに対応し、公開操作の前にプレビューと確認を行います。

主な機能

  1. 01チャンネル、投稿、ファイルの一覧
  2. 02ソーシャル投稿の作成と編集
  3. 03承認リンクの作成と追跡
  4. 04公開前のプレビューと確認
  5. 05インサイトとレポートの確認

活用シーン

  1. 01キャンペーン用の投稿準備
  2. 02クライアントへの下書き承認依頼
  3. 03投稿の予約または再試行
  4. 04パフォーマンスレポートの共有

MCP 対応

Creatif Spaceのアカウント、コンテンツ、承認、公開、インサイト機能をMCPツールとして提供します。呼び出し元のBearerトークンで既存のV1 APIにアクセスします。

設定

リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。

エンドポイントhttps://mcp.creatif.space/mcp
インストールコマンドをコピー
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。

ツール

詳細

creatif.space MCP サーバー

creatif.space 用のリモート MCP サーバーです。コネクター URL:https://mcp.creatif.space/mcp(/ でも応答します)。Streamable HTTP、ステートレス、Node 22、 公式の @modelcontextprotocol/sdk を使用しています。

これは薄いレイヤーです。各ツールは呼び出し元自身のベアラートークンを使って既存の V1 API を呼び出すため、所有権、プラン、Credits、検証は引き続き Laravel が処理します。ビジネスロジックはここにはありません。

60 秒で試す(Claude)

  1. Claude で Settings → Connectors → Add custom connector を開き、名前を creatif.space にして、コネクター URL を貼り付けます: https://mcp.creatif.space/mcp
  2. Connect をクリックし、creatif.space にサインインしてアクセスを許可します。これで Claude は チャンネル、下書き、承認リンクを参照できます。あなたの OK なしに投稿されることはありません: 送信のたびに、まずプレビューが表示されます。
  3. 次のいずれかを尋ねます。それぞれ、すぐに使えるプロンプトを実行します(Claude の プロンプトメニューにもあります):
    • 「来週の計画を立てて:冬のローンチについて Instagram の投稿を 5 件。」 → plan_week がチャンネル用の投稿を下書きします。下書きのみで、投稿はされません。
    • 「承認のために、下書きを [email protected] に送って。」 → send_for_approval が、クライアントが承認したり変更を依頼したりできる承認リンクを作成します。
    • 「今週の結果はどうだった?クライアント用のリンクを作って。」 → weekly_results が直近 7 日間の結果をまとめ、誰でも開けるリンクを作成します。
    • 「クライアント用に先月のレポートを作って。」 → monthly_report が 1 か月分の結果をまとめ、同様のリンクを作成します。

エンドポイント

パス内容
POST /mcp(および POST /)MCP JSON-RPC(ベアラー認証が必要)
GET /health稼働状況。認証不要:{ok, name, version} — serverInfo と同じバージョン(package.json から取得。CHANGELOG.md を参照)
GET /.well-known/glama.jsonGlama コネクターの申告。認証不要(HEAD にも対応)。同じドキュメントを GET /mcp/.well-known/glama.json でも提供
GET /.well-known/oauth-protected-resourceRFC 9728 メタデータ:resource: "https://mcp.creatif.space/mcp"、authorization_servers: ["https://api.creatif.space"]
GET /.well-known/oauth-protected-resource/mcpRFC 9728 のパス形式による同じドキュメント
POST /freeCreatif Space Free Tools — 独立した MCP サーバー。認証不要、IP ごとに 1 分あたり 30 回

/mcp、/、/free における CORS(MCP Inspector web や Web IDE などのブラウザークライアント向け):OPTIONS → 204。Access-Control-Allow-Origin: *(認証情報は使用しません — 認証には Bearer ヘッダーのみを使用)、Allow-Methods: GET, POST, DELETE, OPTIONS、Allow-Headers: authorization, content-type, mcp-protocol-version, mcp-session-id, last-event-id、Expose-Headers: mcp-session-id, www-authenticate、Max-Age: 600。401 や 429 を含め、これらのパスからのすべての応答に同じヘッダーが付与されます。Node アプリ(src/cors.ts)で処理します。nginx は OPTIONS をそのまま通し、独自の Access-Control-* ヘッダーを追加してはいけません。

トークンがない、または無効な場合 → 401 と WWW-Authenticate: Bearer resource_metadata="https://mcp.creatif.space/.well-known/oauth-protected-resource/mcp"(RFC 9728 のパス形式。オリジンから構築。ルートの well-known も同じドキュメントを提供します)。

認証

トークン(Passport OAuth 2.1 アクセストークンまたは cs_live_… API キー)は、 POST {V1_API_URL}/oauth/introspect、ヘッダー X-MCP-Secret、本文 {token} → {active, user_ulid, scopes[], client_id, client_name, token_type, exp} で検証されます。 応答は 60 秒間キャッシュされます(exp を超えることはありません)。同じベアラーがその後、 V1 のルートに転送されます(OAuth PR に組み込まれた mcp ガードを使用します)。

スコープ(scopes_supported):read、draft、approve、publish、approvals:decide — API の config/mcp.php と同じ名前です。すべての V1 呼び出しには、API の監査ログ用に X-MCP-Tool と X-MCP-Client が含まれます(コンテンツは含まれません)。 レート制限:トークンあたり 1 分間に 60 リクエスト(429 + Retry-After)。

クライアントは、動的クライアント登録(POST /oauth/register)または OAuth の クライアント ID メタデータドキュメントによって client_id を取得します。 client_id は、{client_id, client_name, redirect_uris, token_endpoint_auth_method: "none"} を配信する https URL です。API はこれを 取得し(公開アドレスのみ、リダイレクトなし、≤ 5 KB、Cache-Control に従って 5 分〜24 時間キャッシュ)、client_id_metadata_document_supported: true を通知します。

ツール

ツールスコープV1 エンドポイント
list_channels — 再接続が必要なチャンネルには reconnect {reason, next_step} が含まれ、needs_reconnect に一覧表示されます読み取りGET /social-accounts
list_posts (status: draft, waiting, changes_requested, scheduled, published, failed, cancelled; from/to は日付または時刻; channel_id, limit) — waiting / changes_requested は status=scheduled を読み取り、承認待ちの投稿を保持します読み取りGET /social-posts?status&from&to&account_id&limit
list_failed_posts (limit, cursor) — 過去 30 日間、チャンネルごとの failure_code + reason。一部のチャンネルのみ公開に失敗した投稿では、失敗したチャンネルのみ一覧表示します読み取りGET /social-posts?status=failed + ?status=published (from/to = 過去 30 日間)
get_post読み取りGET /social-posts/{id}
list_files (search, type, folder_id, limit)読み取りGET /files
draft_post (caption, channel_ids, file_ids, media_urls, captions_by_channel, type)下書きPOST /social-posts with draft: true
get_account_summary — 1 回の呼び出しでオンボーディングに必要な情報を取得します:プラン、使用済み/残りの上限、残りの Credits、接続済み/再接続が必要なチャンネル、使用済みストレージ、failed_posts (過去 30 日間)、approvals {waiting, changes_requested}、next_steps読み取りGET /credits, GET /social-accounts, GET /files/usage, GET /social-posts?status=failed + ?status=published (list_failed_posts と同様), GET /social-posts?status=scheduled
get_onboarding — 「Get started」チェックリスト (接続、下書き、送信、公開)。各項目は {done, at} を含み、next {step, tool, suggest} は次に提案するステップです読み取りGET /me/onboarding
get_credits — プラン、上限、Credits。spend (今月のアクション別:publish, reply, ai) および renewal (resets_at, days_until)読み取りGET /credits (limits.spend)
create_approval_link (post_ids — または Content Plan: date_from, date_to, timezone, channel_ids — approver_email (必須 — クライアントはこのメールアドレスでサインインして決定します), title, client_name, expires_in_hours) — あらゆるプランに対応。Free:クライアント 1 名 (approver_email で判定)、7 日間、キュー登録 10 件承認POST /social-approval-links (下書きも受け付けます)
create_content_plan (date_from, date_to, timezone, channel_ids, approver_email, title, client_name, expires_in_hours, confirm) — まずプレビューを表示します。confirm: true で Content Plan を作成し、承認者にメールを送信します承認GET /social-accounts, GET /social-posts?from&to (プレビュー); confirm: true → POST /social-approval-links with notify_approver: true
check_approval_status (post_id | link_id)読み取りGET /social-posts/{id} または GET /social-approval-links/{id}
send_approval_reminder (link_id)承認POST /social-approval-links/{id}/remind (リンクごとに 12 時間に 1 回)
update_post (caption, scheduled_at, labels, file_ids | add_file_ids)下書き (下書きおよび承認待ちの投稿のみ)PATCH /social-posts/{id}
schedule_posts (posts: [{post_id, scheduled_at}] 最大 10 件、confirm) — すべての投稿のプレビューと合計 Credits を一度に表示します。confirm: true ですべてを予約するか、何も予約しません公開各投稿のプレビューは GET /social-posts/{id}/send-preview; confirm: true → POST /social-posts/send-batch (まずすべてを確認し、拒否された場合はすでに送信された投稿を取り消します)
schedule_post (post_id, scheduled_at, confirm)公開プレビュー GET /social-posts/{id}/send-preview; confirm: true → POST /social-posts/{id}/send
publish_post (post_id, confirm)公開同様に、今すぐ送信します
retry_post (post_id, confirm) — 投稿のうち失敗したチャンネルに再度送信します。プレビューには各 failure_code と理由が表示されます公開プレビュー GET /social-posts/{id}/retry-preview; confirm: true → POST /social-posts/{id}/retry
get_insight_summary (period: {month} | {from, to} ≤ 92 days, channel_ids) — Pro / Max。Free → plan_required読み取りGET /insight/summary?month | from&to&channel_ids
list_top_posts (period: {month} | {from, to} ≤ 92 days, channel_ids, limit, cursor) — Pro / Max。Free → plan_required読み取りGET /insight/top-posts?month | from&to&channel_ids
get_best_times (days 7–92, channel_ids) — Pro / Max。Free → plan_required読み取りGET /insight/best-times?days&channel_ids
get_insight_csv_link (from, to ≤ 366 days, channel_ids) — Pro / Max。Free → plan_required読み取りPOST /insight/export-csv-link
get_insight_report_link (from, to ≤ 92 days, format onepage|deck|details, channel_ids, locale) — Insight PDF (1 ページ、16:9 のデッキ、または詳細版) をダウンロードするための 15 分間有効な署名付きリンクです。Pro / Max読み取りPOST /insight/export-link
create_insight_share_link (from, to ≤ 92 days, channel_ids, recipient_email) — Insight レポートへの読み取り専用ウェブリンクです。アカウントなしで 30 日間閲覧できます。recipient_email を指定すると、その宛先に一度メールが送信され、list_shared_with_me に表示されます承認POST /insight/share
revoke_insight_share_link (share_id) — 共有 Insight リンクをすぐに無効にします承認DELETE /insight/share/{id}
request_media_upload (filename, mime, size_bytes, folder_id)下書きPOST /files/presign → file_id + 署名付き PUT URL (15 分間有効)
confirm_media_upload (file_id)下書きPOST /files/{id}/complete (409 → GET /files/{id}:すでに準備完了の場合はその状態を返します)
list_conversations (type comment|dm, channel_id, unread_only, since, limit, cursor) — Engage のコメントと DM を 1 つのリストにまとめ、新しい順に表示します読み取りGET /inbox/feed?type&account&unread&since&per_page&cursor
reply_to_conversation (conversation_id, text, confirm) — DM のスレッドへの返信、またはコメントへの公開返信です公開プレビュー GET /inbox/feed/{id}; confirm: true → POST /inbox/feed/{id}/reply
get_storage_usage — 使用量とクォータ (Free:合計 1 GB。有料プラン:Keep クォータ)、保持済みと自動削除の対象 (最も近い日付)、最新の 300 ファイルを表示します読み取りGET /files/usage + GET /files?per_page=60&page=1..5
keep_file (file_id) — Pro/Max。Free → plan_required、クォータ超過 → storage_full、未準備 (409) → file_not_ready下書きPOST /files/{id}/keep
unkeep_file (file_id) — 保持ルールに戻します。auto_delete_at を返します下書きDELETE /files/{id}/keep
suggest_caption (brief, platform) — ユーザーのスタイルに合わせたキャプションとハッシュタグを提案します。保存はしません。Pro/Max。AI_CAPTION_ENABLED がオフの場合は 404 → not_enabled ("キャプションを自分で書いてください")、Free → plan_required下書きPOST /ai/caption
discard_draft (post_id, confirm) — 下書きのみを削除します。まずプレビューを表示し、confirm: true で削除します。scheduled / published / failed の場合は、次のステップとともに not_draft を返します下書きGET /social-posts/{id}, then DELETE /social-posts/{id}/draft
list_approval_links (status active|expired|revoked|all, limit) — ステータス、承認者のメールアドレス、投稿数、承認済み/承認待ち/修正依頼を表示します読み取りGET /social-approval-links
revoke_approval_link (link_id, confirm) — プレビューを表示してからリンクを完全に取り消します。未回答の投稿はユーザーに戻されます承認GET then DELETE /social-approval-links/{id}
list_waiting_approvals — 他のユーザーがこのユーザーに承認を依頼した投稿approvals:decideGET /me/approvals/waiting
decide_approval (link, post_id, decision approve|revise, reason, confirm) — 承認者側の操作です。承認ページと同じルールに従い、mcp として監査記録されますapprovals:decideプレビュー GET /me/approvals/{post}/preview; confirm: true → POST /me/approvals/{post}/decision
list_spaces (status draft|published|archived, search, limit) — Pro/Max読み取りGET /spaces?tab&search
create_space_from_files (title, file_ids 1–100, view_mode) — 常に Draft+Private Space として作成され、公開されることはありません。Pro/Max下書きPOST /spaces with file_ids (作成前に検証されます)
publish_space (space_id, confirm) — Pro/Max公開プレビュー GET /spaces/{id}/publish-preview; confirm: true → POST /spaces/{id}/publish
get_approval_history (post_id) — 1 件の投稿に対するすべての決定を古い順に表示します:実行者 (メールアドレスはマスク)、日時、決定、コメント読み取りGET /social-posts/{id}/approval-audit
get_plan_calendar_link (link_id) — Content Plan の ICS フィード URL (予約済み投稿、キャプションの先頭 60 文字)。読み取り専用で、URL は固定です読み取りGET /social-approval-links/{id}/calendar
get_approval_audit (link_id) — ユーザーのリンクに関するすべての決定を表示します:実行者、投稿、日時、決定、コメント。行単位および CSV で取得できます読み取りGET /social-approval-links/{id}/audit.csv
send_feedback (kind bug|idea|other, message, page) — creatif.space チーム宛てです。公開されず、Credits も消費しません。ユーザーあたり 1 時間に 10 件まで下書きPOST /feedback
get_notification_settings — ユーザーが受信するメールの種類:post_missed_or_failed (“Post missed / failed”;API が独自のキーを提供しない限り、publish_failed スイッチ)、approval_decided、weekly_digest読み取りGET /me/notification-settings
update_notification_settings (post_missed_or_failed — または旧名称の publish_failed —、approval_decided、weekly_digest: true/false;月曜 08:00 のダイジェストのタイムゾーン;少なくとも 1 つ指定)下書きPATCH /me/notification-settings
list_shared_with_me — 「自分と共有されたレポート」:他のユーザーがこのユーザーのメールアドレス宛てに共有した Content Plan と Insight レポートapprovals:decideGET /me/reports/shared
get_connect_link (network) — 手順を含むアプリの接続ページ (https://creatif.space/social/connect?network=…) です。レスポンスにトークンは含まれません。上限に達したプランで新しいネットワークを追加する場合は plan_required読み取りGET /social-accounts + GET /credits (POST /social-accounts/auth-url は使用しません)
メディアのアップロード。 request_media_upload → クライアントが URL に正確なバイト列を PUT します(Content-Type と Content-Length は署名されます)→ confirm_media_upload → ID は draft_post / update_post の file_ids に指定します。アプリと同じ署名付き URL の発行と完了処理を使うため、すべてのルールは Laravel で適用されます。Free は合計 1 GB、Pro は 25 GB、Max は 50 GB の容量上限、ファイルごとの上限、対応形式、マジックバイトのチェックが含まれます。拒否された場合は、storage_full(空き容量確保用の files_url とアップグレード用の billing_url リンク)、file_too_large、unsupported_format、upload_limit、upload_incomplete(PUT の前に確認)、file_not_ready(投稿内で未確認または別ユーザーの ID を使用)として返されます。別のワークスペースの ID は not_found になります。

confirm: true を指定せずに schedule_post / publish_post を呼び出すと、プレビューのみが返されます(チャンネル、Credit のコスト、本日残りの送信数、ブロック要因)。ベアラートークンによる送信は、ユーザーごとに UTC の 1 日あたり 20 件までに制限され、Laravel で適用されます(CapTokenSends、429 daily_send_cap)。アプリの Cookie セッションには上限がありません。

confirm_token。 送信プレビューでは、API が署名した confirm_token が返されます(アプリキーを使った HMAC。ユーザー、投稿、ターゲット ID、Credit の価格に紐付き、有効期間は 10 分です)。ベアラートークン(MCP ガードまたは API キー)による送信では、このトークンを再送する必要があります。トークンがない場合は 422 confirm_token_required、不一致、期限切れ、または偽造の場合は 409 preview_stale になります。承認待ちの下書きとアプリの Cookie セッションには不要です。このサーバーは、ユーザーと投稿ごとに最後のプレビューのトークンをメモリ上に保持し、confirm: true の際に送信します。モデルにトークンが見えることはありません。プレビューの記録がない場合(表示されていない、期限切れ、使用済み、サーバー再起動後)は、新しいプレビューを返すだけで送信は行われません。409 の場合は、新しいプレビューを details.preview に含むツールエラー preview_stale が返されます。

承認と編集には API のルールが適用されます。 クライアントの承認が必要な下書き(またはクライアントが変更を求めた下書き)は、アプリからでもトークンからでも送信・予約されません(409 approval_required)。クライアントに再度承認を求めることのみ可能です。トークンを使っても、編集者自身の承認手順を省略することはできません。トークンで編集できるのは、承認待ちの下書きと投稿のみです(409 not_editable)。

Spaces。 接続済みアプリでは Pro と Max のみ利用できます。トークンがアクセスできるすべての Spaces ルートは config('mcp.route_features') に定義されているため、Free の呼び出し元にはコントローラーの実行前に EnforceTokenScope から標準の 402 plan_required(feature: "spaces")が返されます。ただし、アプリでは Free ユーザーの既存の Spaces も引き続き表示されます。publish_space は publish_post と同様に動作します。プレビューでは confirm_token が返され(ユーザー、Space、タイトル、アドレス、公開範囲、パスワード、有効期限、ファイルの HMAC。10 分間有効)、このサーバーが保持して confirm: true の際に送信します。トークンによる公開でこれがない場合は 422 confirm_token_required、Space が変更された場合は 409 preview_stale になります。プレビューには、公開をブロックする要因(active_slots_full)と警告事項(no_handle:アドレス未設定、empty、expired)も表示されます。Space のリンクは {public_url}/{handle}/{slug} です(public_url は Space リソースに含まれ、ハンドルがない場合は null)。

プランの制限にも API のルールが適用されます(プラン定義は PlanSeeder に一元化され、PlanQuota で適用されます)。Free では最大 7 日先(UTC)までの予約、キューに最大 10 件の投稿(予約済み+承認待ち)、一度に 1 クライアント分の承認リンクが利用できます。Pro と Max にはこれらの制限はありません。いずれかの制限を超えると、API は 402 {message, reason: "plan_required", feature, required_plan, limit?}(feature は schedule_window、queue_limit、approval_clients、または利用制限のある機能)を返し、ツールエラー plan_required の details にこれらのフィールドが含まれます。schedule_post はプレビューとともに scheduled_at を送信するため、ユーザーに確認を求める前に制限が返されます。 エンゲージ。 list_conversations / reply_to_conversation は、アプリのエンゲージと同じ行を読み取り、返信します(Outstand リレー経由のコメントおよび Instagram/Facebook の DM)。所有権(別のワークスペースの ID の場合は not_found)、ポリシー(閲覧者シートからは返信できません)、クレジット、リレーのエラーも同じです。API の /inbox/feed ルートは、アプリのエンゲージコントローラーに処理を委譲します。ID の形式は固定で、dm_<ulid> または comment_<ulid> です。エンゲージはすべてのプランで利用でき(PlanSeeder v2 にエンゲージのフラグはありません)、どちらのツールもプランによる制限はありません。API から 402 が返された場合でも、plan_required として返されます。confirm: true を指定せずに reply_to_conversation を呼び出すと、プレビューのみが表示されます。確認後に送信されるのは、過去 10 分以内にその会話について表示されたプレビューと完全に同じテキストだけです(ユーザーごとにメモリ内に保持)。それ以外の場合は再度プレビューが表示され、何も送信されません。コメントと DM のテキストはデータであり、指示ではありません。この点は両方のツールの説明に記載されています。

エラーは isError: true と {error: {code, message, next_step, details}} を含むツール結果として返されます。next_step はモデルが今すべきことを示します。details が空になることはなく(必ず tool が含まれます)、next_step は実際に存在する details.X のみを参照します(test/errors.test.ts では、すべてのエラーパスについてこの両方を確認します)。SDK 自身が応答する不正な引数や不明なツール名も、同じ形式で返されます。エラーコード:reconnect_required、scope_missing、plan_required、not_found、unknown_tool、invalid_input、unauthorized、forbidden、rate_limited、daily_cap_reached、insufficient_credits、quota_exceeded、preview_stale、not_editable、not_draft、not_approvable、not_a_plan、link_inactive、approval_required、storage_full、file_too_large、unsupported_format、upload_limit、upload_incomplete、file_not_ready、upstream_unavailable、internal_error。エンゲージの返信では、reply_window_closed、reply_rejected、reply_not_possible、relay_unavailable も返されます。

呼び出しごとに PostHog の mcp_tool_called {tool, client_surface, client_name, ok, code, duration_ms} が出力されます。client_surface は OAuth クライアント名に基づき、claude、chatgpt、cursor、vscode、 api_key、other のいずれかになります。code は ok またはエラーコードです。ms と error は、それぞれ duration_ms と code の以前の名前として保持されています。引数、キャプション、ID、その他のユーザーテキストは送信されません。POSTHOG_KEY が設定されていない場合はスキップされます。

意図的に MCP ツールではありません:アカウントデータのエクスポート。 POST /api/v1/me/export (ワークスペース全体を ZIP にまとめ、24 時間有効なリンクをメールで送信)は、サインイン済みの creatif.space セッションからのみ利用できます。mcp.routes には含まれていないため、OAuth トークンや API トークンでは 403 が返されます。アカウントの完全なコピーを AI クライアントに渡すべきではありません。

AI チャットから承認する

クライアント向けです。つまり、creatif.space ユーザーから投稿またはコンテンツプランの承認を依頼された人です。自身のアカウント(リンクの送信先メールアドレス)で creatif.space を Claude または ChatGPT に接続し、同意画面で 承認の決定(approvals:decide)を許可すると、承認ページを開かずに確認して決定できます。

ツール機能
list_shared_with_me「あなたと共有されたレポート」:ユーザーの確認済みメールアドレス宛てに共有されたコンテンツプランとインサイトレポートについて、タイトル、日付、送信者、リンク(プランの場合は、承認待ちの投稿数も表示します)。
list_waiting_approvalsユーザーの決定を待っているすべての投稿と、決定に使用するリンク ID および投稿 ID を表示します。
decide_approval承認するか、理由を添えて修正を依頼します。必ず最初にプレビューを表示し、ユーザーが同意した後、confirm: true の場合にのみ決定します。

オーナー側には、さらに 2 つのツール(スコープ read)があります。get_approval_audit は、オーナー自身のリンクのうち 1 つについて、誰がいつ何を決定したかをコメントとともに行および CSV で表示します。get_approval_history は、承認者のメールアドレスをマスキングしたうえで、1 つの投稿が含まれていたすべてのリンクにわたる同じ履歴を表示します。

ツールが適用するルール(API が強制し、ツールは説明のみを行います):

  • ユーザーの確認済みメールアドレス宛てのリンクのみが対象です。それ以外の人には、想定されるアドレスのヒントとともに forbidden が返されます。別のワークスペースの ID には not_found が返されます。
  • すべての決定は 2 段階です。プレビューの後に確定します。確定時には、ユーザーが確認した投稿そのものに対する署名付きトークン(有効期限 10 分)が送信されます。その間に投稿が編集された場合は、新しいプレビューとともに preview_stale が返され、決定は行われません。トークンがモデルに渡されることはありません。
  • 承認ページと同じルールが適用されます。投稿はプランの日付とチャネルの範囲内にあり、まだ承認待ちである必要があります。送信者が Free プランの場合、決定できるのは今後 7 日分のみです(decidable_from を含む invalid_input が返されます)。
  • すべての決定は source: mcp として監査記録に残り、送信者にはページからの場合とまったく同じように通知されます。
  • 最初の承認待ち投稿の公開日の 1 日前に、承認者にリマインダーメールが 1 通送信されます(プランごとに 1 回。メールからオフにするか、オーナーが PATCH /social-approval-links/{id} {reminders: false} を指定してオフにできます)。
会話例

Rani: 今週、承認が必要なものはありますか?

Claude が list_shared_with_me と list_waiting_approvals を呼び出します。

Claude: Bro からコンテンツプラン December が 1 件共有されています (12 月 1 日〜31 日、Asia/Jakarta)。2 件の投稿が承認待ちです:

  1. 「発売日 — 全品 20% オフ…」— Instagram、12 月 2 日(水)09:00
  2. 「スタジオの舞台裏」— Instagram、12 月 4 日(金)18:00

Rani: 1 つ目を承認してください。2 つ目は、チームが写っている写真を使うよう伝えてください。

Claude は投稿 1 に対して decision: "approve"、投稿 2 に対して decision: "revise" と reason: "Please use the photo with the team in it" を指定して decide_approval を呼び出します。どちらも confirm を指定しないため、両方ともプレビューが返されます。

Claude: 次の内容で進めます:

  • 承認:「発売日…」— 12 月 2 日(水)09:00 に Instagram で公開されます。
  • 修正を依頼:「スタジオの舞台裏…」— Bro に「チームが写っている写真を使ってください」と伝えます。

進めてもよろしいですか?

Rani: はい。

Claude は投稿ごとに 1 回ずつ、同じ引数と confirm: true を指定して decide_approval を再度呼び出します。

Claude: 完了しました。「発売日…」は承認され、水曜日の 09:00 に公開されます。Bro には「スタジオの舞台裏…」についてメモを送りました。ほかに承認待ちのものはありません。

オーナー側では、後日次のように確認できます:

Bro: 12 月の発売投稿を誰がいつ承認しましたか?

Claude がプランのリンク ID を指定して get_approval_audit を呼び出します。

Claude: Rani([email protected])は、12 月 1 日 03:10 UTC に「スタジオの舞台裏…」の修正を依頼しました(「チームが写っている写真を使ってください」)。また、03:10 UTC に「発売日…」を承認しました。どちらも AI チャットからの操作です。CSV も必要ですか?

ツールのアノテーション

すべてのツールには、人が読める title があり、4つの MCP ヒントを明示的な ブール値として設定します。list_*、get_*、check_* は readOnlyHint です。公開投稿、削除、取り消し、または取り消せない決定の記録を行うものは destructiveHint です。対象は publish_post、schedule_post、schedule_posts、 reply_to_conversation、retry_post、publish_space、discard_draft、 unkeep_file、decide_approval、revoke_insight_share_link です。公開投稿 (ソーシャルネットワークまたは公開ウェブ)を行うツールのみが openWorldHint です。対象は publish_post、schedule_post、schedule_posts、 reply_to_conversation、retry_post、publish_space です。ディレクトリの審査フォーム向けの ツールごとの説明は、docs/tool-justifications.md にあります。 test/annotations.test.ts はこれらのルールと同ファイルを確認し、スナップショットで すべてのツールのヒントを固定します。すべてのツールのスコープ、ヒント、説明、入力を網羅した リファレンスは docs/mcp-tools.md です。提供される ツール一覧から npm run docs:tools で生成されます。test/tools-doc.test.ts は、古くなっている場合に CI を失敗させます。

プランのエラーと ChatGPT

どのクライアントについても、ツールの説明に価格、プランの階層、アップグレードについての記述はありません (test/no-upsell.test.ts)。OAuth クライアントが ChatGPT の場合、API の イントロスペクションで client_surface: "chatgpt" と判定されるとき(DCR 名、または chatgpt.com / openai.com のリダイレクトホスト)、あるいはクライアント名に ChatGPT / OpenAI が含まれるときは、すべての 402 または plan_required が次のようになります。

{ "error": { "code": "not_available_on_plan", "message": "This isn’t available on this account’s plan.", "next_step": "…no plan change or purchase…", "details": { "tool": "…" } } }

アップグレードリンクや価格提示の手順はなく、その他のエラーからは課金/チャージの リンクが取り除かれます。他のクライアントには、API のメッセージとリンクが変更されずに返されます (test/chatgpt-surface.test.ts)。

レート制限(429)

すべてのツールは、API の 429 を同じエンベロープに変換します。 {code: 'rate_limited', message, next_step, details: {retryable: true, retry_after_seconds}}。

  • message: API 独自のテキストです。
  • retry_after_seconds: 本文の retry_after、なければ Retry-After ヘッダー(EnforceTokenScope のトークン制限ではヘッダーのみが送信されます)、それもなければ 60 が使われます。

2種類の 429 は、それぞれ独自のコードを維持します。upload_limit(本日のアップロードが一時停止中)と daily_cap_reached(接続済みアプリからの送信が1日20回に達した場合)です。test/ratelimit.test.ts はすべてのツールに 429 を送信します。

冪等性(二重送信)

API は Idempotency-Key を含む POST を、ユーザーごと、キーごとに24時間に1回だけ 実行します。再度送信すると、最初の応答が返され(Idempotent-Replayed: true)、 処理は再実行されません。これは公開/予約送信(/send)、/retry、承認リンクの作成に適用されます。 サーバーは確認ごとに1つのキーを送信します。

  • publish_post、schedule_post、retry_post は、確認済みプレビューのトークンからキーを 生成します。確認を2回送信しても、送信と課金はそれぞれ1回だけです。
  • create_approval_link は、10分間のウィンドウ内で引数からキーを生成します。同じリンクを2回要求しても、作成されるのは1つです。

キーはハッシュです。トークンや引数が含まれることはありません。2xx の 応答のみが保持されるため、拒否された確認は、原因を解消すれば再送信できます。

ページネーション

すべての list_* ツールは同じ方法でページ分割します。limit と cursor を受け取り、 next_cursor(次のページがない場合は null)を返します。同じフィルターを指定して next_cursor を cursor として渡すと、次のページを取得できます。

  • 不透明なカーソル: ツール、位置、フィルターのフィンガープリントが含まれます。別のリストからのカーソルや、 異なるフィルターで再利用されたカーソルは、次の手順「カーソルなしで最初からやり直す」とともに invalid_input として拒否されます。
  • list_posts: GET /social-posts の limit + offset でページ分割し、次のページがあるか確認するために行を1つ余分に取得します。
  • list_files: API のページ番号に従います。カーソルには最初のページのページサイズが保持されます。
  • list_conversations: インボックス独自のカーソルを使用します。
  • その他: API から全件を受け取り、サーバー側でページ分割します。

src/tools/paging.ts。テストは test/pagination.test.ts にあります。

構造化出力

list_channels、list_posts、get_post、get_credits、 list_waiting_approvals、check_approval_status、get_insight_summary、 list_files、list_spaces、get_storage_usage は outputSchema を宣言し、 structuredContent を返します。古いクライアント向けに、同じ JSON はテキストブロックにも含まれます。スキーマ(src/tools/outputs.ts)では、エージェントが依存するフィールドの名前と型を定義し、新しいフィールドも受け入れるため、API にフィールドが追加されても呼び出しは失敗しません。エラー結果には structuredContent は含まれず、エラーエンベロープがテキストに含まれます。

プロンプト

prompts/list / prompts/get では、すぐに使える 3 つのワークフローを提供します。それぞれ、既存のツールのみを使ってモデルに手順を示す 1 つのユーザーメッセージです(送信はすべて、引き続きツール独自のプレビューと confirm を経由します)。ユーザーが入力した引数は引用符で囲まれ、データとして明示されます。定義場所は src/prompts.ts です。

プロンプト引数使用するツール
plan_week(「来週の計画」)— チャンネル向けに 1 週間分の投稿を下書きします(下書きのみ)channel_id*、week_start、theme、posts(1~7)list_channels、list_posts、suggest_caption、draft_post
send_for_approval(「クライアントに承認を依頼」)— 下書きを 1 つの承認リンクにまとめますapprover_email*、post_ids(カンマ区切り)、client_namelist_posts、get_post、create_approval_link、check_approval_status
weekly_results(「週間結果」)— 過去 7 日間(または 1 か月分)を集計し、共有リンクを作成しますmonth(過去 7 日間の代わりに指定する YYYY-MM)、share(yes|no)get_insight_summary、create_insight_share_link
monthly_report(「月次レポート」)— 1 か月分を集計し、共有リンクを作成しますmonth(YYYY-MM、デフォルトは先月)、share(yes|no)get_insight_summary、create_insight_share_link

レジストリメタデータ

  • mcp/server.json:公式 MCP レジストリエントリー(io.github.creatifren/creatif-space、リモート https://mcp.creatif.space/mcp、エントリーバージョン 1.2.2)。パブリッシャーが提供する _meta には、OAuth の詳細(認可サーバー、保護されたリソースのメタデータ、スコープ)、すべてのツール、すべてのプロンプト、サーバーバージョンが記載されています。
  • mcp/free-tools/server.json:無料ツールのエントリー(io.github.creatifren/creatif-space-free-tools、リモート https://mcp.creatif.space/free、認証なし、3 つのツール、エントリーバージョン 1.1.0)。
  • glama.json(リポジトリのルート):Glama のメンテナー。レジストリの名前空間と同じオーナーです。
  • test/registry.test.ts では、これらすべてがサーバーと一致していることを確認します。ツール、プロンプト、スコープ、バージョンが一致していること、README の Tools テーブル内のツール数が一致していること、スキーマフィールドのみであることを検証します。
  • 公開は手動で行い、このリポジトリでは実行しません: .github/workflows/mcp-registry.yml は workflow_dispatch でのみ実行されます。公開は Rizal が行う公開操作です。両方のエントリーで使用する正確なコマンドは docs/registry-publish.md に記載されています。

リソース

resources/list と resources/read では、スコープ read の読み取り専用 JSON リソースを 2 つ提供します。定義場所は src/resources.ts です。

URI内容同じ形式のもの
creatif://channels接続済みのチャンネルと、再接続が必要なチャンネルlist_channels(上限 100)
creatif://schedule/next-7-days現在から現在 + 7 日までに予定されている投稿(最大 100 件)、日時が近い順、{from, to, count} を含むlist_posts の status scheduled
  • エラー: スコープが不足している場合や API エラーが発生した場合、data に通常の {code, message, next_step, details} エンベロープを含む JSON-RPC エラーになります。
  • 監査: API 呼び出しには X-MCP-Tool: resource.channels / resource.schedule が付与されるため、監査ログと mcp:usage に表示されます。

無料ツール(/free)

同じプロセス上にある、2 つ目のステートレスな MCP サーバーです:check_caption、 approval_request_template、connect_guide。サインインは不要で、ユーザーデータは保存されません。 各呼び出しでは、既存の POSTHOG_KEY を使って PostHog に free_tool_called {tool, network} を送信します(キャプションのテキストは送信しません)。文面と制限は free-tools/*.json にあります(caption-rules.json、ニッチごとにキー付けされた approval-templates.json、および file:line の根拠情報を含む connect-guides.json。この根拠情報が呼び出し元に送信されることはありません)。connect_guide は account_type も返します。各項目は confirmed(コードを根拠として示す)または check in app(コードで確認できないため、 推測しない)です。レジストリのエントリー free-tools/server.json (io.github.creatifren/creatif-space-free-tools)は、mcp/server.json のみを公開するレジストリのワークフローでは公開されません。

環境

変数デフォルト備考
PORT3010
HOST127.0.0.1前段に nginx を配置
V1_API_URLhttps://api.creatif.space/api/v1
MCP_RESOURCE_URLhttps://mcp.creatif.space/mcpコネクターの正確な URL = リソース ID。Laravel の MCP_RESOURCE_URL と同じ値
MCP_AUTHORIZATION_SERVERhttps://api.creatif.space
MCP_INTROSPECT_SECRET—実稼働モードでは必須。Laravel の値と同じ
MCP_AUTH_MODErealstub はテスト専用で、NODE_ENV=production では拒否されます(トークンは stub:<user_ulid>:<scopes>)
POSTHOG_KEY—未設定の場合、分析データは送信されません
POSTHOG_HOSThttps://us.i.posthog.com
GLAMA_CLAIM公開済みのクレームGET /.well-known/glama.json および GET /mcp/.well-known/glama.json で配信されます(公開状態を維持する必要があります)
OPENAI_APPS_CHALLENGE—OpenAI Apps のドメイン検証トークン。GET /.well-known/openai-apps-challenge で text/plain として配信されます。未設定の場合は 404
MCP_PUBLIC_DISCOVERYオフtrue にすると、initialize、notifications/initialized、ping、tools/list がトークンなしで応答します(レジストリのクローラー、クライアントのプレビュー向け。IP ごとに 30 回/分)。tools/call とそれ以外のすべてのリクエストでは引き続き、サインインを求める 401 と WWW-Authenticate(resource_metadata)が返されます。トークン付きのリクエストは常に通常の認証を行います。QA で確認が済むまではオフにしておいてください。

開発

cd mcp
npm ci
npm run lint && npm run typecheck && npm test && npm run build
MCP_AUTH_MODE=stub npm start   # local only

デプロイチェックリスト(QA)

  1. サーバーにNode 22 LTS(node -v → v22.x)と nginx がインストールされていること。DNS の mcp.creatif.space がこのホストを指し、TLS 証明書が発行済みであること(certbot --nginx -d mcp.creatif.space)。
  2. まず API 側を設定します。OAuth PR がデプロイされ、マイグレーションが実行済みであること。Laravel の .env に MCP_INTROSPECT_SECRET と MCP_RESOURCE_URL=https://mcp.creatif.space/mcp が設定されていること。 MCP_RESOURCE_URL は両方の環境(Laravel の .env と /etc/creatif-mcp.env)で、正確に https://mcp.creatif.space/mcp にする必要があります(オリジンのみの値は不可)。
  3. /etc/creatif-mcp.env(モード 600、所有者 root)に、次の名前を設定します: PORT、HOST、V1_API_URL、MCP_RESOURCE_URL、MCP_AUTHORIZATION_SERVER、 MCP_INTROSPECT_SECRET(Laravel と同じ値)、MCP_AUTH_MODE(real、または未設定)、 POSTHOG_KEY、POSTHOG_HOST。ここでは MCP_AUTH_MODE=stub を絶対に設定しないでください。
  4. cd /var/www/creatif.space-api && git pull && cd mcp && npm ci && npm run build && npm prune --omit=dev
  5. 以下の systemd ユニットをインストールし、systemctl daemon-reload && systemctl enable --now creatif-mcp を実行します。以降のデプロイでは systemctl restart creatif-mcp を実行します。
  6. 以下の nginx vhost をインストールし、nginx -t && systemctl reload nginx を実行します。
  7. 動作確認:
    • curl -s https://mcp.creatif.space/health → {"ok":true,...}
    • curl -si -X POST https://mcp.creatif.space/mcp | grep -i www-authenticate → Bearer resource_metadata="https://mcp.creatif.space/.well-known/oauth-protected-resource/mcp"
    • curl -s https://mcp.creatif.space/.well-known/oauth-protected-resource/mcp → "resource":"https://mcp.creatif.space/mcp"
    • journalctl -u creatif-mcp -n 20 に listening on http://127.0.0.1:3010 (auth: real) と表示されること
  8. Claude で、Settings → Connectors → Add custom connector → https://mcp.creatif.space/mcp の順に進み、サインインして list_channels を実行します。

使用状況レポート(日次起動チェック)

API ホストで実行します:php artisan mcp:usage --days=7(1~90。機械可読形式の出力を追加するには --json を指定します)。mcp_audit_logs から、ツールごとの API 呼び出し数、エラー(HTTP ≥ 400)、エラー率、上位のエラーコード(ステータスをモデルが認識する MCP コードにマッピング:402 → plan_required、404 → not_found、5xx → upstream_unavailable…)を集計します。集計データのみを扱い、ユーザー、トークン、IP、クライアント名は含みません。ツール呼び出しではなく API リクエスト数をカウントします(1 つのツールが複数のリクエストを行う場合があります)。また、不正な引数やスコープ不足などの理由でこのサーバー内で拒否された呼び出しは API に到達しないため、集計に含まれません。

レイテンシ:過去 24 時間のツールごとの p50/p95(計測対象の呼び出し数とエラー数も表示)。mcp_audit_logs.duration_ms から取得します。これは API が応答するまでにかかった時間で、EnforceTokenScope によって記録されます。このカラムが存在する前の行には計測時間がないため、対象外です。p95 が遅い順に並びます。--json では latency_24h です。

本番環境での実行

デプロイごとに一度だけビルドします:npm ci && npm run build(続いて npm prune --omit=dev を実行します)。

systemd — /etc/systemd/system/creatif-mcp.service
[Unit]
Description=creatif.space MCP server
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/creatif.space-api/mcp
EnvironmentFile=/etc/creatif-mcp.env
Environment=NODE_ENV=production
ExecStart=/usr/bin/node dist/index.js
Restart=always
RestartSec=3
NoNewPrivileges=true
ProtectSystem=full

[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload && sudo systemctl enable --now creatif-mcp
または pm2 — mcp/ecosystem.config.cjs
module.exports = {
  apps: [{
    name: 'creatif-mcp',
    cwd: '/var/www/creatif.space-api/mcp',
    script: 'dist/index.js',
    env: { NODE_ENV: 'production', PORT: 3010 }, // secrets via the shell env / .env loader
    max_memory_restart: '300M',
  }],
};
nginx — mcp.creatif.space

SSE に対応:バッファリングなし、読み取りタイムアウトを長く設定し、アップストリームへの接続には HTTP/1.1 を使用します。

server {
    listen 443 ssl http2;
    server_name mcp.creatif.space;

    ssl_certificate     /etc/letsencrypt/live/mcp.creatif.space/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mcp.creatif.space/privkey.pem;

    client_max_body_size 2m;

    location / {
        proxy_pass http://127.0.0.1:3010;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Streamable HTTP / SSE
        proxy_buffering off;
        proxy_cache off;
        chunked_transfer_encoding on;
        proxy_read_timeout 3600s;
        proxy_send_timeout 3600s;
        add_header X-Accel-Buffering no;
    }
}

server {
    listen 80;
    server_name mcp.creatif.space;
    return 301 https://$host$request_uri;
}

確認:curl -s https://mcp.creatif.space/health と curl -si -X POST https://mcp.creatif.space/mcp | grep -i www-authenticate。

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。