Ble Hrm Server について
ble-hrm-server は、Bluetooth 心拍計に接続する Python 製 MCP サーバーです。MCP クライアントを利用するアプリ向けに、心拍の監視、測定値の取得、集計、グラフ生成を提供します。
主な機能
- 01HRM プロファイル対応デバイスの検出
- 02指定時間の心拍監視
- 03直近の測定値から平均を取得
- 04最大心拍数の評価
- 05時間区分ごとの値とグラフの提供
活用シーン
- 01運動中の心拍監視
- 02直近の平均心拍数の確認
- 03運動後のピーク心拍数の確認
- 04直近の測定値のグラフ化
MCP 対応
HRM デバイス検出リソースと、心拍の監視、取得、評価、グラフ化を行うツールを MCP クライアントに公開します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
ble-hrm-server
HRM デバイスに接続するための BLE Heart Rate Monitoring として機能する MCP サーバーです。
ビルド状況
インストール
依存関係の管理には、仮想環境と uv を使用することをおすすめします。
このプロジェクトでは、依存関係の管理に pyproject.toml を使用します。
# Create and activate a virtual environment
python3 -m venv .venv
source .venv/bin/activate # On Windows use `.venv\Scripts\activate`
# Install uv if not already installed
pip install uv
# Install dependencies
uv sync
環境設定
このプロジェクトでは、.env ファイルによる設定に対応しています。用意されている .env.sample をテンプレートとして使用できます。
cp .env.sample .env
以下の環境変数を使用します。
QINIU_ACCESS_KEY:Qiniu のアクセスキー。QINIU_SECRET_KEY:Qiniu のシークレットキー。QINIU_BUCKET_NAME:Qiniu バケットの名前。QINIU_BUCKET_DOMAIN:Qiniu バケットに関連付けられたドメイン。
使用方法
サーバーを実行する
uv run src/hrm/server.py
PyPI からインストールした後は、次のコマンドでサーバーを直接実行できます。
uvx ble-hrm-server
テストを実行する
uv run pytest
カバレッジを測定してテストを実行する
uv run coverage run -m pytest
uv run coverage html
MCP の定義
リソース
Bluetooth HRM は Bluetooth プロトコルに基づいているため、bleak を使用してデバイスを検出し、接続します。
- Bluetooth デバイスを検出し、HRM プロファイル(Heart Rate Service 0x180D)でフィルタリングします
- リソース:
discover://hrm
ツール
-
ツール:心拍数のモニタリング
monitoring_heart_rate- 概要:指定された時間、デバイスの心拍数のモニタリングを開始します。デフォルトのモニタリング時間は30分(1800秒)です。モニタリングはバックグラウンドで実行されます。
- 入力:
- device_id:str、モニタリング対象のデバイス UUID
- duration:int、モニタリング時間。デフォルトは1800秒(30分)
- 出力:なし
-
ツール:心拍数の取得
get_heart_rate- 概要:直近10秒間の心拍数を取得し、平均値を返します。
- 入力:なし(基準値の測定を前提とします)
- 出力:現在の心拍数(int)、例:
{"avg_hr": 60}
-
ツール:運動時心拍数の評価
evaluate_active_heart_rate- 概要:直近60秒間の最大心拍数を評価し、この運動中に観測された最大値を運動時心拍数として記録します。
- 入力:なし(基準値の測定を前提とします)
- 出力:最大心拍数:int、例:
{"max_hr": 100}
-
ツール:心拍数バケットの取得
get_heart_rate_bucket- 概要:直近10秒間の心拍数バケットを取得します。バケットのサイズは1秒です。
- 入力:
- since_from:float、モニタリング開始時刻。デフォルトは10秒前
- bucket_size:float、バケットのサイズ。デフォルトは1秒
- 出力:心拍数バケット:list[dict]、例:
[{"time": 1715904000, "value": 60}, {"time": 1715904001, "value": 61}]
-
ツール:心拍数グラフの作成
build_heart_rate_chart- 概要:直近600秒間の心拍数グラフを作成します。バケットサイズは動的に設定され、デフォルトは1秒です。バケット数の上限は60です。バケット数が60を超える場合、バケットサイズは
duration / 60秒に増加します。 - 入力:
- since_from:float、モニタリング開始時刻。デフォルトは600秒前
- 出力:心拍数グラフの PNG URL:str、例:
https://example.com/chart.png
- 概要:直近600秒間の心拍数グラフを作成します。バケットサイズは動的に設定され、デフォルトは1秒です。バケット数の上限は60です。バケット数が60を超える場合、バケットサイズは
MCP の設定
サーバーの MCP 設定は次のとおりです。
{
"mcpServers": {
"blue-hrm": {
"command": "uvx",
"args": [
"ble-hrm-server"
]
}
}
}
以下は、DeepSeek V3.1 でテストした LLM 向けのプロンプト例です。
你是一位健康专家,通过心率来检测测试者的心脏健康程度,现在测试者携带了蓝牙的心率带,
以下为检测步骤
- 你通过发现来获取的设备ID,通过rssi获取最接近的设备,再以此设备开始监控。
- 获取当前测试者的静息心率。
- 当测试结束后,提示测试者开始中高强度运动,比如波比跳,当测试者完成运动后,回复后,立刻测试其最高运动心率。
- 之后提示测试者计时休息2分钟,得到确认后,再次获取当前心率,并与最高心率的差额作为恢复心率。
最后通过恢复心率的值和以下列表评估测试者的心脏健康程度,并用健康专家的口吻给测试者一些关于心脏健康方面的建议。
------
- <22: 身体年龄略大于 真实年龄
- 22~52: 身体年龄= 真实年龄
- 53~58: 身体年龄略小于真实年龄
- 59~65: 身体年龄比真实年龄小
- >=66: 身体年龄比真实年龄小很多
コードカバレッジ
| 名前 | Stmts | Miss | Cover |
|---|---|---|---|
| src/hrm/__init__.py | 0 | 0 | 100% |
| src/hrm/bt_client.py | 139 | 5 | 96% |
| src/hrm/ts_db.py | 41 | 1 | 98% |
| TOTAL | 180 | 6 | 97% |
スポンサー
ストレージサービスを提供してくださった Qiniu Cloud に心より感謝します。Qiniu は LLM 推論サービスも提供しています。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。