remnote-mcp-server 0.14.0 → 0.14.2

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/CHANGELOG.md CHANGED
@@ -7,6 +7,42 @@ Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.14.2] - 2026-05-08
11
+
12
+ ### Changed
13
+
14
+ - Reject RemNote bridge WebSocket connections that do not send a compatible bridge `hello.version`, with a clearer
15
+ disconnect reason and server log message pointing users to `MCP/OpenClaw Automation Bridge`.
16
+ - Added prominent README troubleshooting guidance for wrong or incompatible RemNote Marketplace plugin installs,
17
+ including the related `quentintou/remnote-mcp-bridge#8` report.
18
+ - Updated Claude Desktop / Cowork setup docs to clarify that local MCPB works for Cowork in the Claude Desktop app
19
+ when desktop extensions are enabled, while remote connectors remain required for web/mobile, cloud-hosted clients,
20
+ and managed deployments without local MCPB.
21
+
22
+ ## [0.14.1] - 2026-05-08
23
+
24
+ ### Added
25
+
26
+ - Added a `remnote-local` MCPB package for Claude Desktop that proxies stdio MCP calls to a locally running
27
+ `remnote-mcp-server` Streamable HTTP endpoint without public HTTPS, including setup docs, screenshots, and official
28
+ MCPB references.
29
+ - Added `remnote-mcp-server mcpb-path` to print the bundled Claude Desktop extension path after npm installation.
30
+ - Added the `remnote-mcp-stdio` executable for local MCP clients that consume stdio servers, including help/version
31
+ output and smoke-test commands in the configuration guide.
32
+ - Added Codex TUI and Codex.app configuration documentation covering Streamable HTTP MCP, `remnote-mcp-stdio`, and
33
+ `remnote-cli` skill setup.
34
+ - Added MCP protocol compatibility guidance clarifying that `2025-11-25` initialize requests are supported and separate
35
+ from bridge/server package versions.
36
+ - Added clearer stdio proxy prerequisites and cross-links between the generic stdio MCP client section and the Codex
37
+ stdio setup example.
38
+
39
+ ### Changed
40
+
41
+ - Reordered the README AI client setup list to include Codex and prioritize the local Claude Desktop MCPB path before
42
+ remote connector setup.
43
+ - Updated documentation and agent repo maps to reflect that the old standalone `remnote-cli` repository is
44
+ discontinued and the maintained CLI lives in this package.
45
+
10
46
  ## [0.14.0] - 2026-05-07
11
47
 
12
48
  ### Added
package/README.md CHANGED
@@ -11,13 +11,20 @@ plugin](https://github.com/robert7/remnote-mcp-bridge).
11
11
 
12
12
  > If you run into any issues, please [report them here](https://github.com/robert7/remnote-mcp-server/issues).
13
13
 
14
+ > **Connection issue? Check the RemNote plugin first.** The RemNote Marketplace may show multiple similarly named
15
+ > `MCP Bridge` plugins. For this server, install the official **MCP/OpenClaw Automation Bridge** plugin by Robert
16
+ > Spiegel and keep it on the same `0.x` minor version line as `remnote-mcp-server` (for example `0.14.x` with
17
+ > `0.14.x`). Wrong plugin flavors or incompatible marketplace copies can connect briefly and then disconnect with a
18
+ > `1008` compatibility message. See the related upstream marketplace confusion report:
19
+ > [quentintou/remnote-mcp-bridge#8](https://github.com/quentintou/remnote-mcp-bridge/issues/8).
20
+
14
21
  ## What is This?
15
22
 
16
23
  The RemNote MCP Server enables AI assistants like Claude Code to interact directly with your RemNote knowledge base
17
24
  through the Model Context Protocol (MCP). The same npm package also provides `remnote-cli`, a command-line MCP client
18
- for local scripts and coding harnesses. Create notes, hierarchical markdown trees, and RemNote-native flashcards;
19
- search and read your knowledge base; update existing notes; and maintain your daily journal through MCP tools or shell
20
- commands.
25
+ for local scripts and coding harnesses, and `remnote-mcp-stdio`, a stdio MCP proxy for clients that cannot consume
26
+ Streamable HTTP directly. Create notes, hierarchical markdown trees, and RemNote-native flashcards; search and read
27
+ your knowledge base; update existing notes; and maintain your daily journal through MCP tools or shell commands.
21
28
 
22
29
  ## Demo
23
30
 
@@ -29,10 +36,11 @@ This system consists of **two separate runtime components** that work together:
29
36
 
30
37
  1. **[RemNote Automation Bridge](https://github.com/robert7/remnote-mcp-bridge)** - A RemNote plugin that runs in your
31
38
  browser or RemNote desktop app and exposes RemNote API functionality via WebSocket
32
- 2. **RemNote MCP Server** (this project) - A standalone server package that provides the `remnote-mcp-server`
33
- executable for MCP clients and the `remnote-cli` executable for command-line workflows
39
+ 2. **RemNote MCP Server** (this project) - A standalone server package that provides `remnote-mcp-server` for MCP
40
+ HTTP clients, `remnote-mcp-stdio` for stdio MCP clients, and `remnote-cli` for command-line workflows
34
41
 
35
- The `remnote-cli` command is not a second server. It calls the MCP endpoint exposed by `remnote-mcp-server`.
42
+ The `remnote-cli` and `remnote-mcp-stdio` commands are not second RemNote-facing servers. They call the MCP endpoint
43
+ exposed by `remnote-mcp-server`.
36
44
 
37
45
  For the detailed bridge connection lifecycle, retry phases, and wake-up triggers, use the bridge repo as the source of
38
46
  truth: [Connection Lifecycle Guide](https://github.com/robert7/remnote-mcp-bridge/blob/main/docs/guides/connection-lifecycle.md).
@@ -41,12 +49,14 @@ truth: [Connection Lifecycle Guide](https://github.com/robert7/remnote-mcp-bridg
41
49
 
42
50
  ```text
43
51
  AI agents (HTTP) -> MCP HTTP Server :3001 -> WebSocket Server :3002 -> RemNote Plugin -> RemNote
52
+ AI agents (stdio) -> remnote-mcp-stdio -> MCP HTTP Server :3001 -> WebSocket Server :3002 -> RemNote Plugin -> RemNote
44
53
  CLI commands -> remnote-cli -> MCP HTTP Server :3001 -> WebSocket Server :3002 -> RemNote Plugin -> RemNote
45
54
  ```
46
55
 
47
56
  The server acts as a bridge:
48
57
 
49
58
  - Communicates with AI agents via Streamable HTTP transport (MCP protocol) - supports both local and remote access
59
+ - Provides `remnote-mcp-stdio` as a local stdio MCP proxy for clients that need stdio transport
50
60
  - Provides `remnote-cli` as a bundled command-line MCP client for local automation
51
61
  - HTTP server (port 3001) manages MCP sessions for multiple concurrent agents
52
62
  - WebSocket server (port 3002) connects to the RemNote browser plugin
@@ -55,9 +65,11 @@ The server acts as a bridge:
55
65
  **Multi-Agent Support:** Multiple AI agents can connect simultaneously to the same RemNote knowledge base. Each agent
56
66
  gets its own MCP session while sharing the WebSocket bridge.
57
67
 
58
- **Remote Access:** By default, the server binds to localhost (127.0.0.1) for local AI agents. Cloud-based services like
59
- Claude Desktop and Claude Cowork require remote access—use tunneling tools like ngrok to expose the HTTP endpoint securely. The WebSocket
60
- connection always stays local for security. See [Remote Access Guide](docs/guides/remote-access.md) for setup.
68
+ **Remote Access:** By default, the server binds to localhost (127.0.0.1) for local AI agents. Claude Desktop and Claude
69
+ Cowork can use the bundled local MCPB extension when desktop extensions are enabled. Cloud-based clients, web/mobile
70
+ surfaces, and managed Claude deployments without local MCPB require remote access—use tunneling tools like ngrok to
71
+ expose the HTTP endpoint securely. The WebSocket connection always stays local for security. See
72
+ [Remote Access Guide](docs/guides/remote-access.md) for setup.
61
73
 
62
74
  ## Features
63
75
 
@@ -79,18 +91,20 @@ connection always stays local for security. See [Remote Access Guide](docs/guide
79
91
  npm install -g remnote-mcp-server
80
92
  ```
81
93
 
82
- The package installs both commands:
94
+ The package installs these commands:
83
95
 
84
96
  ```bash
85
97
  remnote-mcp-server --version
86
98
  remnote-cli --version
99
+ remnote-mcp-stdio --version
87
100
  ```
88
101
 
89
102
  ### 2. Install the RemNote Plugin
90
103
 
91
- Install the [RemNote Automation Bridge plugin](https://github.com/robert7/remnote-mcp-bridge) in your RemNote app.
92
- Currently available from GitHub; registration in the RemNote marketplace is pending approval. Configure the plugin
93
- to connect to `ws://127.0.0.1:3002`.
104
+ Install the official [MCP/OpenClaw Automation Bridge plugin](https://github.com/robert7/remnote-mcp-bridge) in your
105
+ RemNote app. If installing from the RemNote Marketplace, verify the plugin name and author; similarly named
106
+ `MCP Bridge` variants may be incompatible with this server and cause connection loops or `1008` disconnects. Configure
107
+ the plugin to connect to `ws://127.0.0.1:3002`.
94
108
 
95
109
  ### 3. Start the Server
96
110
 
@@ -101,7 +115,7 @@ remnote-mcp-server
101
115
  Expected output:
102
116
 
103
117
  ```text
104
- RemNote MCP Server v0.14.0 listening { wsPort: 3002, httpPort: 3001 }
118
+ RemNote MCP Server v0.14.1 listening { wsPort: 3002, httpPort: 3001 }
105
119
  ```
106
120
 
107
121
  Keep this terminal running.
@@ -109,10 +123,13 @@ Keep this terminal running.
109
123
  ### 4. Configure Your AI Client
110
124
 
111
125
  - [Configuration Guide](docs/guides/configuration.md) - Overview and generic setup
126
+ - [Codex TUI / Codex.app](docs/guides/configuration-codex.md) - HTTP MCP, stdio proxy, and `remnote-cli` skill setup
127
+ - [Claude Desktop / Cowork Local MCPB](docs/guides/configuration-claude-desktop-local-mcpb.md) - Preferred local desktop setup, no public HTTPS required
128
+ - [Claude Desktop / Cowork Remote Connector](docs/guides/configuration-claude-desktop-cowork.md) - Remote connector setup when local MCPB is not applicable
129
+ - [Claude Code CLI](docs/guides/configuration-claude-code-CLI.md) - Claude Code local MCP setup
112
130
  - [ChatGPT](docs/guides/configuration-chatgpt.md) - ChatGPT Apps configuration
113
- - [Claude Desktop / Cowork](docs/guides/configuration-claude-desktop-cowork.md) - Remote connector setup (requires remote access setup)
114
- - [Claude Code CLI](docs/guides/configuration-claude-code-CLI.md) - Detailed Claude Code CLI configuration
115
131
  - [Accomplish](docs/guides/configuration-accomplish.md) - Accomplish (Openwork) configuration
132
+ - [Generic stdio MCP clients](docs/guides/configuration.md#stdio-mcp-clients) - Use `remnote-mcp-stdio`
116
133
 
117
134
  ## Documentation
118
135
 
@@ -124,6 +141,7 @@ Keep this terminal running.
124
141
  \- Match server version to installed bridge plugin version (`0.x` semver)
125
142
  - **[Bridge Connection Lifecycle](https://github.com/robert7/remnote-mcp-bridge/blob/main/docs/guides/connection-lifecycle.md)** - Canonical bridge connect/retry behavior
126
143
  - **[Configuration Guide](docs/guides/configuration.md)** - Configure Claude Code CLI, Accomplish, and other clients
144
+ - **[Codex Configuration Guide](docs/guides/configuration-codex.md)** - Set up Codex TUI and Codex.app with RemNote
127
145
  - **[ChatGPT Configuration Guide](docs/guides/configuration-chatgpt.md)** - Set up ChatGPT Apps with your MCP server
128
146
  - **[Demo & Screenshots](docs/demo.md)** - See the server in action with different AI clients
129
147
 
@@ -132,7 +150,8 @@ Keep this terminal running.
132
150
  - **[CLI Options Reference](docs/guides/cli-options.md)** - Command-line options and environment variables
133
151
  - **[remnote-cli Command Reference](docs/guides/cli-command-reference.md)** - Shell command reference for the bundled CLI
134
152
  - **[MCP Tools Reference](docs/guides/tools-reference.md)** - Detailed reference for all 9 RemNote tools
135
- - **[Remote Access Setup](docs/guides/remote-access.md)** - Expose server for Claude Desktop / Cowork (ngrok, etc.)
153
+ - **[Remote Access Setup](docs/guides/remote-access.md)** - Expose server for cloud clients or remote connector flows
154
+ (ngrok, etc.)
136
155
 
137
156
  ### Help & Advanced
138
157
 
@@ -163,14 +182,21 @@ Tools that declare an `outputSchema` return MCP `structuredContent` plus a JSON
163
182
  See the [MCP tools specification](https://modelcontextprotocol.io/specification/2025-11-25/server/tools) for the
164
183
  protocol contract.
165
184
 
185
+ The server uses `@modelcontextprotocol/sdk` and supports current MCP protocol negotiation, including `2025-11-25`.
186
+ Do not confuse MCP protocol versions with `remnote-mcp-server` or bridge plugin package versions; package versions use
187
+ `0.x` semver and should usually match by minor line.
188
+
166
189
  See the [Tools Reference](docs/guides/tools-reference.md) for detailed usage and examples.
167
190
 
168
191
  ## Supported AI Clients
169
192
 
170
193
  - **[Claude Code CLI](https://claude.com/claude-code)** - Local terminal-based agent
171
- - **Claude Desktop / Cowork** - Remote connector clients (require [remote access](docs/guides/remote-access.md))
194
+ - **Codex TUI / Codex.app** - Local OpenAI coding agent clients
195
+ - **Claude Desktop / Cowork** - Local MCPB clients when desktop extensions are enabled, or remote connector clients
196
+ when local MCPB is not applicable
172
197
  - **[Accomplish](https://github.com/accomplish-ai/accomplish)** - Task-based MCP client (formerly Openwork)
173
198
  - **Any MCP client** supporting Streamable HTTP transport
199
+ - **Any local MCP client** supporting stdio transport through `remnote-mcp-stdio`
174
200
  - **Any local command runner** that can call `remnote-cli`
175
201
 
176
202
  ## Example Usage
@@ -253,7 +279,7 @@ See the [Troubleshooting Guide](docs/guides/troubleshooting.md) for detailed sol
253
279
  git clone https://github.com/robert7/remnote-mcp-server.git
254
280
  cd remnote-mcp-server
255
281
  ./link-cli.sh
256
- # Later, remove the local links for both remnote-mcp-server and remnote-cli:
282
+ # Later, remove the local links for package executables:
257
283
  ./unlink-cli.sh
258
284
  ```
259
285
 
@@ -274,8 +300,6 @@ For the canonical workflow for updating and running shared live integration cove
274
300
  ## Related Projects
275
301
 
276
302
  - [RemNote Automation Bridge](https://github.com/robert7/remnote-mcp-bridge) - Browser plugin for RemNote integration
277
- - [Legacy remnote-cli repository](https://github.com/robert7/remnote-cli) - Historical source; the maintained CLI now
278
- ships from this package
279
303
  - [Model Context Protocol](https://modelcontextprotocol.io/) - Open protocol for AI-application integration
280
304
 
281
305
  ## License
package/dist/cli.d.ts CHANGED
@@ -9,6 +9,11 @@ export interface CliOptions {
9
9
  requestLog?: string;
10
10
  responseLog?: string;
11
11
  }
12
+ export declare function getBundledMcpbPath(): string;
13
+ /**
14
+ * Handle utility commands that do not start the MCP server.
15
+ */
16
+ export declare function handleUtilityCommand(argv?: string[]): boolean;
12
17
  /**
13
18
  * Parse CLI arguments and return typed options
14
19
  */
package/dist/cli.js CHANGED
@@ -1,8 +1,23 @@
1
1
  import { Command } from 'commander';
2
2
  import { createRequire } from 'module';
3
+ import { fileURLToPath } from 'url';
3
4
  const require = createRequire(import.meta.url);
4
5
  const packageJson = require('../package.json');
5
6
  const validLogLevels = ['debug', 'info', 'warn', 'error'];
7
+ const MCPB_PATH_COMMAND = 'mcpb-path';
8
+ export function getBundledMcpbPath() {
9
+ return fileURLToPath(new URL('../mcpb/remnote-local/remnote-local.mcpb', import.meta.url));
10
+ }
11
+ /**
12
+ * Handle utility commands that do not start the MCP server.
13
+ */
14
+ export function handleUtilityCommand(argv = process.argv) {
15
+ if (argv[2] !== MCPB_PATH_COMMAND) {
16
+ return false;
17
+ }
18
+ console.log(getBundledMcpbPath());
19
+ return true;
20
+ }
6
21
  /**
7
22
  * Parse CLI arguments and return typed options
8
23
  */
@@ -12,6 +27,7 @@ export function parseCliArgs() {
12
27
  .name('remnote-mcp-server')
13
28
  .description('MCP server bridge for RemNote knowledge base')
14
29
  .version(packageJson.version)
30
+ .addHelpText('after', '\nCommands:\n mcpb-path Print the bundled Claude Desktop MCPB extension path')
15
31
  .option('--ws-port <number>', 'WebSocket port (default: 3002, env: REMNOTE_WS_PORT)', parsePort)
16
32
  .option('--http-port <number>', 'HTTP MCP port (default: 3001, env: REMNOTE_HTTP_PORT)', parsePort)
17
33
  .option('--http-host <host>', 'HTTP server bind address (default: 127.0.0.1, env: REMNOTE_HTTP_HOST). Use 0.0.0.0 for Docker/VPS deployments', validateHost)
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { createRequire } from 'module';
3
3
  import { WebSocketServer } from './websocket-server.js';
4
4
  import { HttpMcpServer } from './http-server.js';
5
- import { parseCliArgs } from './cli.js';
5
+ import { handleUtilityCommand, parseCliArgs } from './cli.js';
6
6
  import { getConfig } from './config.js';
7
7
  import { createLogger, ensureLogDirectory, createRequestResponseLogger } from './logger.js';
8
8
  const require = createRequire(import.meta.url);
@@ -69,6 +69,9 @@ async function main() {
69
69
  process.on('SIGINT', shutdown);
70
70
  process.on('SIGTERM', shutdown);
71
71
  }
72
+ if (handleUtilityCommand()) {
73
+ process.exit(0);
74
+ }
72
75
  main().catch((error) => {
73
76
  // Pre-logger error handling
74
77
  console.error('[MCP Server] Fatal error:', error);
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -19,7 +19,7 @@ export class McpServerClient {
19
19
  clientInfo;
20
20
  client = null;
21
21
  transport = null;
22
- constructor(mcpUrl, clientInfo = { name: 'remnote-cli', version: '0.14.0' }) {
22
+ constructor(mcpUrl, clientInfo = { name: 'remnote-cli', version: '0.14.1' }) {
23
23
  this.mcpUrl = normalizeMcpUrl(mcpUrl);
24
24
  this.clientInfo = clientInfo;
25
25
  }
@@ -1,5 +1,6 @@
1
1
  import type { Logger } from './logger.js';
2
2
  export declare const REQUEST_TIMEOUT_MS = 15000;
3
+ export declare const HELLO_TIMEOUT_MS = 2000;
3
4
  export declare class WebSocketServer {
4
5
  private wss;
5
6
  private client;
@@ -10,6 +11,8 @@ export declare class WebSocketServer {
10
11
  private responseLogger;
11
12
  private serverVersion;
12
13
  private bridgeVersion;
14
+ private clientAccepted;
15
+ private helloTimeout;
13
16
  private pendingRequests;
14
17
  private connectCallbacks;
15
18
  private disconnectCallbacks;
@@ -23,4 +26,6 @@ export declare class WebSocketServer {
23
26
  onClientConnect(callback: () => void): void;
24
27
  onClientDisconnect(callback: () => void): void;
25
28
  private handleMessage;
29
+ private rejectBridge;
30
+ private clearHelloTimeout;
26
31
  }
@@ -2,6 +2,10 @@ import { WebSocketServer as WSServer, WebSocket } from 'ws';
2
2
  import { randomUUID } from 'crypto';
3
3
  import { checkVersionCompatibility } from './version-compat.js';
4
4
  export const REQUEST_TIMEOUT_MS = 15000;
5
+ export const HELLO_TIMEOUT_MS = 2000;
6
+ const POLICY_VIOLATION = 1008;
7
+ const INCOMPATIBLE_BRIDGE_REASON = 'Wrong/incompatible RemNote plugin installed. Install MCP/OpenClaw Automation Bridge matching server.';
8
+ const BRIDGE_REJECTION_LOG_PREFIX = `Rejecting bridge connection: ${INCOMPATIBLE_BRIDGE_REASON}`;
5
9
  export class WebSocketServer {
6
10
  wss = null;
7
11
  client = null;
@@ -12,6 +16,8 @@ export class WebSocketServer {
12
16
  responseLogger = null;
13
17
  serverVersion;
14
18
  bridgeVersion = null;
19
+ clientAccepted = false;
20
+ helloTimeout = null;
15
21
  pendingRequests = new Map();
16
22
  connectCallbacks = [];
17
23
  disconnectCallbacks = [];
@@ -37,11 +43,18 @@ export class WebSocketServer {
37
43
  // Only allow single client connection
38
44
  if (this.client && this.client.readyState === WebSocket.OPEN) {
39
45
  this.logger.warn('Rejecting connection: client already connected');
40
- ws.close(1008, 'Only one client allowed');
46
+ ws.close(POLICY_VIOLATION, 'Only one client allowed');
41
47
  return;
42
48
  }
43
49
  this.client = ws;
50
+ this.clientAccepted = false;
44
51
  this.logger.info('WebSocket client connected');
52
+ this.helloTimeout = setTimeout(() => {
53
+ if (this.client === ws && !this.clientAccepted && ws.readyState === WebSocket.OPEN) {
54
+ this.logger.warn(`${BRIDGE_REJECTION_LOG_PREFIX} Detail: hello timeout.`);
55
+ ws.close(POLICY_VIOLATION, INCOMPATIBLE_BRIDGE_REASON);
56
+ }
57
+ }, HELLO_TIMEOUT_MS);
45
58
  setImmediate(() => {
46
59
  if (ws.readyState !== WebSocket.OPEN) {
47
60
  return;
@@ -52,7 +65,6 @@ export class WebSocketServer {
52
65
  version: this.serverVersion,
53
66
  }));
54
67
  });
55
- this.connectCallbacks.forEach((cb) => cb());
56
68
  ws.on('message', (data) => {
57
69
  try {
58
70
  this.handleMessage(data.toString());
@@ -63,15 +75,22 @@ export class WebSocketServer {
63
75
  });
64
76
  ws.on('close', () => {
65
77
  this.logger.info('WebSocket client disconnected');
66
- this.client = null;
67
- this.bridgeVersion = null;
78
+ const wasAccepted = this.clientAccepted;
79
+ if (this.client === ws) {
80
+ this.client = null;
81
+ this.bridgeVersion = null;
82
+ this.clientAccepted = false;
83
+ this.clearHelloTimeout();
84
+ }
68
85
  // Reject all pending requests
69
86
  for (const [_id, pending] of this.pendingRequests.entries()) {
70
87
  clearTimeout(pending.timeout);
71
88
  pending.reject(new Error('Connection lost'));
72
89
  }
73
90
  this.pendingRequests.clear();
74
- this.disconnectCallbacks.forEach((cb) => cb());
91
+ if (wasAccepted) {
92
+ this.disconnectCallbacks.forEach((cb) => cb());
93
+ }
75
94
  });
76
95
  ws.on('error', (error) => {
77
96
  this.logger.error({ error }, 'WebSocket client error');
@@ -84,6 +103,9 @@ export class WebSocketServer {
84
103
  if (this.client) {
85
104
  this.client.close();
86
105
  this.client = null;
106
+ this.bridgeVersion = null;
107
+ this.clientAccepted = false;
108
+ this.clearHelloTimeout();
87
109
  }
88
110
  if (this.wss) {
89
111
  this.wss.close(() => {
@@ -98,7 +120,7 @@ export class WebSocketServer {
98
120
  });
99
121
  }
100
122
  async sendRequest(action, payload) {
101
- if (!this.client || this.client.readyState !== WebSocket.OPEN) {
123
+ if (!this.isConnected()) {
102
124
  throw new Error('RemNote plugin not connected. Please ensure the plugin is installed and running.');
103
125
  }
104
126
  const id = randomUUID();
@@ -152,7 +174,7 @@ export class WebSocketServer {
152
174
  });
153
175
  }
154
176
  isConnected() {
155
- return this.client !== null && this.client.readyState === WebSocket.OPEN;
177
+ return this.client !== null && this.client.readyState === WebSocket.OPEN && this.clientAccepted;
156
178
  }
157
179
  getBridgeVersion() {
158
180
  return this.bridgeVersion;
@@ -174,12 +196,20 @@ export class WebSocketServer {
174
196
  }, 'Received message');
175
197
  // Handle hello from bridge plugin
176
198
  if ('type' in message && message.type === 'hello') {
177
- this.bridgeVersion = message.version;
178
- this.logger.info({ bridgeVersion: message.version }, 'Bridge identified');
199
+ if (typeof message.version !== 'string') {
200
+ this.rejectBridge('Bridge hello missing version', INCOMPATIBLE_BRIDGE_REASON);
201
+ return;
202
+ }
179
203
  const warning = checkVersionCompatibility(this.serverVersion, message.version);
180
204
  if (warning) {
181
- this.logger.warn({ warning }, 'Bridge version compatibility warning');
205
+ this.rejectBridge(warning, INCOMPATIBLE_BRIDGE_REASON);
206
+ return;
182
207
  }
208
+ this.bridgeVersion = message.version;
209
+ this.clientAccepted = true;
210
+ this.clearHelloTimeout();
211
+ this.logger.info({ bridgeVersion: message.version }, 'Bridge identified');
212
+ this.connectCallbacks.forEach((cb) => cb());
183
213
  return;
184
214
  }
185
215
  // Handle pong response to ping
@@ -195,6 +225,10 @@ export class WebSocketServer {
195
225
  }
196
226
  // Handle response to our request
197
227
  if ('id' in message) {
228
+ if (!this.clientAccepted) {
229
+ this.rejectBridge('Bridge sent response before compatible hello', INCOMPATIBLE_BRIDGE_REASON);
230
+ return;
231
+ }
198
232
  const response = message;
199
233
  const pending = this.pendingRequests.get(response.id);
200
234
  if (pending) {
@@ -211,10 +245,30 @@ export class WebSocketServer {
211
245
  this.logger.warn({ id: response.id }, 'Unknown request ID');
212
246
  }
213
247
  }
248
+ if (!this.clientAccepted) {
249
+ this.rejectBridge('Bridge sent message before compatible hello', INCOMPATIBLE_BRIDGE_REASON);
250
+ }
214
251
  }
215
252
  catch (error) {
216
253
  this.logger.error({ error }, 'Error parsing message');
254
+ if (!this.clientAccepted) {
255
+ this.rejectBridge('Bridge sent invalid JSON before compatible hello', INCOMPATIBLE_BRIDGE_REASON);
256
+ }
257
+ }
258
+ }
259
+ rejectBridge(detail, closeReason) {
260
+ this.logger.warn({ detail }, BRIDGE_REJECTION_LOG_PREFIX);
261
+ this.clearHelloTimeout();
262
+ if (this.client && this.client.readyState === WebSocket.OPEN) {
263
+ this.client.close(POLICY_VIOLATION, closeReason);
264
+ }
265
+ }
266
+ clearHelloTimeout() {
267
+ if (!this.helloTimeout) {
268
+ return;
217
269
  }
270
+ clearTimeout(this.helloTimeout);
271
+ this.helloTimeout = null;
218
272
  }
219
273
  }
220
274
  //# sourceMappingURL=websocket-server.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"websocket-server.js","sourceRoot":"","sources":["../src/websocket-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"websocket-server.js","sourceRoot":"","sources":["../src/websocket-server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ node_modules/.cache/
2
+ *.log
3
+ coverage/
4
+ dist/
5
+ test/
@@ -0,0 +1,26 @@
1
+ # RemNote Local MCPB
2
+
3
+ Claude Desktop extension that exposes a local `remnote-mcp-server` to Claude Desktop and eligible Claude Cowork
4
+ desktop sessions without a public HTTPS tunnel.
5
+
6
+ ## Usage
7
+
8
+ 1. Install and start `remnote-mcp-server`.
9
+ 2. Open RemNote with the Automation Bridge plugin enabled and connected.
10
+ 3. Install this extension's `.mcpb` file in Claude Desktop.
11
+ 4. Keep the default MCP URL unless your server uses a custom port:
12
+
13
+ ```text
14
+ http://127.0.0.1:3001/mcp
15
+ ```
16
+
17
+ This extension does not start or supervise `remnote-mcp-server`. It is a stdio proxy that forwards Claude Desktop and
18
+ eligible Claude Cowork tool calls to the local Streamable HTTP endpoint.
19
+
20
+ ## Installed Package Path
21
+
22
+ When installed from npm, print the bundled `.mcpb` path with:
23
+
24
+ ```bash
25
+ remnote-mcp-server mcpb-path
26
+ ```
@@ -0,0 +1,87 @@
1
+ {
2
+ "manifest_version": "0.3",
3
+ "name": "remnote-local",
4
+ "display_name": "RemNote Local",
5
+ "version": "0.14.1",
6
+ "description": "Use a locally running RemNote MCP Server from Claude Desktop or Cowork without a public HTTPS tunnel.",
7
+ "long_description": "RemNote Local is a Claude Desktop extension that exposes RemNote MCP tools over stdio and forwards calls to a local remnote-mcp-server Streamable HTTP endpoint. It can also be used by Claude Cowork in Claude Desktop when desktop extensions are enabled. Start remnote-mcp-server and keep the RemNote Automation Bridge plugin connected before using the tools.",
8
+ "author": {
9
+ "name": "Robert Spiegel",
10
+ "email": "nightingale7@gmail.com"
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/robert7/remnote-mcp-server.git"
15
+ },
16
+ "homepage": "https://github.com/robert7/remnote-mcp-server",
17
+ "documentation": "https://github.com/robert7/remnote-mcp-server/tree/main/docs/guides",
18
+ "support": "https://github.com/robert7/remnote-mcp-server/issues",
19
+ "server": {
20
+ "type": "node",
21
+ "entry_point": "server/index.js",
22
+ "mcp_config": {
23
+ "command": "node",
24
+ "args": ["${__dirname}/server/index.js"],
25
+ "env": {
26
+ "REMNOTE_MCP_URL": "${user_config.mcp_url}"
27
+ }
28
+ }
29
+ },
30
+ "tools": [
31
+ {
32
+ "name": "remnote_create_note",
33
+ "description": "Create a new note in RemNote."
34
+ },
35
+ {
36
+ "name": "remnote_search",
37
+ "description": "Search the RemNote knowledge base."
38
+ },
39
+ {
40
+ "name": "remnote_search_by_tag",
41
+ "description": "Find notes by tag."
42
+ },
43
+ {
44
+ "name": "remnote_read_note",
45
+ "description": "Read a specific note from RemNote by Rem ID."
46
+ },
47
+ {
48
+ "name": "remnote_update_note",
49
+ "description": "Update an existing note in RemNote."
50
+ },
51
+ {
52
+ "name": "remnote_append_journal",
53
+ "description": "Append content to today's daily document in RemNote."
54
+ },
55
+ {
56
+ "name": "remnote_read_table",
57
+ "description": "Read an Advanced Table from RemNote."
58
+ },
59
+ {
60
+ "name": "remnote_get_playbook",
61
+ "description": "Get an operations playbook for MCP agents."
62
+ },
63
+ {
64
+ "name": "remnote_status",
65
+ "description": "Check bridge connection health and write-policy capabilities."
66
+ }
67
+ ],
68
+ "tools_generated": true,
69
+ "keywords": ["remnote", "mcp", "notes", "knowledge-base", "local"],
70
+ "license": "MIT",
71
+ "compatibility": {
72
+ "claude_desktop": ">=1.0.0",
73
+ "platforms": ["darwin", "win32", "linux"],
74
+ "runtimes": {
75
+ "node": ">=20.0.0"
76
+ }
77
+ },
78
+ "user_config": {
79
+ "mcp_url": {
80
+ "type": "string",
81
+ "title": "Local MCP URL",
82
+ "description": "Local remnote-mcp-server Streamable HTTP endpoint.",
83
+ "default": "http://127.0.0.1:3001/mcp",
84
+ "required": true
85
+ }
86
+ }
87
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "remnote-local-mcpb",
3
+ "version": "0.14.2",
4
+ "description": "Claude Desktop MCPB stdio proxy for a local RemNote MCP Server",
5
+ "type": "module",
6
+ "private": true,
7
+ "main": "server/index.js",
8
+ "dependencies": {
9
+ "@modelcontextprotocol/sdk": "^1.29.0"
10
+ }
11
+ }
@@ -0,0 +1,300 @@
1
+ #!/usr/bin/env node
2
+
3
+ import process from 'node:process';
4
+ import { realpathSync } from 'node:fs';
5
+ import { fileURLToPath, URL, pathToFileURL } from 'node:url';
6
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
7
+ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
8
+ import { Server } from '@modelcontextprotocol/sdk/server/index.js';
9
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
10
+ import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
11
+
12
+ export const DEFAULT_MCP_URL = 'http://127.0.0.1:3001/mcp';
13
+ export const SERVER_INFO = { name: 'remnote-mcp-stdio', version: '0.14.1' };
14
+
15
+ export const FALLBACK_TOOLS = [
16
+ {
17
+ name: 'remnote_create_note',
18
+ description:
19
+ 'Create a new note in RemNote with optional content, parent, and tags. Supports hierarchical markdown in content and flashcard syntax.',
20
+ inputSchema: {
21
+ type: 'object',
22
+ properties: {
23
+ title: { type: 'string', description: 'The title of the note' },
24
+ content: { type: 'string', description: 'Content as plain text or hierarchical markdown' },
25
+ parentId: { type: 'string', description: 'Parent Rem ID' },
26
+ tags: { type: 'array', items: { type: 'string' }, description: 'Tags to apply' },
27
+ },
28
+ },
29
+ },
30
+ {
31
+ name: 'remnote_search',
32
+ description: 'Search the RemNote knowledge base.',
33
+ inputSchema: {
34
+ type: 'object',
35
+ properties: {
36
+ query: { type: 'string', description: 'Search query text' },
37
+ limit: { type: 'number', description: 'Maximum results' },
38
+ includeContent: { type: 'string', enum: ['none', 'markdown', 'structured'] },
39
+ depth: { type: 'number', description: 'Depth of child hierarchy to render' },
40
+ childLimit: { type: 'number', description: 'Maximum children per level' },
41
+ maxContentLength: { type: 'number', description: 'Maximum rendered content length' },
42
+ },
43
+ required: ['query'],
44
+ },
45
+ },
46
+ {
47
+ name: 'remnote_search_by_tag',
48
+ description: 'Find notes by tag.',
49
+ inputSchema: {
50
+ type: 'object',
51
+ properties: {
52
+ tag: { type: 'string', description: 'Tag name to search' },
53
+ limit: { type: 'number', description: 'Maximum results' },
54
+ includeContent: { type: 'string', enum: ['none', 'markdown', 'structured'] },
55
+ depth: { type: 'number', description: 'Depth of child hierarchy to render' },
56
+ childLimit: { type: 'number', description: 'Maximum children per level' },
57
+ maxContentLength: { type: 'number', description: 'Maximum rendered content length' },
58
+ },
59
+ required: ['tag'],
60
+ },
61
+ },
62
+ {
63
+ name: 'remnote_read_note',
64
+ description: 'Read a specific note from RemNote by its Rem ID.',
65
+ inputSchema: {
66
+ type: 'object',
67
+ properties: {
68
+ remId: { type: 'string', description: 'The Rem ID to read' },
69
+ depth: { type: 'number', description: 'Depth of child hierarchy to render' },
70
+ includeContent: { type: 'string', enum: ['none', 'markdown', 'structured'] },
71
+ childLimit: { type: 'number', description: 'Maximum children per level' },
72
+ maxContentLength: { type: 'number', description: 'Maximum rendered content length' },
73
+ },
74
+ required: ['remId'],
75
+ },
76
+ },
77
+ {
78
+ name: 'remnote_update_note',
79
+ description: 'Update an existing note in RemNote.',
80
+ inputSchema: {
81
+ type: 'object',
82
+ properties: {
83
+ remId: { type: 'string', description: 'The Rem ID to update' },
84
+ title: { type: 'string', description: 'New title' },
85
+ appendContent: { type: 'string', description: 'Content to append as children' },
86
+ replaceContent: { type: 'string', description: 'Content to replace direct children' },
87
+ addTags: { type: 'array', items: { type: 'string' }, description: 'Tags to add' },
88
+ removeTags: { type: 'array', items: { type: 'string' }, description: 'Tags to remove' },
89
+ },
90
+ required: ['remId'],
91
+ },
92
+ },
93
+ {
94
+ name: 'remnote_append_journal',
95
+ description: "Append content to today's daily document in RemNote.",
96
+ inputSchema: {
97
+ type: 'object',
98
+ properties: {
99
+ content: { type: 'string', description: "Content to append to today's daily document" },
100
+ timestamp: { type: 'boolean', description: 'Include timestamp' },
101
+ },
102
+ required: ['content'],
103
+ },
104
+ },
105
+ {
106
+ name: 'remnote_read_table',
107
+ description: 'Read an Advanced Table from RemNote by exact title or Rem ID.',
108
+ inputSchema: {
109
+ type: 'object',
110
+ properties: {
111
+ tableRemId: { type: 'string', description: 'Table Rem ID' },
112
+ tableTitle: { type: 'string', description: 'Exact Advanced Table title' },
113
+ limit: { type: 'number', description: 'Maximum rows to return' },
114
+ offset: { type: 'number', description: '0-based row offset for pagination' },
115
+ propertyFilter: {
116
+ type: 'array',
117
+ items: { type: 'string' },
118
+ description: 'Only return these property/column names',
119
+ },
120
+ },
121
+ },
122
+ },
123
+ {
124
+ name: 'remnote_get_playbook',
125
+ description: 'Get an operations playbook for MCP agents.',
126
+ inputSchema: { type: 'object', properties: {} },
127
+ },
128
+ {
129
+ name: 'remnote_status',
130
+ description:
131
+ 'Check bridge connection health, compatibility warnings, and write-policy capabilities.',
132
+ inputSchema: { type: 'object', properties: {} },
133
+ },
134
+ ];
135
+
136
+ export function normalizeMcpUrl(value) {
137
+ const trimmed = String(value || DEFAULT_MCP_URL).trim();
138
+ if (trimmed.endsWith('/mcp')) {
139
+ return trimmed;
140
+ }
141
+ return `${trimmed.replace(/\/+$/, '')}/mcp`;
142
+ }
143
+
144
+ export function createSdkHttpClient(mcpUrl, clientInfo = SERVER_INFO) {
145
+ const transport = new StreamableHTTPClientTransport(new URL(mcpUrl));
146
+ const client = new Client(clientInfo);
147
+ return { client, transport };
148
+ }
149
+
150
+ export class RemNoteLocalProxy {
151
+ constructor(options = {}) {
152
+ this.mcpUrl = normalizeMcpUrl(options.mcpUrl ?? process.env.REMNOTE_MCP_URL);
153
+ this.createClient = options.createClient ?? createSdkHttpClient;
154
+ }
155
+
156
+ async listTools() {
157
+ try {
158
+ return await this.withClient((client) => client.listTools());
159
+ } catch {
160
+ return { tools: FALLBACK_TOOLS };
161
+ }
162
+ }
163
+
164
+ async callTool(params) {
165
+ try {
166
+ return await this.withClient((client) => client.callTool(params));
167
+ } catch (error) {
168
+ return {
169
+ isError: true,
170
+ content: [{ type: 'text', text: this.formatConnectionError(error) }],
171
+ };
172
+ }
173
+ }
174
+
175
+ registerHandlers(server) {
176
+ server.setRequestHandler(ListToolsRequestSchema, async () => this.listTools());
177
+ server.setRequestHandler(CallToolRequestSchema, async (request) =>
178
+ this.callTool({
179
+ name: request.params.name,
180
+ arguments: request.params.arguments ?? {},
181
+ })
182
+ );
183
+ }
184
+
185
+ async withClient(operation) {
186
+ const { client, transport } = this.createClient(this.mcpUrl, SERVER_INFO);
187
+
188
+ try {
189
+ await client.connect(transport);
190
+ return await operation(client);
191
+ } finally {
192
+ await closeBestEffort(transport, client);
193
+ }
194
+ }
195
+
196
+ formatConnectionError(error) {
197
+ const detail = error instanceof Error ? error.message : String(error);
198
+ return [
199
+ `Cannot connect to local RemNote MCP Server at ${this.mcpUrl}.`,
200
+ 'Start remnote-mcp-server, open RemNote, and ensure the Automation Bridge plugin is connected.',
201
+ `Details: ${detail}`,
202
+ ].join(' ');
203
+ }
204
+ }
205
+
206
+ export function createStdioServer(options = {}) {
207
+ const server = new Server(SERVER_INFO, { capabilities: { tools: {} } });
208
+ const proxy = new RemNoteLocalProxy(options);
209
+ proxy.registerHandlers(server);
210
+ return server;
211
+ }
212
+
213
+ export async function run() {
214
+ const server = createStdioServer();
215
+ await server.connect(new StdioServerTransport());
216
+ }
217
+
218
+ export function formatUsage() {
219
+ return [
220
+ 'remnote-mcp-stdio - stdio MCP proxy for a local RemNote MCP Server',
221
+ '',
222
+ 'Usage:',
223
+ ' remnote-mcp-stdio Run stdio MCP transport for an MCP client',
224
+ ' remnote-mcp-stdio --help, -h Print this help',
225
+ ' remnote-mcp-stdio --version, -V Print version',
226
+ '',
227
+ 'This command is normally launched by a stdio MCP client.',
228
+ 'Start remnote-mcp-server separately first, then let the RemNote Automation Bridge connect to it.',
229
+ `Default target: ${DEFAULT_MCP_URL}`,
230
+ '',
231
+ 'Environment:',
232
+ ' REMNOTE_MCP_URL Override the local MCP endpoint',
233
+ ].join('\n');
234
+ }
235
+
236
+ export function handleUtilityCommand(argv = process.argv) {
237
+ if (argv.includes('--version') || argv.includes('-V') || argv.includes('-v')) {
238
+ process.stdout.write(`${SERVER_INFO.version}\n`);
239
+ return true;
240
+ }
241
+
242
+ if (argv.includes('--help') || argv.includes('-h')) {
243
+ process.stdout.write(`${formatUsage()}\n`);
244
+ return true;
245
+ }
246
+
247
+ return false;
248
+ }
249
+
250
+ export function isInteractiveTerminalInvocation(
251
+ argv = process.argv,
252
+ stdin = process.stdin,
253
+ stdout = process.stdout
254
+ ) {
255
+ return argv.length <= 2 && Boolean(stdin.isTTY) && Boolean(stdout.isTTY);
256
+ }
257
+
258
+ export function isMainModule(argv = process.argv, moduleUrl = import.meta.url) {
259
+ if (!argv[1]) {
260
+ return false;
261
+ }
262
+
263
+ try {
264
+ return realpathSync(argv[1]) === realpathSync(fileURLToPath(moduleUrl));
265
+ } catch {
266
+ return pathToFileURL(argv[1]).href === moduleUrl;
267
+ }
268
+ }
269
+
270
+ async function closeBestEffort(transport, client) {
271
+ try {
272
+ if (typeof transport.terminateSession === 'function') {
273
+ await transport.terminateSession();
274
+ }
275
+ } catch {
276
+ // Best-effort cleanup: the proxy process can continue serving future calls.
277
+ }
278
+
279
+ try {
280
+ await client.close();
281
+ } catch {
282
+ // Best-effort cleanup: failed closes should not mask the original operation result.
283
+ }
284
+ }
285
+
286
+ if (isMainModule()) {
287
+ if (handleUtilityCommand()) {
288
+ process.exit(0);
289
+ }
290
+
291
+ if (isInteractiveTerminalInvocation()) {
292
+ process.stderr.write(`${formatUsage()}\n`);
293
+ process.exit(1);
294
+ }
295
+
296
+ run().catch((error) => {
297
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
298
+ process.exit(1);
299
+ });
300
+ }
package/package.json CHANGED
@@ -1,15 +1,17 @@
1
1
  {
2
2
  "name": "remnote-mcp-server",
3
- "version": "0.14.0",
3
+ "version": "0.14.2",
4
4
  "description": "MCP server bridge for RemNote knowledge base",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
7
7
  "bin": {
8
8
  "remnote-mcp-server": "dist/index.js",
9
- "remnote-cli": "dist/remnote-cli/index.js"
9
+ "remnote-cli": "dist/remnote-cli/index.js",
10
+ "remnote-mcp-stdio": "mcpb/remnote-local/server/index.js"
10
11
  },
11
12
  "scripts": {
12
- "build": "tsc && node scripts/chmod-bins.mjs",
13
+ "build": "tsc && node scripts/chmod-bins.mjs && node scripts/build-mcpb.mjs",
14
+ "build:mcpb": "node scripts/build-mcpb.mjs",
13
15
  "dev": "tsx watch src/index.ts",
14
16
  "start": "node dist/index.js",
15
17
  "typecheck": "tsc --noEmit",
@@ -19,12 +21,13 @@
19
21
  "test:coverage": "vitest run --coverage",
20
22
  "test:integration": "./run-integration-test.sh",
21
23
  "test:integration:mcp": "tsx test/integration/run-integration.ts",
24
+ "test:integration:mcpb": "tsx test/integration/run-integration.ts --transport mcpb",
22
25
  "test:integration:cli": "tsx test/integration/cli/run-integration.ts",
23
26
  "test:ui": "vitest --ui",
24
- "lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\"",
25
- "lint:fix": "eslint \"src/**/*.ts\" \"test/**/*.ts\" --fix",
26
- "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
27
- "format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"",
27
+ "lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\" \"mcpb/**/*.js\" \"scripts/**/*.mjs\"",
28
+ "lint:fix": "eslint \"src/**/*.ts\" \"test/**/*.ts\" \"mcpb/**/*.js\" \"scripts/**/*.mjs\" --fix",
29
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"mcpb/**/*.js\" \"mcpb/**/*.json\" \"mcpb/**/*.md\" \"scripts/**/*.mjs\"",
30
+ "format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\" \"mcpb/**/*.js\" \"mcpb/**/*.json\" \"mcpb/**/*.md\" \"scripts/**/*.mjs\"",
28
31
  "quality": "./code-quality.sh",
29
32
  "precommit": "./code-quality.sh"
30
33
  },
@@ -39,10 +42,11 @@
39
42
  "websocket",
40
43
  "bridge"
41
44
  ],
42
- "author": "nightingale7 <nightingale7@gmail.com>",
45
+ "author": "Robert Spiegel <nightingale7@gmail.com>",
43
46
  "license": "MIT",
44
47
  "files": [
45
48
  "dist/",
49
+ "mcpb/",
46
50
  "README.md",
47
51
  "LICENSE",
48
52
  "CHANGELOG.md"