MCPサーバー
SupDesk の MCP(Model Context Protocol)サーバーは、AI アシスタントやその他の LLM を使うツールに、プロジェクトのヘルプセンター、フィードバックボード、チェンジログ、メッセージスレッド、ベータプログラム、ウェイトリストへの直接アクセスを提供します。
エンドポイント
https://mcp.supdesk.app/mcp認証
API キーを Bearer トークンとして渡します。
Authorization: Bearer sd_live_...キーは SupDesk コンソールの ワークスペース設定 → API キー で生成します。
キーがプロジェクトを決めるため、どのツールも project_id 引数を取りません。モデルが推測したり間違えたりする余地がありません。
利用できるもの
どのツールが現れるかはプロジェクト次第です。プロジェクト設定 でオフにした機能のツールは tools/list にまったく現れません。REST API がそのルートを 404 で返すのと同じ扱いです。
| グループ | ツール数 | 必要な設定 |
|---|---|---|
| ヘルプセンター | 10 | ヘルプセンターが有効 |
| フィードバックボード | 5 | フィードバックボードが有効 |
| チェンジログ | 5 | チェンジログが有効 |
| メッセージ | 5 | プライベートメッセージが有効 |
| ベータテスト | 8 | ベータが有効 |
| ウェイトリスト | 4 | ウェイトリストが有効 |
| 概況 | 1 | 常に利用可能 |
読み取りはどのプランでも動きます。書き込みには有料プランが必要です — 読み取り専用のキーで作成・更新・削除を行うと forbidden が返りますが、同じキーでの読み取りは問題なく動きます。
ヘルプセンター
list_articles— 記事を更新の新しい順に返します。下書きとアーカイブ済みも含むため、顧客に見えるものだけが必要ならstatusで絞り込みます。get_article— id で記事を 1 件、Markdown 本文つきで取得します。search_articles— 公開済み の記事を対象とした全文検索。関連度順で、抜粋つきです。create_article— 下書き を作成します。公開は別の呼び出しなので、誤って顧客に届くことはありません。update_article— 任意のフィールドを更新します。statusをpublishedまたはarchivedに設定します。delete_article— 完全削除です。記事を残したい場合はアーカイブしてください。list_article_categories、create_article_category、update_article_category、delete_article_category— カテゴリを削除しても記事はそのまま残り、カテゴリ無しになります。
記事の本文は HTML ではなく Markdown です。ポータルは HTML を決して評価しないビューアで描画するため、HTML はそのままの文字列として読者に届きます。
プランの記事枠を使い切ると、create_article は limit_reached で失敗します — Free 5、Pro 50、Team 無制限です。
フィードバックボード
list_feedback— 投稿を新しい順に返します。typeで絞り込まない限り、3 種類(bug、feature、feedback)すべてを対象とします。get_feedback、create_feedback、update_feedback—update_feedbackで投稿をbacklog → open → planned → in_progress → doneと進めます。delete_feedback— 投稿とその投票・コメントを削除します。
チェンジログ、メッセージ、ベータ、ウェイトリスト
REST API と同じクエリを使った完全な機能対応です。
- チェンジログ —
list_changelog、get_changelog_entry、create_changelog_entry、update_changelog_entry、delete_changelog_entry。エントリは下書きから始まります。購読者への告知メールを送るのは公開の操作だからです。 - メッセージ —
list_threads、get_thread(全メッセージ履歴つき)、create_thread、reply_to_thread、update_thread。 - ベータテスト —
list_beta_programs、get_beta_program、create_beta_program、update_beta_program、delete_beta_program、list_beta_testers、add_beta_tester、remove_beta_tester。add_beta_testerはメールアドレスに対して冪等で、受諾トークンを返します。このサーバーはメールを送らないため、招待の送付は呼び出す側の役割です。 - ウェイトリスト —
list_waitlist、add_waitlist_signup(メールアドレスに対して冪等)、update_waitlist_signup、remove_waitlist_signup。
概況
project_stats はプロジェクト全体の件数を返します — ステータス別のフィードバック投稿数、未対応のスレッド数、公開済みと下書きの記事数、それらの記事が集めた「役立った / 役立たなかった」票数です。4 つのページ送りリストをたどらずに「どれだけ未処理があるか」に答えられます。
構造化出力
すべてのツールが outputSchema を宣言し、structuredContent(型付きで検証済み)と、同じデータを JSON で持つ content テキストブロックの両方を返します。クライアントが対応している方を処理してください。
const result = await mcpClient.callTool("get_article", { id: "8f7a..." });
result.structuredContent.article.title; // 型付き
JSON.parse(result.content[0].text); // 同じデータ、フォールバック用アノテーション
クライアントが呼び出す前に内容を判断できるよう、すべてのツールにアノテーションが付いています。
| アノテーション | 付与対象 |
|---|---|
readOnlyHint: true | list_*、get_*、search_*、project_stats |
idempotentHint: true | 読み取り系と update_* |
destructiveHint: true | delete_*、remove_* |
ページ送り
一覧系ツールは不透明な cursor を受け取り、next_cursor を返します。次のページではそれをそのまま渡し、null になったら止めてください。
let cursor;
do {
const page = await mcpClient.callTool("list_articles", { status: "published", cursor });
handle(page.structuredContent.data);
cursor = page.structuredContent.next_cursor;
} while (cursor);カーソルは計算するものではなくトークンなので、不透明なものとして扱ってください。壊れたカーソルは、黙って 1 ページ目に戻る代わりに invalid_request を返します。黙って戻すと、ページ送りの走査が永久に終わらなくなるからです。
なお、これは各ツール自身の引数スキーマ上の取り決めです。MCP のプロトコルレベルのカーソルは ツールやリソースの一覧 に適用されるもので、ツールの戻り値には適用されません。下のリソース一覧は本来の仕組みを使っています。
リソース
ツールを呼んで結果を貼り付ける代わりに、プロジェクトの内容をコンテキストとして添付するためのものです。
| URI | 内容 |
|---|---|
supdesk://articles/{slug} | 公開済みのヘルプ記事、Markdown 形式。 |
supdesk://board | プロジェクトの未対応フィードバック投稿、JSON 形式。 |
記事の一覧は本当にプロトコルレベルでページ送りされ、対象は 公開済みの記事のみ です。リソースはクライアントがそのまま提示しうる内容であり、下書きが未公開なのには理由があるからです。
プロンプト
プロジェクトの実データに接続された 2 つの出発点です。
draft_article_from_thread— 解決済みのサポート会話をヘルプセンター記事に変えます。同じ質問を持つ次の顧客が、スレッドを開く代わりに答えを見つけられるようになります。ヘルプセンター と プライベートメッセージの両方が有効である必要があります。triage_feedback— 投稿を 1 件評価し、根拠とともにステータスを提案します。先にsearch_articlesを確認するため、既存の答えがあれば新しい作業を提案する代わりにそれを示します。
どちらも引数に MCP の補完機能を使います。カテゴリを入力している間、サーバーはプロジェクトの実際のカテゴリスラッグを返すので、推測する必要がありません。
ログ
複数手順の書き込みは MCP のログ機能で進捗を通知します — create_article はプランの枠を確認し、空いているスラッグを探し、それから挿入します。その各段階を知らせます。ログに対応していないクライアントでも影響はなく、書き込みはどちらの場合も実行されます。
例
Claude Desktop
~/Library/Application Support/Claude/claude_desktop_config.json に追加します。
{
"mcpServers": {
"sup-desk": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://mcp.supdesk.app/mcp",
"--header",
"Authorization: Bearer sd_live_..."
]
}
}
}質問に答える、あるいは答えを書く
// ヘルプセンターにすでにあるか確認する。
const hits = await mcpClient.callTool("search_articles", {
query: "パスワード リセット",
limit: 5
});
if (hits.structuredContent.data.length === 0) {
// まだ無いので下書きを作る。作成されるのは下書き。
const created = await mcpClient.callTool("create_article", {
title: "パスワードをリセットするには?",
body: "**設定** を開き、*パスワードをリセット* を選びます。",
category_id: "3c2b..."
});
// 公開は意図的に別の手順。
await mcpClient.callTool("update_article", {
id: created.structuredContent.article.id,
status: "published"
});
}ボードを仕分ける
const open = await mcpClient.callTool("list_feedback", {
status: "open",
limit: 10
});
await mcpClient.callTool("update_feedback", {
id: open.structuredContent.data[0].id,
status: "planned"
});未処理をひと呼び出しで
const stats = await mcpClient.callTool("project_stats", {});
// { posts_by_status: { open: 12, planned: 3, ... }, open_threads: 4,
// articles_published: 18, articles_draft: 2,
// article_helpful: 240, article_not_helpful: 11 }レート制限
MCP サーバーは REST API と同じ制限を共有します:プロジェクトあたり 60 秒間に 120 リクエストです。レート制限と利用状況を参照ください。
エラー
失敗したツール呼び出しは isError: true を返し、REST API と同じエラー語彙を使います。
{
"error": {
"code": "limit_reached",
"message": "Your plan allows 5 help-center articles."
}
}| コード | 意味 |
|---|---|
unauthorized | API キーが無い、形式が不正、失効済み、または未知。 |
forbidden | キーは有効だが、プランに API 書き込みアクセスが無い。 |
invalid_request | 引数が不正 — 壊れた cursor を含む。 |
not_found | このプロジェクトにその id は無い。 |
limit_reached | プランの枠を使い切った(記事の上限など)。 |
rate_limited | 現在のウィンドウでのリクエストが多すぎる。 |
internal_error | 当方側で問題が発生。再試行しても安全。 |
全一覧はエラーに記載しています。