Opensearch MCPを動かしてみる
AIにコンテンツを作成させる際、リソース(いわゆる背景画像やicon、SEなど)の作成までAIにお願いできたらな~と怠惰が極まってきました。生成AIを使用して直接画像や音声を生成することもできますが、今回は既に存在する大量の素材からAI自身て適した素材を選択する手法をとりたいと思います。
Opensearchに素材データ(カテゴリや、素材自体の説明)を格納しておき、AIに自由に検索できるようにすればいい感じになるんじゃないの?というきっかけで、Opensearch MCPを試してみました。
Opensearch MCP
Introducing MCP in OpenSearchによると、Opensearch MCPにはBuilt-in MCP server型とStandalone OpenSearch MCP server型の2種類があります。今回はBuilt-in MCP server型を構築してみました。
-
Built-in MCP server型

-
Standalone OpenSearch MCP server型

環境
Windows 10のDockerコンテナ上にOpensearchサーバを構築します。
MCPの動作確認用のクライアントとしてClaude Desktopを使用します。
手順
Docker Desktopをインストールします。記事の本題とずれるため手順は省略します。
1. Opensearchの起動
Docker image opensearchproject/opensearch を使用してOpensesarchサーバーを起動します。
$ dcoker pull opensearchproject/opensearch
$ docker run -d \
--name opensearch-node \
-p 9200:9200 \
-e "discovery.type=single-node" \
-e "plugins.security.disabled=true" \
-e 'OPENSEARCH_INITIAL_ADMIN_PASSWORD=myStrongPassword123@456' \
opensearchproject/opensearch:latest
パスワードは小大英字+数字+記号を含む必要があります。条件を満たさないとコンテナが起動しません。
また、今回はローカルで試すだけなのでHTTPプロトコルを許容するためplugins.security.disabled=trueを設定しています。
下記のような応答があれば起動完了です。
$ curl -X GET "http://localhost:9200"
{
"name" : "4b7589d56f0a",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "9eWNe5L4TVK_OH62rV3mRg",
"version" : {
"distribution" : "opensearch",
"number" : "3.1.0",
"build_type" : "tar",
"build_hash" : "8ff7c6ee924a49f0f59f80a6e1c73073c8904214",
"build_date" : "2025-06-21T08:05:43.345081313Z",
"build_snapshot" : false,
"lucene_version" : "10.2.1",
"minimum_wire_compatibility_version" : "2.19.0",
"minimum_index_compatibility_version" : "2.0.0"
},
"tagline" : "The OpenSearch Project: https://opensearch.org/"
}
2. データの投入
検索対象のサンプルデータを投入します。
sample-logsデータの投入
OPENSEARCH_URL="http://localhost:9200"
AUTH_USER="admin"
AUTH_PASS="myStrongPassword123@456"
# 1. インデックスの作成
curl $CURL_OPTS -X PUT "$OPENSEARCH_URL/sample-logs" \
-u "$AUTH_USER:$AUTH_PASS" \
-H "Content-Type: application/json" \
-d '{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"properties": {
"timestamp": {
"type": "date"
},
"level": {
"type": "keyword"
},
"message": {
"type": "text"
},
"service": {
"type": "keyword"
},
"user_id": {
"type": "integer"
},
"ip_address": {
"type": "ip"
}
}
}
}'
# 2. サンプルドキュメントの投入
DOCUMENTS=(
'{"timestamp":"2024-01-15T10:00:00Z","level":"INFO","message":"User login successful","service":"auth","user_id":1001,"ip_address":"192.168.1.100"}'
'{"timestamp":"2024-01-15T10:05:00Z","level":"ERROR","message":"Database connection failed","service":"api","user_id":1002,"ip_address":"192.168.1.101"}'
'{"timestamp":"2024-01-15T10:10:00Z","level":"WARN","message":"High memory usage detected","service":"worker","user_id":1003,"ip_address":"192.168.1.102"}'
'{"timestamp":"2024-01-15T10:15:00Z","level":"INFO","message":"Cache cleared successfully","service":"cache","user_id":1001,"ip_address":"192.168.1.100"}'
'{"timestamp":"2024-01-15T10:20:00Z","level":"DEBUG","message":"Processing user request","service":"api","user_id":1004,"ip_address":"192.168.1.103"}'
'{"timestamp":"2024-01-15T10:25:00Z","level":"ERROR","message":"Payment processing failed","service":"payment","user_id":1005,"ip_address":"192.168.1.104"}'
'{"timestamp":"2024-01-15T10:30:00Z","level":"INFO","message":"Backup completed","service":"backup","user_id":null,"ip_address":"192.168.1.200"}'
'{"timestamp":"2024-01-15T10:35:00Z","level":"WARN","message":"Slow query detected","service":"database","user_id":1002,"ip_address":"192.168.1.101"}'
)
# 各ドキュメントを投入
for i in "${!DOCUMENTS[@]}"; do
echo "ドキュメント $((i+1)) を投入中..."
curl $CURL_OPTS -X POST "$OPENSEARCH_URL/sample-logs/_doc" \
-u "$AUTH_USER:$AUTH_PASS" \
-H "Content-Type: application/json" \
-d "${DOCUMENTS[$i]}"
echo ""
done
sample-productsデータの投入
OPENSEARCH_URL="http://localhost:9200"
AUTH_USER="admin"
AUTH_PASS="myStrongPassword123@456"
curl $CURL_OPTS -X PUT "$OPENSEARCH_URL/sample-products" \
-u "$AUTH_USER:$AUTH_PASS" \
-H "Content-Type: application/json" \
-d '{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"properties": {
"name": {
"type": "text",
"analyzer": "standard"
},
"category": {
"type": "keyword"
},
"price": {
"type": "float"
},
"description": {
"type": "text"
},
"in_stock": {
"type": "boolean"
},
"tags": {
"type": "keyword"
},
"created_at": {
"type": "date"
}
}
}
}'
PRODUCTS=(
'{"name":"MacBook Pro","category":"electronics","price":2499.99,"description":"High-performance laptop for professionals","in_stock":true,"tags":["laptop","apple","professional"],"created_at":"2024-01-01T00:00:00Z"}'
'{"name":"iPhone 15","category":"electronics","price":999.99,"description":"Latest smartphone with advanced features","in_stock":true,"tags":["smartphone","apple","mobile"],"created_at":"2024-01-02T00:00:00Z"}'
'{"name":"Nike Air Max","category":"shoes","price":129.99,"description":"Comfortable running shoes","in_stock":false,"tags":["shoes","nike","running"],"created_at":"2024-01-03T00:00:00Z"}'
'{"name":"Coffee Maker","category":"appliances","price":79.99,"description":"Automatic drip coffee maker","in_stock":true,"tags":["coffee","kitchen","appliance"],"created_at":"2024-01-04T00:00:00Z"}'
'{"name":"Wireless Headphones","category":"electronics","price":199.99,"description":"Noise-cancelling wireless headphones","in_stock":true,"tags":["headphones","wireless","audio"],"created_at":"2024-01-05T00:00:00Z"}'
)
for i in "${!PRODUCTS[@]}"; do
echo "商品 $((i+1)) を投入中..."
curl $CURL_OPTS -X POST "$OPENSEARCH_URL/sample-products/_doc" \
-u "$AUTH_USER:$AUTH_PASS" \
-H "Content-Type: application/json" \
-d "${PRODUCTS[$i]}"
echo ""
done
以下のコマンドで正常にデータが登録できているか確認します。
curl $CURL_OPTS -X GET "$OPENSEARCH_URL/sample-logs/_count" \
-u "$AUTH_USER:$AUTH_PASS"
curl $CURL_OPTS -X GET "$OPENSEARCH_URL/sample-products/_count" \
-u "$AUTH_USER:$AUTH_PASS"
3. MCP Toolの登録
MCPサーバーを有効にします。
curl -X PUT $OPENSEARCH_URL/_cluster/settings/ \
-u "$AUTH_USER:$AUTH_PASS" \
-H "Content-Type: application/json" \
-d '{
"persistent": {
"plugins.ml_commons.mcp_server_enabled": "true"
}
}'
MCPツールを登録します。ツールは複数登録できます。今回はIndex内を検索してデータを取得して欲しいので、SearchIndexToolを登録します。
$ curl $CURL_OPTS -X POST "$OPENSEARCH_URL/_plugins/_ml/mcp/tools/_register" \
-u "$AUTH_USER:$AUTH_PASS" \
-H "Content-Type: application/json" \
-d '{
"tools": [
{
"name": "SearchIndexTool",
"type": "SearchIndexTool",
"description": "Use this tool to search an index by providing two parameters: 'index' for the index name, and 'query' for the OpenSearch DSL formatted query. Only use this tool when both index name and DSL query is available.",
"attributes": {
"input_schema": {
"type": "object",
"properties": {
"index": {
"type": "string"
},
"query": {
"type": "string"
}
},
"additionalProperties": false
}
}
}
]
}'
登録結果の確認
$ curl "$OPENSEARCH_URL/_plugins/_ml/mcp/tools/_list?pretty" -u "$AUTH_USER:$AUTH_PASS"
公式ドキュメントのRegister MCP toolsページのExample request: Zero-configuration toolsにツールのサンプルがあるので、気になった物を登録するとよいでしょう。
ちなみにIntroducing MCP in OpenSearchページに記載されている、以下のようなtype属性だけのツールは登録できませんでした。
POST /_plugins/_ml/mcp/tools/_register
{
"tools": [
{
"type": "ListIndexTool"
}
]
}
4. 動作確認
- Claude Desktopの開発者モードを有効にします
-
%USER_HOME%\AppData\Roaming\Claude\claude_desktop_config.jsonを新規作成 -
claude_desktop_config.jsonを以下の通り編集してClaude Desktopを再起動claude_desktop_config.json{ "mcpServers": { "opensearch-mcp-server": { "command": "uvx", "args": [ "test-opensearch-mcp" ], "env": { "OPENSEARCH_URL": "http://localhost:9200", "OPENSEARCH_USERNAME": "admin", "OPENSEARCH_PASSWORD": "myStrongPassword123@456" } } } }
以下のようにMCPを使用してOpensesarchからデータを検索してくれるようになりました。



おわりに
今回はサンプルデータを投入しましたが、実際には素材データを投入し、たとえば「ピンボールゲームを作りたいので、ボールの素材に使えそうなものはありますか」と問いかけたら適切な素材を返してくれるようにしたいです。
Discussion