Skip to main content
Glama
brianellin

Bluesky MCP Server

by brianellin

get-profile

Retrieve a Bluesky user's profile by entering their handle, enabling access to key information via the Bluesky MCP Server for direct integration with AI assistants.

Instructions

Get a user's profile from Bluesky

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
handleYesThe handle of the user (e.g., alice.bsky.social)

Implementation Reference

  • The handler function for the 'get-profile' tool. It fetches the user's profile from Bluesky using AtpAgent.getProfile after cleaning the handle input, formats the profile information into a readable text summary, and returns it as an MCP success response. Handles errors appropriately.
    async ({ handle }) => { if (!agent) { return mcpErrorResponse("Not logged in. Please check your environment variables."); } try { const response = await agent.getProfile({ actor: cleanHandle(handle) }); if (!response.success) { return mcpErrorResponse(`Failed to get profile for ${handle}.`); } const profile = response.data; let profileText = `Profile for ${profile.displayName || handle} (@${profile.handle}) DID: ${profile.did} ${profile.description ? `Bio: ${profile.description}` : ''} Followers: ${profile.followersCount || 0} Following: ${profile.followsCount || 0} Posts: ${profile.postsCount || 0} ${profile.labels?.length ? `Labels: ${profile.labels.map((l: any) => l.val).join(', ')}` : ''}`; return mcpSuccessResponse(profileText); } catch (error) { return mcpErrorResponse(`Error fetching profile: ${error instanceof Error ? error.message : String(error)}`); } } );
  • src/index.ts:268-301 (registration)
    The server.tool call that registers the 'get-profile' tool on the MCP server, including the tool name, description, input schema, and references the handler function.
    server.tool( "get-profile", "Get a user's profile from Bluesky", { handle: z.string().describe("The handle of the user (e.g., alice.bsky.social)"), }, async ({ handle }) => { if (!agent) { return mcpErrorResponse("Not logged in. Please check your environment variables."); } try { const response = await agent.getProfile({ actor: cleanHandle(handle) }); if (!response.success) { return mcpErrorResponse(`Failed to get profile for ${handle}.`); } const profile = response.data; let profileText = `Profile for ${profile.displayName || handle} (@${profile.handle}) DID: ${profile.did} ${profile.description ? `Bio: ${profile.description}` : ''} Followers: ${profile.followersCount || 0} Following: ${profile.followsCount || 0} Posts: ${profile.postsCount || 0} ${profile.labels?.length ? `Labels: ${profile.labels.map((l: any) => l.val).join(', ')}` : ''}`; return mcpSuccessResponse(profileText); } catch (error) { return mcpErrorResponse(`Error fetching profile: ${error instanceof Error ? error.message : String(error)}`); } } );
  • Zod input schema for the 'get-profile' tool, defining a required 'handle' parameter as a string with description.
    { handle: z.string().describe("The handle of the user (e.g., alice.bsky.social)"),
  • The cleanHandle utility function used in the get-profile handler to normalize the input handle by removing leading '@' if present and preserving DIDs.
    export function cleanHandle(input: string): string { if (!input) return ''; // If it's a DID, return it as is if (input.startsWith('did:')) { return input; } // If it has a leading @, remove it if (input.startsWith('@')) { return input.substring(1); } // Otherwise return as is return input;

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/brianellin/bsky-mcp-server'

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