2025年7月9日水曜日

Chainlitをコンテナで実行してSQLclのMCPサーバーを組み込む

以前に公開した記事「Chainlitをコンテナで実行してOracleに問い合わせるMCPサーバーを組み込む」ではお手製のMCPサーバーを組み込んでいました。このMCPサーバーを、オラクルが最近リリースしたSQLclのMCPサーバーに置き換えます。

作業は以前と同様にmacOS上のpodmanを使って実施します。

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

mkdir chainlit-sqlcl-mcp
cd chainlit-sqlcl-mcp

% mkdir chainlit-sqlcl-mcp

ynakakoshi@Ns-Macbook Documents % cd chainlit-sqlcl-mcp

chainlit-sqlcl-mcp % 


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


Manoranjan Rajguru(monuminu)さんのAOAI_Samplesのリポジトリより、app.pyをダウンロードします。


オリジナルのapp.pyに以下の変更を加えます。オリジナルはMicrosoft AzureOpenAIを使うようにコーディングされていますが、OpenAIに置き換えています。また、モデルやAPIキーの設定を設定ファイルopenai.envより読み込むように変更しています。


変更内容をapp.diffとして作成し、パッチとして適用します。

patchコマンドを実行します。

patch app.py < app.diff

chainlit-sqlcl-mcp % patch app.py < app.diff

patching file app.py

chainlit-sqlcl-mcp % 


SQLclをダウンロードします。SQLclの最新版はつねに同じURLからダウンロードできます。

curl -OL https://download.oracle.com/otn_software/java/sqldeveloper/sqlcl-latest.zip

chainlit-sqlcl-mcp % curl -OL https://download.oracle.com/otn_software/java/sqldeveloper/sqlcl-latest.zip

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current

                                 Dload  Upload   Total   Spent    Left  Speed

100 87.7M  100 87.7M    0     0  8859k      0  0:00:10  0:00:10 --:--:-- 8538k

chainlit-sqlcl-mcp % 


app.pyの制約で、MCPサーバーはnpxコマンドで実行する必要があります。SQLclを呼び出すスクリプトsqlを、npxから呼び出せるようにパッケージを作成します。

ディクレトリsqlcl-mcpを作成します。

mkdir sqlcl-mcp

chainlit-sqlcl-mcp % mkdir sqlcl-mcp

chainlit-sqlcl-mcp % 


作成したディレクトリsqlcl-mcpの下に、以下の内容でファイルpackage.jsonを作成します。
{
  "name": "sqlcl-mcp",
  "version": "1.0.0",
  "bin": {
    "run-sqlcl-mcp": "./sqlcl-mcp.sh"
  }
}
同じディレクトリに、SQLclをオプション-mcpを付けて呼び出すsqlcl-mcp.shを作成します。
#!/bin/sh
/home/oracle/sqlcl/bin/sql -mcp
作成したファイルsqlcl-mcp.shに実行権限を付与します。

chmod 755 sqlcl-mcp/sqlcl-mcp.sh

chainlit-sqlcl-mcp % chmod 755 sqlcl-mcp/sqlcl-mcp.sh 

chainlit-sqlcl-mcp % 


作成したpackage.jsonsqlcl-mcp.shを含んだディレクトリsqlcl-mcpを、ZIPファイルsqlcl-mcp.zipに固めます。

zip -r sqlcl-mcp.zip sqlcl-mcp

chainlit-sqlcl-mcp % zip -r sqlcl-mcp.zip sqlcl-mcp

  adding: sqlcl-mcp/ (stored 0%)

  adding: sqlcl-mcp/sqlcl-mcp.sh (deflated 5%)

  adding: sqlcl-mcp/package.json (deflated 28%)

chainlit-sqlcl-mcp %


以上で準備完了です。コンテナ・イメージをchainlit-sqlcl-mcpとして作成します。

podman build -f Dockerfile -t chainlit-sqlcl-mcp

chainlit-sqlcl-mcp % podman build -f Dockerfile -t chainlit-sqlcl-mcp

STEP 1/15: FROM oraclelinux:9

STEP 2/15: RUN dnf update -y &&     dnf install -y sudo passwd unzip python3.12 python3.12-pip npm java-21-openjdk-headless &&     dnf clean all

Oracle Linux 9 BaseOS Latest (aarch64)          9.4 MB/s |  82 MB     00:08    

Oracle Linux 9 Application Stream Packages (aar  10 MB/s |  37 MB     00:03    

Last metadata expiration check: 0:00:05 ago on Wed Jul  9 06:12:32 2025.

Dependencies resolved.

==========================================================================================

 Package                       Arch     Version                   Repository          Size

==========================================================================================

Upgrading:

 alternatives                  aarch64  1.24-2.0.1.el9            ol9_baseos_latest   36 k

 audit-libs                    aarch64  3.1.5-4.0.1.el9           ol9_baseos_latest  125 k

 bzip2-libs                    aarch64  1.0.8-10.el9_5            ol9_baseos_latest   40 k

 chkconfig                     aarch64  1.24-2.0.1.el9            ol9_baseos_latest  233 k

 coreutils                     aarch64  8.32-39.0.1.el9           ol9_baseos_latest  1.2 M

 coreutils-common              aarch64  8.32-39.0.1.el9           ol9_baseos_latest  2.1 M

 crypto-policies               noarch   20250128-1.git5269e22.el9 ol9_baseos_latest  178 k

 dnf                           noarch   4.14.0-25.0.1.el9         ol9_baseos_latest  532 k


[中略]


--> 3f9fe801480e

STEP 12/15: RUN unzip sqlcl-mcp.zip

Archive:  sqlcl-mcp.zip

   creating: sqlcl-mcp/

  inflating: sqlcl-mcp/sqlcl-mcp.sh  

  inflating: sqlcl-mcp/package.json  

--> cc7dbec62677

STEP 13/15: RUN ln -s /home/oracle/work/openai.env /home/oracle/openai.env

--> 3075c32451ba

STEP 14/15: EXPOSE 8000

--> 80424d635a6c

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

COMMIT chainlit-sqlcl-mcp

--> 642b60a6cbe6

Successfully tagged localhost/chainlit-sqlcl-mcp:latest

642b60a6cbe62480e6eb3999e53e314e42f1c43aacced799d1be904fde2fffe2

chainlit-sqlcl-mcp % 


作成されたコンテナ・イメージを確認します。

podman image ls chainlit-sqlcl-mcp

chainlit-sqlcl-mcp % podman image ls chainlit-sqlcl-mcp

REPOSITORY                    TAG         IMAGE ID      CREATED             SIZE

localhost/chainlit-sqlcl-mcp  latest      642b60a6cbe6  About a minute ago  1.42 GB

chainlit-sqlcl-mcp % 


作成したコンテナ・イメージを元に、コンテナsqlcl-mcpを作成し実行します。ポート番号8000をホストの8000にマップしています。また、ホストに配置した環境設定ファイルopenai.envをコンテナから参照するため、カレント・ディレクトリをコンテナ内の/home/oracle/workにマウントします。

podman run -d --name sqlcl-mcp -p 8000:8000 -v $PWD:/home/oracle/work localhost/chainlit-sqlcl-mcp:latest

chainlit-sqlcl-mcp % podman run -d --name sqlcl-mcp -p 8000:8000 -v $PWD:/home/oracle/work localhost/chainlit-sqlcl-mcp:latest

b3e71635c08edf82e8b0626998463920dbd873697a82f659b93a90838fb7cf8e

chainlit-sqlcl-mcp % 


この状態でChainlitは起動していますが、OpenAIのモデルとAPIキーの設定がないためにエラーが発生しています。


作業ディレクトリにファイルopenai.envを作成し、OPENAI_MODELOPENAI_API_KEYを設定します。以下では使用するモデルとして、gpt-4oを指定してます。
OPENAI_MODEL=gpt-4o
OPENAI_API_KEY=[OpenAIのAPIキー]
MCPサーバーの接続先となるデータベースをSQLclに設定します。接続先をAutonomous Databaseにするため、ウォレット・ファイルWallet_APEXDEV.zipをカレント・ディレクトリにコピーします。

ウォレット・ファイルは接続先となるAutonomous Databaseで異なります。また、オンプレミスのデータベースが接続先の場合は、ウォレット・ファイルは不要です。

ホスト上の作業ディレクトリは以下のようになります。

chainlit-sqlcl-mcp % ls

app.diff Dockerfile sqlcl-mcp

app.py openai.env sqlcl-mcp.zip

app.py.orig sqlcl-latest.zip Wallet_APEXDEV.zip

chainlit-sqlcl-mcp % 


コンテナsqlcl-mcpに接続します。

podman exec -it sqlcl-mcp bash

chainlit-sqlcl-mcp % podman exec -it sqlcl-mcp bash

[oracle@b3e71635c08e ~]$ 


SQLclを起動します。色々警告が出ていますが、ARM64でJavaを実行する際の警告なので無視します。

./sqlcl/bin/sql /nolog

[oracle@b3e71635c08e ~]$ ./sqlcl/bin/sql /nolog

OpenJDK 64-Bit Server VM warning: Unable to get SVE vector length on this system. Disabling SVE. Specify -XX:UseSVE=0 to shun this warning.



SQLcl: Release 25.2 Production on Wed Jul 09 06:33:01 2025


Copyright (c) 1982, 2025, Oracle.  All rights reserved.


/bin/bash: line 1: tput: command not found

/bin/bash: line 1: tput: command not found

SQL> 


データベースに接続します。その際にパスワードを含めて、接続そのものを名前をつけて保存します。

以下では接続にadb_mcpという名前を付けています。ホストの作業ディレクトリに配置しているウォレット・ファイルは、コンテナからは/home/oracle/workから参照できます。

接続ユーザー、パスワードおよび接続先となるTNS別名は、環境に合わせて調整します。

conn -save adb_mcp -cloudconfig /home/oracle/work/Wallet_APEXDEV.zip -savepwd wksp_apexdev@apexdev_low

SQL> conn -save adb_mcp -cloudconfig /home/oracle/work/Wallet_APEXDEV.zip -savepwd wksp_apexdev@apexdev_low

Password? (**********?) **************

Name: adb_mcp

Connect String: apexdev_low

User: wksp_apexdev

Password: ******

oracle.net.wallet_location: (SOURCE=(METHOD=FILE)(METHOD_DATA=(DIRECTORY=${TNS_ADMIN})))

TNSNAMES.ORA: /home/oracle/.dbtools/connections/lL71TGyuKUaBw3hS_TI8JQ/tnsnames.ora

TNS Descriptor: apexdev_low = (description=(retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1522)(host=adb.us-ashburn-1.oraclecloud.com))(connect_data=(service_name=*************_apexdev_low.adb.oraclecloud.com))(security=(ssl_server_dn_match=yes)))

Connected.

SQL> 


作成した接続はconnmgrコマンドで確認できます。

connmgr list

SQL> connmgr list

.

└── adb_mcp

SQL> 


connmgr show adb_mcp

SQL> connmgr show adb_mcp

Name: adb_mcp

Connect String: apexdev_low

User: wksp_apexdev

Password: ******

oracle.net.wallet_location: (SOURCE=(METHOD=FILE)(METHOD_DATA=(DIRECTORY=${TNS_ADMIN})))

TNSNAMES.ORA: /home/oracle/.dbtools/connections/lL71TGyuKUaBw3hS_TI8JQ/tnsnames.ora

TNS Descriptor: apexdev_low = (description=(retry_count=20)(retry_delay=3)(address=(protocol=tcps)(port=1522)(host=adb.us-ashburn-1.oraclecloud.com))(connect_data=(service_name=bp9ncf74sqibu4p_apexdev_low.adb.oraclecloud.com))(security=(ssl_server_dn_match=yes)))

SQL> 


connmgrには、この他にもコマンドがあります。help connmgrでコマンドが一覧されます。

help connmgr

SQL> help connmgr


Connection Manager


The Connection manager (CONNMGR)  command allows you to import 

connections from SQLDeveloper, list and test them.

These connections can be used with the connect command to 

connect to a database 


   E.g., connmgr import connections.json 

         connmgr list myconnection 


Subcommands:

  import

  Import one or more connections into the common connection store


  list

  List the existing connection folders and the connections contained within them


  show

  Show the details for a connection


  test

  Test a connection


  clone

  Clone an existing connection


  add

  Add a new connection folder


  delete

  Delete a connection or a folder, non-empty folders cannot be deleted unless

  the -force flag is used, which permanently removes the folder along with all

  its contents, including the connections


  move

  Move a connection name or a folder to another location


  rename

  Rename a connection name or a folder


More help topics:

  CONNMGR EXAMPLES

  CONNMGR SYNTAX

  CONNMGR IMPORT

  CONNMGR LIST

  CONNMGR SHOW

  CONNMGR TEST

  CONNMGR CLONE

  CONNMGR ADD

  CONNMGR DELETE

  CONNMGR MOVE

  CONNMGR RENAME


SQL> 


OpenAIのAPIを呼び出す設定およびデータベースへの接続が設定できたので、コンテナを抜けて、コンテナを再起動します。

podman restart sqlcl-mcp

SQL> exit

Disconnected from Oracle Database 23ai Enterprise Edition Release 23.0.0.0.0 - for Oracle Cloud and Engineered Systems

Version 23.8.0.25.06

[oracle@b3e71635c08e ~]$ exit

exit

chainlit-sqlcl-mcp % podman restart sqlcl-mcp

sqlcl-mcp

chainlit-sqlcl-mcp % 


Chainlitのアプリケーションに接続し、MCPサーバーを追加します。


Connect an MCPを選択します。

Namesqlclとし、Typestdioを選択します。Commandに以下を記述します。

npx /home/oracle/sqlcl-mcp run-sqlcl-mcp

以上で確認をクリックします。


MCPサーバーとしてsqlclが追加されると、My MCPsに表示されます。


後はChainlitの画面より、動作を確認します。

sqlclで使用できる接続を一覧して。


adb_mcpに接続して。


スキーマSHにある表と表の定義を覚えて。


DESCRIBE SHを実行した結果、SHが無いって返されました。

オラクルのビューを確認して。

延々と結果が返ってこないから中断して、SQLを確認したらALL_VIEWSを検索していました。


総じてClaudeのモデルの方がSQLの生成が得意に感じますが、こちらは簡易版のMCPホストですのでフェアな比較とは言えないです。

サーバー側のプロセスを確認すると、ブラウザを開くたびにMCPサーバーとなるSQLclのプロセスが起動しています。ただし、ブラウザを閉じてもプロセスは残るようです。

[oracle@b3e71635c08e ~]$ ps -ef | grep 'sql -mcp'

oracle       500     499  0 07:20 ?        00:00:00 /bin/bash /home/oracle/sqlcl/bin/sql -mcp

oracle       660     659  0 07:22 ?        00:00:00 /bin/bash /home/oracle/sqlcl/bin/sql -mcp

oracle       774     773  0 07:23 ?        00:00:00 /bin/bash /home/oracle/sqlcl/bin/sql -mcp

oracle       936     935  0 07:26 ?        00:00:00 /bin/bash /home/oracle/sqlcl/bin/sql -mcp

oracle      1039     230  0 07:26 pts/0    00:00:00 grep --color=auto sql -mcp

[oracle@b3e71635c08e ~]$ 


たまにコンテナの再起動が必要かもしれません。もともと、ChainlitでMCPサーバーを呼び出す実装のサンプルですので、動くだけでも十分です。

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