219 lines
No EOL
6.6 KiB
JavaScript
219 lines
No EOL
6.6 KiB
JavaScript
#!/usr/bin/env node
|
|
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
import readline from 'readline';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const __filename = fileURLToPath(import.meta.url);
|
|
const __dirname = path.dirname(__filename);
|
|
|
|
const rl = readline.createInterface({
|
|
input: process.stdin,
|
|
output: process.stdout
|
|
});
|
|
|
|
function question(prompt) {
|
|
return new Promise((resolve) => {
|
|
rl.question(prompt, (answer) => {
|
|
resolve(answer.trim());
|
|
});
|
|
});
|
|
}
|
|
|
|
function findProjectRoot() {
|
|
let currentDir = process.cwd();
|
|
|
|
while (currentDir !== path.dirname(currentDir)) {
|
|
// Check for common project indicators
|
|
const indicators = ['.git', 'package.json', '.claude', 'pyproject.toml', 'Cargo.toml'];
|
|
const hasIndicator = indicators.some(indicator =>
|
|
fs.existsSync(path.join(currentDir, indicator))
|
|
);
|
|
|
|
if (hasIndicator) {
|
|
return currentDir;
|
|
}
|
|
|
|
currentDir = path.dirname(currentDir);
|
|
}
|
|
|
|
return process.cwd(); // Fallback to current directory
|
|
}
|
|
|
|
async function main() {
|
|
console.log('🚀 TickTick MCP Server Installation Tool');
|
|
console.log('=====================================\n');
|
|
|
|
const projectRoot = findProjectRoot();
|
|
console.log(`📁 Project root detected: ${projectRoot}\n`);
|
|
|
|
const mcpJsonPath = path.join(projectRoot, '.mcp.json');
|
|
let mcpConfig = {};
|
|
|
|
// Load existing .mcp.json if it exists
|
|
if (fs.existsSync(mcpJsonPath)) {
|
|
try {
|
|
const content = fs.readFileSync(mcpJsonPath, 'utf8');
|
|
mcpConfig = JSON.parse(content);
|
|
console.log('✅ Found existing .mcp.json file');
|
|
} catch (error) {
|
|
console.log('⚠️ Found .mcp.json but could not parse it. Creating backup...');
|
|
fs.copyFileSync(mcpJsonPath, `${mcpJsonPath}.backup`);
|
|
console.log(` Backup saved as: .mcp.json.backup`);
|
|
}
|
|
} else {
|
|
console.log('📝 Creating new .mcp.json file');
|
|
}
|
|
|
|
if (!mcpConfig.mcpServers) {
|
|
mcpConfig.mcpServers = {};
|
|
}
|
|
|
|
console.log('\n🔧 TickTick MCP Server Configuration Options:');
|
|
console.log('1. Local Build (production mode)');
|
|
console.log('2. Demo Mode (no authentication required)');
|
|
console.log('3. Both production and demo');
|
|
console.log('4. Exit');
|
|
|
|
const choice = await question('\nSelect option (1-4): ');
|
|
|
|
const serverPath = path.join(__dirname, 'dist/index.js');
|
|
|
|
const configs = {
|
|
production: {
|
|
name: 'ticktick',
|
|
config: {
|
|
command: 'node',
|
|
args: [serverPath]
|
|
}
|
|
},
|
|
demo: {
|
|
name: 'ticktick-demo',
|
|
config: {
|
|
command: 'node',
|
|
args: [serverPath, '--demo']
|
|
}
|
|
}
|
|
};
|
|
|
|
switch (choice) {
|
|
case '1':
|
|
mcpConfig.mcpServers[configs.production.name] = configs.production.config;
|
|
console.log('✅ Added production mode configuration');
|
|
break;
|
|
case '2':
|
|
mcpConfig.mcpServers[configs.demo.name] = configs.demo.config;
|
|
console.log('✅ Added demo mode configuration');
|
|
break;
|
|
case '3':
|
|
mcpConfig.mcpServers[configs.production.name] = configs.production.config;
|
|
mcpConfig.mcpServers[configs.demo.name] = configs.demo.config;
|
|
console.log('✅ Added both production and demo configurations');
|
|
break;
|
|
case '4':
|
|
console.log('👋 Exiting without changes');
|
|
rl.close();
|
|
return;
|
|
break;
|
|
default:
|
|
console.log('❌ Invalid choice. Exiting...');
|
|
rl.close();
|
|
return;
|
|
}
|
|
|
|
// Write .mcp.json
|
|
try {
|
|
fs.writeFileSync(mcpJsonPath, JSON.stringify(mcpConfig, null, 2));
|
|
console.log(`\n💾 Successfully updated: ${mcpJsonPath}`);
|
|
} catch (error) {
|
|
console.error(`❌ Failed to write .mcp.json: ${error.message}`);
|
|
rl.close();
|
|
return;
|
|
}
|
|
|
|
// Check and update Claude settings
|
|
const claudeDir = path.join(projectRoot, '.claude');
|
|
const settingsPath = path.join(claudeDir, 'settings.local.json');
|
|
|
|
if (fs.existsSync(settingsPath)) {
|
|
console.log('\n🔍 Checking Claude Code settings...');
|
|
|
|
try {
|
|
const settingsContent = fs.readFileSync(settingsPath, 'utf8');
|
|
const settings = JSON.parse(settingsContent);
|
|
|
|
let updated = false;
|
|
|
|
// Enable all project MCP servers
|
|
if (!settings.enableAllProjectMcpServers) {
|
|
settings.enableAllProjectMcpServers = true;
|
|
updated = true;
|
|
}
|
|
|
|
// Add enabled servers
|
|
if (!settings.enabledMcpjsonServers) {
|
|
settings.enabledMcpjsonServers = [];
|
|
}
|
|
|
|
const newServers = Object.keys(mcpConfig.mcpServers);
|
|
newServers.forEach(server => {
|
|
if (!settings.enabledMcpjsonServers.includes(server)) {
|
|
settings.enabledMcpjsonServers.push(server);
|
|
updated = true;
|
|
}
|
|
});
|
|
|
|
// Add permissions
|
|
if (!settings.permissions) {
|
|
settings.permissions = { allow: [], deny: [], ask: [] };
|
|
}
|
|
|
|
if (!settings.permissions.allow.includes('mcp__ticktick__*')) {
|
|
settings.permissions.allow.push('mcp__ticktick__*');
|
|
updated = true;
|
|
}
|
|
|
|
if (updated) {
|
|
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
console.log('✅ Updated Claude Code settings');
|
|
} else {
|
|
console.log('✅ Claude Code settings are already configured');
|
|
}
|
|
|
|
} catch (error) {
|
|
console.log('⚠️ Could not update Claude Code settings automatically');
|
|
console.log(' Please add the following to your .claude/settings.local.json:');
|
|
console.log(' "enableAllProjectMcpServers": true,');
|
|
console.log(' "enabledMcpjsonServers": ' + JSON.stringify(Object.keys(mcpConfig.mcpServers)));
|
|
}
|
|
} else {
|
|
console.log('\n📋 Claude Code settings not found. Manual setup required:');
|
|
console.log(' Create .claude/settings.local.json with:');
|
|
console.log(' {');
|
|
console.log(' "enableAllProjectMcpServers": true,');
|
|
console.log(' "enabledMcpjsonServers": ' + JSON.stringify(Object.keys(mcpConfig.mcpServers)));
|
|
console.log(' }');
|
|
}
|
|
|
|
console.log('\n🎉 Installation Complete!');
|
|
console.log('========================');
|
|
console.log('\nNext steps:');
|
|
console.log('1. Start Claude Code CLI from this directory:');
|
|
console.log(` cd ${projectRoot}`);
|
|
console.log(' claude');
|
|
console.log('\n2. Test TickTick integration:');
|
|
console.log(' "TickTick MCPサーバーが利用可能か確認して"');
|
|
console.log('\n3. For first-time setup (if using real TickTick):');
|
|
console.log(' npx ticktick-mcp-server-interactive --setup');
|
|
console.log('\n4. To test with demo data:');
|
|
console.log(' Use the ticktick-demo server configuration');
|
|
|
|
rl.close();
|
|
}
|
|
|
|
main().catch(error => {
|
|
console.error('❌ Installation failed:', error);
|
|
rl.close();
|
|
process.exit(1);
|
|
}); |