io.github.cyanheads/bluesky-mcp-server
REMOTE · BLUESKY.CASEYJHAND.COM · 2 COMPONENTS
Search Bluesky posts and feeds; read profiles, threads, and trends. STDIO or Streamable HTTP.
Available components
Last scanned (22 hours ago)
Scores higher than 97% of remote servers
Reachable. Last reached 5 Nov 2026.
Category News and Social
How this component scores in each security and reliability category. Every signal is checked automatically against the live server, and we only credit what we can confirm. How we score → Why this is hard to score →
Endpoint Security83
- The endpoint's TLS certificate is valid, in date, and uses a strong key. View diagnostics → Pass
- No authorisation is required to call this server. Nothing on it is marked destructive, but we can't show that an anonymous caller can only read: full credit needs the server to list at least one tool and every tool to be verifiably read-only. We use a best-effort check of tool names and descriptions to tell read-only tools from tools that change things, so some genuinely read-only tools may not get full credit. Names that start with a read verb (get, list, read, search and similar) and accurate readOnlyHint annotations help. Meet that to earn full credit, or require authorisation. See how to fix → View diagnostics → Partial
- HTTPS is enforced; there's no plaintext access path. View diagnostics → Pass
- The HSTS (Strict-Transport-Security) header is present. View diagnostics → Pass
- DNSSEC is configured correctly; the domain's records validate against the full chain to the root. View diagnostics → Pass
Transport & Reachability100
- Verified streamable-http transport via a live MCP handshake. View diagnostics → Pass
Schema Quality & AI Usability75
- 100% of prompts and resources have a non-trivial description (not blank, and not just the item's name).Pass
- AI-judged instruction clarity (excellent).Pass
- Context-footprint check failed: tool/resource definitions use about 5132 tokens (~427/item across 12 items; 10 tools + 2 resources), over budget; trim descriptions and params. See how to fix → Fail
- Usage-examples check failed: none of the tools include examples. See how to fix → Fail
Stability & Change Management100
- No destabilizing schema changes in the last 30 days.Pass
Tool Coverage100
- 100% of tools have a non-trivial description (not blank, and not just the tool's name).Pass
- 100% of tool parameters carry a description.Pass
- Structured output schemas are declared (100% of tools); any adoption earns full credit.Pass
Tool Safety100
- No prompt-injection markers were found in the server instructions, tool names or descriptions we captured.Pass
- We read all 10 captured tool definition(s), and no name or description among them implies an irreversible operation.Pass
- An AI judge read all 12 captured unit(s) of tool text and found none that tries to manipulate the model reading it.Pass
Capabilities100
- Implements a current MCP spec version (2026-07-28).Pass
Checks we ran (13)
- TLS certificate
- Authorization
- HTTPS
- HSTS header
- DNSSEC
- Transport
- Schema quality
- Stability
- Tool coverage
- Injection markers
- Destructive annotations
- Judged manipulation
- MCP protocol
Does not apply to this hosted endpoint (2)
- Supply Chain SecurityScored on package channels only. This is a hosted endpoint, so there is nothing to install or inspect.
- Provenance & TransparencyScored on package channels only. This is a hosted endpoint, so there is nothing to install or inspect.
The score does not measure everything. What the score does not measure →
Every change we have recorded for this component, newest first. Security-relevant changes are always shown. ▲ marks a change for the better, ▼ a change for the worse; unmarked changes are neutral.
- 3 Nov 26 0
- The server rewrote its instructions, which are the text every model session reads security
- Tool “bsky_get_follows” rewrote its description, which is the text the model reads security
- Tool “bsky_get_profile” rewrote its description, which is the text the model reads security
- Tool “bsky_search_actors” rewrote its description, which is the text the model reads security
- New resource “bluesky-guide” functional
- Server version: 0.6.0 → 0.7.0 functional
- New tool “bsky_get_post_interactions” functional
- 25 Oct 26 +2
- Stability: fail → pass ▲ security
- 23 Oct 26 0
- The server rewrote its instructions, which are the text every model session reads security
- Tool “bsky_get_feed” rewrote its description, which is the text the model reads security
- Tool “bsky_get_post_quotes” rewrote its description, which is the text the model reads security
- Tool “bsky_get_profile” rewrote its description, which is the text the model reads security
- Server version: 0.5.2 → 0.6.0 functional
- New tool “bsky_search_feeds” functional
- “bsky_get_post_quotes” added an optional parameter “sort” cosmetic
- “bsky_get_author_feed” reworded the description of “limit” cosmetic
- “bsky_get_feed” reworded the description of “limit” cosmetic
- “bsky_get_follows” reworded the description of “limit” cosmetic
- “bsky_get_post_quotes” reworded the description of “cursor” cosmetic
- “bsky_get_post_quotes” reworded the description of “limit” cosmetic
- “bsky_get_post_thread” reworded the description of “depth” cosmetic
- “bsky_get_post_thread” reworded the description of “parent_height” cosmetic
- “bsky_get_trending” reworded the description of “limit” cosmetic
- “bsky_search_actors” reworded the description of “limit” cosmetic
- 9 Oct 26 0
- Server version: 0.5.1 → 0.5.2 functional
- 28 Sept 26 0
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
- 25 Sept 26 0
- Stability: pass → fail ▼ security
- Tool “bsky_search_posts” was removed ▼ security
- The server rewrote its instructions, which are the text every model session reads security
- Tool “bsky_get_profile” rewrote its description, which is the text the model reads security
- Tool “bsky_get_author_feed” rewrote its description, which is the text the model reads security
- Tool “bsky_search_actors” rewrote its description, which is the text the model reads security
- Tool “bsky_get_post_thread” rewrote its description, which is the text the model reads security
- Tool “bsky_get_follows” rewrote its description, which is the text the model reads security
- Tool “bsky_get_trending” rewrote its description, which is the text the model reads security
- Schema quality: 363 → 475 ▼ functional
- Schema quality: 363 → 425 ▼ functional
- We updated how we score, so this day's move reflects our rubric, not a change to the server See what changed → functional
- Server version: 0.5.0 → 0.5.1 functional
- Server version: 0.4.0 → 0.5.0 functional
- Server version: 0.3.2 → 0.4.0 functional
- New tool “bsky_get_post_quotes” functional
- New tool “bsky_get_feed” functional
- “bsky_get_follows” added an optional parameter “sort” cosmetic
- “bsky_get_author_feed” added an optional parameter “include_pins” cosmetic
- “bsky_get_post_quotes” reworded the description of “limit” cosmetic
- “bsky_get_author_feed” reworded the description of “limit” cosmetic
- “bsky_get_feed” reworded the description of “limit” cosmetic
- “bsky_get_follows” reworded the description of “actor” cosmetic
- “bsky_get_feed” reworded the description of “feed” cosmetic
- “bsky_get_author_feed” reworded the description of “filter” cosmetic
- “bsky_get_author_feed” reworded the description of “cursor” cosmetic
- “bsky_get_author_feed” reworded the description of “actor” cosmetic
- “bsky_get_profile” reworded the description of “actor” cosmetic
- “bsky_get_post_thread” reworded the description of “uri” cosmetic
- “bsky_get_trending” reworded the description of “limit” cosmetic
- “bsky_search_actors” reworded the description of “cursor” cosmetic
- 20 Sept 26 0
- Server version: 0.3.1 → 0.3.2 functional
- 9 Sept 26 0
- Stability: 0.97 → pass security
Diagnostic detail from the automated scan of this channel: what the scanner observed at each step, so you can see exactly where a check passed or failed. It is informational only and never changes the trust score.
Captured 5 Nov 2026 · Probed https://bluesky.caseyjhand.com/mcp
TLS valid
Negotiated TLS 1.3 with TLS_AES_128_GCM_SHA256 .
| Subject | Issuer | Valid from | Valid until | Key | Signature | Serial |
|---|---|---|---|---|---|---|
| CN=caseyjhand.com | CN=WE1,O=Google Trust Services,C=US | 2 Nov 2026 | 31 Jan 2027 | ECDSA 256 | ECDSA-SHA256 | 995a30681ab772540e934241ca1d576c |
| SANs: caseyjhand.com, *.caseyjhand.com | ||||||
| CN=WE1,O=Google Trust Services,C=US (CA) | CN=GTS Root R4,O=Google Trust Services LLC,C=US | 13 Dec 2023 | 20 Feb 2029 | ECDSA 256 | ECDSA-SHA384 | 7ff31977972c224a76155d13b6d685e3 |
| CN=GTS Root R4,O=Google Trust Services LLC,C=US (CA) | CN=GlobalSign Root CA,OU=Root CA,O=GlobalSign nv-sa,C=BE | 15 Nov 2023 | 28 Jan 2028 | ECDSA 384 | SHA256-RSA | 7fe530bf331343bedd821610493d8a1b |
Background: What to check on a remote MCP endpoint →
DNSSEC secure
Validation of bluesky.caseyjhand.com. — Secure
| Zone | DS | Keys | Algorithms | Outcome |
|---|---|---|---|---|
| . | Trust anchor | 20326, 38696 | 8, 8 | Verified |
| com. | DS published | 19718 | 13 | Verified |
| caseyjhand.com. | DS published | 2371 | 13 | Verified |
| bluesky.caseyjhand.com. | Verified address RRset verified with the apex keys |
Authentication No authorisation required
The endpoint answered without asking for a token. Anyone who knows the URL can reach it.
| Result | No authorisation required |
|---|---|
| HTTP status | 200 |
| Header | Value |
|---|---|
| strict-transport-security | max-age=63072000; includeSubDomains; preload |
| x-content-type-options | nosniff |
Background: How OAuth 2.1 works in the 2026 MCP spec →
Transports 2 probes
| Transport | URL | Outcome | Status | Location |
|---|---|---|---|---|
| streamable-http | https://bluesky.caseyjhand.com/mcp | Verified | 200 | |
| http (plaintext) | http://bluesky.caseyjhand.com/mcp | HTTPS enforced | 301 | https://bluesky.caseyjhand.com/mcp |
The tools this component advertises to a client, with an estimated token cost for each. Expand a tool to see its parameters and schema. The per-tool counts are indicative and are not scored directly; the schema's total context footprint is one signal in Schema Quality & AI Usability. A tool's description is untrusted text the model reads on every call, which is what makes this list a security surface and not just an inventory: how tool poisoning works →
bsky_get_author_feed Get Bluesky Author Feed ~615
Get a Bluesky user's recent feed ordered newest-first. Filter by post type: "posts_with_replies" (everything), "posts_no_replies" (excludes replies), "posts_and_author_threads" (posts the author started), "posts_with_media" (the actor's own posts with images or video — no link cards), or "posts_with_video" (the actor's own video posts). The first three include reposts, so items authored by other accounts appear alongside the actor's own writing — a "repostedBy" field marks those, and the "author" field always names who actually wrote the post; the two media filters return no reposts. Set include_pins to also get the post pinned to the profile, marked "pinned", first on the first page — in addition to "limit", and whether or not it matches the filter. Returns posts with full text, engagement counts, embeds, and AT-URIs for drilling into threads via bsky_get_post_thread. Because "limit" counts reposts too, a page from an account that reposts heavily holds far fewer of that account's own posts than the limit suggests; the enrichment fields report the split, so read "originalPosts" rather than the limit when you want the actor's own writing. Supports cursor pagination.
| Name | Type | Req | Description |
|---|---|---|---|
| actor | string | yes | Handle (e.g. "alice.bsky.social") or DID of the author whose feed to fetch. A leading "@" and the account's bsky.app page ("https://bsky.app/profile/alice.bsky.social") are accepted and read as the h… |
| cursor | string | – | Opaque pagination cursor from a previous response for the same actor, passed back unchanged. Omit for the first page. |
| filter | string | – | Filter for post types: "posts_no_replies" excludes replies, "posts_with_replies" for everything, "posts_and_author_threads" for threads the author started — all three include reposts, so check "repos… |
| include_pins | boolean | – | Also return the post pinned to the actor's profile, marked "pinned: true", first on the first page. It arrives in addition to "limit", whether or not it matches "filter", and is not repeated on later… |
| limit | integer | – | Maximum number of posts to return. Default 25; values above 100 are clamped with a notice unless read-limit clamping is disabled. A page that would pass the 48,000-byte response budget comes back wit… |
| Name | Type | Req | Description |
|---|---|---|---|
| budgetCapped | boolean | – | True when a page of the requested limit would have passed this server's 48,000-byte response budget, so Bluesky was asked again for fewer posts and that page was returned whole. The cursor comes from… |
| cap | number | – | The limit applied to this page. |
| cursor | string | – | Opaque cursor for the next page. Absent on the last page. |
| error | object | – | Present when the call failed. Absent on success. |
| notice | string | – | Guidance when the result set is empty or constrained. |
| originalPosts | number | – | How many items on this page the requested actor wrote, a pinned post included. Present whenever the page carries at least one repost — the number a caller asking for the actor's own writing is after,… |
| posts | array | – | Feed items, newest-first — the actor's own posts and the posts they reposted. Items carrying "repostedBy" were written by the account named in "author", not by the requested actor. |
| reposts | number | – | How many items on this page are posts the requested actor reposted rather than wrote. Present only when there is at least one; these items carry "repostedBy". |
| shown | number | – | Number of posts returned on this page. |
| totalReturned | number | – | Number of posts in this response page. |
| truncated | boolean | – | True when more posts exist beyond this page (a cursor was returned). |
No examples provided.
bsky_get_feed Get Bluesky Feed ~490
Read the posts a Bluesky feed generator serves, in the order the feed ranks them. Accepts the feed's AT-URI (at://<handle-or-did>/app.bsky.feed.generator/<rkey>) or its bsky.app page (https://bsky.app/profile/<handle-or-did>/feed/<rkey>). Feeds come from the "feedUri" of each bsky_get_trending topic — the way to read what a trend is about — from bsky_search_feeds catalog results, from a quoted feed in a post (an embed with recordKind "generator"), or from a shared link; Discover is at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot. Returns posts with full text, engagement counts, embeds, and AT-URIs for drilling into threads via bsky_get_post_thread. A post the feed pinned to its top carries "pinned: true"; a repost carries "repostedBy". Personalized feeds, which Bluesky serves only to a signed-in account, cannot be read here. Supports cursor pagination.
| Name | Type | Req | Description |
|---|---|---|---|
| cursor | string | – | Opaque pagination cursor from a previous response of the same feed. Omit for the first page. |
| feed | string | yes | The feed to read — its AT-URI, e.g. "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot", or its bsky.app URL, e.g. "https://bsky.app/profile/bsky.app/feed/whats-hot"; a trailing… |
| limit | integer | – | Maximum number of posts to return. Default 25; values above 100 are clamped with a notice unless read-limit clamping is disabled. A feed may return fewer than the limit on a page that still has more… |
| Name | Type | Req | Description |
|---|---|---|---|
| budgetCapped | boolean | – | True when a page of the requested limit would have passed this server's 48,000-byte response budget, so the feed was asked again for fewer posts and that page was returned whole. The cursor comes fro… |
| cap | number | – | The limit applied to this page. |
| cursor | string | – | Opaque cursor for the next page. Absent when the feed has nothing further. |
| error | object | – | Present when the call failed. Absent on success. |
| notice | string | – | Guidance when the feed returned nothing, or was cut. |
| posts | array | – | Posts the feed served, in the order it ranked them. |
| shown | number | – | Number of posts returned on this page. |
| totalReturned | number | – | Number of posts in this response page. |
| truncated | boolean | – | True when the feed has more posts after this page (a cursor was returned). |
No examples provided.
bsky_get_follows Get Bluesky Social Graph ~382
Fetch the social graph edges for a Bluesky account — who follows them, or who they follow. Returns paginated actor profiles (handle, DID, displayName, bio, account creation timestamp, moderation labels with provenance, pronouns when set, and Bluesky verification status) plus a summary of the subject account. Follower, following, and post counts and the website are not on this view, for the listed accounts or the subject — bsky_get_profile returns them for one account. Accounts with large social graphs return only the first page; use cursor pagination to walk through the full list, or sort "top" to put the accounts Bluesky ranks most prominent first.
| Name | Type | Req | Description |
|---|---|---|---|
| actor | string | yes | Handle (e.g. "alice.bsky.social") or DID of the account to query. A leading "@" and the account's bsky.app page ("https://bsky.app/profile/alice.bsky.social") are accepted and read as the handle or D… |
| cursor | string | – | Opaque pagination cursor from a previous response. Omit for the first page. |
| direction | string | yes | "followers" returns accounts that follow this actor. "following" returns accounts this actor follows. |
| limit | integer | – | Maximum number of actors to return per page. Default 25; values above 100 are clamped with a notice unless read-limit clamping is disabled. |
| sort | string | – | Order of the list. "latest" (Bluesky's default, and what omitting this gives) puts the most recent follows first; "top" is Bluesky's own ranking, which surfaces prominent accounts but is not a follow… |
| Name | Type | Req | Description |
|---|---|---|---|
| actors | array | – | Actors in the requested direction of the social graph. |
| cap | number | – | The limit applied to this page. |
| cursor | string | – | Opaque cursor for the next page. Absent on the last page. |
| error | object | – | Present when the call failed. Absent on success. |
| notice | string | – | Guidance when the result set is empty or constrained. |
| shown | number | – | Number of actors returned on this page. |
| subject | object | – | Profile summary of the queried actor. |
| totalReturned | number | – | Number of actors in this response page. |
| truncated | boolean | – | True when Bluesky returned a cursor, whatever this page held. A cursor is not proof more accounts exist: the next page can come back empty when the remaining accounts are unavailable. |
No examples provided.
bsky_get_post_interactions Get Bluesky Post Interactions ~284
List the accounts behind a post’s likes or reposts without credentials, in provider order. Accepts a post AT-URI or bsky.app post URL; a handle authority costs one extra resolution request. Returns actor summaries with account creation and label provenance when supplied, and a separate likedAt timestamp for likes. Account counts and website are available through bsky_get_profile. Post likeCount and repostCount are upper bounds on retrievable interactions: cursor exhaustion does not prove every counted interaction was returned. Follow returned cursors with the same post and kind; no pages are walked automatically. Repost cursors retain Bluesky’s behavior, which can ignore malformed cursors and repeat a page.
| Name | Type | Req | Description |
|---|---|---|---|
| cursor | string | – | Opaque cursor from the previous response for the same post and kind. Pass unchanged; omit for the first page. |
| kind | string | yes | Interaction to list: likes includes likedAt; reposts has no interaction timestamp. |
| limit | integer | – | Maximum accounts per page, default 25. Values above 100 are clamped with a notice unless read-limit clamping is disabled. |
| uri | string | yes | Post AT-URI or https://bsky.app/profile/<handle-or-did>/post/<rkey> URL. URL trailing slash, query, and fragment are accepted. Feed, profile, and list references are rejected. |
| Name | Type | Req | Description |
|---|---|---|---|
| actors | array | – | Accounts in provider order. |
| cap | number | – | Applied page limit when a continuation cursor is present. |
| cursor | string | – | Opaque continuation cursor. Absence ends traversal, without proving every counted interaction was returned. |
| error | object | – | Present when the call failed. Absent on success. |
| kind | string | – | Interaction whose accounts are returned. |
| notice | string | – | Pagination, empty-page, clamping, and counter-completeness guidance. |
| shown | number | – | Accounts shown on a page with a continuation cursor. |
| totalReturned | number | – | Accounts returned on this page. |
| truncated | boolean | – | True exactly when Bluesky returned a cursor, regardless of page size. |
| uri | string | – | DID-form AT-URI of the queried post. |
No examples provided.
bsky_get_post_quotes Get Bluesky Post Quotes ~506
Read the quote posts behind a Bluesky post's "quoteCount" — the posts that embed it with commentary of their own. Sort latest (default) is newest first; top is descending like count as ordered by Bluesky. On Bluesky this is where much of the reaction to a post lives; bsky_get_post_thread returns replies only. Accepts the post's AT-URI (at://<handle-or-did>/app.bsky.feed.post/<rkey>) from the "uri" field of any returned post, or its bsky.app URL (https://bsky.app/profile/<handle-or-did>/post/<rkey>); a handle costs one extra lookup. Returns each quote post with full text, author, engagement counts, and AT-URI. Each result's embed names the queried post by AT-URI and CID only — its text is not repeated on every result — and keeps any media the quoting post attached. "quoteCount" is an upper bound on what this returns: Bluesky's counter keeps quotes that have left the index. Supports cursor pagination.
| Name | Type | Req | Description |
|---|---|---|---|
| cursor | string | – | Opaque pagination cursor from a previous response for the same post and sort, passed back unchanged. Omit for the first page. |
| limit | integer | – | Maximum number of quote posts to return; values above 100 are clamped with notice unless strict limits are configured. Default 25. Pages often hold fewer than the limit and still continue — follow th… |
| sort | string | – | Provider ordering: latest is newest first (default); top is descending like count. Reuse cursors with the same post and sort. |
| uri | string | yes | The post whose quotes to read — its AT-URI, e.g. "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/3l6oveex3ii2l", or its bsky.app URL, e.g. "https://bsky.app/profile/bsky.app/post/3l6oveex3i… |
| Name | Type | Req | Description |
|---|---|---|---|
| budgetCapped | boolean | – | True when a page of the requested limit would have passed this server's 48,000-byte response budget, so Bluesky was asked again for fewer quotes and that page was returned whole. The cursor comes fro… |
| cap | number | – | The limit applied to this page. |
| cursor | string | – | Opaque cursor for the next page. Absent when there are no more quotes. |
| error | object | – | Present when the call failed. Absent on success. |
| notice | string | – | Guidance on the page: that more quotes can be fetched with the returned cursor, or why the page is empty — the post has no readable quotes, or the last page was reached. |
| posts | array | – | Posts quoting the queried post, in the applied sort order. |
| shown | number | – | Number of quote posts returned on this page. |
| sort | string | – | Applied provider ordering: latest is newest first; top is descending like count. |
| totalReturned | number | – | Number of quote posts in this response page. |
| truncated | boolean | – | True when Bluesky returned a cursor, whatever this page held — pages often come back short of the limit with more behind them. |
| uri | string | – | AT-URI of the post whose quotes these are, in DID form — the form Bluesky was asked in, whatever form the input took. |
No examples provided.
bsky_get_post_thread Get Bluesky Post Thread ~920
Fetch the conversation for a post by AT-URI — the parent chain upward and the reply tree downward. Enter the thread at any point and traverse the discussion. AT-URIs have the format "at://<handle-or-did>/<collection>/<rkey>" and are returned in the "uri" field of every post the other post-returning tools emit, such as bsky_get_feed and bsky_get_author_feed; a bsky.app post URL (https://bsky.app/profile/<handle-or-did>/post/<rkey>) works as-is. Returns the root post, parent chain, and nested replies with per-post author and engagement data. Replies only: quote posts are not part of a thread — read them with bsky_get_post_quotes. The response is often a fraction of the conversation: Bluesky holds replies back past a per-post limit and offers no way to page the rest, so a thread with thousands of replies commonly returns a few hundred. Any node returning fewer replies than its own replyCount carries "truncated: true" with "unreturnedReplies" and a "truncationReason" — "depth" means the reply tree ended there and fetching that node's AT-URI as its own thread continues below it, "unavailable" means no request closes the gap. Read "unreturnedReplies" as an upper bound on what is missing rather than a count of readable replies: Bluesky's counter also includes replies that have left the index, so a small difference often means nothing is left to fetch. The parent chain is disclosed the same way: when it stops at parent_height instead of at the start of the conversation, the topmost node carries "parentChainTruncated: true" and fetching its AT-URI as its own thread continues upward. The enrichment fields total the difference for the whole thread; check them before describing a conversation as complete or naming its first post. A thread that would pass this server's 48,000-byte response budget is cut between whole posts — the target kept first, then its parents nearest-first, then replies level by level — with "budgetCapped: true" and the cut marked where it happened: "budge…
| Name | Type | Req | Description |
|---|---|---|---|
| depth | integer | – | How many levels of replies to include below the target post. Default 6; values above 10 are clamped with notice unless strict limits are configured — Bluesky itself returns no more than 10 levels how… |
| parent_height | integer | – | How many parent posts to include in the parent chain above the target post. Default 80; values above 100 are clamped with notice unless strict limits are configured. The chain is returned level for l… |
| uri | string | yes | AT-URI of the post to fetch, e.g. "at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.post/abc123". All three segments are required — authority (handle or DID), collection, and record key. Obtain fr… |
| Name | Type | Req | Description |
|---|---|---|---|
| budgetCapped | boolean | – | True when the whole thread would have passed this server's 48,000-byte response budget, so posts Bluesky returned were left out whole — the target first kept, then its parents nearest-first, then rep… |
| budgetOmitted | number | – | How many posts Bluesky returned that the response budget left out, set alongside budgetCapped. totalReturned counts the posts kept. |
| error | object | – | Present when the call failed. Absent on success. |
| notice | string | – | What this response is missing, how much of the gap is explained, and which part of it can still be reached by a further request. |
| parentChainTruncated | boolean | – | True when the parent chain stopped at parent_height instead of reaching the start of the conversation, so the topmost post returned above the target is not the conversation root. Independent of "trun… |
| thread | object | – | The conversation thread rooted at the requested post — a recursive node tree. Each node has: post: { uri, cid, text, facets?, author: { did, handle, displayName?, avatar?, verification? }, replyCount… |
| threadgate | object | – | The thread author's reply restrictions, present only when they set one. Hidden replies are counted in replyCount whether or not they were returned, so a gated thread is one reason the counts run ahea… |
| totalReturned | number | – | Thread nodes in this response — the target post, its parent chain, and every reply returned. |
| truncated | boolean | – | True when at least one post in the reply tree returned fewer replies than Bluesky counts for it — counted over every post Bluesky returned, including any the response budget left out. |
| unreturnedReplies | number | – | How far the reply counts run ahead of the replies returned, summed across the reply tree. An upper bound on what is missing, not a count of readable replies — Bluesky's counters keep including replie… |
No examples provided.
bsky_get_profile Get Bluesky Profile ~311
Fetch a Bluesky actor's public profile by handle (e.g. "bsky.app") or DID (e.g. "did:plc:z72i7hdynmk6r22z27h6tvur"). Returns displayName, handle, DID, bio, pronouns, website, ordered profile links, follower/following/post counts, associated list/feed/starter-pack counts and labeler status when supplied, avatar URL, moderation labels, pinned post AT-URI, and Bluesky verification — whether the account is verified or a trusted verifier, and who verified it. Use this as the first step to resolve a handle to a DID before calling tools that require a DID or AT-URI. Handles and DIDs are interchangeable as input, and "@bsky.app" or the account's bsky.app page (https://bsky.app/profile/bsky.app) work as-is.
| Name | Type | Req | Description |
|---|---|---|---|
| actor | string | yes | Handle (e.g. "bsky.app", "alice.bsky.social") or DID (e.g. "did:plc:z72i7hdynmk6r22z27h6tvur") of the actor to look up. A leading "@" ("@bsky.app") and the account's bsky.app page ("https://bsky.app/… |
| Name | Type | Req | Description |
|---|---|---|---|
| associated | object | – | Selected associated profile metadata. Only supplied fields appear; an empty object is distinct from absent. |
| avatar | string | – | URL of the profile avatar image. |
| createdAt | string | – | ISO 8601 timestamp of account creation. |
| description | string | – | Biography / about text. |
| did | string | – | Decentralized Identifier — the permanent, portable identity key for this account. |
| displayName | string | – | Display name set by the user. May differ from the handle. |
| error | object | – | Present when the call failed. Absent on success. |
| followersCount | number | – | Number of accounts following this actor. |
| followsCount | number | – | Number of accounts this actor follows. |
| handle | string | – | Human-readable username, e.g. "alice.bsky.social". |
| indexedAt | string | – | ISO 8601 timestamp when the AppView last indexed this profile. |
| labels | array | – | Moderation labels applied to this profile. |
| links | array | – | Profile links in upstream display order. Omitted when not supplied; an explicit empty array stays empty. |
| pinnedPostUri | string | – | AT-URI of the pinned post, if any. Pass to bsky_get_post_thread to read it. |
| postsCount | number | – | Total posts authored by this actor. |
| pronouns | string | – | Free-form pronouns the account set, e.g. "they/he". Absent when it set none. Account-authored text bounded only by length, not a fixed vocabulary — read it as written rather than parsing it. |
| verification | object | – | Bluesky verification state — what tells a verified account from a look-alike handle. Absent when Bluesky sent none, which it does for an account neither verified nor a trusted verifier. |
| website | string | – | URL the account set as its website, in the profile field of that name rather than in the bio. Absent when it set none. Independent of the ordered profile links. |
No examples provided.
bsky_get_trending Get Bluesky Trending Topics ~188
Fetch the current real-time trending topics on Bluesky. Returns topics with display name, Bluesky's one-sentence summary of the story, post count, category (politics, sports, pop-culture, etc.), status, start time, and the representative accounts driving each topic — so "who is talking about this" needs no follow-up call. Entry point for "what is Bluesky talking about right now". Each trend is a feed: pass its feedUri to bsky_get_feed to read the trend's posts. Note: uses the app.bsky.unspecced.getTrends endpoint, which is not part of Bluesky's stable lexicon and may change without notice.
| Name | Type | Req | Description |
|---|---|---|---|
| limit | integer | – | Maximum number of trending topics to return. Default 10. Values above Bluesky's maximum of 25 are clamped with notice unless strict limits are configured. |
| Name | Type | Req | Description |
|---|---|---|---|
| cap | number | – | The limit applied to this request. |
| error | object | – | Present when the call failed. Absent on success. |
| notice | string | – | Guidance when the result set is empty or constrained. |
| shown | number | – | Number of trending topics returned. |
| totalReturned | number | – | Number of trending topics returned. |
| trends | array | – | Current trending topics, ordered by prominence. |
| truncated | boolean | – | True when more topics were trending than limit — raising limit shows them. Never set at limit 25, Bluesky's maximum. |
No examples provided.
bsky_search_actors Search Bluesky Actors ~224
Find Bluesky accounts by name or handle fragment. Returns ranked profiles with handle, DID, displayName, bio, account creation timestamp, moderation labels with provenance, pronouns when the account set them, and Bluesky verification status — which tells a verified account from a look-alike handle. Follower, following, and post counts and the website are not on this view — bsky_get_profile returns them for one account. Use before bsky_get_profile or bsky_get_author_feed when you have a name but not a confirmed handle. Supports cursor-based pagination for browsing beyond the first page of results.
| Name | Type | Req | Description |
|---|---|---|---|
| cursor | string | – | Opaque pagination cursor from a previous response to the same query. Omit for the first page. |
| limit | integer | – | Maximum number of actors to return. Default 25; values above 100 are clamped with a notice unless read-limit clamping is disabled. |
| query | string | yes | Name or handle fragment to search for, e.g. "alice" or "nytimes.com". Must not be blank. |
| Name | Type | Req | Description |
|---|---|---|---|
| actors | array | – | Matching actor profiles, ranked by relevance. |
| cap | number | – | The limit applied to this page. |
| cursor | string | – | Opaque cursor for the next page — pass it back with the same query. Absent on the last page. |
| error | object | – | Present when the call failed. Absent on success. |
| notice | string | – | Guidance when the result set is empty or constrained. |
| shown | number | – | Number of actors returned on this page. |
| totalReturned | number | – | Number of actors in this response page. |
| truncated | boolean | – | True when Bluesky returned a cursor for another page, whatever this page held — pages often hold fewer actors than limit and still continue. |
No examples provided.
bsky_search_feeds Search Bluesky Feeds ~187
Search metadata in the provider’s public feed catalog, without credentials. This searches feed names and descriptions, not post text, and does not enumerate every feed. Returns feeds in provider order with generator AT-URIs and creator identities; pass a feedUri to bsky_get_feed to read its posts. Uses app.bsky.unspecced.getPopularFeedGenerators, an unstable upstream API that may change or become unavailable. Continue with the returned opaque cursor and the same query.
| Name | Type | Req | Description |
|---|---|---|---|
| cursor | string | – | Opaque cursor from a previous response to this same query. Omit for the first page. |
| limit | integer | – | Maximum feeds to return. Default 25; values above 100 are clamped with a notice unless read-limit clamping is disabled. |
| query | string | yes | Feed catalog metadata to search, e.g. "science". Must not be blank. |
| Name | Type | Req | Description |
|---|---|---|---|
| cap | number | – | The limit applied to this page. |
| cursor | string | – | Opaque next-page cursor. Its presence signals continuation even when feeds is empty; absent at the end. |
| error | object | – | Present when the call failed. Absent on success. |
| feeds | array | – | Matching feeds in provider order. |
| notice | string | – | Continuation, empty-result, or clamping guidance. |
| shown | number | – | Number of feeds returned on this page. |
| totalReturned | number | – | Number of feeds on this page. |
| truncated | boolean | – | True when a cursor is present, regardless of the number of feeds returned. |
No examples provided.
How do I install the io.github.cyanheads/bluesky-mcp-server server?
io.github.cyanheads/bluesky-mcp-server is a hosted endpoint at https://bluesky.caseyjhand.com/mcp, so there is nothing to install locally. Ready-made configuration for Claude, Cursor, VS Code, Codex and 5 more is on this page, copied from each client's own documentation.
remote · bluesky.caseyjhand.com
claude mcp add --transport http cyanheads-bluesky-mcp-server 'https://bluesky.caseyjhand.com/mcp'
What is the io.github.cyanheads/bluesky-mcp-server server?
io.github.cyanheads/bluesky-mcp-server is listed in the public MCP registry as io.github.cyanheads/bluesky-mcp-server. Search Bluesky posts and feeds; read profiles, threads, and trends. STDIO or Streamable HTTP. This page covers its hosted endpoint (https://bluesky.caseyjhand.com/mcp).
Is the io.github.cyanheads/bluesky-mcp-server server safe to use?
io.github.cyanheads/bluesky-mcp-server scores 89 out of 100 on VerifyMCP. That is a record of what we were able to check automatically, not an endorsement. The category breakdown on this page shows every signal behind the number, including the ones we could not confirm.
What tools does the io.github.cyanheads/bluesky-mcp-server server expose?
io.github.cyanheads/bluesky-mcp-server exposes 10 tools: bsky_get_profile, bsky_search_actors, bsky_get_trending, bsky_search_feeds, bsky_get_feed, and 5 more. Their descriptions and schemas cost roughly 4,107 tokens of context every time the server is loaded.
Does the io.github.cyanheads/bluesky-mcp-server server require authentication?
No. We connected to io.github.cyanheads/bluesky-mcp-server without credentials and it answered, so anything it exposes is reachable by anyone who knows the address.
Is the io.github.cyanheads/bluesky-mcp-server server still maintained?
io.github.cyanheads/bluesky-mcp-server is still listed as active in the MCP registry. We last reached this channel on 5 November 2026. Those dates come from our own scans of the registry and the channel itself, not from anything the publisher announced.
What did VerifyMCP test on the io.github.cyanheads/bluesky-mcp-server server?
VerifyMCP ran 13 checks on io.github.cyanheads/bluesky-mcp-server, covering TLS certificate, Authorization, HTTPS, HSTS header and 9 more. Supply Chain Security and Provenance & Transparency do not apply to a hosted endpoint, so they were not tested. The score does not measure everything, and the scoring documentation lists what it leaves out.