atproto-mcp 0.4.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.
Files changed (186) hide show
  1. package/README.md +41 -20
  2. package/dist/cli.d.ts +24 -1
  3. package/dist/cli.js +57 -18
  4. package/dist/health-check.d.ts +0 -1
  5. package/dist/health-check.js +2 -2
  6. package/dist/index.d.ts +93 -3
  7. package/dist/index.js +543 -109
  8. package/dist/prompts/index.d.ts +26 -4
  9. package/dist/prompts/index.js +48 -11
  10. package/dist/resources/base.d.ts +0 -1
  11. package/dist/resources/base.js +0 -1
  12. package/dist/resources/conversation-context-resource.d.ts +7 -8
  13. package/dist/resources/conversation-context-resource.js +10 -12
  14. package/dist/resources/index.d.ts +2 -3
  15. package/dist/resources/index.js +8 -6
  16. package/dist/resources/templates.d.ts +82 -0
  17. package/dist/resources/templates.js +231 -0
  18. package/dist/tools/implementations/advanced-social-tools.d.ts +0 -1
  19. package/dist/tools/implementations/advanced-social-tools.js +13 -2
  20. package/dist/tools/implementations/analytics-tools.d.ts +13 -2
  21. package/dist/tools/implementations/analytics-tools.js +12 -8
  22. package/dist/tools/implementations/analyze-account-tool.d.ts +452 -1
  23. package/dist/tools/implementations/analyze-account-tool.js +397 -9
  24. package/dist/tools/implementations/base-tool.d.ts +49 -7
  25. package/dist/tools/implementations/base-tool.js +49 -14
  26. package/dist/tools/implementations/batch-operations-tools.d.ts +22 -8
  27. package/dist/tools/implementations/batch-operations-tools.js +131 -28
  28. package/dist/tools/implementations/bookmark-tools.d.ts +314 -0
  29. package/dist/tools/implementations/bookmark-tools.js +411 -0
  30. package/dist/tools/implementations/composite-tools.d.ts +0 -1
  31. package/dist/tools/implementations/composite-tools.js +0 -1
  32. package/dist/tools/implementations/content-discovery-tools.d.ts +8 -3
  33. package/dist/tools/implementations/content-discovery-tools.js +100 -67
  34. package/dist/tools/implementations/content-management-tools.d.ts +91 -9
  35. package/dist/tools/implementations/content-management-tools.js +51 -32
  36. package/dist/tools/implementations/create-post-tool.d.ts +514 -12
  37. package/dist/tools/implementations/create-post-tool.js +317 -33
  38. package/dist/tools/implementations/create-thread-tool.d.ts +49 -2
  39. package/dist/tools/implementations/create-thread-tool.js +99 -2
  40. package/dist/tools/implementations/discover-tool.d.ts +235 -1
  41. package/dist/tools/implementations/discover-tool.js +238 -21
  42. package/dist/tools/implementations/dm-tools.d.ts +414 -0
  43. package/dist/tools/implementations/dm-tools.js +493 -0
  44. package/dist/tools/implementations/follow-user-tool.d.ts +0 -1
  45. package/dist/tools/implementations/follow-user-tool.js +0 -1
  46. package/dist/tools/implementations/get-author-feed-tool.d.ts +0 -1
  47. package/dist/tools/implementations/get-author-feed-tool.js +0 -1
  48. package/dist/tools/implementations/get-user-profile-tool.d.ts +0 -1
  49. package/dist/tools/implementations/get-user-profile-tool.js +0 -1
  50. package/dist/tools/implementations/index.d.ts +3 -1
  51. package/dist/tools/implementations/index.js +6 -1
  52. package/dist/tools/implementations/like-post-tool.d.ts +9 -3
  53. package/dist/tools/implementations/like-post-tool.js +15 -6
  54. package/dist/tools/implementations/media-tools.d.ts +90 -8
  55. package/dist/tools/implementations/media-tools.js +292 -60
  56. package/dist/tools/implementations/moderation-tools.d.ts +0 -1
  57. package/dist/tools/implementations/moderation-tools.js +0 -1
  58. package/dist/tools/implementations/reply-to-post-tool.d.ts +5 -2
  59. package/dist/tools/implementations/reply-to-post-tool.js +15 -2
  60. package/dist/tools/implementations/repost-tool.d.ts +3 -2
  61. package/dist/tools/implementations/repost-tool.js +5 -13
  62. package/dist/tools/implementations/rich-media-tools.d.ts +13 -15
  63. package/dist/tools/implementations/rich-media-tools.js +2 -17
  64. package/dist/tools/implementations/search-actors-tool.d.ts +0 -1
  65. package/dist/tools/implementations/search-actors-tool.js +0 -1
  66. package/dist/tools/implementations/search-posts-tool.d.ts +3 -32
  67. package/dist/tools/implementations/search-posts-tool.js +0 -60
  68. package/dist/tools/implementations/social-graph-tools.d.ts +1 -3
  69. package/dist/tools/implementations/social-graph-tools.js +5 -3
  70. package/dist/tools/implementations/starter-pack-tools.d.ts +412 -0
  71. package/dist/tools/implementations/starter-pack-tools.js +395 -0
  72. package/dist/tools/implementations/timeline-tools.d.ts +0 -28
  73. package/dist/tools/implementations/timeline-tools.js +0 -74
  74. package/dist/tools/index.d.ts +0 -1
  75. package/dist/tools/index.js +12 -2
  76. package/dist/types/index.d.ts +55 -12
  77. package/dist/types/index.js +6 -3
  78. package/dist/utils/atp-client.d.ts +15 -2
  79. package/dist/utils/atp-client.js +65 -11
  80. package/dist/utils/config.d.ts +3 -2
  81. package/dist/utils/config.js +10 -7
  82. package/dist/utils/logger.d.ts +8 -1
  83. package/dist/utils/logger.js +17 -4
  84. package/dist/utils/oauth-client.d.ts +0 -1
  85. package/dist/utils/oauth-client.js +4 -5
  86. package/dist/utils/performance.d.ts +0 -1
  87. package/dist/utils/performance.js +0 -1
  88. package/dist/utils/security.d.ts +0 -1
  89. package/dist/utils/security.js +0 -1
  90. package/dist/utils/url-safety.d.ts +0 -1
  91. package/dist/utils/url-safety.js +0 -1
  92. package/package.json +25 -22
  93. package/dist/cli.d.ts.map +0 -1
  94. package/dist/cli.js.map +0 -1
  95. package/dist/health-check.d.ts.map +0 -1
  96. package/dist/health-check.js.map +0 -1
  97. package/dist/index.d.ts.map +0 -1
  98. package/dist/index.js.map +0 -1
  99. package/dist/prompts/index.d.ts.map +0 -1
  100. package/dist/prompts/index.js.map +0 -1
  101. package/dist/resources/base.d.ts.map +0 -1
  102. package/dist/resources/base.js.map +0 -1
  103. package/dist/resources/conversation-context-resource.d.ts.map +0 -1
  104. package/dist/resources/conversation-context-resource.js.map +0 -1
  105. package/dist/resources/index.d.ts.map +0 -1
  106. package/dist/resources/index.js.map +0 -1
  107. package/dist/test/integration-config.d.ts +0 -60
  108. package/dist/test/integration-config.d.ts.map +0 -1
  109. package/dist/test/integration-config.js +0 -93
  110. package/dist/test/integration-config.js.map +0 -1
  111. package/dist/test/setup.d.ts +0 -78
  112. package/dist/test/setup.d.ts.map +0 -1
  113. package/dist/test/setup.js +0 -138
  114. package/dist/test/setup.js.map +0 -1
  115. package/dist/tools/implementations/advanced-social-tools.d.ts.map +0 -1
  116. package/dist/tools/implementations/advanced-social-tools.js.map +0 -1
  117. package/dist/tools/implementations/analytics-tools.d.ts.map +0 -1
  118. package/dist/tools/implementations/analytics-tools.js.map +0 -1
  119. package/dist/tools/implementations/analyze-account-tool.d.ts.map +0 -1
  120. package/dist/tools/implementations/analyze-account-tool.js.map +0 -1
  121. package/dist/tools/implementations/base-tool.d.ts.map +0 -1
  122. package/dist/tools/implementations/base-tool.js.map +0 -1
  123. package/dist/tools/implementations/batch-operations-tools.d.ts.map +0 -1
  124. package/dist/tools/implementations/batch-operations-tools.js.map +0 -1
  125. package/dist/tools/implementations/composite-tools.d.ts.map +0 -1
  126. package/dist/tools/implementations/composite-tools.js.map +0 -1
  127. package/dist/tools/implementations/content-discovery-tools.d.ts.map +0 -1
  128. package/dist/tools/implementations/content-discovery-tools.js.map +0 -1
  129. package/dist/tools/implementations/content-management-tools.d.ts.map +0 -1
  130. package/dist/tools/implementations/content-management-tools.js.map +0 -1
  131. package/dist/tools/implementations/create-post-tool.d.ts.map +0 -1
  132. package/dist/tools/implementations/create-post-tool.js.map +0 -1
  133. package/dist/tools/implementations/create-thread-tool.d.ts.map +0 -1
  134. package/dist/tools/implementations/create-thread-tool.js.map +0 -1
  135. package/dist/tools/implementations/discover-tool.d.ts.map +0 -1
  136. package/dist/tools/implementations/discover-tool.js.map +0 -1
  137. package/dist/tools/implementations/follow-user-tool.d.ts.map +0 -1
  138. package/dist/tools/implementations/follow-user-tool.js.map +0 -1
  139. package/dist/tools/implementations/get-author-feed-tool.d.ts.map +0 -1
  140. package/dist/tools/implementations/get-author-feed-tool.js.map +0 -1
  141. package/dist/tools/implementations/get-user-profile-tool.d.ts.map +0 -1
  142. package/dist/tools/implementations/get-user-profile-tool.js.map +0 -1
  143. package/dist/tools/implementations/index.d.ts.map +0 -1
  144. package/dist/tools/implementations/index.js.map +0 -1
  145. package/dist/tools/implementations/like-post-tool.d.ts.map +0 -1
  146. package/dist/tools/implementations/like-post-tool.js.map +0 -1
  147. package/dist/tools/implementations/media-tools.d.ts.map +0 -1
  148. package/dist/tools/implementations/media-tools.js.map +0 -1
  149. package/dist/tools/implementations/moderation-tools.d.ts.map +0 -1
  150. package/dist/tools/implementations/moderation-tools.js.map +0 -1
  151. package/dist/tools/implementations/reply-to-post-tool.d.ts.map +0 -1
  152. package/dist/tools/implementations/reply-to-post-tool.js.map +0 -1
  153. package/dist/tools/implementations/repost-tool.d.ts.map +0 -1
  154. package/dist/tools/implementations/repost-tool.js.map +0 -1
  155. package/dist/tools/implementations/rich-media-tools.d.ts.map +0 -1
  156. package/dist/tools/implementations/rich-media-tools.js.map +0 -1
  157. package/dist/tools/implementations/search-actors-tool.d.ts.map +0 -1
  158. package/dist/tools/implementations/search-actors-tool.js.map +0 -1
  159. package/dist/tools/implementations/search-posts-tool.d.ts.map +0 -1
  160. package/dist/tools/implementations/search-posts-tool.js.map +0 -1
  161. package/dist/tools/implementations/social-graph-tools.d.ts.map +0 -1
  162. package/dist/tools/implementations/social-graph-tools.js.map +0 -1
  163. package/dist/tools/implementations/timeline-tools.d.ts.map +0 -1
  164. package/dist/tools/implementations/timeline-tools.js.map +0 -1
  165. package/dist/tools/index.d.ts.map +0 -1
  166. package/dist/tools/index.js.map +0 -1
  167. package/dist/types/index.d.ts.map +0 -1
  168. package/dist/types/index.js.map +0 -1
  169. package/dist/utils/atp-client.d.ts.map +0 -1
  170. package/dist/utils/atp-client.js.map +0 -1
  171. package/dist/utils/config.d.ts.map +0 -1
  172. package/dist/utils/config.js.map +0 -1
  173. package/dist/utils/firehose-client.d.ts +0 -140
  174. package/dist/utils/firehose-client.d.ts.map +0 -1
  175. package/dist/utils/firehose-client.js +0 -351
  176. package/dist/utils/firehose-client.js.map +0 -1
  177. package/dist/utils/logger.d.ts.map +0 -1
  178. package/dist/utils/logger.js.map +0 -1
  179. package/dist/utils/oauth-client.d.ts.map +0 -1
  180. package/dist/utils/oauth-client.js.map +0 -1
  181. package/dist/utils/performance.d.ts.map +0 -1
  182. package/dist/utils/performance.js.map +0 -1
  183. package/dist/utils/security.d.ts.map +0 -1
  184. package/dist/utils/security.js.map +0 -1
  185. package/dist/utils/url-safety.d.ts.map +0 -1
  186. package/dist/utils/url-safety.js.map +0 -1
package/README.md CHANGED
@@ -42,9 +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**: Batch operations for bulk actions, advanced analytics
46
- > and insights, intelligent content discovery, and a conversation-context
47
- > scratchpad resource.
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`).
48
48
 
49
49
  ## Architecture
50
50
 
@@ -87,10 +87,11 @@ server to access AT Protocol functionality.
87
87
  (follow/like/repost up to 25 items at once)
88
88
  - **Analytics & Insights**: Analyze engagement patterns, network connections,
89
89
  and get content strategy recommendations
90
- - **Content Discovery**: Find similar users, trending topics, and influential
91
- voices in your areas of interest
92
- - **Conversation Context**: An MCP resource that acts as a scratchpad for
93
- conversation state (not auto-populated yet)
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
94
95
 
95
96
  ### Core Features
96
97
 
@@ -104,13 +105,16 @@ server to access AT Protocol functionality.
104
105
  - **MCP Server Compliance**: Built with `@modelcontextprotocol/sdk` following
105
106
  MCP specification
106
107
  - **Type-Safe**: Written in TypeScript with strict type checking
107
- - **Comprehensive Tools**: 43 MCP tools for social networking operations
108
+ - **Comprehensive Tools**: 51 MCP tools for social networking operations
108
109
  - **Rate Limiting**: Built-in respect for AT Protocol rate limits
109
110
  - **Extensible**: Modular architecture for easy customization
110
111
 
111
- > **Planned**: OAuth login and real-time firehose streaming are on the roadmap
112
- > but not yet functional. App-password authentication is the supported auth path
113
- > today.
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).
114
118
 
115
119
  ## Who Is This For?
116
120
 
@@ -227,10 +231,10 @@ config:
227
231
  `get_timeline`)
228
232
  - All write operations (create, like, repost, follow, etc.)
229
233
  - Resources (timeline, profile, notifications) - these are listed but require
230
- authentication to return data (the `conversation-context` scratchpad resource
231
- is readable without auth and simply returns near-empty placeholder content)
232
- - Prompts (content composition, reply templates) - these are listed but require
233
- authentication to be available
234
+ authentication to return data
235
+
236
+ Prompts (content composition, reply templates) are pure text templates and work
237
+ without authentication.
234
238
 
235
239
  **Important:** All tools, resources, and prompts are listed by the MCP server
236
240
  regardless of authentication state. Most tools and resources that require
@@ -270,7 +274,7 @@ credentials.
270
274
 
271
275
  ## Available Tools
272
276
 
273
- The server provides **43 MCP tools** across multiple categories. See the
277
+ The server provides **51 MCP tools** across multiple categories. See the
274
278
  [complete API documentation](https://cameronrye.github.io/atproto-mcp/api/) for
275
279
  detailed information on each tool.
276
280
 
@@ -289,6 +293,8 @@ detailed information on each tool.
289
293
  enriches the underlying API call when authenticated)
290
294
  - `get_post_context` - Get a post with optional thread, author profile,
291
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)
292
298
 
293
299
  **Rich Media**
294
300
 
@@ -320,6 +326,18 @@ for most endpoints that were previously public, including `search_posts`.
320
326
  cheap unread badge count)
321
327
  - `mark_notifications_seen` - Mark notifications as seen up to a timestamp
322
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
+
323
341
  **Content Management**
324
342
 
325
343
  - `upload_image` / `upload_video` - Upload media content
@@ -524,10 +542,13 @@ This project is licensed under the MIT License.
524
542
 
525
543
  ## Deployment
526
544
 
527
- This is a **stdio MCP server**: it is normally launched by an MCP client (e.g.
528
- Claude Desktop) via `npx atproto-mcp` and communicates over stdin/stdout. It
529
- does not listen on a network port, so there is no HTTP endpoint to expose or
530
- scale.
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.
531
552
 
532
553
  ### Built-in safeguards
533
554
 
package/dist/cli.d.ts CHANGED
@@ -2,9 +2,32 @@
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
  */
8
24
  declare function main(): Promise<void>;
25
+ /**
26
+ * Detect whether a module is the process entry point. Node realpath-resolves
27
+ * import.meta.url for the main module, but argv[1] stays the literal invoked
28
+ * path — and npm installs bins as symlinks — so a naive string comparison
29
+ * against `file://${argv[1]}` breaks symlinked, relative, and space-containing
30
+ * paths. Compare realpath-resolved file URLs instead.
31
+ */
32
+ export declare function isMainModule(importMetaUrl: string, argv1: string | undefined): boolean;
9
33
  export { main as runCli };
10
- //# sourceMappingURL=cli.d.ts.map
package/dist/cli.js CHANGED
@@ -3,9 +3,9 @@
3
3
  * Command-line interface for the AT Protocol MCP Server
4
4
  */
5
5
  import { parseArgs } from 'node:util';
6
- import { existsSync, readFileSync } from 'node:fs';
6
+ import { existsSync, readFileSync, realpathSync } from 'node:fs';
7
7
  import { dirname, join } from 'node:path';
8
- import { fileURLToPath } from 'node:url';
8
+ import { fileURLToPath, pathToFileURL } from 'node:url';
9
9
  import { ConfigurationError } from './types/index.js';
10
10
  import { AtpMcpServer } from './index.js';
11
11
  import { LogLevel, Logger } from './utils/logger.js';
@@ -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',
@@ -73,7 +78,7 @@ const CLI_OPTIONS = {
73
78
  },
74
79
  host: {
75
80
  type: 'string',
76
- short: 'h',
81
+ short: 'H',
77
82
  description: 'Server host (default: localhost)',
78
83
  },
79
84
  service: {
@@ -93,6 +98,7 @@ const CLI_OPTIONS = {
93
98
  },
94
99
  help: {
95
100
  type: 'boolean',
101
+ short: 'h',
96
102
  description: 'Show help message',
97
103
  },
98
104
  version: {
@@ -112,17 +118,22 @@ AT Protocol MCP Server - Comprehensive interface for LLMs to interact with AT Pr
112
118
 
113
119
  Usage: atproto-mcp [options]
114
120
 
115
- Transport: this server communicates over stdio (for MCP clients such as Claude
116
- Desktop). It does not listen on a TCP port; --port/--host are accepted but
117
- currently have no effect.
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.
118
128
 
119
129
  Options:
120
- -p, --port <number> Server port (reserved; stdio transport ignores it)
121
- -h, --host <string> Server host (reserved; stdio transport ignores it)
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)
122
133
  -s, --service <url> AT Protocol service URL (default: https://bsky.social)
123
134
  -a, --auth <method> Authentication method: app-password|oauth (optional)
124
135
  -l, --log-level <level> Log level: debug|info|warn|error (default: info)
125
- --help Show this help message
136
+ -h, --help Show this help message
126
137
  -v, --version Show version information
127
138
 
128
139
  🔓 Unauthenticated Mode (Default):
@@ -154,8 +165,8 @@ Examples:
154
165
  # Start in unauthenticated mode (works immediately!)
155
166
  atproto-mcp
156
167
 
157
- # Start with custom port and debug logging
158
- 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
159
170
 
160
171
  # Enable authentication with app password
161
172
  export ATPROTO_IDENTIFIER="your-handle.bsky.social"
@@ -184,11 +195,13 @@ function showVersion() {
184
195
  }
185
196
  }
186
197
  /**
187
- * Parse command line arguments
198
+ * Parse command line arguments. `argv` defaults to the process arguments and
199
+ * is injectable for tests.
188
200
  */
189
- function parseCliArgs() {
201
+ export function parseCliArgs(argv = process.argv.slice(2)) {
190
202
  try {
191
203
  const { values } = parseArgs({
204
+ args: argv,
192
205
  options: CLI_OPTIONS,
193
206
  allowPositionals: false,
194
207
  });
@@ -211,6 +224,15 @@ function parseCliArgs() {
211
224
  throw new ConfigurationError(`Invalid log level: ${values['log-level']}. Must be one of: debug, info, warn, error`);
212
225
  }
213
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
+ }
214
236
  // Build configuration from CLI arguments
215
237
  const config = {};
216
238
  if (values.port != null && values.port !== '') {
@@ -246,7 +268,7 @@ function parseCliArgs() {
246
268
  }
247
269
  config.atproto = atproto;
248
270
  }
249
- return config;
271
+ return { config, transport };
250
272
  }
251
273
  catch (error) {
252
274
  if (error instanceof ConfigurationError) {
@@ -266,7 +288,7 @@ async function main() {
266
288
  // visible to ConfigManager and the rest of the server.
267
289
  loadEnvFile();
268
290
  // Parse command line arguments
269
- const cliConfig = parseCliArgs();
291
+ const { config: cliConfig, transport } = parseCliArgs();
270
292
  // Create and start server
271
293
  const server = new AtpMcpServer(cliConfig);
272
294
  // Setup graceful shutdown handlers
@@ -297,7 +319,7 @@ async function main() {
297
319
  process.exit(1);
298
320
  });
299
321
  // Start the server
300
- await server.start();
322
+ await server.start({ transport });
301
323
  // Keep the process running
302
324
  logger.info('AT Protocol MCP Server is running. Press Ctrl+C to stop.');
303
325
  }
@@ -311,12 +333,29 @@ async function main() {
311
333
  process.exit(1);
312
334
  }
313
335
  }
336
+ /**
337
+ * Detect whether a module is the process entry point. Node realpath-resolves
338
+ * import.meta.url for the main module, but argv[1] stays the literal invoked
339
+ * path — and npm installs bins as symlinks — so a naive string comparison
340
+ * against `file://${argv[1]}` breaks symlinked, relative, and space-containing
341
+ * paths. Compare realpath-resolved file URLs instead.
342
+ */
343
+ export function isMainModule(importMetaUrl, argv1) {
344
+ if (argv1 == null || argv1 === '') {
345
+ return false;
346
+ }
347
+ try {
348
+ return importMetaUrl === pathToFileURL(realpathSync(argv1)).href;
349
+ }
350
+ catch {
351
+ return false;
352
+ }
353
+ }
314
354
  // Run CLI if this file is executed directly
315
- if (import.meta.url === `file://${process.argv[1]}`) {
355
+ if (isMainModule(import.meta.url, process.argv[1])) {
316
356
  main().catch(error => {
317
357
  console.error('Fatal error:', error);
318
358
  process.exit(1);
319
359
  });
320
360
  }
321
361
  export { main as runCli };
322
- //# sourceMappingURL=cli.js.map
@@ -11,4 +11,3 @@
11
11
  * and reporting them would be misleading.
12
12
  */
13
13
  export {};
14
- //# sourceMappingURL=health-check.d.ts.map
@@ -10,6 +10,7 @@
10
10
  * connection counts of the running server — a fresh process cannot observe those
11
11
  * and reporting them would be misleading.
12
12
  */
13
+ import { isMainModule } from './cli.js';
13
14
  import { AtpMcpServer } from './index.js';
14
15
  function healthCheck() {
15
16
  try {
@@ -47,7 +48,6 @@ function healthCheck() {
47
48
  }
48
49
  }
49
50
  // Run health check if this script is executed directly
50
- if (import.meta.url === `file://${process.argv[1]}`) {
51
+ if (isMainModule(import.meta.url, process.argv[1])) {
51
52
  void healthCheck();
52
53
  }
53
- //# sourceMappingURL=health-check.js.map
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
- start(): Promise<void>;
151
+ getHttpAddress(): {
152
+ host: string;
153
+ port: number;
154
+ } | null;
64
155
  /**
65
156
  * Stop the MCP server
66
157
  */
@@ -131,4 +222,3 @@ export declare class AtpMcpServer {
131
222
  * await server.start();
132
223
  */
133
224
  export default AtpMcpServer;
134
- //# sourceMappingURL=index.d.ts.map