chron-mcp 0.1.10 → 0.1.12
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/dist/index.js +25 -9
- package/dist/setup.d.ts +8 -0
- package/dist/setup.js +118 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -39,7 +39,7 @@ const os_1 = require("os");
|
|
|
39
39
|
const path_1 = require("path");
|
|
40
40
|
const index_1 = require("./db/index");
|
|
41
41
|
const server_1 = require("./server");
|
|
42
|
-
const VERSION = '0.1.
|
|
42
|
+
const VERSION = '0.1.12';
|
|
43
43
|
// --version: quick install check, safe to run anywhere
|
|
44
44
|
if (process.argv[2] === '--version' || process.argv[2] === '-v') {
|
|
45
45
|
process.stdout.write(`chron-mcp ${VERSION}\n`);
|
|
@@ -47,15 +47,31 @@ if (process.argv[2] === '--version' || process.argv[2] === '-v') {
|
|
|
47
47
|
}
|
|
48
48
|
async function main() {
|
|
49
49
|
const dbPath = process.env.CHRON_DB_PATH ?? (0, path_1.join)((0, os_1.homedir)(), '.chron', 'chron.db');
|
|
50
|
-
// Running interactively in a terminal —
|
|
50
|
+
// Running interactively in a terminal — auto-configure all detected MCP clients
|
|
51
51
|
if (process.stdin.isTTY) {
|
|
52
|
-
process.stdout.write(`chron-mcp ${VERSION}
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
process.stdout.write(`chron-mcp ${VERSION}\n\n`);
|
|
53
|
+
const { runSetup } = await Promise.resolve().then(() => __importStar(require('./setup')));
|
|
54
|
+
const results = await runSetup();
|
|
55
|
+
const added = results.filter(r => r.status === 'added');
|
|
56
|
+
const already = results.filter(r => r.status === 'already');
|
|
57
|
+
const errors = results.filter(r => r.status === 'error');
|
|
58
|
+
for (const r of added)
|
|
59
|
+
process.stdout.write(` ✓ ${r.tool} — configured\n`);
|
|
60
|
+
for (const r of already)
|
|
61
|
+
process.stdout.write(` · ${r.tool} — already set up\n`);
|
|
62
|
+
for (const r of errors)
|
|
63
|
+
process.stdout.write(` ✗ ${r.tool} — ${r.error}\n`);
|
|
64
|
+
if (results.length === 0) {
|
|
65
|
+
process.stdout.write(` No supported MCP clients detected.\n`);
|
|
66
|
+
process.stdout.write(` See README: https://github.com/SirinivasK/chron\n`);
|
|
67
|
+
}
|
|
68
|
+
else if (added.length > 0) {
|
|
69
|
+
process.stdout.write(`\nRestart ${added.map(r => r.tool).join(', ')} to activate chron.\n`);
|
|
70
|
+
}
|
|
71
|
+
else if (added.length === 0 && errors.length === 0) {
|
|
72
|
+
process.stdout.write(`\nAll detected clients already have chron. You're good to go.\n`);
|
|
73
|
+
}
|
|
74
|
+
process.stdout.write('\n');
|
|
59
75
|
process.exit(0);
|
|
60
76
|
}
|
|
61
77
|
process.stderr.write(`chron-mcp ${VERSION} starting\n`);
|
package/dist/setup.d.ts
ADDED
package/dist/setup.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runSetup = runSetup;
|
|
4
|
+
const fs_1 = require("fs");
|
|
5
|
+
const os_1 = require("os");
|
|
6
|
+
const path_1 = require("path");
|
|
7
|
+
const child_process_1 = require("child_process");
|
|
8
|
+
const CHRON_ENTRY = {
|
|
9
|
+
command: 'npx',
|
|
10
|
+
args: ['-y', 'chron-mcp'],
|
|
11
|
+
};
|
|
12
|
+
function configPath(...parts) {
|
|
13
|
+
return (0, path_1.join)((0, os_1.homedir)(), ...parts);
|
|
14
|
+
}
|
|
15
|
+
const TOOLS = [
|
|
16
|
+
{
|
|
17
|
+
name: 'Claude Desktop',
|
|
18
|
+
path: process.platform === 'win32'
|
|
19
|
+
? (0, path_1.join)(process.env.APPDATA ?? '', 'Claude', 'claude_desktop_config.json')
|
|
20
|
+
: configPath('Library', 'Application Support', 'Claude', 'claude_desktop_config.json'),
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'Cursor',
|
|
24
|
+
path: process.platform === 'win32'
|
|
25
|
+
? (0, path_1.join)(process.env.APPDATA ?? '', 'Cursor', 'User', 'globalStorage', 'cursor.mcp', 'mcp.json')
|
|
26
|
+
: configPath('.cursor', 'mcp.json'),
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
name: 'Windsurf',
|
|
30
|
+
path: configPath('.codeium', 'windsurf', 'mcp_config.json'),
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: 'Claude Code',
|
|
34
|
+
path: configPath('.claude', 'settings.json'),
|
|
35
|
+
},
|
|
36
|
+
];
|
|
37
|
+
function readJson(filePath) {
|
|
38
|
+
if (!(0, fs_1.existsSync)(filePath))
|
|
39
|
+
return {};
|
|
40
|
+
try {
|
|
41
|
+
return JSON.parse((0, fs_1.readFileSync)(filePath, 'utf8'));
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return {};
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function writeJson(filePath, data) {
|
|
48
|
+
(0, fs_1.mkdirSync)((0, path_1.dirname)(filePath), { recursive: true });
|
|
49
|
+
(0, fs_1.writeFileSync)(filePath, JSON.stringify(data, null, 2) + '\n', 'utf8');
|
|
50
|
+
}
|
|
51
|
+
function configureTool(name, filePath) {
|
|
52
|
+
// Skip if the app isn't installed (config dir doesn't exist and it's not Claude Code)
|
|
53
|
+
const dir = (0, path_1.dirname)(filePath);
|
|
54
|
+
if (!(0, fs_1.existsSync)(dir) && name !== 'Claude Code') {
|
|
55
|
+
return { tool: name, status: 'skipped' };
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
const config = readJson(filePath);
|
|
59
|
+
if (!config.mcpServers)
|
|
60
|
+
config.mcpServers = {};
|
|
61
|
+
if (config.mcpServers.chron) {
|
|
62
|
+
return { tool: name, status: 'already', path: filePath };
|
|
63
|
+
}
|
|
64
|
+
config.mcpServers.chron = CHRON_ENTRY;
|
|
65
|
+
writeJson(filePath, config);
|
|
66
|
+
return { tool: name, status: 'added', path: filePath };
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
return { tool: name, status: 'error', error: err.message };
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function configureClaudeCode() {
|
|
73
|
+
// Try `claude mcp add` first — it's the official way
|
|
74
|
+
try {
|
|
75
|
+
(0, child_process_1.execSync)('claude mcp add chron -- npx -y chron-mcp', { stdio: 'pipe' });
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
// Fall back to writing settings.json directly
|
|
79
|
+
const result = configureTool('Claude Code', (0, path_1.join)((0, os_1.homedir)(), '.claude', 'settings.json'));
|
|
80
|
+
if (result.status === 'error')
|
|
81
|
+
return result;
|
|
82
|
+
}
|
|
83
|
+
// Also install the SessionStart hook so Claude auto-logs without manual tool calls
|
|
84
|
+
installClaudeCodeHook();
|
|
85
|
+
return { tool: 'Claude Code', status: 'added' };
|
|
86
|
+
}
|
|
87
|
+
function installClaudeCodeHook() {
|
|
88
|
+
// Copy skill file to ~/.chron/ so the hook can cat it
|
|
89
|
+
const skillSrc = (0, path_1.join)(__dirname, '..', 'skills', 'chron.skill.md');
|
|
90
|
+
const skillDst = (0, path_1.join)((0, os_1.homedir)(), '.chron', 'chron.skill.md');
|
|
91
|
+
if ((0, fs_1.existsSync)(skillSrc)) {
|
|
92
|
+
(0, fs_1.mkdirSync)((0, path_1.dirname)(skillDst), { recursive: true });
|
|
93
|
+
(0, fs_1.copyFileSync)(skillSrc, skillDst);
|
|
94
|
+
}
|
|
95
|
+
const settingsPath = (0, path_1.join)((0, os_1.homedir)(), '.claude', 'settings.json');
|
|
96
|
+
const settings = readJson(settingsPath);
|
|
97
|
+
if (!settings.hooks)
|
|
98
|
+
settings.hooks = {};
|
|
99
|
+
if (!settings.hooks.SessionStart)
|
|
100
|
+
settings.hooks.SessionStart = [];
|
|
101
|
+
const alreadyInstalled = settings.hooks.SessionStart.some((h) => Array.isArray(h.hooks) && h.hooks.some((c) => c.command?.includes('chron')));
|
|
102
|
+
if (!alreadyInstalled) {
|
|
103
|
+
settings.hooks.SessionStart.push({
|
|
104
|
+
hooks: [{ type: 'command', command: 'cat ~/.chron/chron.skill.md' }],
|
|
105
|
+
});
|
|
106
|
+
writeJson(settingsPath, settings);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
async function runSetup() {
|
|
110
|
+
const results = [];
|
|
111
|
+
for (const tool of TOOLS) {
|
|
112
|
+
const result = tool.name === 'Claude Code'
|
|
113
|
+
? configureClaudeCode()
|
|
114
|
+
: configureTool(tool.name, tool.path);
|
|
115
|
+
results.push(result);
|
|
116
|
+
}
|
|
117
|
+
return results.filter(r => r.status !== 'skipped');
|
|
118
|
+
}
|