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 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.10';
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 — not from an MCP client
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} ✓\n`);
53
- process.stdout.write(`database: ${dbPath}\n\n`);
54
- process.stdout.write(`Installation verified. Add to your MCP config:\n\n`);
55
- process.stdout.write(` Claude Code: claude mcp add chron -- npx -y chron-mcp\n`);
56
- process.stdout.write(` Claude Desktop: add to claude_desktop_config.json\n`);
57
- process.stdout.write(` Cursor: add to ~/.cursor/mcp.json\n\n`);
58
- process.stdout.write(`See README: https://github.com/SirinivasK/chron\n`);
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`);
@@ -0,0 +1,8 @@
1
+ export type SetupStatus = 'added' | 'already' | 'skipped' | 'error';
2
+ export interface SetupResult {
3
+ tool: string;
4
+ status: SetupStatus;
5
+ path?: string;
6
+ error?: string;
7
+ }
8
+ export declare function runSetup(): Promise<SetupResult[]>;
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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chron-mcp",
3
- "version": "0.1.10",
3
+ "version": "0.1.12",
4
4
  "mcpName": "io.github.SirinivasK/chron",
5
5
  "description": "Audit-grade timestamped logs for every AI conversation",
6
6
  "repository": {