現役のITエンジニアが、 システム開発の現場で求められる知識を発信
記事検索
公開

ChatGPT GPTs × GAS で業務を自動化する ── Actions と MCP の使い分け

生成AI関連

はじめに

「チャットで質問に答えてもらうだけでなく、AIに外部のデータを操作させたい」──生成AIの活用が進むにつれ、こうしたニーズが増えています。
例えば、スプレッドシートへのデータ追加や一覧取得といった操作を、自然言語で指示するだけで完了させたいという場面です。
以前の記事では、AIと外部システムを連携させる手段としてMCP(Model Context Protocol)を紹介しました。

生成AI関連
MCPサーバーを活用する【前編:自作編】

今回は、ChatGPT を活用したGPTs Actionsを取り上げます。
「いつ・なぜ GPTs Actions を選ぶのか」を軸に、MCP との使い分けを整理したうえで、GAS(Google Apps Script)を使った実装例を交えて解説します。

GPTs Actions とは何か

GPTs の概要

GPTs(カスタム GPT)は、ChatGPT を特定の用途向けにカスタマイズできる機能です。
GPT では、Instructions(指示)、Knowledge(参照ファイル)、Capabilities(機能拡張。Custom Actions もここに含まれます)を設定できます。
作成した GPT は、リンク共有やワークスペース内への共有が可能です。
共同編集(Can edit)などの権限管理はワークスペース機能に依存するため、ワークスペース外のユーザーには共同編集権限を付与できない点に注意しましょう。

参考:GPTs の共有に関する公式ヘルプ

Actions の仕組み

Actions は、GPTs に外部 API の呼び出し能力を持たせる機能です。
OpenAPI スキーマで API 仕様を定義して GPT に登録すると、ユーザーの入力に応じて GPT がアクションを呼び出してくれます。
つまり、「自然言語インターフェース」+「確定的な API 処理」という組み合わせを実現できるわけです。
たとえば、ユーザーが「現在のタスク状況を一覧表示して」と入力すると、GPT が OpenAPI 定義に沿って API を呼び出し、結果を整形して返してくれます。

GPTs を構成する3つの要素

実務では、GPTs は以下の3要素を押さえておくとよいでしょう。

要素 役割
Instructions GPT の振る舞いや応答スタイルを定義する指示
Knowledge GPT が参照するアップロードファイル
Capabilities 機能拡張(Web browsing、Code Interpreter、Custom Actions など)

この中で Custom Actions が、GPT を「情報を返すだけのチャットボット」から「外部システムを操作できるエージェント」へと進化させる要素です。

参考:OpenAI Help: Creating a GPT

GPTs Actions vs MCP ── 使い分けの判断基準

GPTs Actions は、ChatGPT 上のカスタム GPT から外部 API を呼び出すための仕組みです。
一方の MCP は、AI アプリケーションがローカル・リモート問わずデータソースやツールに接続するためのオープン標準です。
どちらが優れているかではなく、相補的な関係として捉えるのがよいでしょう。

比較テーブル

観点 GPTs Actions MCP
利用起点 ChatGPT の GPT 設定画面から構成 MCP ホスト(対応クライアント)から接続
仕様 OpenAPI ベースでアクションを定義 MCP プロトコルでツール/リソースを接続
接続先 主に Web API(HTTP) ローカル/リモート双方(例: ファイル、DB、API)
共有・配布 GPT の共有設定(リンク/ワークスペース) サーバー設定やクライアント設定で接続
適した場面 定型業務のチャット操作を展開したいとき 開発・運用で複数データソースを統合したいとき

参考:GPT Actions 公式ガイド / MCP Introduction / MCP Architecture

GPTs Actions の「直接的」な良さ

両者の大きな違いのひとつは、操作対象の指定方法です。
GPTs Actions では、バックエンド側に操作対象をあらかじめ埋め込んでおけます。
たとえば、GAS のコード内にスプレッドシート ID を直接記述しておけば、ユーザーは「データを追加して」と言うだけで OK です。
「どのファイルに?」「どのシートに?」といった指定を毎回プロンプトで行う必要がないため、定型業務ではとても扱いやすい設計になります。
一方 MCP は、ツールとリソースを汎用的に公開し、実行時にどの対象を扱うかを指定できる設計です。
柔軟性が高い反面、接続先・権限・公開範囲をきちんと管理する必要があります。

参考:MCP Architecture

判断基準の具体例

迷ったときは、以下のように考えると整理しやすくなります。

ケース 推奨
非エンジニアがチャットでスプレッドシートを操作したい GPTs Actions
開発者が複数データソースを統合してAI連携したい MCP
特定の業務フローをリンク1つでチームに展開したい GPTs Actions
ローカル/社内データを接続対象として柔軟に扱いたい MCP

実践: GAS でスプレッドシート操作の Actions を構築する

ここからは、GAS(Google Apps Script)を使ってスプレッドシートを操作する Actions を実際に構築していきます。

なぜ GAS を選ぶのか

GPTs Actions のバックエンドには任意の Web API を使えますが、GAS は以下の点で手軽に始められる選択肢です。

観点 内容
サーバーレスで始めやすい Apps Script は Google のインフラ上で動くサーバーレス環境なので、サーバー管理が不要です
Google サービスとの連携が容易 SpreadsheetApp などの組み込みサービスから、スプレッドシートを直接操作できます
クォータ前提で運用設計できる 実行回数・実行時間などのクォータ があるため、規模に応じた設計がしやすくなっています

GAS 側の実装

GAS を Web アプリとして公開する場合、doGet(e) / doPost(e) がエントリーポイントになります。
以下のコードをスプレッドシートに紐づく GAS プロジェクトに記述しましょう。

Code.gs

function getConfig() {
  const props = PropertiesService.getScriptProperties();
  const spreadsheetId = props.getProperty('SPREADSHEET_ID');
  const sheetName = props.getProperty('SHEET_NAME');
  const apiKey = props.getProperty('X_API_KEY');

  if (!spreadsheetId || !sheetName || !apiKey) {
    return null;
  }
  return { spreadsheetId, sheetName, apiKey };
}

function configError() {
  return ContentService
    .createTextOutput(JSON.stringify({
      error: 'Missing script properties: SPREADSHEET_ID, SHEET_NAME, X_API_KEY'
    }))
    .setMimeType(ContentService.MimeType.JSON);
}

function parseBody(e) {
  if (!e.postData || !e.postData.contents) return {};
  try {
    return JSON.parse(e.postData.contents);
  } catch (error) {
    return {};
  }
}

function validation(e, body, expectedApiKey) {
  const apiKey = e.parameter['x_api_key'] || (body && body['x_api_key']);
  if (apiKey !== expectedApiKey) {
    return ContentService
      .createTextOutput(JSON.stringify({ error: 'Unauthorized' }))
      .setMimeType(ContentService.MimeType.JSON);
  }
  return null;
}

function doGet(e) {
  const config = getConfig();
  if (!config) return configError();

  const authError = validation(e, null, config.apiKey);
  if (authError) return authError;

  const sheet = SpreadsheetApp.openById(config.spreadsheetId).getSheetByName(config.sheetName);
  const data = sheet.getDataRange().getValues();
  const headers = data[0];
  const rows = data.slice(1).map(row => {
    const obj = {};
    headers.forEach((h, i) => obj[h] = row[i]);
    return obj;
  });

  return ContentService
    .createTextOutput(JSON.stringify({ items: rows, total: data.length - 1 }))
    .setMimeType(ContentService.MimeType.JSON);
}

function doPost(e) {
  const config = getConfig();
  if (!config) return configError();

  const body = parseBody(e);
  const authError = validation(e, body, config.apiKey);
  if (authError) return authError;

  const sheet = SpreadsheetApp.openById(config.spreadsheetId).getSheetByName(config.sheetName);
  const headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
  const newRow = headers.map(h => body[h] || '');

  sheet.appendRow(newRow);

  return ContentService
    .createTextOutput(JSON.stringify({ status: 'ok', added: body }))
    .setMimeType(ContentService.MimeType.JSON);
}

コードのポイントを簡単にまとめます。

項目 内容
設定値の管理 SPREADSHEET_ID / SHEET_NAME / X_API_KEY をスクリプトプロパティから取得するため、値をコードに直書きしません
API キー検証 validation(e, body, expectedApiKey) で API キーを検証し、不一致の場合は 401 Unauthorized 相当のレスポンスを返します(詳細は後述)
ボディの安全な解析 parseBody(e) で POST の JSON を安全にパースし、パース失敗時は空オブジェクトを扱います
件数情報の返却 レスポンスに total(全件数)を含めることで、GPT がユーザーに残りのデータがあることを伝えられます
追記前の整合性確認 appendRow の前に「リクエストキーとシートヘッダーが一致しているか」を確認し、不一致時はエラーを返します
JSON での応答 ContentService.createTextOutput(…).setMimeType(…) で JSON 形式のレスポンスを返します

補足: GPTs Actions にはレスポンスサイズの上限があり、データ量が多いと ResponseTooLargeError が発生する場合があります。件数制御やページングを実装しておくと安定します。

なぜスクリプトプロパティにするのか?

理由 内容
1 API キーや ID をコードに残さず管理できる
2 環境ごと(検証/本番)に値を切り替えやすい
3 値の更新時にコード差分を増やさず運用できる

スクリプトプロパティの設定箇所

各 API の詳細は SpreadsheetApp / Sheet / ContentService の公式リファレンスをご覧ください。

GAS のデプロイ手順

手順 内容
1 GAS エディタの「プロジェクトの設定」から「スクリプト プロパティ」を開く
2 スクリプトプロパティにキーを追加する
2-1 SPREADSHEET_ID: 対象スプレッドシートの ID
2-2 SHEET_NAME: 対象シート名(例: シート1
2-3 X_API_KEY: ランダムな API キー(例: openssl rand -hex 32
3 GAS エディタで「デプロイ」→「新しいデプロイ」を選択
4 種類として「ウェブアプリ」を選択
5 ウェブアプリの公開設定を行う
5-1 実行ユーザー(Execute as): 「自分」(Me)
5-2 アクセス権(Who has access): 「全員」(Anyone)
6 デプロイ後に表示される URL をコピー(Actions の servers.url で使用)

なぜ「全員」にする必要があるのか?
GPTs Actions は、OpenAI のサーバーからバックエンド URL を HTTP リクエストで呼び出します。この呼び出し元は Google アカウントによる認証を通過できないため、GAS のアクセス権を「全員」に設定しないとリクエストが到達しません。

デプロイ設定の詳細は Web Apps の公式ドキュメントで確認してください。

API キーによるアクセス制御

アクセス権を「全員」に設定すると、URL を知っている人なら誰でもリクエストを送信できる状態になります。
つまり、URL が第三者に漏れた場合、スプレッドシートのデータを読み取られたり、不正なデータを書き込まれたりするリスクがあります。
この対策として、API キーによる簡易認証をバックエンド側に実装しています。
先ほどの validation(e, body, expectedApiKey) 関数がその役割を担っています。


function validation(e, body, expectedApiKey) {
  const apiKey = e.parameter['x_api_key'] || (body && body['x_api_key']);
  if (apiKey !== expectedApiKey) {
    return ContentService
      .createTextOutput(JSON.stringify({ error: 'Unauthorized' }))
      .setMimeType(ContentService.MimeType.JSON);
  }
  return null;
}
観点 内容
API キーの受け取り GET リクエストではクエリパラメータから、POST リクエストではリクエストボディから x_api_key を取得します
不一致時の挙動 スクリプトプロパティの X_API_KEY と一致しない場合はエラーレスポンスを返し、スプレッドシートへのアクセスをブロックします
キー値の要件 X_API_KEY には推測されにくいランダムな文字列を設定してください(例: openssl rand -hex 32 で生成した値など)

注意: GAS の Web アプリでは HTTP ステータスコードを制御できないため、ステータスは常に 200 で返ります。そのためレスポンスボディの error フィールドでエラーを判定する設計としています。
重要: GAS の doGet(e) / doPost(e) では、リクエストヘッダーの値を直接参照できません。そのため、この実装で API キーを受け取る場所はクエリまたは JSON ボディです。

補足: API キーによる認証は簡易的な対策です。機密性の高いデータを扱う場合は、OAuth 2.0 による認証など、より堅牢な認証方式を検討する必要があり、本構成での実現はできません。

OpenAPI スキーマの定義

GPT に登録するアクション仕様は、OpenAPI の形式で記述します。
servers.url には、先ほどデプロイした GAS の URL を設定してください。

openapi.yaml

openapi: 3.1.0
info:
  title: スプレッドシート操作 API
  version: 1.0.0
  description: GAS 経由でスプレッドシートのデータを取得・追加する API
servers:
  - url: https://script.google.com/macros/s/あなたのデプロイID
paths:
  /exec:
    get:
      operationId: getItems
      summary: スプレッドシートのデータを一覧取得する
      description: スプレッドシートの全行を JSON 配列で返します。
      parameters:
        - name: x_api_key
          in: query
          required: true
          schema:
            type: string
          description: API キー
      responses:
        "200":
          description: データの一覧
          content:
            application/json:
              schema:
                type: object
                properties:
                  items:
                    type: array
                    items:
                      type: object
    post:
      operationId: addItem
      summary: スプレッドシートにデータを追加する
      description: JSON で指定されたデータをスプレッドシートの末尾に1行追加します。
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              description: 追加するデータ(キーはスプレッドシートのヘッダーに対応)
              properties:
                x_api_key:
                  type: string
                  description: API キー
                日付:
                  type: string
                  pattern: '^\d{4}/\d{2}/\d{2}$'
                  example: '2026/03/04'
                  description: 日付(YYYY/MM/DD)
                タスク:
                  type: string
                  description: タスク
              required:
                - x_api_key
      responses:
        "200":
          description: 追加成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                  added:
                    type: object

ポイントは以下の通りです。

項目 内容
operationId 各操作を一意に識別するための ID です(OpenAPI の Operation Object で定義)
summary / description 具体的に書いておくと、アクションの意図が管理しやすくなります
pattern 入力制約のヒントになりますが、実運用では doPost 側で正規化・検証(/ 変換や不正日付判定)も実装しておくと安全です

トラブルシュート(200 だが保存されない)

確認項目 内容
レスポンス確認 GAS は仕様上 HTTP ステータスが常に 200 になるため、レスポンスボディの status / error を確認してください
API キー不一致 x_api_key 不一致の場合、Unauthorized が返って保存されません
requestBody のキー名 requestBody のキー名(例: date, task)とスプレッドシートの1行目ヘッダー名が一致しない場合、値は入りません

参考:GPT Actions 公式ガイド

GPTs への設定

手順 内容
1 ChatGPT の「GPT を作成」画面を開く(2026年3月時点で、GPT の作成には Pro / Plus / Team / Enterprise / Edu プランが必要)
2 「構成」タブで設定を行う
2-1 Instructions: GPT の振る舞いを記述(後述)
2-2 Actions: 「アクションを作成」から OpenAPI スキーマを登録
3 Actions の登録後、認証(Authentication)None のままにする
4 x_api_key は OpenAPI 定義の query / requestBody パラメータとして送信し、X_API_KEY と同じ値を渡す
5 「プレビュー」でテストする

GPTs画面

GPTs作成画面

GPTsアクション編集画面

補足: API キーをヘッダーで秘匿して扱いたい場合は、GAS の前段に Cloud Run / Cloud Functions などのプロキシ API を置き、そこでヘッダー検証する構成にしなければなりません。

Instructions の書き方

Instructions は、GPT がどのように振る舞うかを決める重要な設定です。
Actions と組み合わせる場合、どのアクションをどんな状況で呼び出すかを明確に記述しておくと、GPT の応答精度が向上します。
今回のスプレッドシート操作 GPT であれば、たとえば以下のような Instructions が考えられます。


あなたはスプレッドシートのデータを管理するアシスタントです。

## できること
- データの一覧表示(getItems アクションを使用)
- データの追加(addItem アクションを使用)

## アクション実行時の必須ルール
- getItems を呼び出すときは、query パラメータ `x_api_key` に `<<X_API_KEY>>` を必ず設定してください。
- addItem を呼び出すときは、requestBody に `x_api_key: <<X_API_KEY>>` を必ず含めてください。
- `x_api_key` は内部設定値です。ユーザーに値を尋ねたり、回答文に表示したりしないでください。

## 応答ルール
- ユーザーがデータの確認・表示を求めたら、getItems を呼び出し、結果を見やすい表形式で返してください。
- ユーザーがデータの追加を求めたら、必要な項目を確認したうえで addItem を呼び出してください。
  - 必要な項目が不足している場合は、追加前にユーザーに確認してください。
- データの更新・削除はこの GPT では対応していません。依頼された場合はその旨を伝えてください。
- Unauthorized エラーが返った場合は、`x_api_key` の設定不備の可能性を案内し、管理者確認を促してください。

## 注意事項
- スプレッドシートの構造やIDについてユーザーに尋ねる必要はありません
- 機密情報や個人情報の取り扱いには注意し、不明な場合は管理者への確認を促してください。

Instructions を書く際のポイントは以下の通りです。

ポイント 内容
アクションとの対応を明示する 「一覧表示には getItems を使う」のように、ユーザーの意図とアクションの対応関係を書いておくと、GPT が適切にアクションを選択しやすくなります
認証パラメータの扱いを明示する x_api_key をどの操作でどこに入れるか、ユーザーへ開示しないことまで書いておくと、Unauthorized の発生や情報漏えいリスクを下げられます
対応範囲を明確にする この GPT で「できること」と「できないこと」を区別しておくと、想定外の操作を防げます
確認フローを組み込む データ追加のように副作用のある操作では、実行前にユーザーへ確認するよう指示しておくと安全です

参考:OpenAI Help: Creating a GPT

テスト

テスト入力 想定結果
「データを一覧表示して」 getItems が呼ばれ、スプレッドシートの内容が表示される
「日付: 2026/03/04、タスク: 技術ブログを書く」 addItem が呼ばれ、行が追加される

テスト用スプレッドシート

getItems実行前

getItems実行後

addItem実行前

addItem実行後

addItem実行後のテスト用スプレッドシート

参考:OpenAI Help: Creating a GPT / GPT Actions 公式ガイド

コードは AI に下書きさせる

ここまで GAS のコードと OpenAPI スキーマを紹介しましたが、これらは生成 AI に下書きさせることもできます。
たとえば、ChatGPT に以下のように指示して、ひな形を作らせる運用は実務でも有効です。

プロンプト例
「スプレッドシートのデータを JSON で返す GAS の doGet 関数を書いて」
「GAS の Web API 用の OpenAPI 3.1 スキーマを作成して」

ただし、以下の点は必ず人間が確認・対応してください。

確認項目
GAS のデプロイ設定とアクセス権
スプレッドシート ID とシート構造の整合性
実データでの取得・追加の動作検証

まとめ

GPTs Actions は、ChatGPT 上で OpenAPI ベースの外部 API 連携を行う仕組みです。GPT の共有機能と組み合わせることで、定型業務をチームへ展開しやすいのが特徴です。
MCP は、ローカル/リモートのデータソースやツールをAIアプリケーションに接続するためのオープン標準です。
そのため、両者は競合というより、用途に応じて使い分ける関係と考えるのが実践的です。
GAS をバックエンドに選べば、比較的少ない構成でスプレッドシート連携のアクションを構築できます。
「AI が自然言語を理解し、確定的な API 操作を実行する」パターンは、業務自動化の現場で再利用しやすい実装方式です。
MCP について詳しく知りたい方は、こちらの記事も参考にしてください。

生成AI関連
MCPサーバーを活用する【前編:自作編】

生成AI活用支援サービスのご紹介

Tech Funでは、お客様のフェーズに合わせ、生成AI活用に向けた支援を3つのパックでご提供しています。

  1. 無料診断パック:業務・プロセスの現状を無料で診断し、生成AI活用の可能性をレポートします。
  2. 検証(PoC)パック:診断で有効性が確認された業務を対象に、プロトタイプ構築を支援します。
  3. コンサルティングサービス:生成AI導入戦略の策定から運用体制構築までを包括的に支援します。

生成AIに限らず、Web・業務システム開発やインフラ設計など、技術領域を問わずご相談を承っています。「何から始めれば良いか分からない」という段階でも構いませんので、ぜひお気軽にお問い合わせください。

執筆・編集

Tech Fun Magazine R&Dチーム
Tech Funの生成AI研究に携わるエンジニアが、最新のAIモデル動向やプロンプト設計、実業務への応用手法など、生成AIに特化した知見を執筆・編集しています。
モデル評価や業務シナリオに応じたAI活用設計など、日々のR&D活動で得られる実践的なノウハウをわかりやすく紹介します。

ARTICLE
生成AI関連記事一覧

生成AI関連

ChatGPT GPTs × GAS で業務を自動化する ─…

生成AI関連

Structured Outputsの基本と実践

生成AI関連

AI最新情報のキャッチアップ術

生成AI関連

Knowledge Base × S3 Vectors In…

生成AI関連

RAGの評価指標 ─ 何を・どう測るかを整理する

生成AI関連

Guardrails for Amazon Bedrock …

生成AI関連

生成AIに精度を求めすぎない

生成AI関連

Amazon Bedrock Knowledge Baseで…

生成AI関連

はじめての人のための:AI・機械学習・統計・生成AI・AGI…

記事一覧を見る