Skip to main content
Glama

bluesky_thread

Fetch the full conversation around any Bluesky post: see parent posts above and reply tree below. Understand the context before replying. Free, no credentials needed for public threads.

Instructions

Fetch the full conversation around a Bluesky post: parent posts above, reply tree below. Use this before bluesky_reply to understand the conversation. FREE. No credentials required for public threads. Returns: { thread: { post, parent?, replies?: thread[] } }. Common errors: post URI not found (VALIDATION_ERROR), AppView 5xx (PLATFORM_ERROR).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
uriYesAT-URI of the post to fetch context for (e.g. at://did:plc:.../app.bsky.feed.post/xyz).
depthNoHow many reply levels below to include (default 6).
parent_heightNoHow many parent levels above to include (default 80).

Implementation Reference

  • src/index.ts:278-282 (registration)
    Registration of the 'bluesky_thread' tool on the MCP server, with description and invocation of handleBlueskyThread.
    server.tool("bluesky_thread", "Fetch the full conversation around a Bluesky post: parent posts above, reply tree below. Use this before bluesky_reply to understand the conversation. FREE. No credentials required for public threads. Returns: { thread: { post, parent?, replies?: thread[] } }. Common errors: post URI not found (VALIDATION_ERROR), AppView 5xx (PLATFORM_ERROR).", blueskyThreadSchema.shape, async (input) => {
      const parsed = blueskyThreadSchema.parse(input);
      const result = await handleBlueskyThread(parsed);
      return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
    });
  • Zod schema for bluesky_thread input: uri (AT-URI string), optional depth (0-1000, default 6), optional parent_height (0-1000, default 80).
    /** Zod schema for the `bluesky_thread` tool input. */
    export const blueskyThreadSchema = z.object({
      uri: z.string().describe("AT-URI of the post to fetch context for (e.g. at://did:plc:.../app.bsky.feed.post/xyz)."),
      depth: z.number().int().min(0).max(1000).optional().describe("How many reply levels below to include (default 6)."),
      parent_height: z.number().int().min(0).max(1000).optional().describe("How many parent levels above to include (default 80)."),
    });
  • Handler function handleBlueskyThread that validates input via schema and delegates to getBlueskyThread in the broadcast layer.
    /**
     * Fetch the full conversation around a post so a reply can be drafted in
     * context. Unauthenticated.
     */
    export async function handleBlueskyThread(
      input: z.infer<typeof blueskyThreadSchema>
    ) {
      return getBlueskyThread(input.uri, {
        depth: input.depth,
        parentHeight: input.parent_height,
      });
    }
  • Core implementation getBlueskyThread: makes an unauthenticated GET request to the Bluesky AppView's getPostThread XRPC endpoint, normalizes the response.
    export async function getBlueskyThread(
      uri: string,
      options?: { depth?: number; parentHeight?: number }
    ): Promise<ToolResult<BlueskyThread>> {
      if (!uri.startsWith("at://")) {
        return makeError("VALIDATION_ERROR", `Expected an at-uri, got: ${uri}`);
      }
      const depth = options?.depth ?? 6;
      const parentHeight = options?.parentHeight ?? 80;
      const params = new URLSearchParams();
      params.set("uri", uri);
      params.set("depth", String(depth));
      params.set("parentHeight", String(parentHeight));
    
      const result = await httpRequest(
        `${PUBLIC_APPVIEW}/xrpc/app.bsky.feed.getPostThread?${params.toString()}`,
        { method: "GET" }
      );
    
      if (!result.success) {
        return makeError(result.error.code, result.error.message, {
          platform: "bluesky",
          retryable: result.error.retryable,
        });
      }
    
      const data = result.data as { thread?: unknown };
      const normalized = normalizeThreadNode(data.thread);
      if (!normalized) {
        return makeError("NOT_FOUND", `Thread not found or unviewable: ${uri}`, {
          platform: "bluesky",
        });
      }
      return makeSuccess(normalized);
    }
  • Type definitions: BlueskyThreadPost (uri, cid, author, text, indexedAt, url) and BlueskyThread (post, parent?, replies[]) used by the tool.
    export interface BlueskyThreadPost {
      uri: string;
      cid: string;
      author: { did: string; handle: string; displayName?: string };
      text: string;
      indexedAt: string;
      url: string;
    }
    
    export interface BlueskyThread {
      post: BlueskyThreadPost;
      parent?: BlueskyThread;
      replies: BlueskyThread[];
    }
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description fully carries the behavioral disclosure burden. It mentions the tool is free, requires no credentials for public threads, describes the return format, and lists common errors (VALIDATION_ERROR, PLATFORM_ERROR). It does not mention rate limits or side effects, but for a read-only tool this is sufficient.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three compact sentences front-load purpose, usage guideline, output/errors. Every sentence adds unique value with no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite no output schema, the description specifies the return shape ({ thread: { post, parent?, replies?: thread[] } }) and mentions common errors. It covers all essential context for a read-only conversation fetch tool given the sibling list and annotations absence.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Input schema has 100% parameter description coverage (uri, depth, parent_height). The description adds value by stating defaults (depth default 6, parent_height default 80) beyond the schema's min/max constraints, making parameter usage clearer.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly identifies the tool's function with specific verb 'Fetch' and resource 'full conversation around a Bluesky post', and distinguishes it from siblings like bluesky_reply by stating it should be used before replying.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states 'Use this before bluesky_reply to understand the conversation', giving clear context for when to use. Also notes 'FREE' and 'No credentials required' for public threads. Missing explicit when-not-to-use statements, but the direction is strong.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/MendleM/pipepost'

If you have feedback or need assistance with the MCP directory API, please join our Discord server