atproto-mcp 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -15
- package/dist/cli.d.ts +16 -0
- package/dist/cli.js +33 -12
- package/dist/index.d.ts +93 -2
- package/dist/index.js +408 -52
- package/dist/prompts/index.d.ts +14 -0
- package/dist/prompts/index.js +27 -0
- package/dist/resources/index.d.ts +1 -0
- package/dist/resources/index.js +2 -0
- package/dist/resources/templates.d.ts +82 -0
- package/dist/resources/templates.js +231 -0
- package/dist/tools/implementations/bookmark-tools.d.ts +314 -0
- package/dist/tools/implementations/bookmark-tools.js +411 -0
- package/dist/tools/implementations/create-post-tool.d.ts +115 -1
- package/dist/tools/implementations/create-post-tool.js +202 -1
- package/dist/tools/implementations/create-thread-tool.d.ts +49 -1
- package/dist/tools/implementations/create-thread-tool.js +82 -1
- package/dist/tools/implementations/dm-tools.d.ts +414 -0
- package/dist/tools/implementations/dm-tools.js +493 -0
- package/dist/tools/implementations/index.d.ts +3 -0
- package/dist/tools/implementations/index.js +6 -0
- package/dist/tools/implementations/starter-pack-tools.d.ts +412 -0
- package/dist/tools/implementations/starter-pack-tools.js +395 -0
- package/dist/tools/index.js +12 -1
- package/dist/types/index.d.ts +25 -0
- package/dist/utils/atp-client.js +4 -3
- package/package.json +15 -17
- package/dist/utils/firehose-client.d.ts +0 -139
- package/dist/utils/firehose-client.js +0 -350
package/README.md
CHANGED
|
@@ -42,8 +42,9 @@ write operations, private data, feeds).
|
|
|
42
42
|
> **Zero-config launch**: `npx atproto-mcp` runs the server in unauthenticated
|
|
43
43
|
> public-data mode — no credentials required.
|
|
44
44
|
>
|
|
45
|
-
> **Recent additions**:
|
|
46
|
-
>
|
|
45
|
+
> **Recent additions**: Bluesky direct messages, private bookmarks, starter pack
|
|
46
|
+
> discovery, reply/quote controls on posts, parameterized MCP resource
|
|
47
|
+
> templates, and an optional Streamable HTTP transport (`--transport http`).
|
|
47
48
|
|
|
48
49
|
## Architecture
|
|
49
50
|
|
|
@@ -86,10 +87,11 @@ server to access AT Protocol functionality.
|
|
|
86
87
|
(follow/like/repost up to 25 items at once)
|
|
87
88
|
- **Analytics & Insights**: Analyze engagement patterns, network connections,
|
|
88
89
|
and get content strategy recommendations
|
|
89
|
-
- **Content Discovery**: Find similar users, trending topics, and
|
|
90
|
-
voices in your areas of interest
|
|
91
|
-
- **
|
|
92
|
-
|
|
90
|
+
- **Content Discovery**: Find similar users, trending topics, starter packs, and
|
|
91
|
+
influential voices in your areas of interest
|
|
92
|
+
- **Direct Messages**: List conversations, read message history, and send
|
|
93
|
+
Bluesky DMs (requires a DM-enabled app password)
|
|
94
|
+
- **Private Bookmarks**: Save, list, and remove private bookmarks on posts
|
|
93
95
|
|
|
94
96
|
### Core Features
|
|
95
97
|
|
|
@@ -103,13 +105,16 @@ server to access AT Protocol functionality.
|
|
|
103
105
|
- **MCP Server Compliance**: Built with `@modelcontextprotocol/sdk` following
|
|
104
106
|
MCP specification
|
|
105
107
|
- **Type-Safe**: Written in TypeScript with strict type checking
|
|
106
|
-
- **Comprehensive Tools**:
|
|
108
|
+
- **Comprehensive Tools**: 51 MCP tools for social networking operations
|
|
107
109
|
- **Rate Limiting**: Built-in respect for AT Protocol rate limits
|
|
108
110
|
- **Extensible**: Modular architecture for easy customization
|
|
109
111
|
|
|
110
|
-
> **Planned**: OAuth login
|
|
111
|
-
>
|
|
112
|
-
>
|
|
112
|
+
> **Planned**: OAuth login is on the roadmap but not yet functional —
|
|
113
|
+
> app-password authentication is the supported auth path today. Real-time
|
|
114
|
+
> firehose streaming is **not** planned as MCP tools: a request/response tool
|
|
115
|
+
> cannot honestly expose a continuous stream, and the unused firehose client
|
|
116
|
+
> code has been removed. If streaming ever ships it will be built fresh on
|
|
117
|
+
> [Jetstream](https://docs.bsky.app/blog/jetstream).
|
|
113
118
|
|
|
114
119
|
## Who Is This For?
|
|
115
120
|
|
|
@@ -269,7 +274,7 @@ credentials.
|
|
|
269
274
|
|
|
270
275
|
## Available Tools
|
|
271
276
|
|
|
272
|
-
The server provides **
|
|
277
|
+
The server provides **51 MCP tools** across multiple categories. See the
|
|
273
278
|
[complete API documentation](https://cameronrye.github.io/atproto-mcp/api/) for
|
|
274
279
|
detailed information on each tool.
|
|
275
280
|
|
|
@@ -288,6 +293,8 @@ detailed information on each tool.
|
|
|
288
293
|
enriches the underlying API call when authenticated)
|
|
289
294
|
- `get_post_context` - Get a post with optional thread, author profile,
|
|
290
295
|
engagement metrics, and media (ENHANCED mode)
|
|
296
|
+
- `search_starter_packs` / `get_starter_pack` - Search Bluesky starter packs by
|
|
297
|
+
keyword and fetch a pack's details (ENHANCED mode)
|
|
291
298
|
|
|
292
299
|
**Rich Media**
|
|
293
300
|
|
|
@@ -319,6 +326,18 @@ for most endpoints that were previously public, including `search_posts`.
|
|
|
319
326
|
cheap unread badge count)
|
|
320
327
|
- `mark_notifications_seen` - Mark notifications as seen up to a timestamp
|
|
321
328
|
|
|
329
|
+
**Direct Messages**
|
|
330
|
+
|
|
331
|
+
- `list_conversations` - List your Bluesky DM conversations
|
|
332
|
+
- `get_conversation_messages` - Read a conversation's message history
|
|
333
|
+
- `send_direct_message` - Send a DM (requires an app password created with
|
|
334
|
+
"Allow access to your direct messages" enabled)
|
|
335
|
+
|
|
336
|
+
**Bookmarks**
|
|
337
|
+
|
|
338
|
+
- `add_bookmark` / `remove_bookmark` - Privately bookmark and un-bookmark posts
|
|
339
|
+
- `get_bookmarks` - List your private bookmarks
|
|
340
|
+
|
|
322
341
|
**Content Management**
|
|
323
342
|
|
|
324
343
|
- `upload_image` / `upload_video` - Upload media content
|
|
@@ -523,10 +542,13 @@ This project is licensed under the MIT License.
|
|
|
523
542
|
|
|
524
543
|
## Deployment
|
|
525
544
|
|
|
526
|
-
|
|
527
|
-
Claude Desktop) via `npx atproto-mcp` and communicates over
|
|
528
|
-
|
|
529
|
-
|
|
545
|
+
By default this is a **stdio MCP server**: it is normally launched by an MCP
|
|
546
|
+
client (e.g. Claude Desktop) via `npx atproto-mcp` and communicates over
|
|
547
|
+
stdin/stdout, binding no network port. Alternatively, `--transport http` serves
|
|
548
|
+
the MCP **Streamable HTTP** transport at `http://<host>:<port>/mcp` (default
|
|
549
|
+
binding `127.0.0.1:3000`, loopback only); exposing it beyond loopback (e.g.
|
|
550
|
+
`--host 0.0.0.0`) is the operator's responsibility to secure. stdio remains the
|
|
551
|
+
default and the recommended setup for MCP clients.
|
|
530
552
|
|
|
531
553
|
### Built-in safeguards
|
|
532
554
|
|
package/dist/cli.d.ts
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Command-line interface for the AT Protocol MCP Server
|
|
4
4
|
*/
|
|
5
|
+
import { type IMcpServerConfig } from './types/index.js';
|
|
6
|
+
import { type McpTransportKind } from './index.js';
|
|
7
|
+
/**
|
|
8
|
+
* Result of CLI argument parsing: configuration overrides plus the selected
|
|
9
|
+
* transport. The transport is deliberately NOT part of IMcpServerConfig — it
|
|
10
|
+
* is a process-level startup choice, passed to AtpMcpServer.start().
|
|
11
|
+
*/
|
|
12
|
+
export interface ICliArgs {
|
|
13
|
+
config: Partial<IMcpServerConfig>;
|
|
14
|
+
transport: McpTransportKind;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Parse command line arguments. `argv` defaults to the process arguments and
|
|
18
|
+
* is injectable for tests.
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseCliArgs(argv?: string[]): ICliArgs;
|
|
5
21
|
/**
|
|
6
22
|
* Main CLI function
|
|
7
23
|
*/
|
package/dist/cli.js
CHANGED
|
@@ -66,6 +66,11 @@ function loadEnvFile() {
|
|
|
66
66
|
* CLI argument definitions
|
|
67
67
|
*/
|
|
68
68
|
const CLI_OPTIONS = {
|
|
69
|
+
transport: {
|
|
70
|
+
type: 'string',
|
|
71
|
+
short: 't',
|
|
72
|
+
description: 'Transport: stdio|http (default: stdio)',
|
|
73
|
+
},
|
|
69
74
|
port: {
|
|
70
75
|
type: 'string',
|
|
71
76
|
short: 'p',
|
|
@@ -113,13 +118,18 @@ AT Protocol MCP Server - Comprehensive interface for LLMs to interact with AT Pr
|
|
|
113
118
|
|
|
114
119
|
Usage: atproto-mcp [options]
|
|
115
120
|
|
|
116
|
-
Transport: this server communicates over stdio (for MCP clients
|
|
117
|
-
Desktop).
|
|
118
|
-
|
|
121
|
+
Transport: by default this server communicates over stdio (for MCP clients
|
|
122
|
+
such as Claude Desktop). With --transport http it serves the MCP Streamable
|
|
123
|
+
HTTP transport at http://<host>:<port>/mcp instead. The default binding is the
|
|
124
|
+
loopback interface (127.0.0.1), so only local clients can connect; binding any
|
|
125
|
+
other host (e.g. --host 0.0.0.0) exposes the server to the network, and
|
|
126
|
+
securing that exposure (firewalling, reverse proxy, authentication) is the
|
|
127
|
+
operator's responsibility.
|
|
119
128
|
|
|
120
129
|
Options:
|
|
121
|
-
-
|
|
122
|
-
-
|
|
130
|
+
-t, --transport <mode> Transport: stdio|http (default: stdio)
|
|
131
|
+
-p, --port <number> HTTP port for --transport http (default: 3000; stdio ignores it)
|
|
132
|
+
-H, --host <string> HTTP bind host for --transport http (default: 127.0.0.1, loopback; stdio ignores it)
|
|
123
133
|
-s, --service <url> AT Protocol service URL (default: https://bsky.social)
|
|
124
134
|
-a, --auth <method> Authentication method: app-password|oauth (optional)
|
|
125
135
|
-l, --log-level <level> Log level: debug|info|warn|error (default: info)
|
|
@@ -155,8 +165,8 @@ Examples:
|
|
|
155
165
|
# Start in unauthenticated mode (works immediately!)
|
|
156
166
|
atproto-mcp
|
|
157
167
|
|
|
158
|
-
#
|
|
159
|
-
atproto-mcp --port 8080 --log-level debug
|
|
168
|
+
# Serve the Streamable HTTP transport on loopback port 8080
|
|
169
|
+
atproto-mcp --transport http --port 8080 --log-level debug
|
|
160
170
|
|
|
161
171
|
# Enable authentication with app password
|
|
162
172
|
export ATPROTO_IDENTIFIER="your-handle.bsky.social"
|
|
@@ -185,11 +195,13 @@ function showVersion() {
|
|
|
185
195
|
}
|
|
186
196
|
}
|
|
187
197
|
/**
|
|
188
|
-
* Parse command line arguments
|
|
198
|
+
* Parse command line arguments. `argv` defaults to the process arguments and
|
|
199
|
+
* is injectable for tests.
|
|
189
200
|
*/
|
|
190
|
-
function parseCliArgs() {
|
|
201
|
+
export function parseCliArgs(argv = process.argv.slice(2)) {
|
|
191
202
|
try {
|
|
192
203
|
const { values } = parseArgs({
|
|
204
|
+
args: argv,
|
|
193
205
|
options: CLI_OPTIONS,
|
|
194
206
|
allowPositionals: false,
|
|
195
207
|
});
|
|
@@ -212,6 +224,15 @@ function parseCliArgs() {
|
|
|
212
224
|
throw new ConfigurationError(`Invalid log level: ${values['log-level']}. Must be one of: debug, info, warn, error`);
|
|
213
225
|
}
|
|
214
226
|
}
|
|
227
|
+
// Validate the transport selection. stdio stays the default; http serves
|
|
228
|
+
// the Streamable HTTP transport using the --port/--host binding.
|
|
229
|
+
let transport = 'stdio';
|
|
230
|
+
if (values.transport != null && values.transport !== '') {
|
|
231
|
+
if (values.transport !== 'stdio' && values.transport !== 'http') {
|
|
232
|
+
throw new ConfigurationError(`Invalid transport: ${values.transport}. Must be 'stdio' or 'http'`);
|
|
233
|
+
}
|
|
234
|
+
transport = values.transport;
|
|
235
|
+
}
|
|
215
236
|
// Build configuration from CLI arguments
|
|
216
237
|
const config = {};
|
|
217
238
|
if (values.port != null && values.port !== '') {
|
|
@@ -247,7 +268,7 @@ function parseCliArgs() {
|
|
|
247
268
|
}
|
|
248
269
|
config.atproto = atproto;
|
|
249
270
|
}
|
|
250
|
-
return config;
|
|
271
|
+
return { config, transport };
|
|
251
272
|
}
|
|
252
273
|
catch (error) {
|
|
253
274
|
if (error instanceof ConfigurationError) {
|
|
@@ -267,7 +288,7 @@ async function main() {
|
|
|
267
288
|
// visible to ConfigManager and the rest of the server.
|
|
268
289
|
loadEnvFile();
|
|
269
290
|
// Parse command line arguments
|
|
270
|
-
const cliConfig = parseCliArgs();
|
|
291
|
+
const { config: cliConfig, transport } = parseCliArgs();
|
|
271
292
|
// Create and start server
|
|
272
293
|
const server = new AtpMcpServer(cliConfig);
|
|
273
294
|
// Setup graceful shutdown handlers
|
|
@@ -298,7 +319,7 @@ async function main() {
|
|
|
298
319
|
process.exit(1);
|
|
299
320
|
});
|
|
300
321
|
// Start the server
|
|
301
|
-
await server.start();
|
|
322
|
+
await server.start({ transport });
|
|
302
323
|
// Keep the process running
|
|
303
324
|
logger.info('AT Protocol MCP Server is running. Press Ctrl+C to stop.');
|
|
304
325
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,23 @@ import { AtpClient } from './utils/atp-client.js';
|
|
|
12
12
|
import { ConfigManager } from './utils/config.js';
|
|
13
13
|
import { type IPerformanceMetrics } from './utils/performance.js';
|
|
14
14
|
import { SecurityManager } from './utils/security.js';
|
|
15
|
+
/**
|
|
16
|
+
* Transports the server can speak. stdio is the default (MCP clients such as
|
|
17
|
+
* Claude Desktop spawn the process and own its stdin/stdout); http serves the
|
|
18
|
+
* MCP Streamable HTTP transport on a TCP port at /mcp.
|
|
19
|
+
*/
|
|
20
|
+
export type McpTransportKind = 'stdio' | 'http';
|
|
21
|
+
/**
|
|
22
|
+
* Options for {@link AtpMcpServer.start}. port/host apply to the http
|
|
23
|
+
* transport only and override the configured values (config.port/config.host),
|
|
24
|
+
* which lets tests bind an ephemeral port (0) that the config schema does not
|
|
25
|
+
* allow.
|
|
26
|
+
*/
|
|
27
|
+
export interface IServerStartOptions {
|
|
28
|
+
transport?: McpTransportKind;
|
|
29
|
+
port?: number;
|
|
30
|
+
host?: string;
|
|
31
|
+
}
|
|
15
32
|
/**
|
|
16
33
|
* Main server class for AT Protocol MCP Server
|
|
17
34
|
*/
|
|
@@ -24,9 +41,21 @@ export declare class AtpMcpServer {
|
|
|
24
41
|
private securityManager;
|
|
25
42
|
private metricsInterval?;
|
|
26
43
|
private transport;
|
|
44
|
+
private httpServer;
|
|
45
|
+
private httpSessions;
|
|
46
|
+
private httpAllowedHosts;
|
|
27
47
|
private isRunning;
|
|
28
48
|
private isShuttingDown;
|
|
29
49
|
constructor(configOverrides?: Partial<IMcpServerConfig>);
|
|
50
|
+
/**
|
|
51
|
+
* Construct an MCP Server instance with every handler registered.
|
|
52
|
+
*
|
|
53
|
+
* This is the single construction path for ALL transports: the constructor
|
|
54
|
+
* builds the stdio server through it, and the http transport builds one
|
|
55
|
+
* fresh Server per session through it (each Streamable HTTP session needs
|
|
56
|
+
* its own Server because the SDK Protocol binds 1:1 to a transport).
|
|
57
|
+
*/
|
|
58
|
+
private createMcpServer;
|
|
30
59
|
/**
|
|
31
60
|
* Set up the MCP server with basic handlers
|
|
32
61
|
* Register tools, resources, and prompts with the MCP server
|
|
@@ -50,6 +79,18 @@ export declare class AtpMcpServer {
|
|
|
50
79
|
* Register MCP prompts with the server
|
|
51
80
|
*/
|
|
52
81
|
private registerPrompts;
|
|
82
|
+
/**
|
|
83
|
+
* Register the completion/complete handler (declared via the `completions`
|
|
84
|
+
* capability).
|
|
85
|
+
*
|
|
86
|
+
* - ref/prompt: serves candidate values for enumerable prompt arguments
|
|
87
|
+
* (each prompt declares its own candidates); free-text arguments complete
|
|
88
|
+
* to an empty list, never an error. Unknown prompt names are invalid params.
|
|
89
|
+
* - ref/resource: serves the {actor} variable of the resource templates with
|
|
90
|
+
* the authenticated user's handle when a session exists, else empty.
|
|
91
|
+
* Unknown templates/arguments complete to an empty list.
|
|
92
|
+
*/
|
|
93
|
+
private registerCompletions;
|
|
53
94
|
/**
|
|
54
95
|
* Convert Zod schema to JSON Schema for MCP compatibility
|
|
55
96
|
*
|
|
@@ -58,9 +99,59 @@ export declare class AtpMcpServer {
|
|
|
58
99
|
*/
|
|
59
100
|
private zodToJsonSchema;
|
|
60
101
|
/**
|
|
61
|
-
* Start the MCP server
|
|
102
|
+
* Start the MCP server.
|
|
103
|
+
*
|
|
104
|
+
* By default the server speaks MCP over stdio. Pass
|
|
105
|
+
* `{ transport: 'http' }` to serve the Streamable HTTP transport instead:
|
|
106
|
+
* a node:http server routes POST/GET/DELETE on /mcp through per-session
|
|
107
|
+
* StreamableHTTPServerTransport instances, each backed by a fresh MCP
|
|
108
|
+
* Server built via the same construction path as the stdio server.
|
|
109
|
+
*/
|
|
110
|
+
start(options?: IServerStartOptions): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Start the Streamable HTTP transport: a node:http server (no express
|
|
113
|
+
* dependency) that routes /mcp through per-session transports.
|
|
114
|
+
*
|
|
115
|
+
* Binding defaults to the configured host, with 'localhost' pinned to the
|
|
116
|
+
* IPv4 loopback 127.0.0.1 so the bind address (and the DNS-rebinding
|
|
117
|
+
* allowlist) is deterministic across platforms whose resolvers disagree
|
|
118
|
+
* about ::1 vs 127.0.0.1. Exposing the server beyond loopback (e.g.
|
|
119
|
+
* --host 0.0.0.0) is the operator's responsibility to secure.
|
|
120
|
+
*/
|
|
121
|
+
private startHttpTransport;
|
|
122
|
+
/**
|
|
123
|
+
* Route a single HTTP request. Only /mcp is served; the SDK transport does
|
|
124
|
+
* the MCP-level work (method dispatch, session validation, SSE streaming).
|
|
125
|
+
*/
|
|
126
|
+
private handleHttpRequest;
|
|
127
|
+
/**
|
|
128
|
+
* Create a Streamable HTTP session: a stateful transport (server-minted
|
|
129
|
+
* session id) wired to a fresh MCP Server from the shared factory. The
|
|
130
|
+
* session registers itself in httpSessions once the SDK accepts the
|
|
131
|
+
* initialize request, and removes itself when the transport closes (DELETE,
|
|
132
|
+
* client disconnect, or shutdown).
|
|
133
|
+
*/
|
|
134
|
+
private createHttpSession;
|
|
135
|
+
/**
|
|
136
|
+
* Read and parse a JSON request body, bounding its size. Responds (413/400)
|
|
137
|
+
* and resolves to undefined when the body is unusable; the caller must stop
|
|
138
|
+
* processing the request in that case.
|
|
139
|
+
*/
|
|
140
|
+
private readJsonBody;
|
|
141
|
+
/**
|
|
142
|
+
* Write a JSON-RPC-shaped HTTP error response (the same shape the SDK
|
|
143
|
+
* transport uses for its own protocol-level rejections).
|
|
144
|
+
*/
|
|
145
|
+
private writeJsonRpcError;
|
|
146
|
+
/**
|
|
147
|
+
* The address the http transport is bound to, or null when the http
|
|
148
|
+
* transport is not running. Exposed so callers (and tests binding port 0)
|
|
149
|
+
* can discover the actual ephemeral port.
|
|
62
150
|
*/
|
|
63
|
-
|
|
151
|
+
getHttpAddress(): {
|
|
152
|
+
host: string;
|
|
153
|
+
port: number;
|
|
154
|
+
} | null;
|
|
64
155
|
/**
|
|
65
156
|
* Stop the MCP server
|
|
66
157
|
*/
|