ラベル Chainlit の投稿を表示しています。 すべての投稿を表示
ラベル Chainlit の投稿を表示しています。 すべての投稿を表示

2025年4月9日水曜日

Chainlitをコンテナで実行してOracleに問い合わせるMCPサーバーを組み込む

以前の記事「ChainlitのアプリケーションにOracle Databaseに問い合わせるMCPサーバーを組み込み質問する」でChainlitを動作させました。このアプリケーションをあまり環境に依存しないように、コンテナで実行させてみました。

作業はmacOSのpodmanを使って行います。

ローカルに適当なディレクトリを作成します。以下ではディレクトリとしてchainlit-mcp-oracleを作成しました。作成したディレクトリに移動して作業します。

mkdir chainlit-mcp-oracle
cd chainlit-mcp-oracle


% mkdir chainlit-mcp-oracle

% cd chainlit-mcp-oracle 

chainlit-mcp-oracle % 


以下の内容でDockerfileを作成します。


こちらの記事「ChainlitのアプリケーションよりPlaywright MCPを呼び出してOracle APEXのアプリケーションを操作する」で作成したapp.pyを、作業ディレクトリ以下に配置します。

https://github.com/monuminu/AOAI_Samples/blob/main/mcp_aoai/app.py

オリジナルのapp.pyに以下の変更を加えます。
< from openai import AzureOpenAI, AsyncAzureOpenAI
---
> from openai import OpenAI, AsyncOpenAI
11c11
< load_dotenv("azure.env")
---
> load_dotenv("openai.env")
17,21c17,19
<         self.deployment_name = os.environ["AZURE_OPENAI_MODEL"]
<         self.client = AsyncAzureOpenAI(
<                 azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
<                 api_key=os.environ["AZURE_OPENAI_API_KEY"],
<                 api_version=os.environ["OPENAI_API_VERSION"]
---
>         self.deployment_name = os.environ["OPENAI_MODEL"]
>         self.client = AsyncOpenAI(
>                 api_key=os.environ["OPENAI_API_KEY"]

作業ディレクトリ以下にファイルopenai.envを作成し、OPENAI_MODELOPENAI_API_KEYの設定を記述します。
OPENAI_MODEL=gpt-4o-mini
OPENAI_API_KEY=[Open AIのAPIキー]
以下の内容を記述したファイルrequirements.txtを作成します。
chainlit
openai
python-dotenv
aiohttp
Oracleに問い合わせるMCPサーバーのコードindex.tsをあらかじめ配置しておきます。

https://gist.github.com/ujnak/22bacdabcf0fa108ff9d1d14d98e1e58

結果として、以下のファイルが作成されます。

chainlit-mcp-oracle % ls

Dockerfile app.py.org openai.env

app.py index.ts requirements.txt

chainlit-mcp-oracle % 


以上で準備は完了です。

コンテナ・イメージをchainlit-oracle-mcpという名前で作成します。

podman build --file Dockerfile --tag chainlit-oracle-mcp

chainlit-mcp-oracle % podman build --file Dockerfile --tag chainlit-oracle-mcp

STEP 1/11: FROM python:3.13-slim

STEP 2/11: ENV DEBIAN_FRONTEND=noninteractive

--> Using cache 1264b22e4ba065c8f8d00b723edd54d3922467ca7690ce0b7e0437945503731c

--> 1264b22e4ba0

STEP 3/11: RUN apt-get update && apt-get install -y curl gnupg &&     curl -fsSL https://deb.nodesource.com/setup_23.x | bash - &&     apt-get install -y nodejs &&     apt-get clean &&     rm -rf /var/lib/apt/lists/*

--> Using cache a2a3cba9b0a4485a807a281f09692dc413fed26aee34c58ceb6b7bd6d38fc051

--> a2a3cba9b0a4

STEP 4/11: WORKDIR /app

--> Using cache 2ae9c5a3f01fd3b031f741025f2218943d522bddc46baf42348ce89df4fa6041

--> 2ae9c5a3f01f

STEP 5/11: COPY requirements.txt .

--> deab204ce2e9

STEP 6/11: COPY app.py .

--> 469e9dbc1871

STEP 7/11: COPY openai.env .

--> f9c558203ec1

STEP 8/11: COPY index.ts .

--> 0741acf2d3c4

STEP 9/11: RUN pip install --no-cache-dir -r requirements.txt

Collecting chainlit (from -r requirements.txt (line 1))

  Downloading chainlit-2.4.400-py3-none-any.whl.metadata (6.3 kB)

Collecting openai (from -r requirements.txt (line 2))

  Downloading openai-1.72.0-py3-none-any.whl.metadata (25 kB)

Collecting python-dotenv (from -r requirements.txt (line 3))

  Downloading python_dotenv-1.1.0-py3-none-any.whl.metadata (24 kB)

Collecting aiohttp (from -r requirements.txt (line 4))

  Downloading aiohttp-3.11.16-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.metadata (7.7 kB)

Collecting aiofiles<25.0.0,>=23.1.0 (from chainlit->-r requirements.txt (line 1))

  Downloading aiofiles-24.1.0-py3-none-any.whl.metadata (10 kB)

Collecting asyncer<0.0.8,>=0.0.7 (from chainlit->-r requirements.txt (line 1))

  Downloading asyncer-0.0.7-py3-none-any.whl.metadata (6.6 kB)


[中略]


[notice] A new release of pip is available: 24.3.1 -> 25.0.1

[notice] To update, run: pip install --upgrade pip

--> b2e0e3dc56c2

STEP 10/11: EXPOSE 8000

--> 3b34cebebc30

STEP 11/11: CMD ["chainlit", "run", "app.py", "--port", "8000", "--host", "0.0.0.0"]

COMMIT chainlit-oracle-mcp

--> 684dab947de4

Successfully tagged localhost/chainlit-oracle-mcp:latest

684dab947de4fbeeaa2ee34f4cbffb86e527d8e6210efd9747321dd1001c8f87

chainlit-mcp-oracle % 


作成されたイメージを確認します。

podman image ls chainlit-oracle-mcp

chainlit-mcp-oracle % podman image ls chainlit-oracle-mcp

REPOSITORY                     TAG         IMAGE ID      CREATED             SIZE

localhost/chainlit-oracle-mcp  latest      684dab947de4  About a minute ago  546 MB

chainlit-mcp-oracle % 


イメージからコンテナをmy-chainlit-mcpという名前で作成して実行します。

podman run -d -p 8000:8000 --name my-chainlit-mcp localhost/chainlit-oracle-mcp

chainlit-mcp-oracle % podman run -d -p 8000:8000 --name my-chainlit-mcp localhost/chainlit-oracle-mcp

31be6d9e26003c31c0122e9940ecc5436bea94316afb34f3da2403bc66a0a8e0

chainlit-mcp-oracle % 


コンテナに接続して、Oracleに接続するMCPサーバーをビルドします。ビルドする手順は記事「Oracle Databaseに接続するMCPサーバーを作成しClaudeから問い合わせる」と同じです。

podman exec -it my-chainlit-mcp bash

chainlit-mcp-oracle % podman exec -it my-chainlit-mcp bash

root@31be6d9e2600:/app# 


以下を実行します。作成するMCPサーバーの名前はoracleとしています。

npx @modelcontextprotocol/create-server oracle-server

root@31be6d9e2600:/app# npx @modelcontextprotocol/create-server oracle-server

Need to install the following packages:

@modelcontextprotocol/create-server@0.3.1

Ok to proceed? (y) y


? What is the name of your MCP server? oracle

? What is the description of your server? My first MCP server

MCP server created successfully!


Next steps:

  cd oracle-server

  npm install

  npm run build  # or: npm run watch

  npm link       # optional, to make available globally


root@31be6d9e2600:/app# 


oracle-server/src以下にあるindex.tsをOracleのMCPサーバーの実装に置き換えます。

cp index.ts oracle-server/src/index.ts

root@31be6d9e2600:/app# cp index.ts oracle-server/src/index.ts 

root@31be6d9e2600:/app# 


Next stepsで案内されている通りにビルドします。

root@31be6d9e2600:/app# cd oracle-server/

root@31be6d9e2600:/app/oracle-server# npm install


> oracle@0.1.0 prepare

> npm run build



> oracle@0.1.0 build

> tsc && node -e "require('fs').chmodSync('build/index.js', '755')"



added 17 packages, and audited 18 packages in 2s


1 package is looking for funding

  run `npm fund` for details


found 0 vulnerabilities

root@31be6d9e2600:/app/oracle-server# npm run build


> oracle@0.1.0 build

> tsc && node -e "require('fs').chmodSync('build/index.js', '755')"


root@31be6d9e2600:/app/oracle-server# npm link


added 1 package, and audited 3 packages in 686ms


found 0 vulnerabilities

root@31be6d9e2600:/app/oracle-server# 


以上でコンテナにOracleに問い合わせるMCPサーバーが作成できました。

実行中のChainlitに、手元のブラウザから接続します。


コンセントのアイコンをクリックします。


Add your first MCP serverをクリックします。


NameOracleとし、Commandに以下を記述します。MCPサーバーの実体であるindex.jsはコンテナ内のパスを指定します。また、ローカルホストで動作しているOracle Databaseを接続先にしているためホスト名としてhost.containers.internalを指定しています。

npx node /app/oracle-server/build/index.js http://host.containers.internal:8181/ords/apexdev/_/sql wksp_apexdev [パスワード]

確認をクリックします。


MCPサーバーとしてOracleが追加されます。


以下の問い合わせを入力し、MCPサーバーの動作を確認します。

「私のOracleにはどのような表がありますか?」


以下のSQLを実行して回答しているので、MCPサーバーとしての組み込みは成功です。
{
    "mcp_name": "Oracle",
    "function_name": "query",
    "function_args": {
        "sql": "SELECT table_name FROM user_tables"
    }
}
今回の記事は以上になります。

2025年4月1日火曜日

ChainlitのアプリケーションにOracle Databaseに問い合わせるMCPサーバーを組み込み質問する

Microsoftから公開されているMCPを扱うChainlitのサンプル・アプリケーションに(こちらの記事を参照のこと)、以前の記事「Oracle Databaseに接続するMCPサーバーを作成しClaudeから問い合わせる」で作成したOracle Databaseに問い合わせるMCPサーバーを組み込み、Chainlitのアプリから質問してみます。

Oracle DatabaseのMCPサーバーを組み込んで、問合せを行なっています。


ChainlitのアプリケーションにOracle Databaseに問い合わせるMCPサーバーを登録します。


Claude DesktopのときはMCPのcommandとしてnodeを指定しましたが、Chainlitのサンプル・アプリケーションで許可されているコマンドはnpxまたはuvxです。そのため、NameOracle Databaseとして、Commandに以下を指定します。index.jsへのパスやURLに含まれるAPEXワークスペース名(以下ではapexdev)、スキーマ名(wksp_apexdev)は環境に合わせて変更します。

npx node /Users/username/Documents/oracle-server/build/index.js http://localhost:8181/ords/apexdev/_/sql wksp_apexdev [パスワード]

確認をクリックして、MCPサーバーを追加します。


MCPサーバーとしてOracle Databaseが追加されます。


MCPサーバーが追加されたので、これからチャットを始めます。

(gpt-4o-miniは今ひとつだったので、環境変数OPENAI_MODELにgpt-4oを設定しています。)

「Oracle Databaseから参照できる表を一覧してください。」

ビューUSER_TABLESを検索し、接続先のスキーマにある表が一覧されます。


「EBAで始まる表の列情報を参照してください。」

ビューUSER_TAB_COLUMNSを検索して、それぞれの表の列を一覧します。


「これらの情報より、アジアで一番人口の少ない国を調べてください。」

生成されたSQLは以下です。
SELECT c.NAME, c.POPULATION FROM EBA_COUNTRIES c JOIN EBA_COUNTRY_REGIONS r ON c.REGION_ID = r.ID WHERE r.NAME = 'Asia' ORDER BY c.POPULATION ASC FETCH FIRST 1 ROW ONLY;


「アジアに含まれる国を、人口の多い順番でリストして。」
SELECT c.NAME, c.POPULATION FROM EBA_COUNTRIES c JOIN EBA_COUNTRY_REGIONS r ON c.REGION_ID = r.ID WHERE r.NAME = 'Asia' ORDER BY c.POPULATION DESC;

Claude DesktopにOracle DatabaseのMCPサーバーを組み込んだときは、Claudeが勝手にスキーマのメタデータやデータそのものを読み出して推論に使っていましたが、このサンプル・アプリケーションはそのようには動かず、チャットの最初に表や列情報を取り出しておく必要がありました。そのようにすれば、その情報を使ってSELECT文が生成されます。

とりあえず、OpenAIとOracle DatabaseのMCPサーバーの組み合わせで動作することが確認できました。

ChainlitのアプリケーションよりPlaywright MCPを呼び出してOracle APEXのアプリケーションを操作する

以前の記事で、Claude DesktopにPlaywright MCPを組み込んでOracle APEXのアプリケーションを操作してみました。MCPサーバーの組み込みがClaude Desktopに限定されている点で、自由度が今ひとつと思っていたところ、株式会社ヘッドウォータース様が公開している以下の記事を見つけました。

Azure OpenAIでMCPを使ったデモアプリを試す
https://zenn.dev/headwaters/articles/223f212b4c1cd6

Microsoftから公開されているAzure OpenAIのサンプルのひとつにMCPとのインテグレーションが含まれていて、それを動かしたことを記事にされています。

記事に含まれるスクリーンショットより、デモアプリケーションはChainlitで作成していることが分かります。ChainlitであればPythonが動けばどこでも実行できそうです。Azure OpenAI向けですが、少し修正してOpenAIで動作させました。

Azure OpenAI MCP Integration
https://github.com/monuminu/AOAI_Samples/tree/main/mcp_aoai

以前の記事と同じ操作を行なっています。サインイン後にダッシュボードのページに移動しなかったり、ユーザー名の入力がうまくできなかったりしましたが、概ねアプリケーションの操作はできています。


以下、作業の手順を紹介します。作業はmacOS 15.3.2で行なっています。

最初に作業ディレクトリを作成して、移動します。

mkdir mcp_aoai
cd mcp_aoai

% mkdir mcp_aoai

% cd mcp_aoai

mcp_aoai % 


必須の作業ではありませんが、仮想環境を作成します。このサンプル・アプリケーションのPrerequisitesは、Python 3.8以上になっています。

python3 -V
python3 -m venv mcp_aoai
source mcp_aoai/bin/activate

mcp_aoai % python3 -V            

Python 3.13.2

mcp_aoai % python3 -m venv mcp_aoai

mcp_aoai % source mcp_aoai/bin/activate

(mcp_aoai) mcp_aoai % 


必要なパッケージをインストールします。

pip install chainlit openai python-dotenv aiohttp

(mcp_aoai) mcp_aoai % pip install chainlit openai python-dotenv aiohttp


Collecting chainlit

  Using cached chainlit-2.4.400-py3-none-any.whl.metadata (6.3 kB)

Collecting openai

  Using cached openai-1.70.0-py3-none-any.whl.metadata (25 kB)

Collecting python-dotenv

  Using cached python_dotenv-1.1.0-py3-none-any.whl.metadata (24 kB)

Collecting aiohttp

  Using cached aiohttp-3.11.12-cp313-cp313-macosx_11_0_arm64.whl.metadata (7.7 kB)

Collecting aiofiles<25.0.0,>=23.1.0 (from chainlit)

  Using cached aiofiles-24.1.0-py3-none-any.whl.metadata (10 kB)

Collecting asyncer<0.0.8,>=0.0.7 (from chainlit)

  Using cached asyncer-0.0.7-py3-none-any.whl.metadata (6.6 kB)

Collecting click<9.0.0,>=8.1.3 (from chainlit)


[中略]


o-5.12.1 pyyaml-6.0.2 regex-2024.11.6 requests-2.32.3 simple-websocket-1.1.0 six-1.17.0 sniffio-1.3.1 sse-starlette-2.2.1 starlette-0.41.3 syncer-2.0.3 tenacity-8.5.0 tiktoken-0.9.0 tokenizers-0.21.1 tomli-2.2.1 tqdm-4.67.1 traceloop-sdk-0.39.0 typing-extensions-4.13.0 typing-inspect-0.9.0 typing-inspection-0.4.0 uptrace-1.31.0 urllib3-2.3.0 uvicorn-0.34.0 watchfiles-0.20.0 wrapt-1.17.2 wsproto-1.2.0 yarl-1.18.3 zipp-3.21.0


[notice] A new release of pip is available: 25.0 -> 25.0.1

[notice] To update, run: pip install --upgrade pip

(mcp_aoai) mcp_aoai % 


Azure OpenAI MCP Integrationのリポジトリに含まれるapp.pyをダウンロードします。


ダウンロードしたapp.pyに以下の変更を加えます。インポートするモジュールをAzureOpenAI、AsyncAzureOpenAIからOpenAI、AsyncOpenAIに変更し、モデルの指定を環境変数OIPENAI_MODEL、APIキーを環境変数OPENAI_API_KEYとして与えるようにします。
8c8
< from openai import AzureOpenAI, AsyncAzureOpenAI
---
> from openai import OpenAI, AsyncOpenAI
17,21c17,19
<         self.deployment_name = os.environ["AZURE_OPENAI_MODEL"]
<         self.client = AsyncAzureOpenAI(
<                 azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
<                 api_key=os.environ["AZURE_OPENAI_API_KEY"],
<                 api_version=os.environ["OPENAI_API_VERSION"]
---
>         self.deployment_name = os.environ["OPENAI_MODEL"]
>         self.client = AsyncOpenAI(
>                 api_key=os.environ["OPENAI_API_KEY"]

環境変数OPENAI_MODELOPENAI_API_KEYを設定します。あまりお金がかからないように、使用するモデルは廉価版のgpt-4o-miniを選択しています。

export OPENAI_MODEL=gpt-4o-mini-2024-07-18
export OPENAI_API_KEY=OpenAIのAPIキー


(mcp_aoai) mcp_aoai % export OPENAI_MODEL=gpt-4o-mini-2024-07-18

(mcp_aoai) mcp_aoai % export OPENAI_API_KEY=OpenAIのAPIキー

(mcp_aoai) mcp_aoai %                                             


以上で準備は完了です。

アプリケーションを実行します。

chainlit run app.py

(mcp_aoai) mcp_aoai % chainlit run app.py

2025-04-01 11:12:09 - Your app is available at http://localhost:8000

2025-04-01 11:12:10 - Translated markdown file for ja not found. Defaulting to chainlit.md.


ブラウザが開きます。コンセントのアイコンをクリックして、MCPサーバーの設定を開きます。


MCPサーバーとしてPlaywright MCPを追加します。

NamePlaywright MCPTypestdioを選択します。Commandに以下を記述します。

npx -y @playwright/mcp@latest

確認をクリックします。


My MCPsにPlaywright MCPが追加されます。緑のインジケータが点いて、14個のツールが登録されます。


コンセントのアイコンにMCPサーバーが1個登録されていることが、アクセントとして表示されます。


あとはChainlitのチャット・インターフェースを通して、Oracle APEXのアプリケーションを操作します。


今回の記事は以上になります。