vibe-annotations-server 0.1.5 → 0.1.7

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Raphael Regnier
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 CHANGED
@@ -1,35 +1,154 @@
1
1
  # vibe-annotations-server
2
2
 
3
- This is the npm wrapper for [vibe-annotations-server](https://github.com/RaphaelRegnier/vibe-annotations-server), the MCP server component of Vibe Annotations.
3
+ Global MCP server for Vibe Annotations browser extension.
4
4
 
5
- ## Quick Start
5
+ ## Installation
6
6
 
7
7
  ```bash
8
- npx vibe-annotations-server
8
+ npm install -g vibe-annotations-server
9
9
  ```
10
10
 
11
- This will automatically:
12
- 1. Install the latest version from GitHub if not already installed
13
- 2. Start the vibe-annotations server
11
+ ## Usage
14
12
 
15
- ## What is Vibe Annotations?
13
+ ### Start the server
16
14
 
17
- AI-powered development annotations for localhost projects. Drop comments on your localhost apps and let your AI coding agent implement the fixes automatically.
15
+ ```bash
16
+ vibe-annotations-server start
17
+ ```
18
+
19
+ The server will run in the background on port 3846.
20
+
21
+ ### Stop the server
22
+
23
+ ```bash
24
+ vibe-annotations-server stop
25
+ ```
26
+
27
+ ### Check server status
28
+
29
+ ```bash
30
+ vibe-annotations-server status
31
+ ```
32
+
33
+ ### Restart the server
34
+
35
+ ```bash
36
+ vibe-annotations-server restart
37
+ ```
38
+
39
+ ### View logs
40
+
41
+ ```bash
42
+ vibe-annotations-server logs
43
+ # or follow logs
44
+ vibe-annotations-server logs -f
45
+ ```
46
+
47
+ ## AI Coding Agent Integration
48
+
49
+ After starting the server, connect it to your AI coding agent. The server supports multiple agents via the MCP (Model Context Protocol) using SSE (Server-Sent Events) transport.
50
+
51
+ ### Claude Code
52
+
53
+ In your project directory, run:
54
+
55
+ ```bash
56
+ claude mcp add --transport sse vibe-annotations http://127.0.0.1:3846/sse
57
+ ```
58
+
59
+ ### Cursor
60
+
61
+ 1. Open Cursor → Settings → Cursor Settings
62
+ 2. Go to the Tools & Integrations tab
63
+ 3. Click + Add new global MCP server
64
+ 4. Enter the following configuration and save:
65
+
66
+ ```json
67
+ {
68
+ "mcpServers": {
69
+ "vibe-annotations": {
70
+ "url": "http://127.0.0.1:3846/sse"
71
+ }
72
+ }
73
+ }
74
+ ```
75
+
76
+ ### Windsurf
77
+
78
+ 1. Navigate to Windsurf → Settings → Advanced Settings
79
+ 2. Scroll down to the Cascade section
80
+ 3. Click "Add new server" or edit the raw JSON config file
81
+ 4. Add the following configuration:
82
+
83
+ ```json
84
+ {
85
+ "mcpServers": {
86
+ "vibe-annotations": {
87
+ "serverUrl": "http://127.0.0.1:3846/sse"
88
+ }
89
+ }
90
+ }
91
+ ```
92
+
93
+ ### VS Code
94
+
95
+ 1. Install an AI extension that supports MCP (like GitHub Copilot Chat or Continue)
96
+ 2. Go to Code → Settings → Settings or use the shortcut ⌘,
97
+ 3. In the search bar, type "MCP"
98
+ 4. Look for MCP server configurations in your AI extension settings
99
+ 5. Add the following SSE configuration:
18
100
 
19
- - 🏠 Works on localhost development projects
20
- - 🤖 Integrates with AI coding agents via MCP
21
- - ⚡ Instant visual feedback system
22
- - 📑 Multi-page annotation support
101
+ ```json
102
+ {
103
+ "mcpServers": {
104
+ "vibe-annotations": {
105
+ "type": "sse",
106
+ "url": "http://127.0.0.1:3846/sse"
107
+ }
108
+ }
109
+ }
110
+ ```
111
+
112
+ **Note:** MCP support varies by AI extension. Check your extension's documentation for specific setup instructions.
113
+
114
+ ### Other Editors
115
+
116
+ Other code editors and tools that support SSE (Server-Sent Events) can also connect to the Vibe Annotations MCP server. If you're using a different editor or tool, check its documentation to confirm it supports SSE-based communication. If it does, you can manually add the server using this configuration:
117
+
118
+ ```json
119
+ {
120
+ "mcpServers": {
121
+ "vibe-annotations": {
122
+ "url": "http://127.0.0.1:3846/sse"
123
+ }
124
+ }
125
+ }
126
+ ```
23
127
 
24
- ## Documentation
128
+ **Note:** The Vibe Annotations MCP server communicates over the SSE protocol. Use your editor's steps for setting up an SSE-compatible MCP server, and use the URL: `http://127.0.0.1:3846/sse`
25
129
 
26
- For full documentation, Chrome extension installation, and setup instructions, visit:
27
- https://github.com/RaphaelRegnier/vibe-annotations
130
+ ## Architecture
28
131
 
29
- ## Source Code
132
+ The server provides:
133
+ - **SSE Endpoint** (`/sse`): For AI coding agent MCP connections
134
+ - **HTTP API** (`/api/annotations`): For Chrome extension communication
135
+ - **Health Check** (`/health`): For status monitoring
30
136
 
31
- The actual server source code is maintained at:
32
- https://github.com/RaphaelRegnier/vibe-annotations-server
137
+ Data is stored in `~/.vibe-annotations/annotations.json`.
138
+
139
+ ## Development
140
+
141
+ ```bash
142
+ # Clone the repository
143
+ git clone <repo-url>
144
+ cd vibe-annotations-server
145
+
146
+ # Install dependencies
147
+ npm install
148
+
149
+ # Run in development mode
150
+ npm run dev
151
+ ```
33
152
 
34
153
  ## License
35
154
 
package/bin/cli.js ADDED
@@ -0,0 +1,227 @@
1
+ #!/usr/bin/env node
2
+
3
+ import { Command } from 'commander';
4
+ import { spawn, exec } from 'child_process';
5
+ import { promisify } from 'util';
6
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync, openSync } from 'fs';
7
+ import { join, dirname } from 'path';
8
+ import { fileURLToPath } from 'url';
9
+ import chalk from 'chalk';
10
+ import { homedir } from 'os';
11
+ import fs from 'fs';
12
+
13
+ const __filename = fileURLToPath(import.meta.url);
14
+ const __dirname = dirname(__filename);
15
+
16
+ // Read version from package.json automatically
17
+ const packageJson = JSON.parse(readFileSync(join(__dirname, '../package.json'), 'utf8'));
18
+
19
+ const execAsync = promisify(exec);
20
+ const program = new Command();
21
+
22
+ // Configuration paths
23
+ const CONFIG_DIR = join(homedir(), '.vibe-annotations');
24
+ const PID_FILE = join(CONFIG_DIR, 'server.pid');
25
+ const LOG_FILE = join(CONFIG_DIR, 'server.log');
26
+ const PORT = 3846;
27
+
28
+ // Ensure config directory exists
29
+ if (!existsSync(CONFIG_DIR)) {
30
+ mkdirSync(CONFIG_DIR, { recursive: true });
31
+ }
32
+
33
+ // Helper functions
34
+ function isServerRunning() {
35
+ if (!existsSync(PID_FILE)) {
36
+ return false;
37
+ }
38
+
39
+ try {
40
+ const pid = readFileSync(PID_FILE, 'utf8').trim();
41
+ process.kill(parseInt(pid), 0); // Check if process exists
42
+ return true;
43
+ } catch (e) {
44
+ // Process doesn't exist
45
+ if (existsSync(PID_FILE)) {
46
+ // Clean up stale PID file
47
+ unlinkSync(PID_FILE);
48
+ }
49
+ return false;
50
+ }
51
+ }
52
+
53
+ async function checkPort() {
54
+ try {
55
+ const response = await fetch(`http://127.0.0.1:${PORT}/health`);
56
+ return response.ok;
57
+ } catch (error) {
58
+ return false;
59
+ }
60
+ }
61
+
62
+ // Commands
63
+ program
64
+ .name('vibe-annotations-server')
65
+ .description('Global MCP server for Vibe Annotations browser extension')
66
+ .version(packageJson.version);
67
+
68
+ program
69
+ .command('start')
70
+ .description('Start the Vibe Annotations server')
71
+ .option('-d, --daemon', 'Run as daemon (background process)')
72
+ .action(async (options) => {
73
+ if (isServerRunning()) {
74
+ console.log(chalk.yellow('✓ Server is already running'));
75
+ console.log(chalk.gray(` Port: ${PORT}`));
76
+ console.log(chalk.gray(` PID: ${readFileSync(PID_FILE, 'utf8').trim()}`));
77
+ return;
78
+ }
79
+
80
+ console.log(chalk.blue('Starting Vibe Annotations server...'));
81
+
82
+ const serverPath = join(dirname(__dirname), 'lib', 'server.js');
83
+
84
+ if (options.daemon) {
85
+ // Run as daemon
86
+ const out = fs.openSync(LOG_FILE, 'a');
87
+ const err = fs.openSync(LOG_FILE, 'a');
88
+
89
+ const child = spawn('node', [serverPath], {
90
+ detached: true,
91
+ stdio: ['ignore', out, err],
92
+ env: { ...process.env, NODE_ENV: 'production' }
93
+ });
94
+
95
+ child.unref();
96
+ writeFileSync(PID_FILE, child.pid.toString());
97
+
98
+ // Wait for server to start
99
+ let attempts = 0;
100
+ while (attempts < 10) {
101
+ if (await checkPort()) {
102
+ console.log(chalk.green('✅ Vibe Annotations server running on http://127.0.0.1:3846/sse'));
103
+ console.log(chalk.gray(` PID: ${child.pid}`));
104
+ console.log(chalk.gray(` Logs: ${LOG_FILE}`));
105
+ break;
106
+ }
107
+ await new Promise(resolve => setTimeout(resolve, 500));
108
+ attempts++;
109
+ }
110
+
111
+ if (attempts >= 10) {
112
+ console.log(chalk.red('❌ Failed to start server. Check logs at:'));
113
+ console.log(chalk.gray(` ${LOG_FILE}`));
114
+ }
115
+ } else {
116
+ // Run in foreground
117
+ const child = spawn('node', [serverPath], {
118
+ stdio: 'inherit',
119
+ env: { ...process.env, NODE_ENV: 'production' }
120
+ });
121
+
122
+ writeFileSync(PID_FILE, child.pid.toString());
123
+
124
+ child.on('exit', () => {
125
+ if (existsSync(PID_FILE)) {
126
+ unlinkSync(PID_FILE);
127
+ }
128
+ });
129
+ }
130
+ });
131
+
132
+ program
133
+ .command('stop')
134
+ .description('Stop the Vibe Annotations server')
135
+ .action(() => {
136
+ if (!isServerRunning()) {
137
+ console.log(chalk.yellow('Server is not running'));
138
+ return;
139
+ }
140
+
141
+ try {
142
+ const pid = readFileSync(PID_FILE, 'utf8').trim();
143
+ process.kill(parseInt(pid), 'SIGTERM');
144
+
145
+ if (existsSync(PID_FILE)) {
146
+ unlinkSync(PID_FILE);
147
+ }
148
+
149
+ console.log(chalk.green('✅ Server stopped'));
150
+ } catch (error) {
151
+ console.log(chalk.red('❌ Failed to stop server:'), error.message);
152
+ }
153
+ });
154
+
155
+ program
156
+ .command('restart')
157
+ .description('Restart the Vibe Annotations server')
158
+ .action(async () => {
159
+ console.log(chalk.blue('Restarting server...'));
160
+
161
+ // Stop if running
162
+ if (isServerRunning()) {
163
+ try {
164
+ const pid = readFileSync(PID_FILE, 'utf8').trim();
165
+ process.kill(parseInt(pid), 'SIGTERM');
166
+
167
+ if (existsSync(PID_FILE)) {
168
+ unlinkSync(PID_FILE);
169
+ }
170
+
171
+ // Wait for process to stop
172
+ await new Promise(resolve => setTimeout(resolve, 1000));
173
+ } catch (error) {
174
+ console.log(chalk.yellow('Warning:'), error.message);
175
+ }
176
+ }
177
+
178
+ // Start with daemon flag
179
+ program.parse(['node', 'cli.js', 'start', '--daemon'], { from: 'user' });
180
+ });
181
+
182
+ program
183
+ .command('status')
184
+ .description('Check server status')
185
+ .action(async () => {
186
+ const running = isServerRunning();
187
+ const portAvailable = await checkPort();
188
+
189
+ if (running && portAvailable) {
190
+ console.log(chalk.green('✅ Server is running'));
191
+ console.log(chalk.gray(` PID: ${readFileSync(PID_FILE, 'utf8').trim()}`));
192
+ console.log(chalk.gray(` Port: ${PORT}`));
193
+ console.log(chalk.gray(` URL: http://127.0.0.1:${PORT}/sse`));
194
+ } else if (running && !portAvailable) {
195
+ console.log(chalk.yellow('⚠️ Server process exists but is not responding'));
196
+ console.log(chalk.gray(' Try running: vibe-annotations-server restart'));
197
+ } else {
198
+ console.log(chalk.gray('○ Server is not running'));
199
+ }
200
+ });
201
+
202
+ program
203
+ .command('logs')
204
+ .description('View server logs')
205
+ .option('-f, --follow', 'Follow log output')
206
+ .option('-n, --lines <number>', 'Number of lines to show', '50')
207
+ .action((options) => {
208
+ if (!existsSync(LOG_FILE)) {
209
+ console.log(chalk.gray('No logs available yet'));
210
+ return;
211
+ }
212
+
213
+ if (options.follow) {
214
+ // Use tail -f
215
+ const tail = spawn('tail', ['-f', LOG_FILE], { stdio: 'inherit' });
216
+
217
+ process.on('SIGINT', () => {
218
+ tail.kill();
219
+ process.exit();
220
+ });
221
+ } else {
222
+ // Show last N lines
223
+ const tail = spawn('tail', ['-n', options.lines, LOG_FILE], { stdio: 'inherit' });
224
+ }
225
+ });
226
+
227
+ program.parse(process.argv);