13
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MCP 入門 ─ Spring AI で作る DB 操作エージェント

13
Last updated at Posted at 2025-12-21

はじめに

こんにちは!

今回は、MCP についての入門記事を書いてみました!
「MCP をこれから触ってみたい」「AI とバックエンドをどのようにつなぐのか知りたい」、そんな方が対象です!
最後まで読んでいただけたら嬉しいです!

🚀 本記事執筆の背景
最近 AI 関連の情報を追っていると、必ず目にするのが MCP という言葉です。話題になってはいますが、「MCP の概念は聞いたことあるけど、実際にどう動くのか分からない」という方も多いのではないでしょうか。
私自身も、MCP の仕組みは何となく理解していたものの、実際に動かしたことはなかったため、今回あらためて MCP サーバーを実装してみることにしました。

本記事のゴール は以下の2つです。

  • MCP(Model Context Protocol)の仕組みと考え方を理解する
  • 実際に MCP サーバーを実装し、「どう動くのか」を体感する

結論

結果だけ知りたい方はこちら

今回は、AI エージェントがローカル DB において CRUD 操作をするための MCP サーバーを構築しました!

以下は Claude に自然言語で DB 操作を指示している様子です。AI が MCP サーバーを利用して、 DB の更新処理をしていることが分かります。

image.png

MCP(Model Context Protocol)とは

MCP(Model Context Protocol)とは、AI モデルが外部ツールやリソースと連携できるようにするための標準化されたプロトコルです。
MCP を利用することで、ChatGPT や Claude などの MCP ホストが MCP サーバーに接続し、AI が外部ツールやデータにアクセスできるようになります。

MCP (Model Context Protocol) is an open-source standard for connecting AI applications to external systems. Using MCP, AI applications like Claude or ChatGPT can connect to data sources (e.g. local files, databases), tools (e.g. search engines, calculators) and workflows (e.g. specialized prompts)—enabling them to access key information and perform tasks.

📝 MCP を分かりやすく例えると
MCP は、AIアプリケーション向けの USB-C ポートによく例えられます。
USB-C が電子機器を接続するための標準化された方法を提供するのと同様に、MCP は AIアプリが外部システムに接続するための標準化された方法を提供します。

この例えは公式でもよく使われる表現のため、参考として紹介しておきます(個人的にはあまりしっくりとは来ませんでしたが、、)

MCP 誕生の背景

MCP 誕生の背景をざっくりと整理します。

LLM(大規模言語モデル)が登場し急速に実用化されるにつれ、単なる文章生成にとどまらず、外部のデータベースや API、業務システムと連携させたいというニーズが高まってきました。

しかし MCP 登場前の従来の方法では、LLM が外部ツールに接続するためには、プロンプトに API の仕様や認証情報を埋め込んだり、レスポンスを自然言語として解釈させたり、安全性・再現性・保守性の面で深刻な問題を抱えていました。具体的には、

  • LLM が想定外の API を呼び出す可能性がある
  • 出力の揺らぎによって処理結果が安定しない
  • API 仕様変更やモデル更新のたびにプロンプトを修正する必要がある

などです。

こうした課題から、「LLM に実行処理そのものを任せる」設計には限界があるとされました。
そこで生まれたのが、「LLM には判断だけを任せ、実行処理は人間が書いたコードに限定する」という責務分離の考え方です。この思想を実現するために、2024年11月 Anthropic社が MCP をオープンプロトコルとして発表しました。MCP では LLM が利用できる機能(Tool)を明示的に定義し、入出力を構造化することで、AI を安全かつ安定してシステムに組み込むことが可能になりました。

つまり MCP によって、LLM は「実験的な存在」から、「信頼して利用できるソフトウェアコンポーネント」へと引き上げられました。

MCP の基本構造

MCP は、クライアント・サーバー方式に基づいています。
MCP ホストは、各 MCP サーバーに対して1つの MCP クライアントを作成し、接続を確立・維持します。

MCP の基本的なアーキテクチャは、以下の3つで構成されています。

構成要素 説明
MCP ホスト 1つ以上の MCP クライアントを調整・管理するAIアプリケーション
MCP クライアント MCP サーバーとの接続を確立・維持する。MCP ホストが使用するコンテキストについて、リクエストを送信して MCP サーバーから取得する。
MCP サーバー MCP クライアントに特定のデータソースやツールへのアクセスを提供する。

例えば、Visual Studio Code は Copilot 拡張機能などを通じて MCP ホストとして動作します。VS Code が、特定の MCP サーバーへの接続を確立すると、MCP クライアントをインスタンス化し、接続を維持します。その後、VS Code が別の MCP サーバーに接続する場合は、VS Code は追加で MCP クライアントを設けます。

MCP の接続方式

AI エージェントと MCP サーバーの接続方式として、主に次の2つがあります。

接続方式 説明
STDIO 標準入出力を使って、ローカルマシン上のプロセス同士が直接通信する方式。AI エージェントが MCP サーバーをサブプロセスとして起動し、そのプロセスとメッセージをやり取りする
Streamable HTTP HTTP を使って MCP クライアントから MCP サーバー にリクエストを送り、必要に応じて Server-Sent Events(SSE)でレスポンスをストリーミングする方式。MCP サーバーをリモート(クラウド上)に配置し、ネットワーク越しに MCP サーバーへ接続ができる

今回は 入門用途・ローカル検証 を目的としているため、構成が最もシンプルな STDIO 方式を採用しています。

MCP サーバーを構築する

今回は、AI エージェントが標準入出力経由で、データベースを操作できるように MCP サーバーを最小構成で構築します。

AI エージェント(Claude Desktop)が OSプロセスとして起動した MCP サーバーと標準入出力(stdio)で通信します。
AI エージェントは「アイテムを追加して」「一覧を表示して」「価格を更新して」「削除して」といった自然言語での指示から、MCP の Tool を使用して、 データベースに対して CRUD 操作を実行します。

なお今回作成したプロジェクトは以下で公開しています。

技術スタック

  • Java 25(実装言語)
  • Gradle 9.0(ビルドツール)
  • Spring Boot 4.0(アプリケーションフレームワーク)
  • Spring AI 2.0.0-M1(AI/MCP連携用ライブラリ)
  • H2 Database(組み込みデータベース)
  • MyBatis(SQLマッピングフレームワーク)

Spring AI とは、Java / Spring を使って、ChatGPT や Claude などのAIサービスと連携するためのライブラリです。Spring AIは、専用のBoot StartersとJavaアノテーションを通じて MCP をサポートし、外部システムと円滑に連携するためのAIアプリケーション開発を簡単にしてくれます。

ディレクトリ構成

作成したプロジェクトのディレクトリ構成は以下です。

src/main
├── java
│   └── com/example/demo
│       ├── McpServerApplication.java
│       ├── client
│       │   └── ClientStdio.java
│       ├── config
│       │   └── JacksonConfig.java
│       ├── model
│       │   └── Item.java
│       ├── repository
│       │   └── ItemRepository.java
│       └── service
│           └── ItemService.java
└── resources
    └── ...

model / repository / service を分けることで、データ構造・DB操作・ビジネスロジックの責務を明確にしています。

  • model は、DB エンティティであると同時に、MCP Tool の引数・戻り値としても使用しています
  • repository は SQL の定義と DB アクセスのみを担当しています
  • service は、AI エージェントが呼び出せる操作(Tool)を明示的に定義しています

repository

repository では DB の CRUD 操作を、最小構成で実装しています。
アイテムデータの登録・取得・更新・削除を行うメソッドを定義しています。

  • findAll:一覧取得
  • findByName:条件検索
  • findById:単一取得
  • save:登録
  • update:更新
  • deleteById:削除

service(MCP Tool)から呼び出す操作を、そのまま安全に DB 操作へマッピングしています。

ItemRepository.java
package com.example.demo.repository;

import com.example.demo.model.Item;
import java.util.List;
import org.apache.ibatis.annotations.*;

@Mapper
public interface ItemRepository {

    String BASE_SELECT = "SELECT id, name, price, description FROM items";

    @Select(BASE_SELECT + " ORDER BY id")
    List<Item> findAll();

    @Select(BASE_SELECT + " WHERE name LIKE CONCAT('%', #{name}, '%') ORDER BY id")
    List<Item> findByName(@Param("name") String name);

    @Select(BASE_SELECT + " WHERE id = #{id}")
    Item findById(@Param("id") Long id);

    @Delete("DELETE FROM items WHERE id = #{id}")
    int deleteById(@Param("id") Long id);

    @Insert("INSERT INTO items(name, price, description) VALUES(#{name}, #{price}, #{description})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int save(Item item);

    @Update("UPDATE items SET name = #{name}, price = #{price}, description = #{description} WHERE id = #{id}")
    int update(Item item);
}

service

service では、MCP から呼び出される Tool を定義しています。
Tool とは、「AI が明示的に呼び出すことができる機能(関数)」のことです。
AI は、この service に定義された Tool しか実行できないため、AI に許可する操作範囲を明示的に制限することができます。

今回は Tool として、DB の CRUD 操作を登録します。以下が ItemService が提供する Tool 一覧です。

  • listItems:一覧取得(Read)
  • searchItemsByName:検索(Read)
  • registerItem:登録(Create)
  • updateItem:更新(Update)
  • removeItem:削除(Delete)

Tool はすべて、「1つの責務に限定」、「副作用が明確」、「引数が構造化されたデータ」であるように設計します。これにより、LLM は定義済みの Tool の中から適切なものを選択しやすくなり、想定外の操作を防ぐことができます。

以下は、DB へアイテムを登録する Tool (registerItem)を記述している部分のコードです。

registerItem
    @Tool(description = "新しいアイテムを登録する")
    public String registerItem(@ToolParam(description = "登録するアイテムの名前、価格、説明") Item item) {
        item.setId(null);
        if (repository.save(item) == 0) {
            return "アイテムの登録に失敗しました";
        }
        return "アイテムを登録しました: " + formatItem(item);
    }

このコードのポイントは以下です。

  • @Toolアノテーションにより MCP から呼び出せる操作として公開している。AI は@Tooldescription を参照し、「この Tool はどのような操作をするのか」を読み取る。ここが、AI が Tool を選択する際の根拠となる箇所であるため、明確にその Tool の役割を記述する必要がある
  • メソッド引数の @ToolParamdescription について、AI はこの箇所から「この Tool を使うとき、どんな情報が必要か」を読み取る。今回の場合、AI は 名前、価格、説明 が必要であることを理解し、自然言語から構造化データに変換して Tool を呼び出す
  • 戻り値として、成功・失敗の結果を String型 で返し、AI エージェントに自然言語で応答する

📝 表記について(日本語 / 英語の使い分け)
本記事では「自然言語で操作している」ことが伝わりやすいように、Tool の説明文や実行結果メッセージを日本語で記述しています。
ただし MCP の通信自体(JSON-RPC の initialize / tools/list / tools/call など)は英語のメソッド名・スキーマに基づいており、実運用や公式サンプルでは英語表記が使われることがほとんどです。

service コード全文
ItemService.java
package com.example.demo.service;

import java.util.List;
import java.util.stream.Collectors;

import com.example.demo.model.Item;
import com.example.demo.repository.ItemRepository;

import org.springframework.ai.tool.annotation.Tool;
import org.springframework.ai.tool.annotation.ToolParam;
import org.springframework.stereotype.Service;

@Service
public class ItemsService {

    private final ItemRepository repository;

    public ItemsService(ItemRepository repository) {
        this.repository = repository;
    }

    @Tool(description = "すべてのアイテムのリストを取得する")
    public String listItems() {
        return formatItems("アイテムリスト", repository.findAll());
    }

    @Tool(description = "指定されたテキストが名前に含まれるアイテムを検索する")
    public String searchItemsByName(@ToolParam(description = "検索する名前") String name) {
        String keyword = name == null ? "" : name.trim();
        if (keyword.isBlank()) {
            return "検索する名前を入力してください";
        }
        return formatItems("「" + keyword + "」の検索結果", repository.findByName(keyword));
    }

    @Tool(description = "新しいアイテムを登録する")
    public String registerItem(@ToolParam(description = "登録するアイテムの名前、価格、説明") Item item) {
        item.setId(null);
        if (repository.save(item) == 0) {
            return "アイテムの登録に失敗しました";
        }
        return "アイテムを登録しました: " + formatItem(item);
    }

    @Tool(description = "指定されたIDのアイテムを削除する")
    public String removeItem(@ToolParam(description = "削除するアイテムのID") Long id) {
        if (id == null) {
            return "削除するアイテムのIDを入力してください";
        }
        Item existing = repository.findById(id);
        if (existing == null) {
            return "IDが " + id + " のアイテムが見つかりません";
        }
        if (repository.deleteById(id) == 0) {
            return "アイテムの削除に失敗しました";
        }
        return "アイテムを削除しました: " + formatItem(existing);
    }

    @Tool(description = "既存のアイテムを更新する")
    public String updateItem(@ToolParam(description = "更新するアイテムのID、名前、価格、説明") Item item) {
        if (item.getId() == null) {
            return "更新するアイテムのIDを入力してください";
        }
        Item existing = repository.findById(item.getId());
        if (existing == null) {
            return "IDが " + item.getId() + " のアイテムが見つかりません";
        }
        Item updated = new Item(
                item.getId(),
                item.getName() != null ? item.getName().trim() : existing.getName(),
                item.getPrice() != null ? item.getPrice() : existing.getPrice(),
                blankToNull(item.getDescription()) != null ? blankToNull(item.getDescription())
                        : existing.getDescription());
        if (repository.update(updated) == 0) {
            return "アイテムの更新に失敗しました";
        }
        return "アイテムを更新しました: " + formatItem(updated);
    }

    private String formatItems(String heading, List<Item> items) {
        if (items.isEmpty()) {
            return heading + "は空です";
        }
        return heading + ":\n" + items.stream().map(this::formatItem).collect(Collectors.joining("\n"));
    }

    private String formatItem(Item item) {
        String base = String.format("#%d %s (%d円)", item.getId(), item.getName(), item.getPrice());
        return isBlank(item.getDescription()) ? base : base + " - " + item.getDescription().trim();
    }

    private boolean isBlank(String text) {
        return text == null || text.trim().isEmpty();
    }

    private String blankToNull(String text) {
        return isBlank(text) ? null : text.trim();
    }
}

MCP サーバーを起動する

それでは実際に、作成したプロジェクトをビルドして実行し、MCP サーバーを起動してみます。自分がクライアントの立場に立って、MCP サーバと標準入出力を通して対話してみます。

MCP サーバと標準入出力で対話している様子
$ ./gradlew bootJar
$ java -jar build/libs/spring-ai-demo-0.0.1-SNAPSHOT.jar
{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}
{"jsonrpc":"2.0","id":1,"result":{"protocolVersion":"2024-11-05","capabilities":{"completions":{},"logging":{},"prompts":{"listChanged":true},"resources":{"subscribe":false,"listChanged":true},"tools":{"listChanged":true}},"serverInfo":{"name":"mcp-server","version":"1.0.0"}}}
{"jsonrpc":"2.0","method":"notifications/initialized"}
{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}
{"jsonrpc":"2.0","id":2,"result":{"tools":[{"name":"removeItem","description":"指定されたIDのアイテムを削除する","inputSchema":{"type":"object","properties":{"id":{"type":"integer","description":"削除するアイテムのID"}},"required":["id"],"additionalProperties":false}},{"name":"listItems","description":"すべてのアイテムのリストを取得する","inputSchema":{"type":"object","properties":{},"required":[],"additionalProperties":false}},{"name":"registerItem","description":"新しいアイテムを登録する","inputSchema":{"type":"object","properties":{"item":{"type":"object","properties":{"description":{"type":"string"},"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"price":{"type":"integer","format":"int32"}},"required":["description","id","name","price"],"description":"登録するアイテムの名前、価格、説明"}},"required":["item"],"additionalProperties":false}},{"name":"updateItem","description":"既存のアイテムを更新する","inputSchema":{"type":"object","properties":{"item":{"type":"object","properties":{"description":{"type":"string"},"id":{"type":"integer","format":"int64"},"name":{"type":"string"},"price":{"type":"integer","format":"int32"}},"required":["description","id","name","price"],"description":"更新するアイテムのID、名前、価格、説明"}},"required":["item"],"additionalProperties":false}},{"name":"searchItemsByName","description":"指定されたテキストが名前に含まれるアイテムを検索する","inputSchema":{"type":"object","properties":{"name":{"type":"string","description":"検索する名前"}},"required":["name"],"additionalProperties":false}}]}}
{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"listItems","arguments":{}}}
{"jsonrpc":"2.0","id":3,"result":{"content":[{"type":"text","text":"\"アイテムリスト:\\n#1 リンゴ (150円) - 新鮮な青森産リンゴ\\n#2 バナナ (120円) - 熟した黄色いバナナ\\n#3 オレンジ (200円) - ビタミンC豊富なオレンジ\""}],"isError":false}}

MCP クライアント・サーバ間の通信

MCP の通信は、JSON-RPC 2.0 形式に基づいて行われます。
MCP クライアントと MCP サーバ間の通信の流れを以下に示します。

これは、MCP サーバの Tool を呼び出すまでの流れです。それでは順に通信の内容を見ていきます。

1 initialize(request)

クライアントからサーバに対して

  • 使いたいプロトコルバージョン(protocolVersion
  • クライアント側が持つ機能(capabilities
  • クライアントの名前/バージョン(clientInfo

を伝えて、「この条件でセッションを始めて良いか?」と交渉する最初のメッセージを送ります。

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": {
    "protocolVersion": "2025-11-25",
    "capabilities": {},
    "clientInfo": { "name": "test", "version": "1.0" }
  }
}

2 initialize(response)

initialize(request)に対して、サーバが「了解。この条件でいけるよ」と返します。

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2025-11-25",
    "capabilities": {
      "completions": {},
      "logging": {},
      "prompts": { "listChanged": true },
      "resources": { "subscribe": false, "listChanged": true },
      "tools": { "listChanged": true }
    },
    "serverInfo": { "name": "mcp-server", "version": "1.0.0" }
  }
}

  • id: 1 が付いているので、さっきの initialize(request) に対する返答だと分かる
  • serverInfo:サーバ名とバージョン
  • capabilities:サーバ側が提供できる機能セット

ここまでで「互いに話せる前提」が合意できました。

3 notifications/initialized(notification)

「initialize のやりとりが完了したから、これから通常リクエストを投げるね」というメッセージを送ります。

{
  "jsonrpc": "2.0",
  "method": "notifications/initialized"
}
  • id が無いので notification(= 返信を要求しない)
  • これを送らない実装だと、サーバ側が「まだ初期化フェーズ中」とみなして tools/list などを処理しないことがある

4 tools/list(request)

ここからが “本題” です。
クライアントからサーバに対して「提供している Tool の一覧(名前・説明・入力スキーマ)を全部ください」と問い合わせます。

{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/list",
  "params": {}
}

5 tools/list(response)

サーバーがクライアントに「提供する Tool の一覧」を返しています。

tools/list(response)は、AI が利用可能な Tool 一覧と、その引数仕様を機械可読な形で提供するものです。これにより、AIは自然言語の要求を、正しい構造の tools/call に変換できます。

...
"tools": [
      {
        "name": "removeItem",
        "description": "指定されたIDのアイテムを削除する",
        "inputSchema": {
          "type": "object",
          "properties": {
            "id": { "type": "integer", "description": "削除するアイテムのID" }
          },
          "required": ["id"],
          "additionalProperties": false
        }
      },
      ...
tools/list(response)全文
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "tools": [
      {
        "name": "removeItem",
        "description": "指定されたIDのアイテムを削除する",
        "inputSchema": {
          "type": "object",
          "properties": {
            "id": { "type": "integer", "description": "削除するアイテムのID" }
          },
          "required": ["id"],
          "additionalProperties": false
        }
      },
      {
        "name": "listItems",
        "description": "すべてのアイテムのリストを取得する",
        "inputSchema": {
          "type": "object",
          "properties": {},
          "required": [],
          "additionalProperties": false
        }
      },
      {
        "name": "registerItem",
        "description": "新しいアイテムを登録する",
        "inputSchema": {
          "type": "object",
          "properties": {
            "item": {
              "type": "object",
              "description": "登録するアイテムの名前、価格、説明",
              "properties": {
                "id": { "type": "integer", "format": "int64" },
                "name": { "type": "string" },
                "price": { "type": "integer", "format": "int32" },
                "description": { "type": "string" }
              },
              "required": ["description", "id", "name", "price"]
            }
          },
          "required": ["item"],
          "additionalProperties": false
        }
      },
      {
        "name": "updateItem",
        "description": "既存のアイテムを更新する",
        "inputSchema": {
          "type": "object",
          "properties": {
            "item": {
              "type": "object",
              "description": "更新するアイテムのID、名前、価格、説明",
              "properties": {
                "id": { "type": "integer", "format": "int64" },
                "name": { "type": "string" },
                "price": { "type": "integer", "format": "int32" },
                "description": { "type": "string" }
              },
              "required": ["description", "id", "name", "price"]
            }
          },
          "required": ["item"],
          "additionalProperties": false
        }
      },
      {
        "name": "searchItemsByName",
        "description": "指定されたテキストが名前に含まれるアイテムを検索する",
        "inputSchema": {
          "type": "object",
          "properties": {
            "name": { "type": "string", "description": "検索する名前" }
          },
          "required": ["name"],
          "additionalProperties": false
        }
      }
    ]
  }
}

6 tools/call(request)

それでは、クライアントからサーバーに対して、listItems という Tool の実行を要求します。

{
  "jsonrpc": "2.0",
  "id": 3,
  "method": "tools/call",
  "params": {
    "name": "listItems",
    "arguments": {}
  }
}

7 tools/call(response)

アイテムリストが取得できています。Tool の実行結果を表す配列 content に実データが格納されていることが分かります。

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "\"アイテムリスト:\n#1 リンゴ (150円) - 新鮮な青森産リンゴ\n#2 バナナ (120円) - 熟した黄色いバナナ\n#3 オレンジ (200円) - ビタミンC豊富なオレンジ\""
      }
    ],
    "isError": false
  }
}

以下が、MCP サーバーから帰ってきた実データです。

アイテムリスト:
#1 リンゴ (150円) - 新鮮な青森産リンゴ
#2 バナナ (120円) - 熟した黄色いバナナ
#3 オレンジ (200円) - ビタミンC豊富なオレンジ

AI エージェントでの設定

今回は AI エージェントとして、Claude Desktop を使用します!

MCP サーバーの登録

Claudeに今回作成した MCP サーバーを登録します。
登録の仕方は、以下のように Claude の設定ファイルにて、ビルドファイルへのパス "C:\\opt\\spring-ai-demo-0.0.1-SNAPSHOT.jar" を記述します。

claude_desktop_config.json
{
    "mcpServers": {
      "itemDatabase": {
        "command": "java",
          "args": [
          "-jar",
          "-Dspring.ai.mcp.server.transport=STDIO",
          "C:\\opt\\spring-ai-demo-0.0.1-SNAPSHOT.jar"
        ]
      }
    }
}

MCP サーバーの登録確認

MCP サーバーの登録が成功していれば、設定 > 開発者 の項目にて、MCP サーバーが確認できます。

image.png

AI に DB 操作させてみる

それでは実際に、 AI エージェントにデータベースを操作をさせてみます!

アイテムの表示

image.png

アイテムの更新

image.png

アイテムの削除・追加

image.png

さいごに

今回は、Spring AI を使って MCP サーバーを実装し、Claude Desktop からローカル DB に対して CRUD 操作するまでを体験しました。

個人的には、「AI が勝手に DB を触る」のではなく、「人間が用意した Tool だけを AI が選んで呼び出す」という構造が、安心感につながるポイントだと感じました。また、MCP は「AI に任せる範囲」と「人間が制御すべき範囲」を切り分けてくれる一方で、Tool の設計次第では安全にも危険にもなる仕組みだとも理解しました。
AI を安全に使うための設計を考える良いきっかけとなりました。

MCP はまだ新しい領域ですが、今後さらに重要になると感じています。
この記事が、MCP を触ってみる最初の一歩になれば嬉しいです!

最後までご覧いただき、ありがとうございました!

参考


※ 本記事は入門・検証用途を想定した内容です。
実運用で AI に DB 操作を許可する場合には、最小権限の適用、操作履歴の監査ログ、削除や一括更新といった危険操作の分離など、十分なセキュリティ設計と運用ルールが必須となります。

13
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?