mcpField
P
protocolsio-integration

protocolsio-integration

github.com/jaechang-hits生産性38469 回インストール1 週間前に更新
リポジトリ

protocolsio-integration について

実験プロトコルを検索・取得する protocols.io REST API を、生命科学研究者やラボ自動化の開発者向けに解説するスキルです。バージョン履歴や材料の抽出に加え、非公開コンテンツや編集に必要な OAuth2 も扱います。

主な機能

  1. 01キーワード、手法、DOI による検索
  2. 02全手順と材料の取得
  3. 03プロトコルのバージョン履歴確認
  4. 04プロトコルカテゴリの閲覧
  5. 05非公開プロトコルと編集の OAuth2 利用

活用シーン

  1. 01実験手法の引用可能なプロトコルを検索
  2. 02自動化ワークフロー向けに手順と試薬を抽出
  3. 03プロトコルの版と DOI を確認
  4. 04特定の試薬や機器を使う手順を検索

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jaechang-hits/sciagent-skills --skill protocolsio-integration

インストール後、Claude Code で/protocolsio-integrationを入力して読み込まれたか確認します。

詳細

protocols.io 連携

概要

protocols.io は、分子生物学、細胞生物学、バイオインフォマティクス、臨床研究、ラボ自動化を網羅する 90,000 件以上のオープンアクセス実験プロトコルを提供する、ライフサイエンス分野をリードするプロトコルリポジトリです。REST API を使用すると、プロトコルの検索、プロトコル全体の取得(手順、試薬、材料、機器)、プロトコルのバージョン管理、ワークスペース管理、プロトコルの公開をプログラムから実行できます。公開プロトコルは無料で利用できます。非公開プロトコルへのアクセスや作成・編集には認証(OAuth2 トークン)が必要です。

使用する場面

  • キーワード、手法、または論文の DOI で、検証済みのウェットラボプロトコルを検索する
  • 自動化や分析のために、プロトコルの手順、試薬、所要時間、容量、注記を含む完全な内容を取得する
  • 特定の試薬、キット、または機器に関連するプロトコルを見つける
  • プロトコルの手順や試薬リストをプログラムで抽出し、ラボ自動化ワークフローを構築する
  • プロトコルのバージョンを確認し、方法のセクションで正しい DOI を引用する
  • 独自の手法に代わる、コミュニティで検証済みのプロトコルを見つける
  • opentrons-protocol-api または benchling-integration と併用し、ダウンロードしたプロトコルを自動化ワークフローに実装する

前提条件

  • Python パッケージ:requests、pandas
  • データ要件:プロトコルのキーワード、DOI、または protocols.io のプロトコル ID
  • 環境:インターネット接続。公開プロトコルには認証不要。非公開プロトコルには https://www.protocols.io/developers で取得する OAuth2 トークンが必要
  • レート制限:公開 API は 1 秒あたり 10 リクエスト。公開プロトコルへの未認証リクエストが許可されています
pip install requests pandas
# For private protocol access or publishing:
# Register at https://www.protocols.io/developers to obtain an API token

クイックスタート

import requests

BASE = "https://www.protocols.io/api/v4"
# For public protocols, no token needed (but add for higher rate limits)
HEADERS = {"Authorization": "Bearer YOUR_TOKEN_HERE"}  # Optional for public

# Search for CRISPR protocols
r = requests.get(f"{BASE}/protocols",
                 params={"q": "CRISPR guide RNA design", "order_field": "views",
                         "page_size": 5},
                 headers=HEADERS)
r.raise_for_status()
data = r.json()
print(f"Total CRISPR protocols: {data['pagination']['total_results']}")
for p in data["items"][:3]:
    print(f"\n  {p['title']}")
    print(f"  DOI: {p.get('doi')} | Views: {p.get('stats', {}).get('number_of_views')}")
    print(f"  Authors: {', '.join(a['name'] for a in p.get('creators', [])[:3])}")

主要 API

クエリ 1:プロトコル検索

キーワード、手法、または全文で protocols.io の公開ライブラリを検索します。

import requests, pandas as pd

BASE = "https://www.protocols.io/api/v4"

def search_protocols(query, page_size=20, order_field="relevance", category_id=None):
    params = {"q": query, "page_size": page_size, "order_field": order_field}
    if category_id:
        params["filter[categories_ids][]"] = category_id
    r = requests.get(f"{BASE}/protocols", params=params)
    r.raise_for_status()
    return r.json()

data = search_protocols("RNA extraction tissue", page_size=10, order_field="views")
total = data["pagination"]["total_results"]
print(f"RNA extraction protocols: {total}")

rows = []
for p in data["items"][:10]:
    rows.append({
        "id": p.get("id"),
        "title": p.get("title"),
        "doi": p.get("doi"),
        "views": p.get("stats", {}).get("number_of_views", 0),
        "created": p.get("created_on"),
        "category": p.get("categories", [{}])[0].get("name", "n/a"),
    })
df = pd.DataFrame(rows).sort_values("views", ascending=False)
print(df.to_string(index=False))
# Search with category filter (get category IDs from /categories endpoint)
data_pcr = search_protocols("qPCR primer design", order_field="views")
print(f"\nqPCR protocols: {data_pcr['pagination']['total_results']}")
for p in data_pcr["items"][:3]:
    print(f"  {p['title'][:70]} (DOI: {p.get('doi', 'n/a')})")
クエリ 2:プロトコル全体の内容を取得

手順、試薬、材料、機器を含むプロトコル全体を取得します。

import requests

BASE = "https://www.protocols.io/api/v4"

def get_protocol(protocol_id):
    r = requests.get(f"{BASE}/protocols/{protocol_id}")
    r.raise_for_status()
    return r.json()

# Retrieve protocol by ID (from search results or DOI lookup)
protocol_id = 45979  # Example: a public protocol
data = get_protocol(protocol_id)
protocol = data.get("payload", data)  # Handle API response structure

print(f"Title: {protocol.get('title')}")
print(f"DOI: {protocol.get('doi')}")
print(f"Authors: {', '.join(a['name'] for a in protocol.get('creators', []))}")
print(f"Steps: {len(protocol.get('steps', []))}")
print(f"Materials: {len(protocol.get('materials', []))}")
print(f"Abstract: {protocol.get('description', '')[:200]}")
# Parse protocol steps
protocol_steps = protocol.get("steps", [])
for i, step in enumerate(protocol_steps[:5], 1):
    step_desc = step.get("description", "")
    duration = step.get("duration", {})
    print(f"\nStep {i}: {step_desc[:120]}")
    if duration:
        print(f"  Duration: {duration.get('duration')} {duration.get('unit_label', '')}")
クエリ 3:DOI からプロトコルを取得

正確な引用情報に基づいて取得するため、DOI を使ってプロトコルを取得します。

import requests, json

BASE = "https://www.protocols.io/api/v4"

def get_protocol_by_doi(doi):
    """Retrieve protocol using its DOI."""
    # URL-encode the DOI for the query
    r = requests.get(f"{BASE}/protocols",
                     params={"q": doi, "page_size": 5})
    r.raise_for_status()
    items = r.json()["items"]
    for item in items:
        if item.get("doi") == doi:
            return item
    return None

doi = "10.17504/protocols.io.bvb3n2qn"  # Example protocols.io DOI
protocol = get_protocol_by_doi(doi)
if protocol:
    print(f"Found: {protocol['title']}")
    print(f"  ID: {protocol['id']}")
    print(f"  Version: {protocol.get('version_id')}")
クエリ 4:試薬と材料を抽出

取得したプロトコルから材料リストを解析して抽出します。

import requests, pandas as pd

BASE = "https://www.protocols.io/api/v4"

def get_reagents(protocol_id):
    r = requests.get(f"{BASE}/protocols/{protocol_id}")
    r.raise_for_status()
    data = r.json()
    protocol = data.get("payload", data)
    return protocol.get("materials", [])

# Get reagents list
materials = get_reagents(45979)  # Example protocol ID
print(f"Materials ({len(materials)} items):")
rows = []
for m in materials[:10]:
    rows.append({
        "name": m.get("name"),
        "quantity": m.get("quantity"),
        "unit": m.get("unit", {}).get("name", ""),
        "supplier": m.get("supplier", {}).get("name", ""),
        "catalog": m.get("sku"),
    })
df = pd.DataFrame(rows)
print(df.to_string(index=False))
クエリ 5:プロトコルのカテゴリを閲覧

対象を絞った検索に利用できるプロトコルのカテゴリを一覧表示します。

import requests, pandas as pd

BASE = "https://www.protocols.io/api/v4"

r = requests.get(f"{BASE}/categories")
r.raise_for_status()
data = r.json()
categories = data.get("items", data.get("payload", []))

print(f"protocols.io categories: {len(categories)}")
df = pd.DataFrame(categories)[["id", "name"]].head(20)
print(df.to_string(index=False))
クエリ 6:プロトコルのバージョン一覧を取得

プロトコルの更新を追跡するため、バージョン履歴を取得します。

import requests

BASE = "https://www.protocols.io/api/v4"

def get_protocol_versions(protocol_id):
    r = requests.get(f"{BASE}/protocols/{protocol_id}")
    r.raise_for_status()
    protocol = r.json().get("payload", r.json())
    return {
        "title": protocol.get("title"),
        "version": protocol.get("version_id"),
        "published": protocol.get("published_on"),
        "doi": protocol.get("doi"),
        "parent_doi": protocol.get("parent_publication", {}).get("doi"),
    }

info = get_protocol_versions(45979)
for k, v in info.items():
    print(f"  {k}: {v}")

主な概念

プロトコルの DOI とバージョン管理

protocols.io で公開された各プロトコルには、引用可能な DOI(形式:10.17504/protocols.io.XXXXX)が付与されます。プロトコルが更新されると、新しい DOI を持つ新バージョンが作成されますが、元の DOI も引き続き有効です。再現性を確保するため、方法のセクションでは必ず特定のバージョンの DOI を引用してください。

API 認証

公開プロトコルは認証なしでアクセスできます。非公開プロトコル、ワークスペース管理、プロトコルの作成・編集、ユーザー固有のクエリには、OAuth2 Bearer トークンが必要です。トークンは https://www.protocols.io/developers で取得してください。

一般的なワークフロー

ワークフロー 1:プロトコルの検索と比較

目的:手法に合致するプロトコルを検索、比較し、応用に最適なものを選択します。

import requests, pandas as pd

BASE = "https://www.protocols.io/api/v4"

def search_and_rank(query, top_n=20):
    """Search protocols and return ranked by views + forks."""
    r = requests.get(f"{BASE}/protocols",
                     params={"q": query, "page_size": top_n, "order_field": "views"})
    r.raise_for_status()
    data = r.json()

    rows = []
    for p in data["items"]:
        stats = p.get("stats", {})
        rows.append({
            "id": p.get("id"),
            "title": p.get("title"),
            "doi": p.get("doi"),
            "views": stats.get("number_of_views", 0),
            "forks": stats.get("number_of_forks", 0),
            "steps": p.get("number_of_steps"),
            "created": p.get("created_on")[:10] if p.get("created_on") else "n/a",
            "category": p.get("categories", [{}])[0].get("name", "n/a"),
        })

    df = pd.DataFrame(rows)
    df["popularity_score"] = df["views"] * 0.7 + df["forks"] * 0.3 * 100
    return df.sort_values("popularity_score", ascending=False)

# Compare western blotting protocols
df = search_and_rank("western blot protein detection", top_n=15)
df.to_csv("western_blot_protocols.csv", index=False)
print("Top western blot protocols:")
print(df[["title", "views", "forks", "steps"]].head(8).to_string(index=False))
ワークフロー 2:自動化に向けたプロトコル手順の抽出

目的:後続の自動化スクリプト作成に向けて、プロトコルの手順、所要時間、試薬の容量を抽出します。

import requests, pandas as pd

BASE = "https://www.protocols.io/api/v4"

def extract_protocol_steps(protocol_id):
    """Extract structured step data from a protocol."""
    r = requests.get(f"{BASE}/protocols/{protocol_id}")
    r.raise_for_status()
    protocol = r.json().get("payload", r.json())

    steps = []
    for i, step in enumerate(protocol.get("steps", []), 1):
        duration = step.get("duration", {})
        steps.append({
            "step_number": i,
            "description": step.get("description", ""),
            "duration_value": duration.get("duration"),
            "duration_unit": duration.get("unit_label", ""),
            "temperature": step.get("temperature", {}).get("value"),
            "temp_unit": step.get("temperature", {}).get("unit_label", ""),
        })

    materials = [{
        "name": m.get("name"),
        "quantity": m.get("quantity"),
        "unit": m.get("unit", {}).get("name", ""),
    } for m in protocol.get("materials", [])]

    return {
        "title": protocol.get("title"),
        "doi": protocol.get("doi"),
        "steps": pd.DataFrame(steps),
        "materials": pd.DataFrame(materials),
    }

result = extract_protocol_steps(45979)
print(f"Protocol: {result['title']}")
print(f"\nSteps ({len(result['steps'])}):")
print(result["steps"][["step_number", "description", "duration_value", "duration_unit"]].head(5).to_string(index=False))
print(f"\nMaterials ({len(result['materials'])}):")
print(result["materials"].head(5).to_string(index=False))

# Export for automation
result["steps"].to_csv("protocol_steps.csv", index=False)
result["materials"].to_csv("protocol_materials.csv", index=False)

主なパラメーター

パラメーターモジュールデフォルト範囲/選択肢効果
q検索—キーワード文字列全文検索クエリ
order_field検索"relevance""relevance"、"views"、"date"、"activity"結果の並べ替え順
page_size検索101–501 ページあたりの結果数
page_id検索1整数ページ番号
filter[categories_ids][]検索—カテゴリの整数 IDプロトコルのカテゴリで絞り込み
Protocol ID取得必須整数取得する特定のプロトコル

ベストプラクティス

  1. 品質を判断するために閲覧数順で並べ替える:十分に検証されたプロトコルを検索する場合は、order_field=viewsを使用してください。閲覧数の多いプロトコルは、多くのグループでテストされています。

  2. 必ず特定のDOIを引用する:protocols.ioのDOIにはバージョンが付与されています。読者が同じプロトコルを再現できるように、メソッドのセクションではプロトコル名だけでなく、正確なバージョンのDOIを引用してください。

  3. 使用前にライセンスを確認する:protocols.ioで公開されているプロトコルは、デフォルトですべてCC-BY 4.0です。商用利用する場合は、各プロトコルのライセンスを確認してください。

  4. 試薬の注文用に材料リストを抽出する:材料APIはカタログ番号とサプライヤー名を返すため、調達リストを直接作成できます。

  5. 再現性のためにプロトコルIDとDOIを保存する:プロジェクトでプロトコルを選択する際は、APIアクセス用の整数IDと、安定した引用に使うDOIの両方を記録してください。

よくあるレシピ

レシピ:試薬名で検索する

使用する場面:特定の市販キットや試薬を使うプロトコルを探す場合。

import requests

r = requests.get("https://www.protocols.io/api/v4/protocols",
                 params={"q": "RNeasy Mini Kit RNA extraction", "page_size": 5,
                         "order_field": "views"})
data = r.json()
print(f"Protocols using RNeasy: {data['pagination']['total_results']}")
for p in data["items"][:3]:
    print(f"  {p['title'][:70]} ({p.get('doi', 'n/a')})")
レシピ:メソッドのセクション用にプロトコルの引用情報を取得する

使用する場面:メソッドのセクション用の引用文字列を生成する場合。

import requests

protocol_id = 45979
r = requests.get(f"https://www.protocols.io/api/v4/protocols/{protocol_id}")
p = r.json().get("payload", r.json())
authors = "; ".join(a["name"] for a in p.get("creators", [])[:3])
print(f"Citation: {authors} ({p.get('created_on', '')[:4]}). ")
print(f"{p.get('title')}. protocols.io. https://doi.org/{p.get('doi')}")
レシピ:フォーク数が最も多いプロトコルを探す

使用する場面:広く応用されているプロトコル(フォーク数が多いほど、多くのラボで応用されています)を特定する場合。

import requests, pandas as pd

r = requests.get("https://www.protocols.io/api/v4/protocols",
                 params={"q": "ChIP-seq chromatin", "page_size": 20})
data = r.json()
df = pd.DataFrame([{
    "title": p["title"][:60],
    "forks": p.get("stats", {}).get("number_of_forks", 0),
    "views": p.get("stats", {}).get("number_of_views", 0),
} for p in data["items"]])
print(df.sort_values("forks", ascending=False).head(5).to_string(index=False))

トラブルシューティング

問題原因解決策
検索結果のitemsが空クエリが具体的すぎる、または一致する項目がないクエリの範囲を広げる。特殊文字を削除する
プロトコルへのアクセス時にHTTP 401が発生する認証なしで非公開プロトコルにアクセスしているOAuth2トークンを取得する。公開プロトコルには認証は不要
プロトコルの手順説明が空プロトコルでリッチテキスト形式が使われているre.sub(r'<[^>]+>', '', text)でdescriptionからHTMLタグを削除する
materialsリストが空プロトコルに構造化された材料情報がない材料情報が手順の説明文にプレーンテキストで埋め込まれている可能性がある
DOI検索で間違ったプロトコルが返されるDOIではなく、類似したタイトルで一致しているDOIフィールドを正確に比較する。文字列の等価性チェックif item.get("doi") == doiを使用する
レート制限エラーが発生するリクエスト数が1秒あたり10件を超えているリクエストの間にtime.sleep(0.15)を追加する

関連スキル

  • opentrons-protocol-api — このスキルで抽出した手順を使って、Opentronsの液体ハンドリングロボットでプロトコルを実行します
  • benchling-integration — 試薬の追跡とともに、取得したプロトコルをBenchling ELNに保存します
  • scientific-manuscript-writing — protocols.ioのDOIを使って、メソッドのセクションでプロトコルを正しく引用します

参考資料

コメント