An MCP server to interact with the Bluesky social network API
mcpbluesky
このリポジトリは、Bluesky の API を操作するための MCP(Model Context Protocol)サーバー(FastMCP)と、動作確認用の簡易クライアントを提供します。
Python パッケージは src/mcpbluesky/ 配下にあり、サーバーは mcpbluesky.server をエントリポイントとして起動します。
pyproject.toml は Hatchling(PEP 517/518)でビルドする構成で、インストールすると mcpbluesky という コンソールスクリプト(mcpbluesky = mcpbluesky.server:main)が導入されます。
何ができるか
- MCP サーバーとして Bluesky API をツール化
- 読み取り(プロフィール取得、タイムライン取得、検索など)
- 書き込み(投稿、返信、いいね、リポスト、フォロー/ブロック、リスト操作など)
- 複数アカウントのセッション管理(永続化)
sessions.jsonにアクセストークン/リフレッシュトークン等を保存acting_handle引数の省略時に使う デフォルトハンドルを保持
- (任意)Jetstream を購読して日本語投稿をローカル SQLite に保存し、検索可能
ディレクトリ構成
主要ファイルは src/mcpbluesky/ にあります。
src/mcpbluesky/server.py- FastMCP サーバー本体
SessionManager(複数ユーザーセッションのロード/セーブ/選択)- Jetstream 購読(オプション)と DB 保存
- ローカルDB検索ツール
bsky_search_local_postsの提供
src/mcpbluesky/tools_bluesky.py- MCP ツール(
bsky_*)の登録 acting_handleによる「どのログインセッションで実行するか」の切替
- MCP ツール(
src/mcpbluesky/bluesky_api.pyBlueskyAPI(HTTP 呼び出しの薄いラッパ)BlueskySession(accessJwt/refreshJwt/did/handle/pds_url)- 投稿テキストのバリデーション(grapheme 300 / bytes 3000)
- URL/ハッシュタグを facets に変換(UTF-8 バイトオフセットで index 設定)
src/mcpbluesky/common_http.pyurllib.requestベースの HTTP 実装(requests 非依存)- スロットリング(最小間隔 0.2 秒)
- リトライ(429/403/5xx 等)
- (環境によっては)Zscaler continue 画面の検知と迂回
src/mcpbluesky/bluesky_db.py- Jetstream から受信した投稿を SQLite へ保存・検索
- 日本語判定(
langsにja、または ひらがな/カタカナ正規表現)
src/mcpbluesky/client.py- HTTP transport(streamable-http)でサーバーに接続し、
list_tools()とbsky_get_profileを呼ぶ動作確認用サンプル
- HTTP transport(streamable-http)でサーバーに接続し、
MCP サーバー(`server.py`)の挙動
セッション管理(`SessionManager`)
- セッションは
sessions.jsonに永続化されます。 SessionManager.default_handleを保持し、各ツールのacting_handleが省略された場合に そのデフォルトのセッションを使います。SessionManager.get_api(handle=None)- 対象セッションが存在すればその
BlueskyAPIを返す - 存在しなければ 未ログイン状態の
BlueskyAPIを返します(この場合auth_params()によりhttps://public.api.bsky.appを使用)
- 対象セッションが存在すればその
Jetstream(オプション)
- 起動時デフォルトでは Jetstream は有効になりません。
--jetstreamを付けた場合のみ Jetstream を別スレッドで起動し、wss://jetstream1.us-east.bsky.network/subscribe?wantedCollections=app.bsky.feed.postを購読します。kind == "commit"かつoperation == "create"の投稿のみを対象にし、BlueskyDB.is_japanese(text, langs)が True のものだけ DB に保存します。
提供ツール(MCP tools)
src/mcpbluesky/tools_bluesky.py と src/mcpbluesky/server.py により、少なくとも以下のツールが登録されます。
セッション系
bsky_login(handle: Optional[str] = None, password: Optional[str] = None)handle/passwordが省略された場合は環境変数から補完BSKY_HANDLEBSKY_APP_PASSWORD
- 既に同一 handle のセッションが存在する場合は
manager.remove_session(handle)で削除してから再ログインします。
bsky_logout(handle: str)bsky_refresh_session(acting_handle: Optional[str] = None)
読み取り系
bsky_get_profile(handle: str, acting_handle: Optional[str] = None)bsky_get_author_feed(handle: str, limit: int = 10, cursor: Optional[str] = None, acting_handle: Optional[str] = None)bsky_get_actor_feeds(handle: str, acting_handle: Optional[str] = None)bsky_get_timeline(limit: int = 20, cursor: Optional[str] = None, acting_handle: Optional[str] = None)(要認証)bsky_get_timeline_page(limit: int = 50, cursor: Optional[str] = None, summary: bool = True, text_max_len: int = 120, acting_handle: Optional[str] = None)(要認証)bsky_get_post_thread(uri: str, depth: int = 6, acting_handle: Optional[str] = None)bsky_get_follows(handle: str, limit: int = 50, cursor: Optional[str] = None, acting_handle: Optional[str] = None)bsky_get_followers(handle: str, limit: int = 50, cursor: Optional[str] = None, acting_handle: Optional[str] = None)bsky_get_notifications(limit: int = 20, cursor: Optional[str] = None, acting_handle: Optional[str] = None)(要認証)bsky_resolve_handle(handle: str, acting_handle: Optional[str] = None)bsky_search_posts(query: str, limit: int = 10, cursor: Optional[str] = None, acting_handle: Optional[str] = None)bsky_get_likes(uri: str, acting_handle: Optional[str] = None)bsky_get_lists(handle: str, limit: int = 50, cursor: Optional[str] = None, acting_handle: Optional[str] = None)bsky_get_list(list_uri: str, limit: int = 50, cursor: Optional[str] = None, acting_handle: Optional[str] = None)bsky_search_users(term: str, limit: int = 10, cursor: Optional[str] = None, acting_handle: Optional[str] = None)
書き込み系(要認証)
bsky_post(text: str, acting_handle: Optional[str] = None)bsky_reply(text: str, parent_uri: str, parent_cid: str, root_uri: str, root_cid: str, acting_handle: Optional[str] = None)bsky_like(uri: str, cid: str, acting_handle: Optional[str] = None)bsky_repost(uri: str, cid: str, acting_handle: Optional[str] = None)bsky_delete_post(post_uri: str, acting_handle: Optional[str] = None)bsky_follow(subject_did: str, acting_handle: Optional[str] = None)
Tools (5)
bsky_loginLogs into Bluesky using handle and password.bsky_postCreates a new post on Bluesky.bsky_get_timelineRetrieves the authenticated user's timeline.bsky_search_postsSearches for posts on Bluesky.bsky_get_profileRetrieves a user profile by handle.Environment Variables
BSKY_HANDLEDefault Bluesky handle for authenticationBSKY_APP_PASSWORDDefault Bluesky app password for authenticationConfiguration
{"mcpServers": {"mcpbluesky": {"command": "mcpbluesky", "args": []}}}