2026年4月17日金曜日

MCP AppsのサンプルアプリCohort Heatmap Serverをデータベースで実行する

GitHubのリポジトリmodelcontextprotocol/ext-appsに含まれているCohort Heatmap Serverをデータベースでホストしてみます。作業はBudget Allocator Serverと同じですが、TypeScriptで記述されたserver.tsのPL/SQLへの変換は、すべてClaude Opus 4.7に実施してもらいました。

Claude DesktopのChatから呼び出しています。


Claude Codeでのセッション履歴はこちらから参照できます。このセッションでのコンテキストウィンドウの使用量は87.2kでした。生成されたファイルは、リポジトリmcp-appのexamples/cohort-heatmap-server以下に保存されています。今回もオリジナルのTypeScriptの実装を忠実に反映しているかどうかは確認していません。MCPアプリが動作すれば、それで良しとしています。

Claudeはデータベース・サーバーへの実装まで行なう勢いでしたが、それは遠慮して自分で作業することにしました。

これからはBudget Allocator Serverの実装と同じ作業を行います。

サーバーをインストールします。スクリプトはchs_install.sqlとして作成されています。

sql -cloudconfig Wallet_SALESADB.zip wksp_apexdev@salesadb_low
@mcp-app/examples/cohort-heatmap-server/chs_install.sql


mcp-salesadb % sql -cloudconfig Wallet_SALESADB.zip wksp_apexdev@salesadb_low


SQLcl: 金 4月 17 12:58:41 2026のリリース25.4 Production


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


パスワード (**********?) ****************

接続先:

Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.31.0.1.0


SQL> @mcp-app/examples/cohort-heatmap-server/chs_install.sql 


Table CHS_METRIC_PARAMSは作成されました。



Table CHS_DATASET_METAは作成されました。



Table CHS_PERIODSは作成されました。



Table CHS_COHORTSは作成されました。



Table CHS_COHORT_CELLSは作成されました。



Commentは作成されました。



Commentは作成されました。



Commentは作成されました。



Commentは作成されました。



Commentは作成されました。



Procedure CHS_GENERATE_COHORT_DATAがコンパイルされました



Function CHS_GET_COHORT_DATA_RESPONSEがコンパイルされました



1行挿入しました。



1行挿入しました。



1行挿入しました。



コミットが完了しました。



PL/SQLプロシージャが正常に完了しました。



コミットが完了しました。


{"content":[{"type":"text","text":"Cohort Analysis: 12 cohorts, 12 periods\nAverage retention: 60.5%\nMetric: retention, Period: monthly"}],"structuredContent":{"cohorts":[{"cohortId":"2025-05","cohortLabel":"May 2025","originalUsers":3329,"cells":[{"cohortIndex":0,"periodIndex":0,"retention":1,"usersRetained":3329,"usersOriginal":3329},{"cohortIndex":0,"periodIndex":1,"retention":0.831585,"usersRetained":2768,"usersOriginal":3329},{"cohortIndex":0,"periodIndex":2,"retention":0.742468,"usersRetained":2472,"usersOriginal":3329},{"cohortIndex":0,"periodIndex":3,"retention":0.692134,"usersRetained":2304,"usersOriginal":3329},{"cohortIndex":0,"periodIndex":4,"retention":0.597086,"usersRetained":1988,"usersOriginal":3329},{"cohortIndex":0,"periodIndex":5,"retention":0.506757,"usersRetained":1687,"usersOriginal":3329},{"cohortIndex":0,"periodIndex":6,"retention":0.485,"usersRetained":1615,"usersOriginal":3329},{"cohortIndex":0,"periodIndex":7,"retention":0.469762,"usersRetained":1564,"usersOriginal":3329},{"cohortIndex":0,"periodIndex":8,"retention":0.41277,"usersRetained":1374,"usersOriginal":3329},{"cohortIndex":0,"periodIndex":9,"retention":0.384362,"usersRetained":1280,"usersOriginal":3329},{"cohortIndex":0,"periodIndex":10,"retention":0.309279,"usersRetained":1030,"usersOriginal":3329},{"cohortIndex":0,"periodIndex":11,"retention":0.307191,"usersRetained":1023,"usersOriginal":3329}]},{"cohortId":"2025-06","cohortLabel":"Jun 2025","originalUsers":3247,"cells":[{"cohortIndex":1,"periodIndex":0,"retention":1,"usersRetained":3247,"usersOriginal":3247},{"cohortIndex":1,"periodIndex":1,"retention":0.809895,"usersRetained":2630,"usersOriginal":3247},{"cohortIndex":1,"periodIndex":2,"retention":0.778759,"usersRetained":2529,"usersOriginal":3247},{"cohortIndex":1,"periodIndex":3,"retention":0.63884,"usersRetained":2074,"usersOriginal":3247},{"cohortIndex":1,"periodIndex":4,"retention":0.615927,"usersRetained":2000,"usersOriginal":3247},{"cohortIndex":1,"periodIndex":5,"retention":0.530365,"usersRetained":1722,"usersOriginal":3247},{"cohortIndex":1,"periodIndex":6,"retention":0.466432,"usersRetained":1515,"usersOriginal":3247},{"cohortIndex":1,"periodIndex":7,"retention":0.458745,"usersRetained":1490,"usersOriginal":3247},{"cohortIndex":1,"periodIndex":8,"retention":0.437283,"usersRetained":1420,"usersOriginal":3247},{"cohortIndex":1,"periodIndex":9,"retention":0.337689,"usersRetained":1096,"usersOriginal":3247},{"cohortIndex":1,"periodIndex":10,"retention":0.327546,"usersRetained":1064,"usersOriginal":3247}]},{"cohortId":"2025-07","cohortLabel":"Jul 2025","originalUsers":4396,"cells":[{"cohortIndex":2,"periodIndex":0,"retention":1,"usersRetained":4396,"usersOriginal":4396},{"cohortIndex":2,"periodIndex":1,"retention":0.82277,"usersRetained":3617,"usersOriginal":4396},{"cohortIndex":2,"periodIndex":2,"retention":0.707806,"usersRetained":3112,"usersOriginal":4396},{"cohortIndex":2,"periodIndex":3,"retention":0.675264,"usersRetained":2968,"usersOriginal":4396},{"cohortIndex":2,"periodIndex":4,"retention":0.627578,"usersRetained":2759,"usersOriginal":4396},{"cohortIndex":2,"periodIndex":5,"retention":0.515941,"usersRetained":2268,"usersOriginal":4396},{"cohortIndex":2,"periodIndex":6,"retention":0.523848,"usersRetained":2303,"usersOriginal":4396},{"cohortIndex":2,"periodIndex":7,"retention":0.443467,"usersRetained":1949,"usersOriginal":4396},{"cohortIndex":2,"periodIndex":8,"retention":0.399864,"usersRetained":1758,"usersOriginal":4396},{"cohortIndex":2,"periodIndex":9,"retention":0.383536,"usersRetained":1686,"usersOriginal":4396}]},{"cohortId":"2025-08","cohortLabel":"Aug 2025","originalUsers":4340,"cells":[{"cohortIndex":3,"periodIndex":0,"retention":1,"usersRetained":4340,"usersOriginal":4340},{"cohortIndex":3,"periodIndex":1,"retention":0.852336,"usersRetained":3699,"usersOriginal":4340},{"cohortIndex":3,"periodIndex":2,"retention":0.755159,"usersRetained":3277,"usersOriginal":4340},{"cohortIndex":3,"periodIndex":3,"retention":0.647924,"usersRetained":2812,"usersOriginal":4340},{"cohortIndex":3,"periodIndex":4,"retention":0.614553,"usersRetained":2667,"usersOriginal":4340},{"cohortIndex":3,"periodIndex":5,"retention":0.577885,"usersRetained":2508,"usersOriginal":4340},{"cohortIndex":3,"periodIndex":6,"retention":0.471343,"usersRetained":2046,"usersOriginal":4340},{"cohortIndex":3,"periodIndex":7,"retention":0.412234,"usersRetained":1789,"usersOriginal":4340},{"cohortIndex":3,"periodIndex":8,"retention":0.432234,"usersRetained":1876,"usersOriginal":4340}]},{"cohortId":"2025-09","cohortLabel":"Sep 2025","originalUsers":2176,"cells":[{"cohortIndex":4,"periodIndex":0,"retention":1,"usersRetained":2176,"usersOriginal":2176},{"cohortIndex":4,"periodIndex":1,"retention":0.79756,"usersRetained":1735,"usersOriginal":2176},{"cohortIndex":4,"periodIndex":2,"retention":0.780148,"usersRetained":1698,"usersOriginal":2176},{"cohortIndex":4,"periodIndex":3,"retention":0.658383,"usersRetained":1433,"usersOriginal":2176},{"cohortIndex":4,"periodIndex":4,"retention":0.62944,"usersRetained":1370,"usersOriginal":2176},{"cohortIndex":4,"periodIndex":5,"retention":0.525048,"usersRetained":1143,"usersOriginal":2176},{"cohortIndex":4,"periodIndex":6,"retention":0.471819,"usersRetained":1027,"usersOriginal":2176},{"cohortIndex":4,"periodIndex":7,"retention":0.415988,"usersRetained":905,"usersOriginal":2176}]},{"cohortId":"2025-10","cohortLabel":"Oct 2025","originalUsers":1495,"cells":[{"cohortIndex":5,"periodIndex":0,"retention":1,"usersRetained":1495,"usersOriginal":1495},{"cohortIndex":5,"periodIndex":1,"retention":0.862656,"usersRetained":1290,"usersOriginal":1495},{"cohortIndex":5,"periodIndex":2,"retention":0.726128,"usersRetained":1086,"usersOriginal":1495},{"cohortIndex":5,"periodIndex":3,"retention":0.664703,"usersRetained":994,"usersOriginal":1495},{"cohortIndex":5,"periodIndex":4,"retention":0.606737,"usersRetained":907,"usersOriginal":1495},{"cohortIndex":5,"periodIndex":5,"retention":0.535005,"usersRetained":800,"usersOriginal":1495},{"cohortIndex":5,"periodIndex":6,"retention":0.47813,"usersRetained":715,"usersOriginal":1495}]},{"cohortId":"2025-11","cohortLabel":"Nov 2025","originalUsers":1730,"cells":[{"cohortIndex":6,"periodIndex":0,"retention":1,"usersRetained":1730,"usersOriginal":1730},{"cohortIndex":6,"periodIndex":1,"retention":0.808085,"usersRetained":1398,"usersOriginal":1730},{"cohortIndex":6,"periodIndex":2,"retention":0.733066,"usersRetained":1268,"usersOriginal":1730},{"cohortIndex":6,"periodIndex":3,"retention":0.678534,"usersRetained":1174,"usersOriginal":1730},{"cohortIndex":6,"periodIndex":4,"retention":0.601015,"usersRetained":1040,"usersOriginal":1730},{"cohortIndex":6,"periodIndex":5,"retention":0.545659,"usersRetained":944,"usersOriginal":1730}]},{"cohortId":"2025-12","cohortLabel":"Dec 2025","originalUsers":4664,"cells":[{"cohortIndex":7,"periodIndex":0,"retention":1,"usersRetained":4664,"usersOriginal":4664},{"cohortIndex":7,"periodIndex":1,"retention":0.797832,"usersRetained":3721,"usersOriginal":4664},{"cohortIndex":7,"periodIndex":2,"retention":0.71077,"usersRetained":3315,"usersOriginal":4664},{"cohortIndex":7,"periodIndex":3,"retention":0.692459,"usersRetained":3230,"usersOriginal":4664},{"cohortIndex":7,"periodIndex":4,"retention":0.604596,"usersRetained":2820,"usersOriginal":4664}]},{"cohortId":"2026-01","cohortLabel":"Jan 2026","originalUsers":4739,"cells":[{"cohortIndex":8,"periodIndex":0,"retention":1,"usersRetained":4739,"usersOriginal":4739},{"cohortIndex":8,"periodIndex":1,"retention":0.827283,"usersRetained":3920,"usersOriginal":4739},{"cohortIndex":8,"periodIndex":2,"retention":0.706674,"usersRetained":3349,"usersOriginal":4739},{"cohortIndex":8,"periodIndex":3,"retention":0.667728,"usersRetained":3164,"usersOriginal":4739}]},{"cohortId":"2026-02","cohortLabel":"Feb 2026","originalUsers":1062,"cells":[{"cohortIndex":9,"periodIndex":0,"retention":1,"usersRetained":1062,"usersOriginal":1062},{"cohortIndex":9,"periodIndex":1,"retention":0.812612,"usersRetained":863,"usersOriginal":1062},{"cohortIndex":9,"periodIndex":2,"retention":0.732734,"usersRetained":778,"usersOriginal":1062}]},{"cohortId":"2026-03","cohortLabel":"Mar 2026","originalUsers":4754,"cells":[{"cohortIndex":10,"periodIndex":0,"retention":1,"usersRetained":4754,"usersOriginal":4754},{"cohortIndex":10,"periodIndex":1,"retention":0.85056,"usersRetained":4044,"usersOriginal":4754}]},{"cohortId":"2026-04","cohortLabel":"Apr 2026","originalUsers":2566,"cells":[{"cohortIndex":11,"periodIndex":0,"retention":1,"usersRetained":2566,"usersOriginal":2566}]}],"periods":["M0","M1","M2","M3","M4","M5","M6","M7","M8","M9","M10","M11"],"periodLabels":["Month 0","Month 1","Month 2","Month 3","Month 4","Month 5","Month 6","Month 7","Month 8","Month 9","Month 10","Month 11"],"metric":"retention","periodType":"monthly","generatedAt":"2026-04-16T18:59:21.447Z"}}



PL/SQLプロシージャが正常に完了しました。


Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production

Version 19.31.0.1.0から切断されました

mcp-salesadb % 


リソースは以下の値で作成しています。

Uri: ui://get-cohort-data/mcp-app.html
Name: Cohort Heatmap
Description: cohort retention heatmap data showing customer retention over time by signup month


作成したリソースCohort Heatmapに登録するUIバンドルは、リポジトリext-appsに含まれるext-apps/examples/cohort-heatmap-server/dist/mcp-app.htmlです。


ツールとしてget-cohort-dataを作成します。

Code: get-cohort-data
Description: Returns cohort retention heatmap data showing customer retention over time by signup month
Input Schema: input_schema.json
Function Call: return chs_get_cohort_data_response(:parameters);
Tags: ext-apps
Resource Id: Cohort Heatmap
Output Schema: output_schema.json


以上で、データベースにMCPアプリCohort Heatmapを登録できました。

Budget Allocatorのときに作成したカスタムコネクタを一旦削除し、Sample MCP Appsとして再登録したのち、get-cohort-dataを呼び出した結果が、記事の先頭にあるGIF動画になります。