@nihalcastelino/project-brain-mcp 1.0.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.
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Automated npm Publish Script
5
+ * Uses NPM_TOKEN from .env for authentication
6
+ */
7
+
8
+ import { spawn } from 'child_process';
9
+ import { readFileSync, writeFileSync, existsSync } from 'fs';
10
+ import { homedir } from 'os';
11
+ import { join } from 'path';
12
+
13
+ console.log("šŸš€ Automated npm Publish for Project Brain MCP\n");
14
+
15
+ // Load .env file
16
+ function loadEnv() {
17
+ const envPath = '.env';
18
+ if (!existsSync(envPath)) {
19
+ console.error("āŒ Error: .env file not found!");
20
+ console.error("\nCreate .env file and add:");
21
+ console.error("NPM_TOKEN=your_npm_access_token_here\n");
22
+ process.exit(1);
23
+ }
24
+
25
+ const envContent = readFileSync(envPath, 'utf8');
26
+ const lines = envContent.split('\n');
27
+
28
+ for (const line of lines) {
29
+ const trimmed = line.trim();
30
+ if (trimmed && !trimmed.startsWith('#')) {
31
+ const [key, ...valueParts] = trimmed.split('=');
32
+ const value = valueParts.join('=').trim();
33
+ if (key === 'NPM_TOKEN') {
34
+ return value;
35
+ }
36
+ }
37
+ }
38
+
39
+ return null;
40
+ }
41
+
42
+ // Get npm token
43
+ const npmToken = loadEnv();
44
+
45
+ if (!npmToken || npmToken === 'YOUR_NPM_ACCESS_TOKEN_HERE') {
46
+ console.error("āŒ Error: NPM_TOKEN not set in .env file!\n");
47
+ console.error("Steps to fix:");
48
+ console.error("1. Go to: https://www.npmjs.com/settings/YOUR_USERNAME/tokens");
49
+ console.error("2. Create a new token (Automation type)");
50
+ console.error("3. Copy the token");
51
+ console.error("4. Edit .env file and replace YOUR_NPM_ACCESS_TOKEN_HERE with your token");
52
+ console.error("5. Run this script again\n");
53
+ process.exit(1);
54
+ }
55
+
56
+ console.log("āœ… NPM_TOKEN found in .env");
57
+
58
+ // Create .npmrc with token
59
+ const npmrcPath = join(homedir(), '.npmrc');
60
+ let existingNpmrc = '';
61
+
62
+ if (existsSync(npmrcPath)) {
63
+ existingNpmrc = readFileSync(npmrcPath, 'utf8');
64
+ console.log("ā„¹ļø Backing up existing .npmrc");
65
+ writeFileSync(npmrcPath + '.backup', existingNpmrc);
66
+ }
67
+
68
+ // Write token to .npmrc
69
+ const npmrcContent = `//registry.npmjs.org/:_authToken=${npmToken}\n`;
70
+ writeFileSync(npmrcPath, npmrcContent);
71
+ console.log("āœ… Configured npm authentication\n");
72
+
73
+ // Run build
74
+ console.log("šŸ“¦ Building package...");
75
+ const buildProc = spawn('npm', ['run', 'build'], {
76
+ stdio: 'inherit',
77
+ shell: true
78
+ });
79
+
80
+ buildProc.on('close', (code) => {
81
+ if (code !== 0) {
82
+ console.error("\nāŒ Build failed!");
83
+ cleanup();
84
+ process.exit(1);
85
+ }
86
+
87
+ console.log("āœ… Build successful\n");
88
+
89
+ // Run publish
90
+ console.log("šŸ“¤ Publishing to npm...");
91
+ const publishProc = spawn('npm', ['publish', '--access', 'public'], {
92
+ stdio: 'inherit',
93
+ shell: true
94
+ });
95
+
96
+ publishProc.on('close', (publishCode) => {
97
+ cleanup();
98
+
99
+ if (publishCode !== 0) {
100
+ console.error("\nāŒ Publish failed!");
101
+ console.error("\nCommon issues:");
102
+ console.error("- Version already published (bump version in package.json)");
103
+ console.error("- Invalid token (check your .env file)");
104
+ console.error("- Network issues");
105
+ process.exit(1);
106
+ }
107
+
108
+ console.log("\n" + "=".repeat(60));
109
+ console.log(" āœ… SUCCESS! Package published to npm!");
110
+ console.log("=".repeat(60));
111
+ console.log("\nšŸ“¦ Package: @nihalcastelino/project-brain-mcp");
112
+ console.log("šŸ”— URL: https://www.npmjs.com/package/@nihalcastelino/project-brain-mcp");
113
+ console.log("\nšŸ“„ Install with:");
114
+ console.log(" npm install -g @nihalcastelino/project-brain-mcp");
115
+ console.log("\nšŸŽ‰ Next steps:");
116
+ console.log(" 1. Test installation");
117
+ console.log(" 2. Make GitHub repo public");
118
+ console.log(" 3. Announce beta!\n");
119
+ });
120
+ });
121
+
122
+ // Cleanup function
123
+ function cleanup() {
124
+ console.log("\n🧹 Cleaning up...");
125
+
126
+ // Restore original .npmrc if it existed
127
+ const backupPath = join(homedir(), '.npmrc.backup');
128
+ if (existsSync(backupPath)) {
129
+ const backup = readFileSync(backupPath, 'utf8');
130
+ writeFileSync(npmrcPath, backup);
131
+ console.log("āœ… Restored original .npmrc");
132
+ }
133
+ // Note: If no backup existed, we leave the .npmrc as-is for now
134
+ // User can manually remove it if needed
135
+ }
136
+
137
+ // Handle interrupts
138
+ process.on('SIGINT', () => {
139
+ console.log("\n\nāš ļø Interrupted by user");
140
+ cleanup();
141
+ process.exit(1);
142
+ });
package/publish.bat ADDED
@@ -0,0 +1,72 @@
1
+ @echo off
2
+ REM Project Brain MCP - Publish to npm Script
3
+ echo ================================================
4
+ echo Publishing Project Brain MCP to npm
5
+ echo ================================================
6
+ echo.
7
+
8
+ echo Step 1: Building package...
9
+ call npm run build
10
+ if errorlevel 1 (
11
+ echo ERROR: Build failed!
12
+ pause
13
+ exit /b 1
14
+ )
15
+ echo āœ… Build successful
16
+ echo.
17
+
18
+ echo Step 2: Logging into npm...
19
+ echo.
20
+ echo INSTRUCTIONS:
21
+ echo - You'll be prompted for username/password OR
22
+ echo - If you have an access token, use:
23
+ echo Username: your-npm-username
24
+ echo Password: paste your access token here
25
+ echo.
26
+ call npm login
27
+ if errorlevel 1 (
28
+ echo ERROR: npm login failed!
29
+ pause
30
+ exit /b 1
31
+ )
32
+ echo āœ… Logged in successfully
33
+ echo.
34
+
35
+ echo Step 3: Verifying package...
36
+ echo Package name: @nihalcastelino/project-brain-mcp
37
+ echo Version: 1.0.0
38
+ echo.
39
+ echo Press any key to continue with publish, or Ctrl+C to cancel...
40
+ pause > nul
41
+
42
+ echo Step 4: Publishing to npm...
43
+ call npm publish --access public
44
+ if errorlevel 1 (
45
+ echo ERROR: Publish failed!
46
+ echo.
47
+ echo Common issues:
48
+ echo - Package version already exists (bump version in package.json)
49
+ echo - Not authorized for @nihalcastelino org
50
+ echo - Network issues
51
+ pause
52
+ exit /b 1
53
+ )
54
+
55
+ echo.
56
+ echo ================================================
57
+ echo āœ… SUCCESS! Package published!
58
+ echo ================================================
59
+ echo.
60
+ echo Your package is now available at:
61
+ echo https://www.npmjs.com/package/@nihalcastelino/project-brain-mcp
62
+ echo.
63
+ echo Users can install it with:
64
+ echo npm install -g @nihalcastelino/project-brain-mcp
65
+ echo.
66
+ echo Next steps:
67
+ echo 1. Verify on npmjs.com
68
+ echo 2. Test installation: npm install -g @nihalcastelino/project-brain-mcp
69
+ echo 3. Make GitHub repo public
70
+ echo 4. Announce beta!
71
+ echo.
72
+ pause
@@ -0,0 +1,238 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Project Brain Free Tier - Zero-Config Setup
5
+ * Automatically configures Claude Desktop, Cursor, and other MCP-compatible tools
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+ const os = require('os');
11
+
12
+ // Color codes for terminal
13
+ const colors = {
14
+ reset: '\x1b[0m',
15
+ bright: '\x1b[1m',
16
+ green: '\x1b[32m',
17
+ yellow: '\x1b[33m',
18
+ blue: '\x1b[34m',
19
+ cyan: '\x1b[36m',
20
+ gray: '\x1b[90m',
21
+ };
22
+
23
+ const log = {
24
+ success: (msg) => console.log(`${colors.green}āœ… ${msg}${colors.reset}`),
25
+ warning: (msg) => console.log(`${colors.yellow}āš ļø ${msg}${colors.reset}`),
26
+ info: (msg) => console.log(`${colors.blue}ā„¹ļø ${msg}${colors.reset}`),
27
+ dim: (msg) => console.log(`${colors.gray} ${msg}${colors.reset}`),
28
+ };
29
+
30
+ // AI Tool configurations
31
+ const AI_TOOLS = {
32
+ claude: {
33
+ name: 'Claude Desktop',
34
+ configPaths: {
35
+ win32: path.join(os.homedir(), 'AppData', 'Roaming', 'Claude', 'claude_desktop_config.json'),
36
+ darwin: path.join(os.homedir(), 'Library', 'Application Support', 'Claude', 'claude_desktop_config.json'),
37
+ linux: path.join(os.homedir(), '.config', 'claude', 'claude_desktop_config.json'),
38
+ },
39
+ },
40
+ cursor: {
41
+ name: 'Cursor',
42
+ configPaths: {
43
+ win32: path.join(os.homedir(), 'AppData', 'Roaming', 'Cursor', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json'),
44
+ darwin: path.join(os.homedir(), 'Library', 'Application Support', 'Cursor', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json'),
45
+ linux: path.join(os.homedir(), '.config', 'Cursor', 'User', 'globalStorage', 'saoudrizwan.claude-dev', 'settings', 'cline_mcp_settings.json'),
46
+ },
47
+ },
48
+ };
49
+
50
+ class FreeTierSetup {
51
+ constructor() {
52
+ this.platform = os.platform();
53
+ this.isGlobalInstall = !__dirname.includes('node_modules');
54
+ this.serverPath = this.getServerPath();
55
+ this.dbPath = path.join(os.homedir(), '.project-brain', 'tasks.db');
56
+ }
57
+
58
+ getServerPath() {
59
+ // If globally installed via npm
60
+ if (process.env.npm_config_global === 'true' || this.isGlobalInstall) {
61
+ const globalNodeModules = require('child_process')
62
+ .execSync('npm root -g')
63
+ .toString()
64
+ .trim();
65
+ return path.join(globalNodeModules, '@project-brain', 'mcp', 'dist', 'server.js');
66
+ }
67
+
68
+ // If locally installed or running from source
69
+ return path.join(__dirname, '..', 'dist', 'server.js');
70
+ }
71
+
72
+ async run() {
73
+ try {
74
+ console.log(`\n${colors.cyan}${colors.bright}🧠 Project Brain - Free Tier Setup${colors.reset}\n`);
75
+
76
+ // Ensure database directory exists
77
+ this.ensureDbDirectory();
78
+
79
+ // Detect and configure AI tools
80
+ const configured = await this.autoConfigureTools();
81
+
82
+ // Print success message
83
+ this.printSuccess(configured);
84
+ } catch (error) {
85
+ log.warning(`Setup encountered an issue: ${error.message}`);
86
+ log.info('You can manually configure your AI tool to use this MCP server');
87
+ this.printManualInstructions();
88
+ }
89
+ }
90
+
91
+ ensureDbDirectory() {
92
+ const dbDir = path.dirname(this.dbPath);
93
+ if (!fs.existsSync(dbDir)) {
94
+ fs.mkdirSync(dbDir, { recursive: true });
95
+ log.success(`Created database directory: ${dbDir}`);
96
+ }
97
+ }
98
+
99
+ async autoConfigureTools() {
100
+ const configured = [];
101
+
102
+ log.info('Detecting AI tools...\n');
103
+
104
+ for (const [toolKey, tool] of Object.entries(AI_TOOLS)) {
105
+ const configPath = tool.configPaths[this.platform];
106
+
107
+ if (!configPath) {
108
+ log.dim(`${tool.name}: Not supported on this platform`);
109
+ continue;
110
+ }
111
+
112
+ const configDir = path.dirname(configPath);
113
+
114
+ // Check if tool exists
115
+ if (!fs.existsSync(configDir) && !fs.existsSync(configPath)) {
116
+ log.dim(`${tool.name}: Not installed`);
117
+ continue;
118
+ }
119
+
120
+ try {
121
+ await this.configureAITool(toolKey, tool, configPath);
122
+ configured.push(tool.name);
123
+ log.success(`${tool.name} configured`);
124
+ } catch (error) {
125
+ log.warning(`${tool.name}: Could not auto-configure (${error.message})`);
126
+ }
127
+ }
128
+
129
+ return configured;
130
+ }
131
+
132
+ async configureAITool(toolKey, tool, configPath) {
133
+ const configDir = path.dirname(configPath);
134
+
135
+ // Ensure directory exists
136
+ if (!fs.existsSync(configDir)) {
137
+ fs.mkdirSync(configDir, { recursive: true });
138
+ }
139
+
140
+ // Load existing config or create new one
141
+ let toolConfig = {};
142
+ if (fs.existsSync(configPath)) {
143
+ try {
144
+ const content = fs.readFileSync(configPath, 'utf8');
145
+ toolConfig = JSON.parse(content);
146
+ } catch (error) {
147
+ log.warning(`Could not parse existing ${tool.name} config, creating backup`);
148
+ fs.copyFileSync(configPath, `${configPath}.backup.${Date.now()}`);
149
+ }
150
+ }
151
+
152
+ // Add Project Brain MCP server configuration
153
+ if (!toolConfig.mcpServers) {
154
+ toolConfig.mcpServers = {};
155
+ }
156
+
157
+ // Check if already configured
158
+ if (toolConfig.mcpServers['project-brain']) {
159
+ log.dim(` ${tool.name} already has project-brain configured, updating...`);
160
+ }
161
+
162
+ toolConfig.mcpServers['project-brain'] = {
163
+ command: 'node',
164
+ args: [this.serverPath],
165
+ env: {
166
+ PROJECT_BRAIN_DB_PATH: this.dbPath
167
+ }
168
+ };
169
+
170
+ // Write updated config
171
+ fs.writeFileSync(configPath, JSON.stringify(toolConfig, null, 2));
172
+ }
173
+
174
+ printSuccess(configured) {
175
+ console.log(`\n${colors.green}${colors.bright}✨ Project Brain Setup Complete!${colors.reset}\n`);
176
+
177
+ if (configured.length > 0) {
178
+ console.log(`${colors.green}Configured AI tools:${colors.reset}`);
179
+ configured.forEach(tool => console.log(` āœ… ${tool}`));
180
+ console.log();
181
+ log.info('Next steps:');
182
+ console.log(' 1. Restart your AI tool(s)');
183
+ console.log(' 2. Try: "Create a task to test Project Brain"');
184
+ console.log(' 3. Try: "List all my tasks"\n');
185
+ } else {
186
+ log.warning('No AI tools detected for auto-configuration\n');
187
+ this.printManualInstructions();
188
+ }
189
+
190
+ console.log(`${colors.cyan}Database location:${colors.reset}`);
191
+ console.log(` ${this.dbPath}\n`);
192
+
193
+ console.log(`${colors.cyan}Features (Free Tier):${colors.reset}`);
194
+ console.log(' āœ… Up to 100 tasks per project');
195
+ console.log(' āœ… Full-text search');
196
+ console.log(' āœ… Import/export');
197
+ console.log(' āœ… 100% local, works offline\n');
198
+
199
+ console.log(`${colors.gray}Need unlimited tasks? Upgrade at: https://projectbrain.ai/pricing${colors.reset}\n`);
200
+ }
201
+
202
+ printManualInstructions() {
203
+ console.log(`\n${colors.cyan}Manual Configuration:${colors.reset}\n`);
204
+
205
+ console.log(`Add this to your AI tool's MCP settings:\n`);
206
+ console.log(colors.gray + JSON.stringify({
207
+ mcpServers: {
208
+ "project-brain": {
209
+ command: "node",
210
+ args: [this.serverPath],
211
+ env: {
212
+ PROJECT_BRAIN_DB_PATH: this.dbPath
213
+ }
214
+ }
215
+ }
216
+ }, null, 2) + colors.reset + '\n');
217
+
218
+ console.log(`${colors.cyan}Config file locations:${colors.reset}`);
219
+ Object.values(AI_TOOLS).forEach(tool => {
220
+ const configPath = tool.configPaths[this.platform];
221
+ if (configPath) {
222
+ console.log(` ${tool.name}: ${configPath}`);
223
+ }
224
+ });
225
+ console.log();
226
+ }
227
+ }
228
+
229
+ // Run setup
230
+ if (require.main === module) {
231
+ const setup = new FreeTierSetup();
232
+ setup.run().catch(error => {
233
+ console.error('Setup failed:', error);
234
+ process.exit(1);
235
+ });
236
+ }
237
+
238
+ module.exports = FreeTierSetup;