openwriter 0.2.2 → 0.3.1

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 CHANGED
@@ -45,7 +45,7 @@ npx skills add https://github.com/travsteward/openwriter --skill openwriter
45
45
 
46
46
  Then add the MCP server for the 24 editing tools:
47
47
  ```bash
48
- claude mcp add -s user open-writer -- npx openwriter --no-open
48
+ claude mcp add -s user openwriter -- npx openwriter --no-open
49
49
  ```
50
50
 
51
51
  The skill teaches your agent how to use OpenWriter's tools effectively — writing strategy, review etiquette, and troubleshooting. The MCP server provides the actual document editing capabilities.
@@ -55,7 +55,7 @@ The skill teaches your agent how to use OpenWriter's tools effectively — writi
55
55
  ```json
56
56
  {
57
57
  "mcpServers": {
58
- "open-writer": {
58
+ "openwriter": {
59
59
  "command": "npx",
60
60
  "args": ["openwriter", "--no-open"]
61
61
  }
@@ -78,7 +78,7 @@ Now your agent has 24 tools to read, write, and organize documents — and every
78
78
  | **Document** | `read_pad`, `write_to_pad`, `edit_text`, `get_pad_status`, + 5 more | Read/write document content, fine-grained text edits, metadata |
79
79
  | **Multi-doc** | `list_documents`, `switch_document`, `create_document` | Navigate and manage multiple documents |
80
80
  | **Workspace** | `create_workspace`, `get_workspace_structure`, `add_doc`, + 6 more | Organize docs into projects with containers and tags |
81
- | **Import** | `import_gdoc` | Import Google Docs, auto-split into chapters |
81
+ | **Import** | `import_gdoc` | Import structured Google Docs, auto-split into chapters |
82
82
 
83
83
  Agents write in markdown or TipTap JSON. The server converts, assigns node IDs, and broadcasts changes to your browser in real-time via WebSocket.
84
84
 
package/dist/bin/pad.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
3
  * CLI entry point for OpenWriter.
4
- * Usage: npx openwriter [--api-key av_live_xxx] [--port 5050] [--no-open] [--av-url URL] [--plugins name1,name2]
4
+ * Usage: openwriter [--api-key av_live_xxx] [--port 5050] [--no-open] [--av-url URL] [--plugins name1,name2]
5
5
  *
6
6
  * API key resolution (first wins):
7
7
  * 1. --api-key CLI flag
@@ -9,11 +9,18 @@
9
9
  * 3. Saved in ~/.openwriter/config.json (from a previous --api-key)
10
10
  *
11
11
  * If no key found, server starts anyway — plugins that need it will report errors.
12
+ *
13
+ * Boot order optimized for fast MCP startup:
14
+ * 1. Parse args + config (light imports only)
15
+ * 2. Port check (fast TCP probe)
16
+ * 3. Start MCP stdio transport (what Claude Code waits for)
17
+ * 4. Lazy-load Express server + plugins (heavy deps deferred)
12
18
  */
13
19
  // Redirect all console output to stderr so MCP stdio protocol stays clean on stdout
14
20
  const originalLog = console.log;
15
21
  console.log = (...args) => console.error(...args);
16
- import { startServer } from '../server/index.js';
22
+ // Only light imports here — helpers.js uses fs/path/os/crypto (all Node stdlib)
23
+ import { createConnection } from 'net';
17
24
  import { readConfig, saveConfig } from '../server/helpers.js';
18
25
  const args = process.argv.slice(2);
19
26
  // Subcommands (run and exit, don't start server)
@@ -66,5 +73,30 @@ else {
66
73
  process.env.AV_API_KEY = avApiKey;
67
74
  if (avBackendUrl)
68
75
  process.env.AV_BACKEND_URL = avBackendUrl;
69
- startServer({ port, noOpen, plugins });
76
+ // Fast port check determines primary vs client mode
77
+ const portTaken = await new Promise((resolve) => {
78
+ const socket = createConnection({ port, host: '127.0.0.1' });
79
+ socket.once('connect', () => { socket.destroy(); resolve(true); });
80
+ socket.once('error', () => { resolve(false); });
81
+ });
82
+ if (portTaken) {
83
+ // Client mode: proxy MCP calls to existing primary server via HTTP
84
+ console.error(`[OpenWriter] Port ${port} in use — entering client mode (proxying to existing server)`);
85
+ const { startMcpClientServer } = await import('../server/mcp-client.js');
86
+ startMcpClientServer(port).catch((err) => {
87
+ console.error('[MCP-Client] Failed to start:', err);
88
+ });
89
+ }
90
+ else {
91
+ // Primary mode: start MCP stdio FIRST, then lazy-load Express
92
+ const { load } = await import('../server/state.js');
93
+ load();
94
+ const { startMcpServer } = await import('../server/mcp.js');
95
+ startMcpServer().catch((err) => {
96
+ console.error('[MCP] Failed to start:', err);
97
+ });
98
+ // Deferred: load Express + plugins (heavy deps) after MCP is connecting
99
+ const { startHttpServer } = await import('../server/index.js');
100
+ startHttpServer({ port, noOpen, plugins });
101
+ }
70
102
  }