From 785a1dfe15457aeb50e852708f149763537ba4ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9F=B4=E7=94=B0=E8=B2=B4=E5=8F=B8?= Date: Mon, 22 Sep 2025 21:54:08 +0900 Subject: [PATCH] install app --- .gitignore | 4 + MCP-INSTALL.md | 162 +++++++++++++++++++++++++++++++++++ install-mcp.js | 224 +++++++++++++++++++++++++++++++++++++++++++++++++ package.json | 10 ++- src/index.ts | 6 ++ 5 files changed, 403 insertions(+), 3 deletions(-) create mode 100644 MCP-INSTALL.md create mode 100644 install-mcp.js diff --git a/.gitignore b/.gitignore index 220c112..988d87e 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,10 @@ build/ .env.test.local .env.production.local +# TickTick MCP configuration (contains sensitive auth data) +.ticktick-mcp/ +config.json + # IDE files .vscode/ .idea/ diff --git a/MCP-INSTALL.md b/MCP-INSTALL.md new file mode 100644 index 0000000..1f7a577 --- /dev/null +++ b/MCP-INSTALL.md @@ -0,0 +1,162 @@ +# TickTick MCP Server - Claude Code CLI Integration + +## ๐Ÿš€ Quick Install + +### Method 1: Git Clone Installation (Recommended) + +```bash +# Clone repository +git clone https://github.com/marketing-shibata50/ticktick-mcp.git +cd ticktick-mcp/ticktick-mcp-server + +# Install dependencies and build +npm install +npm run build + +# Run automatic setup +node install-mcp.js +``` + +This will: +- โœ… Clone the complete project with all dependencies +- โœ… Build from source for maximum compatibility +- โœ… Run interactive setup wizard +- โœ… Configure `.mcp.json` and Claude Code CLI settings + +### Method 2: NPM Installation + +```bash +# Install and configure TickTick MCP for Claude Code CLI +npx ticktick-mcp-install +``` + +**Note**: NPM installation may have dependency issues. Git clone method is more reliable. + +### Method 3: Manual Installation + +1. **Create `.mcp.json` in your project root:** + +```json +{ + "mcpServers": { + "ticktick": { + "command": "npx", + "args": ["ticktick-mcp-server-interactive"] + }, + "ticktick-demo": { + "command": "npx", + "args": ["ticktick-mcp-server-interactive", "--demo"] + } + } +} +``` + +2. **Update `.claude/settings.local.json`:** + +```json +{ + "enableAllProjectMcpServers": true, + "enabledMcpjsonServers": ["ticktick", "ticktick-demo"], + "permissions": { + "allow": ["mcp__ticktick__*"] + } +} +``` + +## ๐ŸŽฏ Usage + +### Start Claude Code CLI + +```bash +cd your-project-directory +claude +``` + +### Test TickTick Integration + +``` +TickTick MCPใ‚ตใƒผใƒใƒผใŒๅˆฉ็”จๅฏ่ƒฝใ‹็ขบ่ชใ—ใฆ +``` + +### TickTick Commands + +``` +ไปŠๆ—ฅใฎใ‚ฟใ‚นใ‚ฏใ‚’่กจ็คบใ—ใฆ +ๆ–ฐใ—ใ„ใ‚ฟใ‚นใ‚ฏใ€Œใ‚ณใƒผใƒ‰ใƒฌใƒ“ใƒฅใƒผใ€ใ‚’่ฟฝๅŠ ใ—ใฆ +ใƒ—ใƒญใ‚ธใ‚งใ‚ฏใƒˆไธ€่ฆงใ‚’่ฆ‹ใ›ใฆ +ๆœŸ้™ๅˆ‡ใ‚Œใฎใ‚ฟใ‚นใ‚ฏใ‚’็ขบ่ชใ—ใฆ +``` + +## ๐Ÿ”ง Configuration Options + +### 1. NPM Package (Production) +```json +{ + "ticktick": { + "command": "npx", + "args": ["ticktick-mcp-server-interactive"] + } +} +``` + +### 2. Demo Mode (No Authentication) +```json +{ + "ticktick-demo": { + "command": "npx", + "args": ["ticktick-mcp-server-interactive", "--demo"] + } +} +``` + +### 3. Local Development +```json +{ + "ticktick-local": { + "command": "node", + "args": ["/path/to/ticktick-mcp-server/dist/index.js"] + } +} +``` + +## ๐Ÿ› ๏ธ First-Time Setup + +### For Real TickTick Integration + +```bash +# Setup authentication (only needed once) +npx ticktick-mcp-server-interactive --setup +``` + +### For Demo/Testing + +Use the `ticktick-demo` configuration - no setup required! + +## ๐Ÿ“‹ Troubleshooting + +### MCP Server Not Recognized + +1. Check `.mcp.json` syntax +2. Restart Claude Code CLI +3. Verify settings in `.claude/settings.local.json` + +### Authentication Issues + +```bash +# Re-run setup +npx ticktick-mcp-server-interactive --setup +``` + +### Test Commands + +```bash +# Test NPM package +npx ticktick-mcp-server-interactive --version + +# Test demo mode +npx ticktick-mcp-server-interactive --demo +``` + +## ๐ŸŽ‰ Success! + +Once installed, you can manage your TickTick tasks directly from Claude Code CLI using natural language! \ No newline at end of file diff --git a/install-mcp.js b/install-mcp.js new file mode 100644 index 0000000..cca39e2 --- /dev/null +++ b/install-mcp.js @@ -0,0 +1,224 @@ +#!/usr/bin/env node + +import fs from 'fs'; +import path from 'path'; +import readline from 'readline'; + +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. NPM Package (recommended for end users)'); + console.log('2. Demo Mode (no authentication required)'); + console.log('3. Local Development (for developers)'); + console.log('4. All of the above'); + + const choice = await question('\nSelect option (1-4): '); + + const configs = { + npm: { + name: 'ticktick', + config: { + command: 'npx', + args: ['ticktick-mcp-server-interactive'] + } + }, + demo: { + name: 'ticktick-demo', + config: { + command: 'npx', + args: ['ticktick-mcp-server-interactive', '--demo'] + } + }, + local: { + name: 'ticktick-local', + config: { + command: 'node', + args: [path.join(projectRoot, 'ticktick-mcp-server/dist/index.js')] + } + } + }; + + switch (choice) { + case '1': + mcpConfig.mcpServers[configs.npm.name] = configs.npm.config; + console.log('โœ… Added NPM package configuration'); + break; + case '2': + mcpConfig.mcpServers[configs.demo.name] = configs.demo.config; + console.log('โœ… Added demo mode configuration'); + break; + case '3': + const localPath = await question(`Local path (default: ${configs.local.config.args[0]}): `); + if (localPath) { + configs.local.config.args[0] = localPath; + } + mcpConfig.mcpServers[configs.local.name] = configs.local.config; + console.log('โœ… Added local development configuration'); + break; + case '4': + mcpConfig.mcpServers[configs.npm.name] = configs.npm.config; + mcpConfig.mcpServers[configs.demo.name] = configs.demo.config; + mcpConfig.mcpServers[configs.local.name] = configs.local.config; + console.log('โœ… Added all configurations'); + 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); +}); \ No newline at end of file diff --git a/package.json b/package.json index 3ba90fc..de4bf10 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,11 @@ { - "name": "@marketing-shibata50/ticktick-mcp-server", - "version": "1.0.0", + "name": "ticktick-mcp-server-interactive", + "version": "1.2.0", "description": "Model Context Protocol server for TickTick task management integration with AI assistants like Claude", "main": "dist/index.js", "bin": { - "ticktick-mcp-server": "dist/index.js" + "ticktick-mcp-server-interactive": "dist/index.js", + "ticktick-mcp-install": "install-mcp.js" }, "type": "module", "scripts": { @@ -13,6 +14,7 @@ "start": "node dist/index.js", "demo": "node dist/index.js --demo", "setup": "node dist/index.js --setup", + "install-mcp": "node install-mcp.js", "test": "jest", "lint": "eslint src/**/*.ts", "format": "prettier --write src/**/*.ts", @@ -44,6 +46,8 @@ "license": "MIT", "files": [ "dist/", + "install-mcp.js", + "MCP-INSTALL.md", "README.md", "AUTHENTICATION.md", "TESTING.md", diff --git a/src/index.ts b/src/index.ts index 102ae56..430b1f9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -6,6 +6,12 @@ import { ConfigManager } from './config/config-manager.js'; import { InteractiveSetup } from './setup/interactive-setup.js'; async function main() { + // Check for version command + if (process.argv.includes('--version') || process.argv.includes('-v')) { + console.log('1.0.0'); + return; + } + // Check for setup command if (process.argv.includes('--setup') || process.argv.includes('--configure')) { console.error('๐Ÿ”ง TickTick MCP Server ใ‚ปใƒƒใƒˆใ‚ขใƒƒใƒ—ใ‚’้–‹ๅง‹ใ—ใพใ™...\n');