remnote-mcp-server 0.14.0 → 0.14.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/CHANGELOG.md CHANGED
@@ -7,6 +7,30 @@ Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.14.1] - 2026-05-08
11
+
12
+ ### Added
13
+
14
+ - Added a `remnote-local` MCPB package for Claude Desktop that proxies stdio MCP calls to a locally running
15
+ `remnote-mcp-server` Streamable HTTP endpoint without public HTTPS, including setup docs, screenshots, and official
16
+ MCPB references.
17
+ - Added `remnote-mcp-server mcpb-path` to print the bundled Claude Desktop extension path after npm installation.
18
+ - Added the `remnote-mcp-stdio` executable for local MCP clients that consume stdio servers, including help/version
19
+ output and smoke-test commands in the configuration guide.
20
+ - Added Codex TUI and Codex.app configuration documentation covering Streamable HTTP MCP, `remnote-mcp-stdio`, and
21
+ `remnote-cli` skill setup.
22
+ - Added MCP protocol compatibility guidance clarifying that `2025-11-25` initialize requests are supported and separate
23
+ from bridge/server package versions.
24
+ - Added clearer stdio proxy prerequisites and cross-links between the generic stdio MCP client section and the Codex
25
+ stdio setup example.
26
+
27
+ ### Changed
28
+
29
+ - Reordered the README AI client setup list to include Codex and prioritize the local Claude Desktop MCPB path before
30
+ remote connector setup.
31
+ - Updated documentation and agent repo maps to reflect that the old standalone `remnote-cli` repository is
32
+ discontinued and the maintained CLI lives in this package.
33
+
10
34
  ## [0.14.0] - 2026-05-07
11
35
 
12
36
  ### Added
package/README.md CHANGED
@@ -15,9 +15,9 @@ plugin](https://github.com/robert7/remnote-mcp-bridge).
15
15
 
16
16
  The RemNote MCP Server enables AI assistants like Claude Code to interact directly with your RemNote knowledge base
17
17
  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.
18
+ for local scripts and coding harnesses, and `remnote-mcp-stdio`, a stdio MCP proxy for clients that cannot consume
19
+ Streamable HTTP directly. Create notes, hierarchical markdown trees, and RemNote-native flashcards; search and read
20
+ your knowledge base; update existing notes; and maintain your daily journal through MCP tools or shell commands.
21
21
 
22
22
  ## Demo
23
23
 
@@ -29,10 +29,11 @@ This system consists of **two separate runtime components** that work together:
29
29
 
30
30
  1. **[RemNote Automation Bridge](https://github.com/robert7/remnote-mcp-bridge)** - A RemNote plugin that runs in your
31
31
  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
32
+ 2. **RemNote MCP Server** (this project) - A standalone server package that provides `remnote-mcp-server` for MCP
33
+ HTTP clients, `remnote-mcp-stdio` for stdio MCP clients, and `remnote-cli` for command-line workflows
34
34
 
35
- The `remnote-cli` command is not a second server. It calls the MCP endpoint exposed by `remnote-mcp-server`.
35
+ The `remnote-cli` and `remnote-mcp-stdio` commands are not second RemNote-facing servers. They call the MCP endpoint
36
+ exposed by `remnote-mcp-server`.
36
37
 
37
38
  For the detailed bridge connection lifecycle, retry phases, and wake-up triggers, use the bridge repo as the source of
38
39
  truth: [Connection Lifecycle Guide](https://github.com/robert7/remnote-mcp-bridge/blob/main/docs/guides/connection-lifecycle.md).
@@ -41,12 +42,14 @@ truth: [Connection Lifecycle Guide](https://github.com/robert7/remnote-mcp-bridg
41
42
 
42
43
  ```text
43
44
  AI agents (HTTP) -> MCP HTTP Server :3001 -> WebSocket Server :3002 -> RemNote Plugin -> RemNote
45
+ AI agents (stdio) -> remnote-mcp-stdio -> MCP HTTP Server :3001 -> WebSocket Server :3002 -> RemNote Plugin -> RemNote
44
46
  CLI commands -> remnote-cli -> MCP HTTP Server :3001 -> WebSocket Server :3002 -> RemNote Plugin -> RemNote
45
47
  ```
46
48
 
47
49
  The server acts as a bridge:
48
50
 
49
51
  - Communicates with AI agents via Streamable HTTP transport (MCP protocol) - supports both local and remote access
52
+ - Provides `remnote-mcp-stdio` as a local stdio MCP proxy for clients that need stdio transport
50
53
  - Provides `remnote-cli` as a bundled command-line MCP client for local automation
51
54
  - HTTP server (port 3001) manages MCP sessions for multiple concurrent agents
52
55
  - WebSocket server (port 3002) connects to the RemNote browser plugin
@@ -79,11 +82,12 @@ connection always stays local for security. See [Remote Access Guide](docs/guide
79
82
  npm install -g remnote-mcp-server
80
83
  ```
81
84
 
82
- The package installs both commands:
85
+ The package installs these commands:
83
86
 
84
87
  ```bash
85
88
  remnote-mcp-server --version
86
89
  remnote-cli --version
90
+ remnote-mcp-stdio --version
87
91
  ```
88
92
 
89
93
  ### 2. Install the RemNote Plugin
@@ -101,7 +105,7 @@ remnote-mcp-server
101
105
  Expected output:
102
106
 
103
107
  ```text
104
- RemNote MCP Server v0.14.0 listening { wsPort: 3002, httpPort: 3001 }
108
+ RemNote MCP Server v0.14.1 listening { wsPort: 3002, httpPort: 3001 }
105
109
  ```
106
110
 
107
111
  Keep this terminal running.
@@ -109,10 +113,13 @@ Keep this terminal running.
109
113
  ### 4. Configure Your AI Client
110
114
 
111
115
  - [Configuration Guide](docs/guides/configuration.md) - Overview and generic setup
116
+ - [Codex TUI / Codex.app](docs/guides/configuration-codex.md) - HTTP MCP, stdio proxy, and `remnote-cli` skill setup
117
+ - [Claude Desktop Local MCPB](docs/guides/configuration-claude-desktop-local-mcpb.md) - Preferred local Claude Desktop setup, no public HTTPS required
118
+ - [Claude Desktop / Cowork](docs/guides/configuration-claude-desktop-cowork.md) - Remote connector setup when local MCPB is not applicable
119
+ - [Claude Code CLI](docs/guides/configuration-claude-code-CLI.md) - Claude Code local MCP setup
112
120
  - [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
121
  - [Accomplish](docs/guides/configuration-accomplish.md) - Accomplish (Openwork) configuration
122
+ - [Generic stdio MCP clients](docs/guides/configuration.md#stdio-mcp-clients) - Use `remnote-mcp-stdio`
116
123
 
117
124
  ## Documentation
118
125
 
@@ -124,6 +131,7 @@ Keep this terminal running.
124
131
  \- Match server version to installed bridge plugin version (`0.x` semver)
125
132
  - **[Bridge Connection Lifecycle](https://github.com/robert7/remnote-mcp-bridge/blob/main/docs/guides/connection-lifecycle.md)** - Canonical bridge connect/retry behavior
126
133
  - **[Configuration Guide](docs/guides/configuration.md)** - Configure Claude Code CLI, Accomplish, and other clients
134
+ - **[Codex Configuration Guide](docs/guides/configuration-codex.md)** - Set up Codex TUI and Codex.app with RemNote
127
135
  - **[ChatGPT Configuration Guide](docs/guides/configuration-chatgpt.md)** - Set up ChatGPT Apps with your MCP server
128
136
  - **[Demo & Screenshots](docs/demo.md)** - See the server in action with different AI clients
129
137
 
@@ -163,14 +171,20 @@ Tools that declare an `outputSchema` return MCP `structuredContent` plus a JSON
163
171
  See the [MCP tools specification](https://modelcontextprotocol.io/specification/2025-11-25/server/tools) for the
164
172
  protocol contract.
165
173
 
174
+ The server uses `@modelcontextprotocol/sdk` and supports current MCP protocol negotiation, including `2025-11-25`.
175
+ Do not confuse MCP protocol versions with `remnote-mcp-server` or bridge plugin package versions; package versions use
176
+ `0.x` semver and should usually match by minor line.
177
+
166
178
  See the [Tools Reference](docs/guides/tools-reference.md) for detailed usage and examples.
167
179
 
168
180
  ## Supported AI Clients
169
181
 
170
182
  - **[Claude Code CLI](https://claude.com/claude-code)** - Local terminal-based agent
183
+ - **Codex TUI / Codex.app** - Local OpenAI coding agent clients
171
184
  - **Claude Desktop / Cowork** - Remote connector clients (require [remote access](docs/guides/remote-access.md))
172
185
  - **[Accomplish](https://github.com/accomplish-ai/accomplish)** - Task-based MCP client (formerly Openwork)
173
186
  - **Any MCP client** supporting Streamable HTTP transport
187
+ - **Any local MCP client** supporting stdio transport through `remnote-mcp-stdio`
174
188
  - **Any local command runner** that can call `remnote-cli`
175
189
 
176
190
  ## Example Usage
@@ -253,7 +267,7 @@ See the [Troubleshooting Guide](docs/guides/troubleshooting.md) for detailed sol
253
267
  git clone https://github.com/robert7/remnote-mcp-server.git
254
268
  cd remnote-mcp-server
255
269
  ./link-cli.sh
256
- # Later, remove the local links for both remnote-mcp-server and remnote-cli:
270
+ # Later, remove the local links for package executables:
257
271
  ./unlink-cli.sh
258
272
  ```
259
273
 
@@ -274,8 +288,6 @@ For the canonical workflow for updating and running shared live integration cove
274
288
  ## Related Projects
275
289
 
276
290
  - [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
291
  - [Model Context Protocol](https://modelcontextprotocol.io/) - Open protocol for AI-application integration
280
292
 
281
293
  ## 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":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AAEpC,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAc/C,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;AAC1D,MAAM,iBAAiB,GAAG,WAAW,CAAC;AAEtC,MAAM,UAAU,kBAAkB;IAChC,OAAO,aAAa,CAAC,IAAI,GAAG,CAAC,0CAA0C,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC7F,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI;IACtD,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,iBAAiB,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC,CAAC;IAClC,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,oBAAoB,CAAC;SAC1B,WAAW,CAAC,8CAA8C,CAAC;SAC3D,OAAO,CAAC,WAAW,CAAC,OAAO,CAAC;SAC5B,WAAW,CACV,OAAO,EACP,+FAA+F,CAChG;SACA,MAAM,CAAC,oBAAoB,EAAE,sDAAsD,EAAE,SAAS,CAAC;SAC/F,MAAM,CACL,sBAAsB,EACtB,uDAAuD,EACvD,SAAS,CACV;SACA,MAAM,CACL,oBAAoB,EACpB,+GAA+G,EAC/G,YAAY,CACb;SACA,MAAM,CACL,qBAAqB,EACrB,sBAAsB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,EACjE,gBAAgB,CACjB;SACA,MAAM,CACL,0BAA0B,EAC1B,+CAA+C,EAC/C,gBAAgB,CACjB;SACA,MAAM,CAAC,WAAW,EAAE,iCAAiC,CAAC;SACtD,MAAM,CAAC,mBAAmB,EAAE,qCAAqC,CAAC;SAClE,MAAM,CAAC,sBAAsB,EAAE,iDAAiD,CAAC;SACjF,MAAM,CAAC,uBAAuB,EAAE,kDAAkD,CAAC,CAAC;IAEvF,OAAO,CAAC,KAAK,EAAE,CAAC;IAEhB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAc,CAAC;IAE3C,0BAA0B;IAC1B,IAAI,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,QAAQ,IAAI,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,QAAQ,EAAE,CAAC;QAC9E,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAC;QACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,SAAS,SAAS,CAAC,KAAa;IAC9B,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACjC,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK,EAAE,CAAC;QAC5C,MAAM,IAAI,KAAK,CAAC,wBAAwB,KAAK,gCAAgC,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,gBAAgB,CAAC,KAAa;IACrC,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,KAAK,CAAC,sBAAsB,KAAK,mBAAmB,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC7F,CAAC;IACD,OAAO,KAAK,CAAC,WAAW,EAAE,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,SAAS,YAAY,CAAC,KAAa;IACjC,yCAAyC;IACzC,IAAI,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,WAAW,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1E,OAAO,KAAK,CAAC;IACf,CAAC;IAED,uBAAuB;IACvB,MAAM,WAAW,GAAG,yBAAyB,CAAC;IAC9C,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CACb,iBAAiB,KAAK,kEAAkE,CACzF,CAAC;IACJ,CAAC;IAED,+BAA+B;IAC/B,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,GAAG,CAAC,EAAE,CAAC;QACrD,MAAM,IAAI,KAAK,CAAC,iBAAiB,KAAK,yCAAyC,CAAC,CAAC;IACnF,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
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
  }
@@ -0,0 +1,5 @@
1
+ node_modules/.cache/
2
+ *.log
3
+ coverage/
4
+ dist/
5
+ test/
@@ -0,0 +1,25 @@
1
+ # RemNote Local MCPB
2
+
3
+ Claude Desktop extension that exposes a local `remnote-mcp-server` to Claude Desktop without a public HTTPS tunnel.
4
+
5
+ ## Usage
6
+
7
+ 1. Install and start `remnote-mcp-server`.
8
+ 2. Open RemNote with the Automation Bridge plugin enabled and connected.
9
+ 3. Install this extension's `.mcpb` file in Claude Desktop.
10
+ 4. Keep the default MCP URL unless your server uses a custom port:
11
+
12
+ ```text
13
+ http://127.0.0.1:3001/mcp
14
+ ```
15
+
16
+ This extension does not start or supervise `remnote-mcp-server`. It is a stdio proxy that forwards Claude Desktop tool
17
+ calls to the local Streamable HTTP endpoint.
18
+
19
+ ## Installed Package Path
20
+
21
+ When installed from npm, print the bundled `.mcpb` path with:
22
+
23
+ ```bash
24
+ remnote-mcp-server mcpb-path
25
+ ```
@@ -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 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. 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.1",
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.1",
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"