examples/atproto_mcp/README.md
This example demonstrates a FastMCP server that provides tools and resources for interacting with the AT Protocol (Bluesky).
.env file in the root directory with your Bluesky credentials:[email protected]
ATPROTO_PASSWORD=your-app-password
ATPROTO_PDS_URL=https://bsky.social # optional, defaults to bsky.social
# Install dependencies
uv pip install -e .
# Run the server
uv run atproto-mcp
The post tool is a single, flexible interface for all posting needs:
async def post(
text: str, # Required: Post content
images: list[str] = None, # Optional: Image URLs (max 4)
image_alts: list[str] = None, # Optional: Alt text for images
links: list[RichTextLink] = None, # Optional: Embedded links
mentions: list[RichTextMention] = None, # Optional: User mentions
reply_to: str = None, # Optional: Reply to post URI
reply_root: str = None, # Optional: Thread root URI
quote: str = None, # Optional: Quote post URI
)
from fastmcp import Client
from atproto_mcp.server import atproto_mcp
async def demo():
async with Client(atproto_mcp) as client:
# Simple post
await client.call_tool("post", {
"text": "Hello from FastMCP!"
})
# Post with image
await client.call_tool("post", {
"text": "Beautiful sunset! ๐
",
"images": ["https://example.com/sunset.jpg"],
"image_alts": ["Sunset over the ocean"]
})
# Reply to a post
await client.call_tool("post", {
"text": "Great point!",
"reply_to": "at://did:plc:xxx/app.bsky.feed.post/yyy"
})
# Quote post
await client.call_tool("post", {
"text": "This is important:",
"quote": "at://did:plc:xxx/app.bsky.feed.post/yyy"
})
# Rich text with links and mentions
await client.call_tool("post", {
"text": "Check out FastMCP by @alternatebuild.dev",
"links": [{"text": "FastMCP", "url": "https://github.com/PrefectHQ/fastmcp"}],
"mentions": [{"handle": "alternatebuild.dev", "display_text": "@alternatebuild.dev"}]
})
# Advanced: Quote with image
await client.call_tool("post", {
"text": "Adding visual context:",
"quote": "at://did:plc:xxx/app.bsky.feed.post/yyy",
"images": ["https://example.com/chart.png"]
})
# Advanced: Reply with rich text
await client.call_tool("post", {
"text": "I agree! See this article for more info",
"reply_to": "at://did:plc:xxx/app.bsky.feed.post/yyy",
"links": [{"text": "this article", "url": "https://example.com/article"}]
})
# Create a thread
await client.call_tool("create_thread", {
"posts": [
{"text": "Starting a thread about Python ๐งต"},
{"text": "Python is great for rapid prototyping"},
{"text": "And the ecosystem is amazing!", "images": ["https://example.com/python.jpg"]}
]
})
The unified API enables natural AI assistant interactions:
reply_to with rich textquote with the article linkimages with descriptive textcreate_thread for automatic linkingThe server is organized as:
server.py - Public API with resources and tools_atproto/ - Private implementation module
_client.py - ATProto client management_posts.py - Unified posting logic_profile.py - Profile operations_read.py - Timeline, search, notifications_social.py - Follow, like, reposttypes.py - TypedDict definitionssettings.py - Configuration management# Run demo (read-only)
uv run python demo.py
# Run demo with posting enabled
uv run python demo.py --post
Store your Bluesky credentials securely in environment variables. Never commit credentials to version control.