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 +24 -0
- package/README.md +25 -13
- package/dist/cli.d.ts +5 -0
- package/dist/cli.js +16 -0
- package/dist/cli.js.map +1 -1
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/dist/remnote-cli/client/mcp-server-client.js +1 -1
- package/mcpb/remnote-local/.mcpbignore +5 -0
- package/mcpb/remnote-local/README.md +25 -0
- package/mcpb/remnote-local/manifest.json +87 -0
- package/mcpb/remnote-local/package.json +11 -0
- package/mcpb/remnote-local/remnote-local.mcpb +0 -0
- package/mcpb/remnote-local/server/index.js +300 -0
- package/package.json +12 -8
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
|
|
19
|
-
|
|
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
|
|
33
|
-
|
|
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`
|
|
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
|
|
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.
|
|
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
|
|
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":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;
|
|
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":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;
|
|
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.
|
|
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,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
|
+
}
|
|
Binary file
|
|
@@ -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.
|
|
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": "
|
|
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"
|