remnote-mcp-server 0.13.1 → 0.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +30 -21
  3. package/dist/remnote-cli/cli.d.ts +3 -0
  4. package/dist/remnote-cli/cli.js +37 -0
  5. package/dist/remnote-cli/cli.js.map +1 -0
  6. package/dist/remnote-cli/client/command-client.d.ts +3 -0
  7. package/dist/remnote-cli/client/command-client.js +9 -0
  8. package/dist/remnote-cli/client/command-client.js.map +1 -0
  9. package/dist/remnote-cli/client/mcp-server-client.d.ts +18 -0
  10. package/dist/remnote-cli/client/mcp-server-client.js +116 -0
  11. package/dist/remnote-cli/client/mcp-server-client.js.map +1 -0
  12. package/dist/remnote-cli/commands/arg-utils.d.ts +33 -0
  13. package/dist/remnote-cli/commands/arg-utils.js +89 -0
  14. package/dist/remnote-cli/commands/arg-utils.js.map +1 -0
  15. package/dist/remnote-cli/commands/content-input.d.ts +31 -0
  16. package/dist/remnote-cli/commands/content-input.js +81 -0
  17. package/dist/remnote-cli/commands/content-input.js.map +1 -0
  18. package/dist/remnote-cli/commands/create.d.ts +2 -0
  19. package/dist/remnote-cli/commands/create.js +61 -0
  20. package/dist/remnote-cli/commands/create.js.map +1 -0
  21. package/dist/remnote-cli/commands/journal.d.ts +2 -0
  22. package/dist/remnote-cli/commands/journal.js +52 -0
  23. package/dist/remnote-cli/commands/journal.js.map +1 -0
  24. package/dist/remnote-cli/commands/read.d.ts +2 -0
  25. package/dist/remnote-cli/commands/read.js +74 -0
  26. package/dist/remnote-cli/commands/read.js.map +1 -0
  27. package/dist/remnote-cli/commands/search.d.ts +3 -0
  28. package/dist/remnote-cli/commands/search.js +107 -0
  29. package/dist/remnote-cli/commands/search.js.map +1 -0
  30. package/dist/remnote-cli/commands/status.d.ts +2 -0
  31. package/dist/remnote-cli/commands/status.js +41 -0
  32. package/dist/remnote-cli/commands/status.js.map +1 -0
  33. package/dist/remnote-cli/commands/table.d.ts +2 -0
  34. package/dist/remnote-cli/commands/table.js +79 -0
  35. package/dist/remnote-cli/commands/table.js.map +1 -0
  36. package/dist/remnote-cli/commands/update.d.ts +2 -0
  37. package/dist/remnote-cli/commands/update.js +62 -0
  38. package/dist/remnote-cli/commands/update.js.map +1 -0
  39. package/dist/remnote-cli/config.d.ts +9 -0
  40. package/dist/remnote-cli/config.js +10 -0
  41. package/dist/remnote-cli/config.js.map +1 -0
  42. package/dist/remnote-cli/index.d.ts +2 -0
  43. package/dist/remnote-cli/index.js +4 -0
  44. package/dist/remnote-cli/index.js.map +1 -0
  45. package/dist/remnote-cli/output/formatter.d.ts +9 -0
  46. package/dist/remnote-cli/output/formatter.js +28 -0
  47. package/dist/remnote-cli/output/formatter.js.map +1 -0
  48. package/dist/remnote-cli/version-compat.d.ts +7 -0
  49. package/dist/remnote-cli/version-compat.js +28 -0
  50. package/dist/remnote-cli/version-compat.js.map +1 -0
  51. package/package.json +7 -4
package/CHANGELOG.md CHANGED
@@ -7,6 +7,22 @@ Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.14.0] - 2026-05-07
11
+
12
+ ### Added
13
+
14
+ - Bundled the `remnote-cli` executable into the `remnote-mcp-server` package. The package now provides both
15
+ `remnote-mcp-server` and `remnote-cli`.
16
+ - Added local `link-cli.sh` and `unlink-cli.sh` helpers for linking both executables during development.
17
+
18
+ ### Changed
19
+
20
+ - Consolidated CLI installation guidance around `npm install -g remnote-mcp-server`; the old standalone
21
+ `remnote-cli` package is now treated as a legacy migration path.
22
+ - Updated agent-assisted and manual integration workflows so the direct MCP and bundled CLI paths run through the
23
+ unified MCP server, with `--suite mcp|cli|all` for targeted reruns.
24
+ - Added server-owned CLI command, troubleshooting, demo, and skill documentation.
25
+
10
26
  ## [0.13.1] - 2026-05-06
11
27
 
12
28
  ### Changed
package/README.md CHANGED
@@ -5,23 +5,19 @@
5
5
  [![npm version](https://img.shields.io/npm/v/remnote-mcp-server)](https://www.npmjs.com/package/remnote-mcp-server)
6
6
  [![codecov](https://codecov.io/gh/robert7/remnote-mcp-server/branch/main/graph/badge.svg)](https://codecov.io/gh/robert7/remnote-mcp-server)
7
7
 
8
- MCP server that bridges AI agents (e.g. Claude Code) to [RemNote](https://remnote.com/) via the [RemNote Automation
9
- Bridge plugin](https://github.com/robert7/remnote-mcp-bridge).
8
+ MCP server and CLI package that bridges AI agents, local scripts, and coding harnesses to
9
+ [RemNote](https://remnote.com/) via the [RemNote Automation Bridge
10
+ plugin](https://github.com/robert7/remnote-mcp-bridge).
10
11
 
11
12
  > If you run into any issues, please [report them here](https://github.com/robert7/remnote-mcp-server/issues).
12
13
 
13
14
  ## What is This?
14
15
 
15
16
  The RemNote MCP Server enables AI assistants like Claude Code to interact directly with your RemNote knowledge base
16
- through the Model Context Protocol (MCP). Create notes, hierarchical markdown trees, and RemNote-native flashcards;
17
- search and read your knowledge base; update existing notes; and maintain your daily journal, all through
18
- conversational commands.
19
-
20
- For some agentic workflows or CLI-first automation, the companion app
21
- **[remnote-cli](https://github.com/robert7/remnote-cli)** may be a better fit than running a full MCP server.
22
- In particular, **coding harnesses** (Claude Code, GitHub Copilot CLI, Codex CLI, etc.) can use `remnote-cli` with
23
- **zero config** — paste one prompt that loads the skill file and the agent handles the rest. See
24
- [Use RemNote from Any Coding Harness](https://github.com/robert7/remnote-cli/blob/main/docs/demo.md#use-remnote-from-any-coding-harness).
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.
25
21
 
26
22
  ## Demo
27
23
 
@@ -29,14 +25,14 @@ See AI agent examples in action with RemNote: **[View Demo →](docs/demo.md)**
29
25
 
30
26
  ### Two-Component Architecture
31
27
 
32
- This system consists of **two separate components** that work together:
28
+ This system consists of **two separate runtime components** that work together:
33
29
 
34
30
  1. **[RemNote Automation Bridge](https://github.com/robert7/remnote-mcp-bridge)** - A RemNote plugin that runs in your
35
31
  browser or RemNote desktop app and exposes RemNote API functionality via WebSocket
36
- 2. **RemNote MCP Server** (this project) - A standalone server that connects your AI assistant to the bridge using MCP
37
- protocol
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
38
34
 
39
- **Both components are required** for AI integration with RemNote.
35
+ The `remnote-cli` command is not a second server. It calls the MCP endpoint exposed by `remnote-mcp-server`.
40
36
 
41
37
  For the detailed bridge connection lifecycle, retry phases, and wake-up triggers, use the bridge repo as the source of
42
38
  truth: [Connection Lifecycle Guide](https://github.com/robert7/remnote-mcp-bridge/blob/main/docs/guides/connection-lifecycle.md).
@@ -44,12 +40,14 @@ truth: [Connection Lifecycle Guide](https://github.com/robert7/remnote-mcp-bridg
44
40
  ### How It Works
45
41
 
46
42
  ```text
47
- AI agents (HTTP) MCP HTTP Server :3001 WebSocket Server :3002 RemNote Plugin RemNote
43
+ AI agents (HTTP) -> MCP HTTP Server :3001 -> WebSocket Server :3002 -> RemNote Plugin -> RemNote
44
+ CLI commands -> remnote-cli -> MCP HTTP Server :3001 -> WebSocket Server :3002 -> RemNote Plugin -> RemNote
48
45
  ```
49
46
 
50
47
  The server acts as a bridge:
51
48
 
52
49
  - Communicates with AI agents via Streamable HTTP transport (MCP protocol) - supports both local and remote access
50
+ - Provides `remnote-cli` as a bundled command-line MCP client for local automation
53
51
  - HTTP server (port 3001) manages MCP sessions for multiple concurrent agents
54
52
  - WebSocket server (port 3002) connects to the RemNote browser plugin
55
53
  - Translates MCP tool calls into RemNote API actions
@@ -81,6 +79,13 @@ connection always stays local for security. See [Remote Access Guide](docs/guide
81
79
  npm install -g remnote-mcp-server
82
80
  ```
83
81
 
82
+ The package installs both commands:
83
+
84
+ ```bash
85
+ remnote-mcp-server --version
86
+ remnote-cli --version
87
+ ```
88
+
84
89
  ### 2. Install the RemNote Plugin
85
90
 
86
91
  Install the [RemNote Automation Bridge plugin](https://github.com/robert7/remnote-mcp-bridge) in your RemNote app.
@@ -96,7 +101,7 @@ remnote-mcp-server
96
101
  Expected output:
97
102
 
98
103
  ```text
99
- RemNote MCP Server v0.2.1 listening { wsPort: 3002, httpPort: 3001 }
104
+ RemNote MCP Server v0.14.0 listening { wsPort: 3002, httpPort: 3001 }
100
105
  ```
101
106
 
102
107
  Keep this terminal running.
@@ -125,6 +130,7 @@ Keep this terminal running.
125
130
  ### Usage
126
131
 
127
132
  - **[CLI Options Reference](docs/guides/cli-options.md)** - Command-line options and environment variables
133
+ - **[remnote-cli Command Reference](docs/guides/cli-command-reference.md)** - Shell command reference for the bundled CLI
128
134
  - **[MCP Tools Reference](docs/guides/tools-reference.md)** - Detailed reference for all 9 RemNote tools
129
135
  - **[Remote Access Setup](docs/guides/remote-access.md)** - Expose server for Claude Desktop / Cowork (ngrok, etc.)
130
136
 
@@ -165,6 +171,7 @@ See the [Tools Reference](docs/guides/tools-reference.md) for detailed usage and
165
171
  - **Claude Desktop / Cowork** - Remote connector clients (require [remote access](docs/guides/remote-access.md))
166
172
  - **[Accomplish](https://github.com/accomplish-ai/accomplish)** - Task-based MCP client (formerly Openwork)
167
173
  - **Any MCP client** supporting Streamable HTTP transport
174
+ - **Any local command runner** that can call `remnote-cli`
168
175
 
169
176
  ## Example Usage
170
177
 
@@ -245,9 +252,9 @@ See the [Troubleshooting Guide](docs/guides/troubleshooting.md) for detailed sol
245
252
  ```bash
246
253
  git clone https://github.com/robert7/remnote-mcp-server.git
247
254
  cd remnote-mcp-server
248
- npm install
249
- npm run build
250
- npm link
255
+ ./link-cli.sh
256
+ # Later, remove the local links for both remnote-mcp-server and remnote-cli:
257
+ ./unlink-cli.sh
251
258
  ```
252
259
 
253
260
  **Development workflow:**
@@ -260,13 +267,15 @@ npm test # Run test suite
260
267
 
261
268
  See the [Development Setup Guide](docs/guides/development-setup.md) for complete instructions.
262
269
 
263
- Pull requests that affect bridge-consumer behavior should follow the shared PR rules in the bridge repo: [Pull Request Guide](https://github.com/robert7/remnote-mcp-bridge/blob/main/docs/guides/pull-request-guide.md). In particular, keep bridge/server/CLI parity for shared functionality changes and link related PRs across the affected repos.
270
+ Pull requests that affect bridge-consumer behavior should follow the shared PR rules in the bridge repo: [Pull Request Guide](https://github.com/robert7/remnote-mcp-bridge/blob/main/docs/guides/pull-request-guide.md). In particular, keep bridge and server-package behavior aligned for shared functionality changes.
264
271
 
265
272
  For the canonical workflow for updating and running shared live integration coverage, see the [Integration Testing Guide](docs/guides/integration-testing.md).
266
273
 
267
274
  ## Related Projects
268
275
 
269
276
  - [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
270
279
  - [Model Context Protocol](https://modelcontextprotocol.io/) - Open protocol for AI-application integration
271
280
 
272
281
  ## License
@@ -0,0 +1,3 @@
1
+ import { Command } from 'commander';
2
+ export declare function createProgram(version: string): Command;
3
+ export declare function runCli(argv?: string[]): void;
@@ -0,0 +1,37 @@
1
+ import { Command } from 'commander';
2
+ import { createRequire } from 'node:module';
3
+ import { DEFAULT_MCP_URL } from './config.js';
4
+ import { registerCreateCommand } from './commands/create.js';
5
+ import { registerSearchByTagCommand, registerSearchCommand } from './commands/search.js';
6
+ import { registerReadCommand } from './commands/read.js';
7
+ import { registerUpdateCommand } from './commands/update.js';
8
+ import { registerJournalCommand } from './commands/journal.js';
9
+ import { registerStatusCommand } from './commands/status.js';
10
+ import { registerReadTableCommand } from './commands/table.js';
11
+ const require = createRequire(import.meta.url);
12
+ const packageJson = require('../../package.json');
13
+ export function createProgram(version) {
14
+ const program = new Command();
15
+ program
16
+ .name('remnote-cli')
17
+ .description('CLI client for RemNote MCP Server')
18
+ .version(version)
19
+ .option('--json', 'JSON output (default)')
20
+ .option('--text', 'Human-readable output')
21
+ .option('--mcp-url <url>', 'RemNote MCP server URL', process.env.REMNOTE_MCP_URL || DEFAULT_MCP_URL)
22
+ .option('--verbose', 'Enable verbose stderr logging');
23
+ registerCreateCommand(program);
24
+ registerSearchCommand(program);
25
+ registerSearchByTagCommand(program);
26
+ registerReadCommand(program);
27
+ registerUpdateCommand(program);
28
+ registerJournalCommand(program);
29
+ registerStatusCommand(program);
30
+ registerReadTableCommand(program);
31
+ return program;
32
+ }
33
+ export function runCli(argv = process.argv) {
34
+ const program = createProgram(packageJson.version);
35
+ program.parse(argv);
36
+ }
37
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/remnote-cli/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,0BAA0B,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAE/D,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,WAAW,GAAG,OAAO,CAAC,oBAAoB,CAAwB,CAAC;AAEzE,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,aAAa,CAAC;SACnB,WAAW,CAAC,mCAAmC,CAAC;SAChD,OAAO,CAAC,OAAO,CAAC;SAChB,MAAM,CAAC,QAAQ,EAAE,uBAAuB,CAAC;SACzC,MAAM,CAAC,QAAQ,EAAE,uBAAuB,CAAC;SACzC,MAAM,CACL,iBAAiB,EACjB,wBAAwB,EACxB,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,eAAe,CAC/C;SACA,MAAM,CAAC,WAAW,EAAE,+BAA+B,CAAC,CAAC;IAExD,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC/B,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC/B,0BAA0B,CAAC,OAAO,CAAC,CAAC;IACpC,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7B,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC/B,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAChC,qBAAqB,CAAC,OAAO,CAAC,CAAC;IAC/B,wBAAwB,CAAC,OAAO,CAAC,CAAC;IAElC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI;IACxC,MAAM,OAAO,GAAG,aAAa,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACnD,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ import { McpServerClient } from './mcp-server-client.js';
3
+ export declare function createCommandClient(program: Command): McpServerClient;
@@ -0,0 +1,9 @@
1
+ import { createRequire } from 'node:module';
2
+ import { McpServerClient } from './mcp-server-client.js';
3
+ const require = createRequire(import.meta.url);
4
+ const packageJson = require('../../../package.json');
5
+ export function createCommandClient(program) {
6
+ const opts = program.opts();
7
+ return new McpServerClient(opts.mcpUrl, { name: 'remnote-cli', version: packageJson.version });
8
+ }
9
+ //# sourceMappingURL=command-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-client.js","sourceRoot":"","sources":["../../../src/remnote-cli/client/command-client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAEzD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,WAAW,GAAG,OAAO,CAAC,uBAAuB,CAAwB,CAAC;AAE5E,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,EAAsB,CAAC;IAChD,OAAO,IAAI,eAAe,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,WAAW,CAAC,OAAO,EAAE,CAAC,CAAC;AACjG,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Short-lived MCP client used by CLI commands to call remnote-mcp-server.
3
+ */
4
+ export declare class McpServerClient {
5
+ private readonly mcpUrl;
6
+ private readonly clientInfo;
7
+ private client;
8
+ private transport;
9
+ constructor(mcpUrl: string, clientInfo?: {
10
+ name: string;
11
+ version: string;
12
+ });
13
+ execute(action: string, payload: Record<string, unknown>): Promise<unknown>;
14
+ close(): Promise<void>;
15
+ private connect;
16
+ private extractText;
17
+ private parseResult;
18
+ }
@@ -0,0 +1,116 @@
1
+ import { Client } from '@modelcontextprotocol/sdk/client/index.js';
2
+ import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
3
+ import { checkVersionCompatibility } from '../version-compat.js';
4
+ const ACTION_TO_TOOL = {
5
+ create_note: 'remnote_create_note',
6
+ search: 'remnote_search',
7
+ search_by_tag: 'remnote_search_by_tag',
8
+ read_note: 'remnote_read_note',
9
+ update_note: 'remnote_update_note',
10
+ append_journal: 'remnote_append_journal',
11
+ get_status: 'remnote_status',
12
+ read_table: 'remnote_read_table',
13
+ };
14
+ /**
15
+ * Short-lived MCP client used by CLI commands to call remnote-mcp-server.
16
+ */
17
+ export class McpServerClient {
18
+ mcpUrl;
19
+ clientInfo;
20
+ client = null;
21
+ transport = null;
22
+ constructor(mcpUrl, clientInfo = { name: 'remnote-cli', version: '0.14.0' }) {
23
+ this.mcpUrl = normalizeMcpUrl(mcpUrl);
24
+ this.clientInfo = clientInfo;
25
+ }
26
+ async execute(action, payload) {
27
+ const toolName = ACTION_TO_TOOL[action];
28
+ if (!toolName) {
29
+ throw new Error(`Unknown bridge action: ${action}`);
30
+ }
31
+ await this.connect();
32
+ const result = await this.client.callTool({ name: toolName, arguments: payload });
33
+ if (result.isError) {
34
+ throw new Error(this.extractText(result));
35
+ }
36
+ const parsed = this.parseResult(result);
37
+ if (action === 'get_status' && parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
38
+ const status = { ...parsed, cliVersion: this.clientInfo.version };
39
+ const serverVersion = status.serverVersion;
40
+ if (typeof serverVersion === 'string') {
41
+ const warning = checkVersionCompatibility(this.clientInfo.version, serverVersion, 'CLI', 'MCP server');
42
+ if (warning) {
43
+ status.version_warning =
44
+ typeof status.version_warning === 'string'
45
+ ? `${status.version_warning}\n${warning}`
46
+ : warning;
47
+ }
48
+ }
49
+ return status;
50
+ }
51
+ return parsed;
52
+ }
53
+ async close() {
54
+ try {
55
+ if (this.transport) {
56
+ await this.transport.terminateSession();
57
+ }
58
+ }
59
+ catch {
60
+ // Ignore shutdown errors; CLI commands are already done at this point.
61
+ }
62
+ try {
63
+ if (this.client) {
64
+ await this.client.close();
65
+ }
66
+ }
67
+ catch {
68
+ // Ignore shutdown errors; connection cleanup is best-effort.
69
+ }
70
+ this.client = null;
71
+ this.transport = null;
72
+ }
73
+ async connect() {
74
+ if (this.client) {
75
+ return;
76
+ }
77
+ this.transport = new StreamableHTTPClientTransport(new URL(this.mcpUrl));
78
+ this.client = new Client(this.clientInfo);
79
+ try {
80
+ await this.client.connect(this.transport);
81
+ }
82
+ catch (error) {
83
+ this.client = null;
84
+ this.transport = null;
85
+ const message = error instanceof Error ? error.message : String(error);
86
+ throw new Error(`Cannot connect to MCP server at ${this.mcpUrl}. Is remnote-mcp-server running? ${message}`, { cause: error });
87
+ }
88
+ }
89
+ extractText(result) {
90
+ const content = result.content;
91
+ const text = content?.find((item) => item.type === 'text' && item.text)?.text;
92
+ return text ?? JSON.stringify(result);
93
+ }
94
+ parseResult(result) {
95
+ if (result.structuredContent &&
96
+ typeof result.structuredContent === 'object' &&
97
+ !Array.isArray(result.structuredContent)) {
98
+ return result.structuredContent;
99
+ }
100
+ const text = this.extractText(result);
101
+ try {
102
+ return JSON.parse(text);
103
+ }
104
+ catch {
105
+ return { _raw: text };
106
+ }
107
+ }
108
+ }
109
+ function normalizeMcpUrl(value) {
110
+ const trimmed = value.trim();
111
+ if (trimmed.endsWith('/mcp')) {
112
+ return trimmed;
113
+ }
114
+ return `${trimmed.replace(/\/+$/, '')}/mcp`;
115
+ }
116
+ //# sourceMappingURL=mcp-server-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server-client.js","sourceRoot":"","sources":["../../../src/remnote-cli/client/mcp-server-client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { type Command } from 'commander';
2
+ /**
3
+ * Determines if a given string value looks like a CLI flag instead of a standard argument.
4
+ * This is used to detect "argument shifting" (e.g., when an empty string "" is swallowed by the shell,
5
+ * causing the next flag to be incorrectly parsed as the value for the current option).
6
+ *
7
+ * @param value - The string argument to evaluate.
8
+ * @param cmd - (Optional) The Command instance. If provided, enables strict matching against registered flags.
9
+ * @returns True if the value is likely a shifted flag; otherwise, false.
10
+ */
11
+ export declare function isFlag(value: string | undefined, cmd?: Command): boolean;
12
+ /**
13
+ * Validates an entire record of parsed arguments to ensure none of them are shifted flags.
14
+ * Useful for running a bulk check after Commander has finished parsing,
15
+ * especially when using dynamic commands or positional arguments.
16
+ *
17
+ * @param fields - A key-value record of parsed arguments (e.g., { title: '--content', parentId: '123' }).
18
+ * @param cmd - (Optional) The Command instance for strict flag matching.
19
+ * @throws {Error} If any value is identified as a shifted flag.
20
+ */
21
+ export declare function checkPayloadForFlags(fields: Record<string, string | undefined>, cmd?: Command): void;
22
+ /**
23
+ * A higher-order function designed to be used as a custom processing function in Commander's `.option()`.
24
+ * It binds the Command context to the validation logic.
25
+ *
26
+ * @param cmd - The current Commander instance.
27
+ * @returns A validation function that throws an InvalidArgumentError if the value is a shifted flag.
28
+ *
29
+ * @example
30
+ * const check = validateNotFlag(program);
31
+ * program.option('--title <text>', 'Note title', check);
32
+ */
33
+ export declare function validateNotFlag(value: string, cmd?: Command): string;
@@ -0,0 +1,89 @@
1
+ import { InvalidArgumentError } from 'commander';
2
+ /**
3
+ * A memory-safe cache that stores the flattened list of registered flags for each Command.
4
+ * Using a WeakMap ensures that once a Command object is garbage collected (e.g., after a test run),
5
+ * its associated cache is also freed, preventing memory leaks.
6
+ */
7
+ const flagCache = new WeakMap();
8
+ /**
9
+ * Traverses the current Command and all its parent commands to collect every registered flag.
10
+ * Uses caching to ensure this expensive traversal only happens once per Command instance.
11
+ *
12
+ * @param cmd - The Commander.js Command instance to inspect.
13
+ * @returns An array of all registered short and long flags (e.g., ['-c', '--content', ...]).
14
+ */
15
+ const getAllRegisteredFlags = (cmd) => {
16
+ if (flagCache.has(cmd)) {
17
+ return flagCache.get(cmd);
18
+ }
19
+ let flags = [];
20
+ let current = cmd;
21
+ while (current) {
22
+ if (current.options) {
23
+ const currentFlags = current.options.flatMap((opt) => [opt.short, opt.long].filter(Boolean));
24
+ flags = [...flags, ...currentFlags];
25
+ }
26
+ // Move up the command tree to catch globally registered options
27
+ current = current.parent;
28
+ }
29
+ flagCache.set(cmd, flags);
30
+ return flags;
31
+ };
32
+ /**
33
+ * Determines if a given string value looks like a CLI flag instead of a standard argument.
34
+ * This is used to detect "argument shifting" (e.g., when an empty string "" is swallowed by the shell,
35
+ * causing the next flag to be incorrectly parsed as the value for the current option).
36
+ *
37
+ * @param value - The string argument to evaluate.
38
+ * @param cmd - (Optional) The Command instance. If provided, enables strict matching against registered flags.
39
+ * @returns True if the value is likely a shifted flag; otherwise, false.
40
+ */
41
+ export function isFlag(value, cmd) {
42
+ if (!value)
43
+ return false;
44
+ // Strict Match: If a Command context is provided, check against actually registered flags.
45
+ if (cmd) {
46
+ const knownFlags = getAllRegisteredFlags(cmd);
47
+ if (knownFlags.includes(value))
48
+ return true;
49
+ }
50
+ return false;
51
+ }
52
+ /**
53
+ * Validates an entire record of parsed arguments to ensure none of them are shifted flags.
54
+ * Useful for running a bulk check after Commander has finished parsing,
55
+ * especially when using dynamic commands or positional arguments.
56
+ *
57
+ * @param fields - A key-value record of parsed arguments (e.g., { title: '--content', parentId: '123' }).
58
+ * @param cmd - (Optional) The Command instance for strict flag matching.
59
+ * @throws {Error} If any value is identified as a shifted flag.
60
+ */
61
+ export function checkPayloadForFlags(fields, cmd) {
62
+ for (const [name, value] of Object.entries(fields)) {
63
+ if (isFlag(value, cmd)) {
64
+ throw new Error(`Argument shifting detected: "${value}" was misinterpreted as the value for "${name}". ` +
65
+ `This usually indicates argument shifting (e.g. the shell swallowed an empty string ""). ` +
66
+ `To fix this, use explicit flags (e.g. --title="", --content="") or check your quoting.`);
67
+ }
68
+ }
69
+ }
70
+ /**
71
+ * A higher-order function designed to be used as a custom processing function in Commander's `.option()`.
72
+ * It binds the Command context to the validation logic.
73
+ *
74
+ * @param cmd - The current Commander instance.
75
+ * @returns A validation function that throws an InvalidArgumentError if the value is a shifted flag.
76
+ *
77
+ * @example
78
+ * const check = validateNotFlag(program);
79
+ * program.option('--title <text>', 'Note title', check);
80
+ */
81
+ export function validateNotFlag(value, cmd) {
82
+ if (isFlag(value, cmd)) {
83
+ throw new InvalidArgumentError(`"${value}" looks like a flag but was passed as an option value. ` +
84
+ `This usually indicates argument shifting (e.g. the shell swallowed an empty string ""). ` +
85
+ `To fix this, use explicit flags (e.g. --title="", --content="") or check your quoting.`);
86
+ }
87
+ return value;
88
+ }
89
+ //# sourceMappingURL=arg-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"arg-utils.js","sourceRoot":"","sources":["../../../src/remnote-cli/commands/arg-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAgB,MAAM,WAAW,CAAC;AAE/D;;;;GAIG;AACH,MAAM,SAAS,GAAG,IAAI,OAAO,EAAqB,CAAC;AAEnD;;;;;;GAMG;AACH,MAAM,qBAAqB,GAAG,CAAC,GAAY,EAAY,EAAE;IACvD,IAAI,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,SAAS,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;IAC7B,CAAC;IAED,IAAI,KAAK,GAAa,EAAE,CAAC;IACzB,IAAI,OAAO,GAAmB,GAAG,CAAC;IAElC,OAAO,OAAO,EAAE,CAAC;QACf,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAC1C,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAa,CAC3D,CAAC;YACF,KAAK,GAAG,CAAC,GAAG,KAAK,EAAE,GAAG,YAAY,CAAC,CAAC;QACtC,CAAC;QACD,gEAAgE;QAChE,OAAO,GAAG,OAAO,CAAC,MAAwB,CAAC;IAC7C,CAAC;IAED,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IAC1B,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,UAAU,MAAM,CAAC,KAAyB,EAAE,GAAa;IAC7D,IAAI,CAAC,KAAK;QAAE,OAAO,KAAK,CAAC;IAEzB,2FAA2F;IAC3F,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,UAAU,GAAG,qBAAqB,CAAC,GAAG,CAAC,CAAC;QAC9C,IAAI,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;IAC9C,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAClC,MAA0C,EAC1C,GAAa;IAEb,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,IAAI,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CACb,gCAAgC,KAAK,0CAA0C,IAAI,KAAK;gBACtF,0FAA0F;gBAC1F,wFAAwF,CAC3F,CAAC;QACJ,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa,EAAE,GAAa;IAC1D,IAAI,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,oBAAoB,CAC5B,IAAI,KAAK,yDAAyD;YAChE,0FAA0F;YAC1F,wFAAwF,CAC3F,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { Readable } from 'node:stream';
2
+ export declare const MAX_WRITE_CONTENT_BYTES: number;
3
+ export declare function readContentFileOrStdin(pathOrDash: string, stdin?: Readable): Promise<string>;
4
+ interface OptionalContentArgs {
5
+ inlineText: string | undefined;
6
+ filePath: string | undefined;
7
+ inlineFlag: string;
8
+ fileFlag: string;
9
+ stdin?: Readable;
10
+ }
11
+ export declare function resolveOptionalInlineOrFileContent({ inlineText, filePath, inlineFlag, fileFlag, stdin, }: OptionalContentArgs): Promise<string | undefined>;
12
+ interface UpdateContentArgs {
13
+ appendText: string | undefined;
14
+ appendFile: string | undefined;
15
+ replaceText: string | undefined;
16
+ replaceFile: string | undefined;
17
+ stdin?: Readable;
18
+ }
19
+ interface ResolvedUpdateContent {
20
+ appendContent: string | undefined;
21
+ replaceContent: string | undefined;
22
+ }
23
+ export declare function resolveUpdateContent({ appendText, appendFile, replaceText, replaceFile, stdin, }: UpdateContentArgs): Promise<ResolvedUpdateContent>;
24
+ interface JournalContentArgs {
25
+ positionalContent: string | undefined;
26
+ optionContent: string | undefined;
27
+ contentFile: string | undefined;
28
+ stdin?: Readable;
29
+ }
30
+ export declare function resolveJournalContent({ positionalContent, optionContent, contentFile, stdin, }: JournalContentArgs): Promise<string>;
31
+ export {};
@@ -0,0 +1,81 @@
1
+ import { readFile } from 'node:fs/promises';
2
+ export const MAX_WRITE_CONTENT_BYTES = 100 * 1024;
3
+ function formatLimit() {
4
+ return `${MAX_WRITE_CONTENT_BYTES / 1024} KB`;
5
+ }
6
+ function ensureWithinLimit(byteLength, sourceLabel) {
7
+ if (byteLength > MAX_WRITE_CONTENT_BYTES) {
8
+ throw new Error(`${sourceLabel} exceeds ${formatLimit()} limit`);
9
+ }
10
+ }
11
+ async function readUtf8FromStream(stream, sourceLabel) {
12
+ const chunks = [];
13
+ let totalBytes = 0;
14
+ for await (const chunk of stream) {
15
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
16
+ totalBytes += buffer.byteLength;
17
+ ensureWithinLimit(totalBytes, sourceLabel);
18
+ chunks.push(buffer);
19
+ }
20
+ return Buffer.concat(chunks).toString('utf8');
21
+ }
22
+ export async function readContentFileOrStdin(pathOrDash, stdin = process.stdin) {
23
+ if (pathOrDash === '-') {
24
+ return readUtf8FromStream(stdin, 'Stdin content');
25
+ }
26
+ try {
27
+ const buffer = await readFile(pathOrDash);
28
+ ensureWithinLimit(buffer.byteLength, `Content file "${pathOrDash}"`);
29
+ return buffer.toString('utf8');
30
+ }
31
+ catch (error) {
32
+ const message = error instanceof Error ? error.message : String(error);
33
+ throw new Error(`Failed to read content file "${pathOrDash}": ${message}`, {
34
+ cause: error,
35
+ });
36
+ }
37
+ }
38
+ export async function resolveOptionalInlineOrFileContent({ inlineText, filePath, inlineFlag, fileFlag, stdin, }) {
39
+ if (inlineText !== undefined && filePath !== undefined) {
40
+ throw new Error(`Cannot use ${inlineFlag} and ${fileFlag} together`);
41
+ }
42
+ if (filePath !== undefined) {
43
+ return readContentFileOrStdin(filePath, stdin);
44
+ }
45
+ // convert literal \n strings into actual newline characters
46
+ return inlineText?.replace(/\\n/g, '\n');
47
+ }
48
+ export async function resolveUpdateContent({ appendText, appendFile, replaceText, replaceFile, stdin, }) {
49
+ const appendContent = await resolveOptionalInlineOrFileContent({
50
+ inlineText: appendText,
51
+ filePath: appendFile,
52
+ inlineFlag: '--append',
53
+ fileFlag: '--append-file',
54
+ stdin,
55
+ });
56
+ const replaceContent = await resolveOptionalInlineOrFileContent({
57
+ inlineText: replaceText,
58
+ filePath: replaceFile,
59
+ inlineFlag: '--replace',
60
+ fileFlag: '--replace-file',
61
+ stdin,
62
+ });
63
+ if (appendContent !== undefined && replaceContent !== undefined) {
64
+ throw new Error('Cannot combine append and replace content options (--append/--append-file with --replace/--replace-file)');
65
+ }
66
+ return { appendContent, replaceContent };
67
+ }
68
+ export async function resolveJournalContent({ positionalContent, optionContent, contentFile, stdin, }) {
69
+ const providedCount = [positionalContent, optionContent, contentFile].filter((value) => value !== undefined).length;
70
+ if (providedCount !== 1) {
71
+ throw new Error('Provide exactly one journal content source: positional <content>, --content <text>, or --content-file <path|->');
72
+ }
73
+ if (contentFile !== undefined) {
74
+ return readContentFileOrStdin(contentFile, stdin);
75
+ }
76
+ if (optionContent !== undefined) {
77
+ return optionContent;
78
+ }
79
+ return positionalContent;
80
+ }
81
+ //# sourceMappingURL=content-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-input.js","sourceRoot":"","sources":["../../../src/remnote-cli/commands/content-input.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ import { Command } from 'commander';
2
+ export declare function registerCreateCommand(program: Command): void;