remnote-mcp-server 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +90 -0
- package/LICENSE +21 -0
- package/README.md +506 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +52 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/remnote-schemas.d.ts +27 -0
- package/dist/schemas/remnote-schemas.js +28 -0
- package/dist/schemas/remnote-schemas.js.map +1 -0
- package/dist/tools/index.d.ts +134 -0
- package/dist/tools/index.js +171 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/types/bridge.d.ts +26 -0
- package/dist/types/bridge.js +2 -0
- package/dist/types/bridge.js.map +1 -0
- package/dist/websocket-server.d.ts +16 -0
- package/dist/websocket-server.js +143 -0
- package/dist/websocket-server.js.map +1 -0
- package/package.json +76 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic
|
|
6
|
+
Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
## [0.1.2] - 2026-02-07
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Documentation of multi-agent limitations in README.md
|
|
15
|
+
- Explains 1:1:1 architecture constraint (one AI agent ↔ one server ↔ one RemNote connection)
|
|
16
|
+
- Details three architectural constraints: stdio point-to-point transport, single-client WebSocket, port binding
|
|
17
|
+
- Provides practical implications and alternative approaches for users needing multiple agents
|
|
18
|
+
- Notes planned migration to HTTP transport (SSE) which would enable multi-agent support
|
|
19
|
+
- Comprehensive testing infrastructure with Vitest (95 tests)
|
|
20
|
+
- Unit tests for WebSocketServer, tools, schemas
|
|
21
|
+
- Coverage thresholds enforced (80% lines/functions/statements, 75% branches)
|
|
22
|
+
- Code quality tools
|
|
23
|
+
- ESLint with TypeScript-specific rules
|
|
24
|
+
- Prettier for consistent code formatting
|
|
25
|
+
- `./code-quality.sh` script for unified quality checks
|
|
26
|
+
- CI/CD integration
|
|
27
|
+
- GitHub Actions workflow running all quality checks on push/PR
|
|
28
|
+
- CI status badge in README
|
|
29
|
+
- npm scripts for testing, linting, and formatting
|
|
30
|
+
- Test helpers and mock implementations for isolated testing
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- MCP server version is now dynamically read from package.json instead of being hardcoded in src/index.ts
|
|
35
|
+
|
|
36
|
+
## [0.1.1] - 2026-02-07
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- README.md now includes explanation of stdio transport architecture and its implications (lifecycle management, message
|
|
41
|
+
protocol, logging constraints)
|
|
42
|
+
- AGENTS.md now references `.agents/dev-documentation.md` for documentation guidelines
|
|
43
|
+
- AGENTS.md now includes critical reminder to read `.agents/dev-workflow.md` before writing code or docs
|
|
44
|
+
- README.md now includes inline verification step for `npm link` using `which` command with concise explanation of what
|
|
45
|
+
npm link creates
|
|
46
|
+
- README.md now explains Node.js environment requirement for Claude Code CLI to execute the `remnote-mcp-server` command
|
|
47
|
+
- LICENSE file (MIT License)
|
|
48
|
+
- Repository, homepage, and bugs fields in package.json for npm registry
|
|
49
|
+
- Files field in package.json to explicitly control published files
|
|
50
|
+
- prepublishOnly script to ensure build before publishing
|
|
51
|
+
- Additional keywords for improved npm discoverability
|
|
52
|
+
- Coauthorship policy documented in CLAUDE.md
|
|
53
|
+
- Publishing documentation in docs/publishing.md for maintainers
|
|
54
|
+
|
|
55
|
+
### Fixed
|
|
56
|
+
|
|
57
|
+
- Version mismatch between package.json (0.1.0) and MCP server declaration (was 1.0.0)
|
|
58
|
+
- Corrected critical configuration error in all documentation files that would prevent users from successfully setting
|
|
59
|
+
up the server
|
|
60
|
+
|
|
61
|
+
### Changed
|
|
62
|
+
|
|
63
|
+
- **BREAKING**: Documentation now shows correct Claude Code configuration format using `~/.claude.json` with
|
|
64
|
+
`mcpServers` key instead of deprecated `~/.claude/.mcp.json` format
|
|
65
|
+
- Completely rewrote README.md for better user experience with comprehensive installation, verification,
|
|
66
|
+
troubleshooting, and usage examples
|
|
67
|
+
- Updated AGENTS.md with correct configuration format and deprecation notices
|
|
68
|
+
- Updated IMPLEMENTATION.md with correct configuration examples
|
|
69
|
+
|
|
70
|
+
### Removed
|
|
71
|
+
|
|
72
|
+
- Deleted CLAUDE_CODE_CONFIG.md (content consolidated into README.md and AGENTS.md to eliminate redundancy)
|
|
73
|
+
|
|
74
|
+
## [0.1.0] - 2026-02-06
|
|
75
|
+
|
|
76
|
+
### Added
|
|
77
|
+
|
|
78
|
+
- Initial release: RemNote MCP Server
|
|
79
|
+
- WebSocket server for RemNote plugin bridge
|
|
80
|
+
- MCP stdio transport for Claude Code integration
|
|
81
|
+
- Six RemNote tools: create_note, search, read_note, update_note, append_journal, status
|
|
82
|
+
- Request/response correlation with UUID tracking
|
|
83
|
+
- 5-second request timeout handling
|
|
84
|
+
- Heartbeat support (ping/pong)
|
|
85
|
+
- Single-client connection model
|
|
86
|
+
- Graceful shutdown handling (SIGINT/SIGTERM)
|
|
87
|
+
- Zod schema validation for all tool parameters
|
|
88
|
+
- TypeScript strict mode compilation
|
|
89
|
+
- Development mode with hot reload
|
|
90
|
+
- Global npm linking support
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 nightingale7 nightingale7@gmail.com
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,506 @@
|
|
|
1
|
+
# RemNote MCP Server
|
|
2
|
+
|
|
3
|
+
[](https://github.com/robert7/remnote-mcp-server/actions/workflows/ci.yml)
|
|
4
|
+
|
|
5
|
+
MCP server that bridges Claude Code (and other MCP clients) to [RemNote](https://remnote.com/) via the [RemNote MCP
|
|
6
|
+
Bridge plugin](https://github.com/robert7/remnote-mcp-bridge).
|
|
7
|
+
|
|
8
|
+
## What is This?
|
|
9
|
+
|
|
10
|
+
The RemNote MCP Server enables AI assistants like Claude Code to interact directly with your RemNote knowledge base
|
|
11
|
+
through the Model Context Protocol (MCP). This allows you to create notes, search your knowledge base, update existing
|
|
12
|
+
notes, and maintain your daily journal—all through conversational commands.
|
|
13
|
+
|
|
14
|
+
**Architecture:**
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
AI agent (e.g. Claude Code, MCP Client) ↔ MCP Server (stdio) ↔ WebSocket Server :3002 ↔ RemNote Plugin ↔ RemNote
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The server acts as a bridge:
|
|
21
|
+
|
|
22
|
+
- Communicates with Claude Code via stdio transport (MCP protocol)
|
|
23
|
+
- Runs a WebSocket server (port 3002) that the RemNote browser plugin connects to
|
|
24
|
+
- Translates MCP tool calls into RemNote API actions
|
|
25
|
+
|
|
26
|
+
## Features
|
|
27
|
+
|
|
28
|
+
- **Create Notes** - Create new notes with optional parent hierarchy and tags
|
|
29
|
+
- **Search Knowledge Base** - Full-text search with configurable result limits
|
|
30
|
+
- **Read Notes** - Retrieve note content with configurable child depth
|
|
31
|
+
- **Update Notes** - Modify titles, append content, add/remove tags
|
|
32
|
+
- **Journal Entries** - Append timestamped entries to daily documents
|
|
33
|
+
- **Connection Status** - Check server and plugin connection health
|
|
34
|
+
|
|
35
|
+
## Important Limitations
|
|
36
|
+
|
|
37
|
+
**This MCP server enforces a strict 1:1:1 relationship:** one AI agent ↔ one MCP server instance ↔ one RemNote plugin
|
|
38
|
+
connection.
|
|
39
|
+
|
|
40
|
+
### Multi-Agent Constraints
|
|
41
|
+
|
|
42
|
+
You **cannot** use multiple AI agents (e.g., two Claude Code sessions) with the same RemNote knowledge base
|
|
43
|
+
simultaneously. Three architectural constraints prevent this:
|
|
44
|
+
|
|
45
|
+
1. **stdio transport is point-to-point** - Each MCP server process communicates with exactly one AI agent via
|
|
46
|
+
stdin/stdout. The transport protocol doesn't support multiple clients.
|
|
47
|
+
2. **WebSocket enforces single-client** - The server explicitly rejects multiple RemNote plugin connections. Only one
|
|
48
|
+
plugin instance can connect to port 3002 at a time (connection code: 1008).
|
|
49
|
+
3. **Port binding conflict** - Multiple server instances attempting to use the default port 3002 will fail with
|
|
50
|
+
`EADDRINUSE`.
|
|
51
|
+
|
|
52
|
+
### Practical Implications
|
|
53
|
+
|
|
54
|
+
- **One agent at a time** - Close one Claude Code session before starting another if both need RemNote access
|
|
55
|
+
- **No concurrent access** - Cannot have multiple AI assistants modifying your RemNote knowledge base simultaneously
|
|
56
|
+
- **Separate workspaces don't help** - Even with different ports, only one plugin instance can connect to RemNote at a
|
|
57
|
+
time
|
|
58
|
+
|
|
59
|
+
### Alternative Approach
|
|
60
|
+
|
|
61
|
+
If you need multiple AI agents with separate note-taking systems, use separate RemNote accounts/workspaces and configure
|
|
62
|
+
each with its own MCP server instance on different ports.
|
|
63
|
+
|
|
64
|
+
### Future Plans
|
|
65
|
+
|
|
66
|
+
**HTTP transport migration planned** - The single-agent limitation is a temporary architectural constraint. A future
|
|
67
|
+
version will migrate from stdio transport to HTTP transport (SSE), which would allow multiple AI agents to connect
|
|
68
|
+
to the same MCP server instance simultaneously. This would remove constraint #1 above while maintaining the existing
|
|
69
|
+
WebSocket bridge to RemNote.
|
|
70
|
+
|
|
71
|
+
## Prerequisites
|
|
72
|
+
|
|
73
|
+
- **Node.js** >= 18.0.0
|
|
74
|
+
- **RemNote app** with [RemNote MCP Bridge plugin](https://github.com/robert7/remnote-mcp-bridge) installed
|
|
75
|
+
- **Claude Code CLI** installed and configured
|
|
76
|
+
|
|
77
|
+
## Installation
|
|
78
|
+
|
|
79
|
+
### 1. Install the MCP Server
|
|
80
|
+
|
|
81
|
+
**From source (recommended for development):**
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
git clone https://github.com/robert7/remnote-mcp-server.git
|
|
85
|
+
cd remnote-mcp-server
|
|
86
|
+
npm install
|
|
87
|
+
npm run build
|
|
88
|
+
|
|
89
|
+
# Creates global symlink: makes remnote-mcp-server command available system-wide
|
|
90
|
+
npm link
|
|
91
|
+
|
|
92
|
+
# Verify it worked
|
|
93
|
+
which remnote-mcp-server
|
|
94
|
+
# Should output e.g.: /Users/<username>/.nvm/versions/node/<version>/bin/remnote-mcp-server
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**What npm link does:** Creates a symbolic link from your global `node_modules` bin directory to this project's
|
|
98
|
+
executable, allowing Claude Code to launch `remnote-mcp-server` from anywhere without publishing to npm.
|
|
99
|
+
|
|
100
|
+
**Important:** Claude Code CLI must have access to the same Node.js environment where you ran `npm link`. If Claude Code
|
|
101
|
+
uses a different Node.js version or environment (e.g., different shell PATH), it won't find the command. Ensure your
|
|
102
|
+
shell configuration (`.bashrc`, `.zshrc`) properly exposes your Node.js environment.
|
|
103
|
+
|
|
104
|
+
**About stdio transport**
|
|
105
|
+
|
|
106
|
+
This MCP server uses [stdio transport](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#stdio),
|
|
107
|
+
the preferred communication mechanism for MCP. In stdio transport, Claude Code launches the server as a subprocess and
|
|
108
|
+
exchanges JSON-RPC messages via standard input/output streams.
|
|
109
|
+
|
|
110
|
+
**Key characteristics:**
|
|
111
|
+
|
|
112
|
+
- **Lifecycle management**: Claude Code automatically starts the server when it launches and stops it on exit. The
|
|
113
|
+
server is launched as a subprocess, not a standalone service.
|
|
114
|
+
- **Message protocol**: Communication uses newline-delimited JSON-RPC messages on stdin (client → server) and stdout
|
|
115
|
+
(server → client). No HTTP/REST endpoints are exposed.
|
|
116
|
+
- **Logging constraint**: stdout is reserved exclusively for MCP protocol messages. All logging must go to stderr, which
|
|
117
|
+
is why the codebase uses `console.error()` for logs.
|
|
118
|
+
|
|
119
|
+
This architecture provides tight integration with Claude Code while maintaining process isolation and security
|
|
120
|
+
boundaries. For technical details, see the [MCP
|
|
121
|
+
specification](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports).
|
|
122
|
+
|
|
123
|
+
### 2. Install RemNote MCP Bridge Plugin
|
|
124
|
+
|
|
125
|
+
Install the [RemNote MCP Bridge plugin](https://github.com/robert7/remnote-mcp-bridge) in your RemNote app:
|
|
126
|
+
|
|
127
|
+
1. Open RemNote
|
|
128
|
+
2. Navigate to plugin installation (see plugin repository for instructions)
|
|
129
|
+
3. Configure WebSocket URL: `ws://127.0.0.1:3002`
|
|
130
|
+
4. Enable auto-reconnect
|
|
131
|
+
|
|
132
|
+
### 3. Configure Claude Code CLI
|
|
133
|
+
|
|
134
|
+
MCP servers are configured in `~/.claude.json` under the `mcpServers` key within project-specific sections.
|
|
135
|
+
|
|
136
|
+
**Add to your `~/.claude.json`:**
|
|
137
|
+
|
|
138
|
+
```json
|
|
139
|
+
{
|
|
140
|
+
"projects": {
|
|
141
|
+
"/Users/username": {
|
|
142
|
+
"mcpServers": {
|
|
143
|
+
"remnote": {
|
|
144
|
+
"type": "stdio",
|
|
145
|
+
"command": "remnote-mcp-server",
|
|
146
|
+
"args": [],
|
|
147
|
+
"env": {
|
|
148
|
+
"REMNOTE_WS_PORT": "3002"
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
**Configuration Notes:**
|
|
158
|
+
|
|
159
|
+
- **Global availability:** Use your home directory path (`/Users/username`) to make RemNote tools available in all
|
|
160
|
+
projects
|
|
161
|
+
- **Project-specific:** Use a specific project path to limit availability to that project
|
|
162
|
+
- **Multiple projects:** Add `mcpServers` configuration under each project path as needed
|
|
163
|
+
|
|
164
|
+
**Example with multiple projects:**
|
|
165
|
+
|
|
166
|
+
```json
|
|
167
|
+
{
|
|
168
|
+
"projects": {
|
|
169
|
+
"/Users/username": {
|
|
170
|
+
"mcpServers": {
|
|
171
|
+
"remnote": {
|
|
172
|
+
"type": "stdio",
|
|
173
|
+
"command": "remnote-mcp-server",
|
|
174
|
+
"args": [],
|
|
175
|
+
"env": {
|
|
176
|
+
"REMNOTE_WS_PORT": "3002"
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
"/Users/username/Projects/my-project": {
|
|
182
|
+
"mcpServers": {
|
|
183
|
+
"remnote": {
|
|
184
|
+
"type": "stdio",
|
|
185
|
+
"command": "remnote-mcp-server",
|
|
186
|
+
"args": [],
|
|
187
|
+
"env": {
|
|
188
|
+
"REMNOTE_WS_PORT": "3002"
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### 4. Restart Claude Code
|
|
198
|
+
|
|
199
|
+
Restart Claude Code completely to load the MCP server configuration. The server will start automatically when Claude
|
|
200
|
+
Code launches.
|
|
201
|
+
|
|
202
|
+
## Verification
|
|
203
|
+
|
|
204
|
+
### Check Server is Running
|
|
205
|
+
|
|
206
|
+
After Claude Code restarts, verify the server started:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
# Check process is running
|
|
210
|
+
ps aux | grep remnote-mcp-server
|
|
211
|
+
|
|
212
|
+
# Check WebSocket port is listening
|
|
213
|
+
lsof -i :3002
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
You should see the `remnote-mcp-server` process running.
|
|
217
|
+
|
|
218
|
+
### Check RemNote Plugin Connection
|
|
219
|
+
|
|
220
|
+
Open RemNote with the MCP Bridge plugin installed. The plugin control panel should show:
|
|
221
|
+
|
|
222
|
+
- **Status:** "Connected" (green)
|
|
223
|
+
- **Server:** ws://127.0.0.1:3002
|
|
224
|
+
- Connection timestamp
|
|
225
|
+
|
|
226
|
+
### Test in Claude Code
|
|
227
|
+
|
|
228
|
+
In any Claude Code session, try:
|
|
229
|
+
|
|
230
|
+
```
|
|
231
|
+
Use remnote_status to check the connection
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Expected response:
|
|
235
|
+
|
|
236
|
+
```json
|
|
237
|
+
{
|
|
238
|
+
"connected": true,
|
|
239
|
+
"actionsProcessed": 0,
|
|
240
|
+
"pluginVersion": "1.1.0",
|
|
241
|
+
"timestamp": "2026-02-07T..."
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Test RemNote Integration
|
|
246
|
+
|
|
247
|
+
Try creating a note:
|
|
248
|
+
|
|
249
|
+
```
|
|
250
|
+
Create a RemNote note titled "MCP Test" with content "Testing the bridge"
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
This should use the `remnote_create_note` tool and create a new note in your RemNote knowledge base.
|
|
254
|
+
|
|
255
|
+
## Available Tools
|
|
256
|
+
|
|
257
|
+
| Tool | Description | Parameters |
|
|
258
|
+
|------|-------------|------------|
|
|
259
|
+
| `remnote_create_note` | Create a new note with optional parent and tags | `title`, `content`, `parentId`, `tags` |
|
|
260
|
+
| `remnote_search` | Search knowledge base | `query`, `limit`, `includeContent` |
|
|
261
|
+
| `remnote_read_note` | Read note by RemNote ID | `remId`, `depth` |
|
|
262
|
+
| `remnote_update_note` | Update title, append content, or modify tags | `remId`, `title`, `appendContent`, `addTags`, `removeTags` |
|
|
263
|
+
| `remnote_append_journal` | Append to today's daily document | `content`, `timestamp` |
|
|
264
|
+
| `remnote_status` | Check connection status and statistics | _(no parameters)_ |
|
|
265
|
+
|
|
266
|
+
## Example Usage
|
|
267
|
+
|
|
268
|
+
### Conversational Commands
|
|
269
|
+
|
|
270
|
+
Claude Code will automatically select the appropriate tool based on your natural language commands:
|
|
271
|
+
|
|
272
|
+
**Create notes:**
|
|
273
|
+
```
|
|
274
|
+
Create a note about "Project Ideas" with content:
|
|
275
|
+
- AI-powered note taking
|
|
276
|
+
- Personal knowledge management
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
**Search:**
|
|
280
|
+
```
|
|
281
|
+
Search my RemNote for notes about "machine learning"
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
**Read specific notes:**
|
|
285
|
+
```
|
|
286
|
+
Read the note with ID abc123
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
**Update notes:**
|
|
290
|
+
```
|
|
291
|
+
Add a tag "important" to note abc123
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
**Journal entries:**
|
|
295
|
+
```
|
|
296
|
+
Add to my journal: "Completed the RemNote MCP integration"
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
**Check status:**
|
|
300
|
+
```
|
|
301
|
+
Check if RemNote is connected
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Configuration
|
|
305
|
+
|
|
306
|
+
### Environment Variables
|
|
307
|
+
|
|
308
|
+
- `REMNOTE_WS_PORT` - WebSocket server port (default: 3002)
|
|
309
|
+
|
|
310
|
+
**Example with custom port:**
|
|
311
|
+
|
|
312
|
+
```json
|
|
313
|
+
{
|
|
314
|
+
"projects": {
|
|
315
|
+
"/Users/username": {
|
|
316
|
+
"mcpServers": {
|
|
317
|
+
"remnote": {
|
|
318
|
+
"type": "stdio",
|
|
319
|
+
"command": "remnote-mcp-server",
|
|
320
|
+
"args": [],
|
|
321
|
+
"env": {
|
|
322
|
+
"REMNOTE_WS_PORT": "3003"
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
**Note:** If you change the port, you must also update the WebSocket URL in the RemNote MCP Bridge plugin settings.
|
|
332
|
+
|
|
333
|
+
### RemNote Plugin Settings
|
|
334
|
+
|
|
335
|
+
Configure in the plugin control panel:
|
|
336
|
+
|
|
337
|
+
- **WebSocket URL:** `ws://127.0.0.1:3002` (or your custom port)
|
|
338
|
+
- **Auto-reconnect:** Enabled (recommended)
|
|
339
|
+
|
|
340
|
+
## Troubleshooting
|
|
341
|
+
|
|
342
|
+
### Server Not Starting
|
|
343
|
+
|
|
344
|
+
1. **Check if globally linked:**
|
|
345
|
+
```bash
|
|
346
|
+
which remnote-mcp-server
|
|
347
|
+
```
|
|
348
|
+
Should return a path to the executable.
|
|
349
|
+
|
|
350
|
+
2. **Re-link if needed:**
|
|
351
|
+
```bash
|
|
352
|
+
cd ~/Projects/_private/remnote-mcp-server
|
|
353
|
+
npm link
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
3. **Check Claude Code logs:**
|
|
357
|
+
```bash
|
|
358
|
+
tail -f ~/.claude/debug/mcp-*.log
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Port 3002 Already in Use
|
|
362
|
+
|
|
363
|
+
If you see "EADDRINUSE" error:
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
# Find what's using the port
|
|
367
|
+
lsof -i :3002
|
|
368
|
+
|
|
369
|
+
# Kill the process if needed
|
|
370
|
+
kill -9 <PID>
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
Alternatively, configure a different port in both `~/.claude.json` and the RemNote plugin settings.
|
|
374
|
+
|
|
375
|
+
### Plugin Won't Connect
|
|
376
|
+
|
|
377
|
+
1. **Verify plugin settings in RemNote:**
|
|
378
|
+
- WebSocket URL: `ws://127.0.0.1:3002`
|
|
379
|
+
- Auto-reconnect: Enabled
|
|
380
|
+
2. **Check plugin console (RemNote Developer Tools):**
|
|
381
|
+
```
|
|
382
|
+
Cmd+Option+I (macOS)
|
|
383
|
+
Ctrl+Shift+I (Windows/Linux)
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
3. **Restart RemNote** after changing settings
|
|
387
|
+
4. **Check server logs** for connection messages
|
|
388
|
+
|
|
389
|
+
### Tools Not Appearing in Claude Code
|
|
390
|
+
|
|
391
|
+
1. **Verify configuration in `~/.claude.json`:**
|
|
392
|
+
```bash
|
|
393
|
+
cat ~/.claude.json | grep -A 10 mcpServers
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
2. **Ensure configuration is under correct project path** (use home directory for global)
|
|
397
|
+
3. **Restart Claude Code completely** (not just reload)
|
|
398
|
+
4. **Check MCP logs:**
|
|
399
|
+
```bash
|
|
400
|
+
tail -f ~/.claude/debug/mcp-*.log
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
### Configuration Not Working
|
|
404
|
+
|
|
405
|
+
**Common issue:** Using the old `~/.claude/.mcp.json` file format
|
|
406
|
+
|
|
407
|
+
❌ **Old format (deprecated):**
|
|
408
|
+
```json
|
|
409
|
+
// File: ~/.claude/.mcp.json
|
|
410
|
+
{
|
|
411
|
+
"remnote": { ... }
|
|
412
|
+
}
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
✅ **Correct format:**
|
|
416
|
+
```json
|
|
417
|
+
// File: ~/.claude.json
|
|
418
|
+
{
|
|
419
|
+
"projects": {
|
|
420
|
+
"/Users/username": {
|
|
421
|
+
"mcpServers": {
|
|
422
|
+
"remnote": { ... }
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
The `enabledMcpjsonServers` setting in `~/.claude/settings.json` is also deprecated and no longer needed.
|
|
430
|
+
|
|
431
|
+
## Development
|
|
432
|
+
|
|
433
|
+
### Setup
|
|
434
|
+
|
|
435
|
+
```bash
|
|
436
|
+
npm install
|
|
437
|
+
npm run build
|
|
438
|
+
npm link # Make command globally available
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
### Development Workflow
|
|
442
|
+
|
|
443
|
+
```bash
|
|
444
|
+
npm run dev # Watch mode with hot reload
|
|
445
|
+
npm run typecheck # Type checking only
|
|
446
|
+
npm run build # Production build
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### Testing
|
|
450
|
+
|
|
451
|
+
```bash
|
|
452
|
+
npm test # Run all tests
|
|
453
|
+
npm run test:watch # Watch mode
|
|
454
|
+
npm run test:coverage # With coverage report
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
### Code Quality
|
|
458
|
+
|
|
459
|
+
```bash
|
|
460
|
+
./code-quality.sh # Run all checks
|
|
461
|
+
npm run lint # ESLint only
|
|
462
|
+
npm run format # Format code
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Before Committing
|
|
466
|
+
|
|
467
|
+
Run `./code-quality.sh` to ensure all checks pass.
|
|
468
|
+
|
|
469
|
+
### Manual Testing
|
|
470
|
+
|
|
471
|
+
To test the server independently (without Claude Code):
|
|
472
|
+
|
|
473
|
+
```bash
|
|
474
|
+
# Stop Claude Code first to free port 3002
|
|
475
|
+
cd ~/Projects/_private/remnote-mcp-server
|
|
476
|
+
npm run dev
|
|
477
|
+
```
|
|
478
|
+
|
|
479
|
+
Expected output:
|
|
480
|
+
```
|
|
481
|
+
[WebSocket Server] Listening on port 3002
|
|
482
|
+
[MCP Server] Server started on stdio
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
When the RemNote plugin connects:
|
|
486
|
+
```
|
|
487
|
+
[WebSocket Server] Client connected
|
|
488
|
+
[RemNote Bridge] RemNote plugin connected
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
Press Ctrl+C to stop.
|
|
492
|
+
|
|
493
|
+
### Development Documentation
|
|
494
|
+
|
|
495
|
+
- **[IMPLEMENTATION.md](./IMPLEMENTATION.md)** - Technical implementation details
|
|
496
|
+
- **[AGENTS.md](./AGENTS.md)** - AI agent and developer guidance
|
|
497
|
+
- **[CHANGELOG.md](./CHANGELOG.md)** - Version history
|
|
498
|
+
|
|
499
|
+
## Related Projects
|
|
500
|
+
|
|
501
|
+
- [RemNote MCP Bridge Plugin](https://github.com/robert7/remnote-mcp-bridge) - Browser plugin for RemNote integration
|
|
502
|
+
- [Model Context Protocol](https://modelcontextprotocol.io/) - Open protocol for AI-application integration
|
|
503
|
+
|
|
504
|
+
## License
|
|
505
|
+
|
|
506
|
+
MIT
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
3
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
4
|
+
import { createRequire } from 'module';
|
|
5
|
+
import { WebSocketServer } from './websocket-server.js';
|
|
6
|
+
import { registerAllTools } from './tools/index.js';
|
|
7
|
+
const require = createRequire(import.meta.url);
|
|
8
|
+
const packageJson = require('../package.json');
|
|
9
|
+
const WS_PORT = parseInt(process.env.REMNOTE_WS_PORT || '3002', 10);
|
|
10
|
+
async function main() {
|
|
11
|
+
// Initialize MCP server
|
|
12
|
+
const mcpServer = new Server({
|
|
13
|
+
name: 'remnote-mcp-server',
|
|
14
|
+
version: packageJson.version,
|
|
15
|
+
}, {
|
|
16
|
+
capabilities: {
|
|
17
|
+
tools: {},
|
|
18
|
+
},
|
|
19
|
+
});
|
|
20
|
+
// Initialize WebSocket server for RemNote plugin
|
|
21
|
+
const wsServer = new WebSocketServer(WS_PORT);
|
|
22
|
+
// Log connection status to stderr (stdio reserved for MCP)
|
|
23
|
+
wsServer.onClientConnect(() => {
|
|
24
|
+
console.error('[RemNote Bridge] RemNote plugin connected');
|
|
25
|
+
});
|
|
26
|
+
wsServer.onClientDisconnect(() => {
|
|
27
|
+
console.error('[RemNote Bridge] RemNote plugin disconnected');
|
|
28
|
+
});
|
|
29
|
+
// Start WebSocket server
|
|
30
|
+
await wsServer.start();
|
|
31
|
+
console.error(`[WebSocket Server] Listening on port ${WS_PORT}`);
|
|
32
|
+
// Register all RemNote MCP tools
|
|
33
|
+
registerAllTools(mcpServer, wsServer);
|
|
34
|
+
// Set up stdio transport for MCP
|
|
35
|
+
const transport = new StdioServerTransport();
|
|
36
|
+
await mcpServer.connect(transport);
|
|
37
|
+
console.error('[MCP Server] Server started on stdio');
|
|
38
|
+
// Graceful shutdown
|
|
39
|
+
const shutdown = async () => {
|
|
40
|
+
console.error('[MCP Server] Shutting down...');
|
|
41
|
+
await wsServer.stop();
|
|
42
|
+
await mcpServer.close();
|
|
43
|
+
process.exit(0);
|
|
44
|
+
};
|
|
45
|
+
process.on('SIGINT', shutdown);
|
|
46
|
+
process.on('SIGTERM', shutdown);
|
|
47
|
+
}
|
|
48
|
+
main().catch((error) => {
|
|
49
|
+
console.error('[MCP Server] Fatal error:', error);
|
|
50
|
+
process.exit(1);
|
|
51
|
+
});
|
|
52
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AACvC,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEpD,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,WAAW,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAE/C,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,MAAM,EAAE,EAAE,CAAC,CAAC;AAEpE,KAAK,UAAU,IAAI;IACjB,wBAAwB;IACxB,MAAM,SAAS,GAAG,IAAI,MAAM,CAC1B;QACE,IAAI,EAAE,oBAAoB;QAC1B,OAAO,EAAE,WAAW,CAAC,OAAO;KAC7B,EACD;QACE,YAAY,EAAE;YACZ,KAAK,EAAE,EAAE;SACV;KACF,CACF,CAAC;IAEF,iDAAiD;IACjD,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,OAAO,CAAC,CAAC;IAE9C,2DAA2D;IAC3D,QAAQ,CAAC,eAAe,CAAC,GAAG,EAAE;QAC5B,OAAO,CAAC,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,kBAAkB,CAAC,GAAG,EAAE;QAC/B,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAChE,CAAC,CAAC,CAAC;IAEH,yBAAyB;IACzB,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC;IACvB,OAAO,CAAC,KAAK,CAAC,wCAAwC,OAAO,EAAE,CAAC,CAAC;IAEjE,iCAAiC;IACjC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAEtC,iCAAiC;IACjC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEnC,OAAO,CAAC,KAAK,CAAC,sCAAsC,CAAC,CAAC;IAEtD,oBAAoB;IACpB,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;QAC1B,OAAO,CAAC,KAAK,CAAC,+BAA+B,CAAC,CAAC;QAC/C,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACtB,MAAM,SAAS,CAAC,KAAK,EAAE,CAAC;QACxB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC;IAEF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IAC/B,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAClC,CAAC;AAED,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE;IACrB,OAAO,CAAC,KAAK,CAAC,2BAA2B,EAAE,KAAK,CAAC,CAAC;IAClD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const CreateNoteSchema: z.ZodObject<{
|
|
3
|
+
title: z.ZodString;
|
|
4
|
+
content: z.ZodOptional<z.ZodString>;
|
|
5
|
+
parentId: z.ZodOptional<z.ZodString>;
|
|
6
|
+
tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
7
|
+
}, z.core.$strip>;
|
|
8
|
+
export declare const SearchSchema: z.ZodObject<{
|
|
9
|
+
query: z.ZodString;
|
|
10
|
+
limit: z.ZodDefault<z.ZodNumber>;
|
|
11
|
+
includeContent: z.ZodDefault<z.ZodBoolean>;
|
|
12
|
+
}, z.core.$strip>;
|
|
13
|
+
export declare const ReadNoteSchema: z.ZodObject<{
|
|
14
|
+
remId: z.ZodString;
|
|
15
|
+
depth: z.ZodDefault<z.ZodNumber>;
|
|
16
|
+
}, z.core.$strip>;
|
|
17
|
+
export declare const UpdateNoteSchema: z.ZodObject<{
|
|
18
|
+
remId: z.ZodString;
|
|
19
|
+
title: z.ZodOptional<z.ZodString>;
|
|
20
|
+
appendContent: z.ZodOptional<z.ZodString>;
|
|
21
|
+
addTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
22
|
+
removeTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
23
|
+
}, z.core.$strip>;
|
|
24
|
+
export declare const AppendJournalSchema: z.ZodObject<{
|
|
25
|
+
content: z.ZodString;
|
|
26
|
+
timestamp: z.ZodDefault<z.ZodBoolean>;
|
|
27
|
+
}, z.core.$strip>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const CreateNoteSchema = z.object({
|
|
3
|
+
title: z.string().describe('The title of the note'),
|
|
4
|
+
content: z.string().optional().describe('Content as child bullets (newline-separated)'),
|
|
5
|
+
parentId: z.string().optional().describe('Parent Rem ID'),
|
|
6
|
+
tags: z.array(z.string()).optional().describe('Tags to apply'),
|
|
7
|
+
});
|
|
8
|
+
export const SearchSchema = z.object({
|
|
9
|
+
query: z.string().describe('Search query text'),
|
|
10
|
+
limit: z.number().int().min(1).max(100).default(20).describe('Maximum results'),
|
|
11
|
+
includeContent: z.boolean().default(false).describe('Include child content'),
|
|
12
|
+
});
|
|
13
|
+
export const ReadNoteSchema = z.object({
|
|
14
|
+
remId: z.string().describe('The Rem ID to read'),
|
|
15
|
+
depth: z.number().int().min(0).max(10).default(3).describe('Depth of children'),
|
|
16
|
+
});
|
|
17
|
+
export const UpdateNoteSchema = z.object({
|
|
18
|
+
remId: z.string().describe('The Rem ID to update'),
|
|
19
|
+
title: z.string().optional().describe('New title'),
|
|
20
|
+
appendContent: z.string().optional().describe('Content to append as children'),
|
|
21
|
+
addTags: z.array(z.string()).optional().describe('Tags to add'),
|
|
22
|
+
removeTags: z.array(z.string()).optional().describe('Tags to remove'),
|
|
23
|
+
});
|
|
24
|
+
export const AppendJournalSchema = z.object({
|
|
25
|
+
content: z.string().describe("Content to append to today's daily document"),
|
|
26
|
+
timestamp: z.boolean().default(true).describe('Include timestamp'),
|
|
27
|
+
});
|
|
28
|
+
//# sourceMappingURL=remnote-schemas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remnote-schemas.js","sourceRoot":"","sources":["../../src/schemas/remnote-schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,uBAAuB,CAAC;IACnD,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,8CAA8C,CAAC;IACvF,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;IACzD,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,eAAe,CAAC;CAC/D,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IACnC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,mBAAmB,CAAC;IAC/C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,iBAAiB,CAAC;IAC/E,cAAc,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,uBAAuB,CAAC;CAC7E,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,CAAC,MAAM,CAAC;IACrC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,oBAAoB,CAAC;IAChD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC;CAChF,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC,MAAM,CAAC;IACvC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,sBAAsB,CAAC;IAClD,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;IAClD,aAAa,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,+BAA+B,CAAC;IAC9E,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,aAAa,CAAC;IAC/D,UAAU,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,gBAAgB,CAAC;CACtE,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC1C,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,6CAA6C,CAAC;IAC3E,SAAS,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC;CACnE,CAAC,CAAC"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import { WebSocketServer } from '../websocket-server.js';
|
|
3
|
+
export declare const CREATE_NOTE_TOOL: {
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
inputSchema: {
|
|
7
|
+
type: "object";
|
|
8
|
+
properties: {
|
|
9
|
+
title: {
|
|
10
|
+
type: string;
|
|
11
|
+
description: string;
|
|
12
|
+
};
|
|
13
|
+
content: {
|
|
14
|
+
type: string;
|
|
15
|
+
description: string;
|
|
16
|
+
};
|
|
17
|
+
parentId: {
|
|
18
|
+
type: string;
|
|
19
|
+
description: string;
|
|
20
|
+
};
|
|
21
|
+
tags: {
|
|
22
|
+
type: string;
|
|
23
|
+
items: {
|
|
24
|
+
type: string;
|
|
25
|
+
};
|
|
26
|
+
description: string;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
required: string[];
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
export declare const SEARCH_TOOL: {
|
|
33
|
+
name: string;
|
|
34
|
+
description: string;
|
|
35
|
+
inputSchema: {
|
|
36
|
+
type: "object";
|
|
37
|
+
properties: {
|
|
38
|
+
query: {
|
|
39
|
+
type: string;
|
|
40
|
+
description: string;
|
|
41
|
+
};
|
|
42
|
+
limit: {
|
|
43
|
+
type: string;
|
|
44
|
+
description: string;
|
|
45
|
+
};
|
|
46
|
+
includeContent: {
|
|
47
|
+
type: string;
|
|
48
|
+
description: string;
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
required: string[];
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
export declare const READ_NOTE_TOOL: {
|
|
55
|
+
name: string;
|
|
56
|
+
description: string;
|
|
57
|
+
inputSchema: {
|
|
58
|
+
type: "object";
|
|
59
|
+
properties: {
|
|
60
|
+
remId: {
|
|
61
|
+
type: string;
|
|
62
|
+
description: string;
|
|
63
|
+
};
|
|
64
|
+
depth: {
|
|
65
|
+
type: string;
|
|
66
|
+
description: string;
|
|
67
|
+
};
|
|
68
|
+
};
|
|
69
|
+
required: string[];
|
|
70
|
+
};
|
|
71
|
+
};
|
|
72
|
+
export declare const UPDATE_NOTE_TOOL: {
|
|
73
|
+
name: string;
|
|
74
|
+
description: string;
|
|
75
|
+
inputSchema: {
|
|
76
|
+
type: "object";
|
|
77
|
+
properties: {
|
|
78
|
+
remId: {
|
|
79
|
+
type: string;
|
|
80
|
+
description: string;
|
|
81
|
+
};
|
|
82
|
+
title: {
|
|
83
|
+
type: string;
|
|
84
|
+
description: string;
|
|
85
|
+
};
|
|
86
|
+
appendContent: {
|
|
87
|
+
type: string;
|
|
88
|
+
description: string;
|
|
89
|
+
};
|
|
90
|
+
addTags: {
|
|
91
|
+
type: string;
|
|
92
|
+
items: {
|
|
93
|
+
type: string;
|
|
94
|
+
};
|
|
95
|
+
description: string;
|
|
96
|
+
};
|
|
97
|
+
removeTags: {
|
|
98
|
+
type: string;
|
|
99
|
+
items: {
|
|
100
|
+
type: string;
|
|
101
|
+
};
|
|
102
|
+
description: string;
|
|
103
|
+
};
|
|
104
|
+
};
|
|
105
|
+
required: string[];
|
|
106
|
+
};
|
|
107
|
+
};
|
|
108
|
+
export declare const APPEND_JOURNAL_TOOL: {
|
|
109
|
+
name: string;
|
|
110
|
+
description: string;
|
|
111
|
+
inputSchema: {
|
|
112
|
+
type: "object";
|
|
113
|
+
properties: {
|
|
114
|
+
content: {
|
|
115
|
+
type: string;
|
|
116
|
+
description: string;
|
|
117
|
+
};
|
|
118
|
+
timestamp: {
|
|
119
|
+
type: string;
|
|
120
|
+
description: string;
|
|
121
|
+
};
|
|
122
|
+
};
|
|
123
|
+
required: string[];
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
export declare const STATUS_TOOL: {
|
|
127
|
+
name: string;
|
|
128
|
+
description: string;
|
|
129
|
+
inputSchema: {
|
|
130
|
+
type: "object";
|
|
131
|
+
properties: {};
|
|
132
|
+
};
|
|
133
|
+
};
|
|
134
|
+
export declare function registerAllTools(server: Server, wsServer: WebSocketServer): void;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
2
|
+
import { CreateNoteSchema } from '../schemas/remnote-schemas.js';
|
|
3
|
+
import { SearchSchema } from '../schemas/remnote-schemas.js';
|
|
4
|
+
import { ReadNoteSchema } from '../schemas/remnote-schemas.js';
|
|
5
|
+
import { UpdateNoteSchema } from '../schemas/remnote-schemas.js';
|
|
6
|
+
import { AppendJournalSchema } from '../schemas/remnote-schemas.js';
|
|
7
|
+
export const CREATE_NOTE_TOOL = {
|
|
8
|
+
name: 'remnote_create_note',
|
|
9
|
+
description: 'Create a new note in RemNote with optional content, parent, and tags',
|
|
10
|
+
inputSchema: {
|
|
11
|
+
type: 'object',
|
|
12
|
+
properties: {
|
|
13
|
+
title: { type: 'string', description: 'The title of the note' },
|
|
14
|
+
content: { type: 'string', description: 'Content as child bullets (newline-separated)' },
|
|
15
|
+
parentId: { type: 'string', description: 'Parent Rem ID' },
|
|
16
|
+
tags: { type: 'array', items: { type: 'string' }, description: 'Tags to apply' },
|
|
17
|
+
},
|
|
18
|
+
required: ['title'],
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
export const SEARCH_TOOL = {
|
|
22
|
+
name: 'remnote_search',
|
|
23
|
+
description: 'Search the RemNote knowledge base for notes matching a query',
|
|
24
|
+
inputSchema: {
|
|
25
|
+
type: 'object',
|
|
26
|
+
properties: {
|
|
27
|
+
query: { type: 'string', description: 'Search query text' },
|
|
28
|
+
limit: { type: 'number', description: 'Maximum results (1-100, default: 20)' },
|
|
29
|
+
includeContent: { type: 'boolean', description: 'Include child content (default: false)' },
|
|
30
|
+
},
|
|
31
|
+
required: ['query'],
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
export const READ_NOTE_TOOL = {
|
|
35
|
+
name: 'remnote_read_note',
|
|
36
|
+
description: 'Read a specific note from RemNote by its Rem ID',
|
|
37
|
+
inputSchema: {
|
|
38
|
+
type: 'object',
|
|
39
|
+
properties: {
|
|
40
|
+
remId: { type: 'string', description: 'The Rem ID to read' },
|
|
41
|
+
depth: { type: 'number', description: 'Depth of children to include (0-10, default: 3)' },
|
|
42
|
+
},
|
|
43
|
+
required: ['remId'],
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
export const UPDATE_NOTE_TOOL = {
|
|
47
|
+
name: 'remnote_update_note',
|
|
48
|
+
description: 'Update an existing note in RemNote (change title, append content, or modify tags)',
|
|
49
|
+
inputSchema: {
|
|
50
|
+
type: 'object',
|
|
51
|
+
properties: {
|
|
52
|
+
remId: { type: 'string', description: 'The Rem ID to update' },
|
|
53
|
+
title: { type: 'string', description: 'New title' },
|
|
54
|
+
appendContent: { type: 'string', description: 'Content to append as children' },
|
|
55
|
+
addTags: { type: 'array', items: { type: 'string' }, description: 'Tags to add' },
|
|
56
|
+
removeTags: { type: 'array', items: { type: 'string' }, description: 'Tags to remove' },
|
|
57
|
+
},
|
|
58
|
+
required: ['remId'],
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
export const APPEND_JOURNAL_TOOL = {
|
|
62
|
+
name: 'remnote_append_journal',
|
|
63
|
+
description: "Append content to today's daily document in RemNote",
|
|
64
|
+
inputSchema: {
|
|
65
|
+
type: 'object',
|
|
66
|
+
properties: {
|
|
67
|
+
content: { type: 'string', description: "Content to append to today's daily document" },
|
|
68
|
+
timestamp: { type: 'boolean', description: 'Include timestamp (default: true)' },
|
|
69
|
+
},
|
|
70
|
+
required: ['content'],
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
export const STATUS_TOOL = {
|
|
74
|
+
name: 'remnote_status',
|
|
75
|
+
description: 'Check the connection status and statistics of the RemNote MCP bridge',
|
|
76
|
+
inputSchema: {
|
|
77
|
+
type: 'object',
|
|
78
|
+
properties: {},
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
export function registerAllTools(server, wsServer) {
|
|
82
|
+
// Single CallTool handler for all tools
|
|
83
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
84
|
+
try {
|
|
85
|
+
switch (request.params.name) {
|
|
86
|
+
case 'remnote_create_note': {
|
|
87
|
+
const args = CreateNoteSchema.parse(request.params.arguments);
|
|
88
|
+
const result = await wsServer.sendRequest('create_note', args);
|
|
89
|
+
return {
|
|
90
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
case 'remnote_search': {
|
|
94
|
+
const args = SearchSchema.parse(request.params.arguments);
|
|
95
|
+
const result = await wsServer.sendRequest('search', args);
|
|
96
|
+
return {
|
|
97
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
case 'remnote_read_note': {
|
|
101
|
+
const args = ReadNoteSchema.parse(request.params.arguments);
|
|
102
|
+
const result = await wsServer.sendRequest('read_note', args);
|
|
103
|
+
return {
|
|
104
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
case 'remnote_update_note': {
|
|
108
|
+
const args = UpdateNoteSchema.parse(request.params.arguments);
|
|
109
|
+
const result = await wsServer.sendRequest('update_note', args);
|
|
110
|
+
return {
|
|
111
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
case 'remnote_append_journal': {
|
|
115
|
+
const args = AppendJournalSchema.parse(request.params.arguments);
|
|
116
|
+
const result = await wsServer.sendRequest('append_journal', args);
|
|
117
|
+
return {
|
|
118
|
+
content: [{ type: 'text', text: JSON.stringify(result, null, 2) }],
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
case 'remnote_status': {
|
|
122
|
+
const connected = wsServer.isConnected();
|
|
123
|
+
if (!connected) {
|
|
124
|
+
return {
|
|
125
|
+
content: [
|
|
126
|
+
{
|
|
127
|
+
type: 'text',
|
|
128
|
+
text: JSON.stringify({ connected: false, message: 'RemNote plugin not connected' }, null, 2),
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
const result = await wsServer.sendRequest('status', {});
|
|
134
|
+
return {
|
|
135
|
+
content: [
|
|
136
|
+
{
|
|
137
|
+
type: 'text',
|
|
138
|
+
text: JSON.stringify({ connected: true, ...(typeof result === 'object' ? result : {}) }, null, 2),
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
default:
|
|
144
|
+
throw new Error(`Unknown tool: ${request.params.name}`);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
return {
|
|
149
|
+
content: [
|
|
150
|
+
{
|
|
151
|
+
type: 'text',
|
|
152
|
+
text: `Error: ${error instanceof Error ? error.message : String(error)}`,
|
|
153
|
+
},
|
|
154
|
+
],
|
|
155
|
+
isError: true,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
// Register list_tools handler
|
|
160
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
161
|
+
tools: [
|
|
162
|
+
CREATE_NOTE_TOOL,
|
|
163
|
+
SEARCH_TOOL,
|
|
164
|
+
READ_NOTE_TOOL,
|
|
165
|
+
UPDATE_NOTE_TOOL,
|
|
166
|
+
APPEND_JOURNAL_TOOL,
|
|
167
|
+
STATUS_TOOL,
|
|
168
|
+
],
|
|
169
|
+
}));
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request sent TO RemNote plugin
|
|
3
|
+
*/
|
|
4
|
+
export interface BridgeRequest {
|
|
5
|
+
id: string;
|
|
6
|
+
action: string;
|
|
7
|
+
payload: Record<string, unknown>;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Response received FROM RemNote plugin
|
|
11
|
+
*/
|
|
12
|
+
export interface BridgeResponse {
|
|
13
|
+
id: string;
|
|
14
|
+
result?: unknown;
|
|
15
|
+
error?: string;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Heartbeat messages
|
|
19
|
+
*/
|
|
20
|
+
export interface HeartbeatPing {
|
|
21
|
+
type: 'ping';
|
|
22
|
+
}
|
|
23
|
+
export interface HeartbeatPong {
|
|
24
|
+
type: 'pong';
|
|
25
|
+
}
|
|
26
|
+
export type BridgeMessage = BridgeRequest | BridgeResponse | HeartbeatPing | HeartbeatPong;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../src/types/bridge.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export declare class WebSocketServer {
|
|
2
|
+
private wss;
|
|
3
|
+
private client;
|
|
4
|
+
private port;
|
|
5
|
+
private pendingRequests;
|
|
6
|
+
private connectCallbacks;
|
|
7
|
+
private disconnectCallbacks;
|
|
8
|
+
constructor(port: number);
|
|
9
|
+
start(): Promise<void>;
|
|
10
|
+
stop(): Promise<void>;
|
|
11
|
+
sendRequest(action: string, payload: Record<string, unknown>): Promise<unknown>;
|
|
12
|
+
isConnected(): boolean;
|
|
13
|
+
onClientConnect(callback: () => void): void;
|
|
14
|
+
onClientDisconnect(callback: () => void): void;
|
|
15
|
+
private handleMessage;
|
|
16
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { WebSocketServer as WSServer, WebSocket } from 'ws';
|
|
2
|
+
import { randomUUID } from 'crypto';
|
|
3
|
+
export class WebSocketServer {
|
|
4
|
+
wss = null;
|
|
5
|
+
client = null;
|
|
6
|
+
port;
|
|
7
|
+
pendingRequests = new Map();
|
|
8
|
+
connectCallbacks = [];
|
|
9
|
+
disconnectCallbacks = [];
|
|
10
|
+
constructor(port) {
|
|
11
|
+
this.port = port;
|
|
12
|
+
}
|
|
13
|
+
async start() {
|
|
14
|
+
return new Promise((resolve, reject) => {
|
|
15
|
+
this.wss = new WSServer({ port: this.port }, () => {
|
|
16
|
+
resolve();
|
|
17
|
+
});
|
|
18
|
+
this.wss.on('error', (error) => {
|
|
19
|
+
console.error('[WebSocket Server] Error:', error);
|
|
20
|
+
reject(error);
|
|
21
|
+
});
|
|
22
|
+
this.wss.on('connection', (ws) => {
|
|
23
|
+
// Only allow single client connection
|
|
24
|
+
if (this.client && this.client.readyState === WebSocket.OPEN) {
|
|
25
|
+
console.error('[WebSocket Server] Rejecting connection: client already connected');
|
|
26
|
+
ws.close(1008, 'Only one client allowed');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
this.client = ws;
|
|
30
|
+
console.error('[WebSocket Server] Client connected');
|
|
31
|
+
this.connectCallbacks.forEach((cb) => cb());
|
|
32
|
+
ws.on('message', (data) => {
|
|
33
|
+
try {
|
|
34
|
+
this.handleMessage(data.toString());
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
console.error('[WebSocket Server] Error handling message:', error);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
ws.on('close', () => {
|
|
41
|
+
console.error('[WebSocket Server] Client disconnected');
|
|
42
|
+
this.client = null;
|
|
43
|
+
// Reject all pending requests
|
|
44
|
+
for (const [_id, pending] of this.pendingRequests.entries()) {
|
|
45
|
+
clearTimeout(pending.timeout);
|
|
46
|
+
pending.reject(new Error('Connection lost'));
|
|
47
|
+
}
|
|
48
|
+
this.pendingRequests.clear();
|
|
49
|
+
this.disconnectCallbacks.forEach((cb) => cb());
|
|
50
|
+
});
|
|
51
|
+
ws.on('error', (error) => {
|
|
52
|
+
console.error('[WebSocket Server] Client error:', error);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
async stop() {
|
|
58
|
+
return new Promise((resolve) => {
|
|
59
|
+
if (this.client) {
|
|
60
|
+
this.client.close();
|
|
61
|
+
this.client = null;
|
|
62
|
+
}
|
|
63
|
+
if (this.wss) {
|
|
64
|
+
this.wss.close(() => {
|
|
65
|
+
this.wss = null;
|
|
66
|
+
resolve();
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
resolve();
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
async sendRequest(action, payload) {
|
|
75
|
+
if (!this.client || this.client.readyState !== WebSocket.OPEN) {
|
|
76
|
+
throw new Error('RemNote plugin not connected. Please ensure the plugin is installed and running.');
|
|
77
|
+
}
|
|
78
|
+
const id = randomUUID();
|
|
79
|
+
const request = { id, action, payload };
|
|
80
|
+
return new Promise((resolve, reject) => {
|
|
81
|
+
const timeout = setTimeout(() => {
|
|
82
|
+
this.pendingRequests.delete(id);
|
|
83
|
+
reject(new Error(`Request timeout: ${action}`));
|
|
84
|
+
}, 5000);
|
|
85
|
+
this.pendingRequests.set(id, { resolve, reject, timeout });
|
|
86
|
+
try {
|
|
87
|
+
this.client.send(JSON.stringify(request));
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
clearTimeout(timeout);
|
|
91
|
+
this.pendingRequests.delete(id);
|
|
92
|
+
reject(error);
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
isConnected() {
|
|
97
|
+
return this.client !== null && this.client.readyState === WebSocket.OPEN;
|
|
98
|
+
}
|
|
99
|
+
onClientConnect(callback) {
|
|
100
|
+
this.connectCallbacks.push(callback);
|
|
101
|
+
}
|
|
102
|
+
onClientDisconnect(callback) {
|
|
103
|
+
this.disconnectCallbacks.push(callback);
|
|
104
|
+
}
|
|
105
|
+
handleMessage(data) {
|
|
106
|
+
try {
|
|
107
|
+
const message = JSON.parse(data);
|
|
108
|
+
// Handle pong response to ping
|
|
109
|
+
if ('type' in message && message.type === 'pong') {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
// Handle ping - respond with pong
|
|
113
|
+
if ('type' in message && message.type === 'ping') {
|
|
114
|
+
if (this.client && this.client.readyState === WebSocket.OPEN) {
|
|
115
|
+
this.client.send(JSON.stringify({ type: 'pong' }));
|
|
116
|
+
}
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
// Handle response to our request
|
|
120
|
+
if ('id' in message) {
|
|
121
|
+
const response = message;
|
|
122
|
+
const pending = this.pendingRequests.get(response.id);
|
|
123
|
+
if (pending) {
|
|
124
|
+
clearTimeout(pending.timeout);
|
|
125
|
+
this.pendingRequests.delete(response.id);
|
|
126
|
+
if (response.error) {
|
|
127
|
+
pending.reject(new Error(response.error));
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
pending.resolve(response.result);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
console.error('[WebSocket Server] Received response for unknown request ID:', response.id);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
console.error('[WebSocket Server] Error parsing message:', error);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=websocket-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"websocket-server.js","sourceRoot":"","sources":["../src/websocket-server.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "remnote-mcp-server",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "MCP server bridge for RemNote knowledge base",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"remnote-mcp-server": "dist/index.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc",
|
|
12
|
+
"dev": "tsx watch src/index.ts",
|
|
13
|
+
"start": "node dist/index.js",
|
|
14
|
+
"typecheck": "tsc --noEmit",
|
|
15
|
+
"prepublishOnly": "npm run build",
|
|
16
|
+
"test": "vitest run",
|
|
17
|
+
"test:watch": "vitest",
|
|
18
|
+
"test:coverage": "vitest run --coverage",
|
|
19
|
+
"test:ui": "vitest --ui",
|
|
20
|
+
"lint": "eslint src test --ext .ts",
|
|
21
|
+
"lint:fix": "eslint src test --ext .ts --fix",
|
|
22
|
+
"format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
23
|
+
"format:check": "prettier --check \"src/**/*.ts\" \"test/**/*.ts\"",
|
|
24
|
+
"quality": "./code-quality.sh",
|
|
25
|
+
"precommit": "./code-quality.sh"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"mcp",
|
|
29
|
+
"remnote",
|
|
30
|
+
"model-context-protocol",
|
|
31
|
+
"knowledge-base",
|
|
32
|
+
"note-taking",
|
|
33
|
+
"ai",
|
|
34
|
+
"assistant",
|
|
35
|
+
"websocket",
|
|
36
|
+
"bridge"
|
|
37
|
+
],
|
|
38
|
+
"author": "nightingale7 <nightingale7@gmail.com>",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"files": [
|
|
41
|
+
"dist/",
|
|
42
|
+
"README.md",
|
|
43
|
+
"LICENSE",
|
|
44
|
+
"CHANGELOG.md"
|
|
45
|
+
],
|
|
46
|
+
"repository": {
|
|
47
|
+
"type": "git",
|
|
48
|
+
"url": "git+https://github.com/robert7/remnote-mcp-server.git"
|
|
49
|
+
},
|
|
50
|
+
"bugs": {
|
|
51
|
+
"url": "https://github.com/robert7/remnote-mcp-server/issues"
|
|
52
|
+
},
|
|
53
|
+
"homepage": "https://github.com/robert7/remnote-mcp-server#readme",
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
56
|
+
"ws": "^8.19.0",
|
|
57
|
+
"zod": "^4.3.6"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@types/node": "^25.2.1",
|
|
61
|
+
"@types/ws": "^8.18.1",
|
|
62
|
+
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
|
63
|
+
"@typescript-eslint/parser": "^6.21.0",
|
|
64
|
+
"@vitest/coverage-v8": "^1.6.1",
|
|
65
|
+
"@vitest/ui": "^1.6.1",
|
|
66
|
+
"eslint": "^8.57.1",
|
|
67
|
+
"eslint-config-prettier": "^9.1.2",
|
|
68
|
+
"prettier": "^3.8.1",
|
|
69
|
+
"tsx": "^4.21.0",
|
|
70
|
+
"typescript": "^5.9.3",
|
|
71
|
+
"vitest": "^1.6.1"
|
|
72
|
+
},
|
|
73
|
+
"engines": {
|
|
74
|
+
"node": ">=18.0.0"
|
|
75
|
+
}
|
|
76
|
+
}
|