Troubleshooting
Common issues and fixes for the AT Protocol MCP Server.
By default this server speaks the Model Context Protocol over stdio — it is launched by your MCP client (Claude Desktop, an IDE, your own script) and communicates over stdin/stdout, binding no network port: no HTTP endpoint, no localhost:3000, and no /health URL to curl. (With --transport http the server instead serves MCP at /mcp — and only /mcp; there is still no /health route.)
This page is symptom → fix. For error codes and recovery patterns, see Error Handling.
Installation & Build Issues
Node.js Version Error
Symptom: An error about the Node.js version being too old.
Error: The engine "node" is incompatible with this moduleFix: This project requires Node.js 20 or newer.
# Check current version
node --version
# Install Node.js 20+ using nvm
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash
nvm install 20
nvm use 20
# Verify
node --version # Should show v20.x.x or newerPermission Denied (Global Install)
Symptom: EACCES: permission denied when installing globally.
Fix: Configure npm to install global packages without sudo.
mkdir ~/.npm-global
npm config set prefix '~/.npm-global'
echo 'export PATH=~/.npm-global/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
npm install -g atproto-mcpBuild Errors (from source)
Symptom: Errors such as Cannot find module 'typescript' when building from source.
Fix: Reinstall dependencies cleanly. This project uses pnpm.
# Clean and reinstall
rm -rf node_modules
pnpm install
# Rebuild
pnpm build
# If problems persist, clear the package manager cache
pnpm store pruneAuthentication Issues
App passwords are the supported authentication path. Set ATPROTO_IDENTIFIER (your handle or DID) and ATPROTO_PASSWORD (an app password, not your main account password). Without credentials the server still starts, but only public tools work (notably get_user_profile). search_posts requires authentication (the AT Protocol search API changed in 2025 to require auth), so it is not available without credentials.
Authentication Failed
Symptom: An "authentication failed" / AUTHENTICATION_FAILED error at startup.
Fix: Work through this checklist.
# 1. Confirm the variables are actually set in this shell
echo $ATPROTO_IDENTIFIER
echo $ATPROTO_PASSWORD
# 2. Set them cleanly (no surrounding quotes, no trailing spaces/newlines)
export ATPROTO_IDENTIFIER=your-handle.bsky.social
export ATPROTO_PASSWORD=xxxx-xxxx-xxxx-xxxx
# 3. Confirm the service URL (defaults to https://bsky.social)
echo $ATPROTO_SERVICE
# 4. Re-run with debug logging to see the underlying error
atproto-mcp --log-level debugNote: when launching via an MCP client, environment variables must be set in that client's config (for example the env block of claude_desktop_config.json), not just in your interactive shell.
Invalid App Password
Symptom: An "invalid password" error even though the handle is correct.
Fix:
- Make sure you are using an app password, not your main account password.
- Generate a fresh one: Bluesky Settings → App Passwords → Add App Password, then copy it immediately.
- Check the App Passwords list for any password you have since revoked.
- Remove any stray characters (spaces, quotes, newlines) introduced when copying.
Session Expired
Symptom: A session/authentication error appears after the server has been running for a while.
Fix: Restart the server (or have your MCP client restart it). On startup it re-authenticates from ATPROTO_IDENTIFIER / ATPROTO_PASSWORD and establishes a new session.
atproto-mcpMCP Client Connection Issues
Because the transport is stdio, "connection" problems are almost always about how the client launches the process, not about networking.
MCP Client Can't Connect
Symptom: Your LLM client reports that it cannot start or reach the server.
Fix:
# 1. Confirm the binary resolves and runs at all
atproto-mcp --version
# 2. Run it directly with debug logging and watch the startup logs.
# Logs go to stderr, so they will not corrupt the stdio JSON-RPC stream.
atproto-mcp --log-level debug
# 3. Inspect the client config. For Claude Desktop (macOS):
cat ~/Library/Application\ Support/Claude/claude_desktop_config.jsonA minimal Claude Desktop entry looks like:
{
"mcpServers": {
"atproto": {
"command": "atproto-mcp",
"env": {
"ATPROTO_IDENTIFIER": "your-handle.bsky.social",
"ATPROTO_PASSWORD": "xxxx-xxxx-xxxx-xxxx"
}
}
}
}Common causes:
commandis not on the client'sPATH(use an absolute path, or the full path tonodeplus the script).- Credentials are set in your shell but not in the client config's
envblock. - Something is writing to stdout other than JSON-RPC. Keep diagnostics on stderr; debug logging already goes there.
Test the server by hand
You can drive the stdio server manually for a quick sanity check. The MCP protocol requires an initialize handshake before any other request, and every message needs the JSON-RPC envelope (jsonrpc, id). See Error Handling → Testing tools manually for a working snippet.
Cannot Reach the AT Protocol Service
Symptom: Network errors or timeouts talking to Bluesky.
Fix:
# 1. Basic connectivity
ping bsky.social
# 2. Point at a specific service if needed (default is https://bsky.social)
atproto-mcp --service https://bsky.social
# 3. Check proxy settings if you are behind one
echo $HTTP_PROXY
echo $HTTPS_PROXY
# 4. Ensure outbound HTTPS (443) is allowed by your firewallRate Limiting
The server applies a per-tool rate limit of 100 requests per minute (a 60-second sliding window, counted independently for each tool). Exceeding it returns a JSON-RPC internal error whose message says the rate limit was exceeded.
Rate Limit Exceeded
Symptom: Rate limit exceeded for tool "<name>" errors.
Fix:
- Slow down: the window is 60 seconds per tool, so brief pauses clear it.
- Spread work across tools where it makes sense, since the limit is counted per tool.
- In your client, add backoff/retry around tool calls. See Error Handling for an example client-side backoff pattern.
Keep in mind Bluesky itself also enforces platform-side rate limits; persistent 429-style failures may originate upstream rather than from this server.
Tool & Resource Issues
Tool Not Found
Symptom: An "unknown tool" / Invalid params error when calling a tool.
Fix:
- Ask your client to list tools (for example, "What tools are available?"). The server exposes 51 tools.
- Tool names are
snake_case(create_post, notcreatePost). - Some tools require authentication; without credentials they are unavailable. See Authentication Issues.
Invalid Parameters
Symptom: An Invalid params (-32602) error.
Fix: Each tool validates its arguments with a schema, and the error message names the offending field.
- Check the parameter types and required fields for the tool (see the Tools reference).
- For
create_postand replies,textmust be non-empty and within Bluesky's limit of 300 graphemes / 3000 UTF-8 bytes. - Language fields (
langs) expect BCP-47 codes such asen,en-US, orpt-BR.
A Tool or Resource From Older Docs Is Missing
Symptom: A tool or resource mentioned in older documentation is not listed by the server.
Fix: Some placeholders were removed because they could never return real data:
- The placeholder
atproto://conversation-contextresource is no longer registered (it always read as empty).
OAuth login is planned but not yet functional, so it is not exposed as a tool. Real-time streaming is not planned as tools (the leftover firehose client code has been removed). See Experimental & Roadmap for the current status.
Resource Not Available or Read Fails
Symptom: A resource cannot be listed or read, or reading returns a Resource not found (-32002) error.
Fix:
- The static resources (
atproto://timeline,atproto://profile,atproto://notifications) call the real API and require authentication — set your credentials. - The resource templates (
atproto://profile/{actor},atproto://feed/{actor}) work without authentication, but{actor}must be a syntactically valid handle or DID — anything else does not match the template. - Use the exact URI form, e.g.
atproto://timeline. Reading a URI that matches neither a static resource nor a template returns JSON-RPC error-32002(Resource not found). - If reads fail after a long session, the session may have expired; restart the server.
Debugging Tips
Enable Debug Logging
The --log-level flag (or the LOG_LEVEL environment variable) controls verbosity. Logs are written to stderr, so they will not interfere with the stdio JSON-RPC stream on stdout.
# Maximum verbosity
atproto-mcp --log-level debug
# Or via environment variable
LOG_LEVEL=debug atproto-mcpVerify Configuration
# Print the AT Protocol environment variables
env | grep ATPROTO
# Confirm the CLI runs and show available flags
atproto-mcp --help
# Show the version
atproto-mcp --versionThe configuration-validation smoke check (dist/health-check.js) loads the package, builds and validates the config, and checks this process's heap. It is process-local — it binds no port and does not probe a running server.
Getting Help
If you are still stuck:
- Search existing issues: GitHub Issues
- Check discussions: GitHub Discussions
- Review the docs: Full Documentation
- Open an issue and include:
- Server version (
atproto-mcp --version) - Node.js version (
node --version) - Operating system
- Error messages (sanitize credentials!)
- Steps to reproduce and relevant logs
- Server version (
Next Steps
- Error Handling — Error codes and recovery patterns
- Deployment — Run it in production
- Contributing — Report bugs or contribute fixes
Previous: Error Handling ← | Next: Deployment →