@mkacki98/chestnut-mcp 0.1.5 → 0.1.7
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/README.md +12 -6
- package/dist/cli.js +1 -13
- package/dist/config.d.ts +0 -2
- package/dist/config.js +1 -7
- package/dist/oauth.js +61 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -21,6 +21,10 @@ This will:
|
|
|
21
21
|
- Prompt you to log in (if not already logged in)
|
|
22
22
|
- Generate an access token
|
|
23
23
|
- Save the token locally
|
|
24
|
+
- **Ask if you want to enable automatic course suggestions globally**
|
|
25
|
+
- If enabled, adds instructions to `~/.claude/CLAUDE.md`
|
|
26
|
+
- Claude will proactively suggest courses across **all your projects**
|
|
27
|
+
- You can disable this later by removing the Chestnut section from `~/.claude/CLAUDE.md`
|
|
24
28
|
|
|
25
29
|
### 2. Configure Claude Code
|
|
26
30
|
|
|
@@ -46,7 +50,6 @@ Claude Code will now automatically suggest courses when it detects learning oppo
|
|
|
46
50
|
- `npx chestnut-mcp auth` - Authenticate with Chestnut
|
|
47
51
|
- `npx chestnut-mcp status` - Check authentication status
|
|
48
52
|
- `npx chestnut-mcp logout` - Clear saved credentials
|
|
49
|
-
- `npx chestnut-mcp config` - View/set configuration
|
|
50
53
|
|
|
51
54
|
## Development
|
|
52
55
|
|
|
@@ -63,11 +66,14 @@ npm run dev
|
|
|
63
66
|
|
|
64
67
|
## How It Works
|
|
65
68
|
|
|
66
|
-
1.
|
|
67
|
-
2.
|
|
68
|
-
3.
|
|
69
|
-
4.
|
|
70
|
-
5.
|
|
69
|
+
1. During auth, you opt-in to global course suggestions
|
|
70
|
+
2. Claude Code (with global instructions) proactively detects learning opportunities
|
|
71
|
+
3. When you could benefit from learning something, Claude calls the `create_pending_course` tool
|
|
72
|
+
4. Tool sends suggestion to your Chestnut account
|
|
73
|
+
5. You see the suggestion in your dashboard at https://chestnut.so
|
|
74
|
+
6. Click "Start Course" to begin learning
|
|
75
|
+
|
|
76
|
+
**Note:** If you enabled global suggestions during auth, Claude will suggest courses across all your projects. To disable, remove the "Chestnut Learning Integration" section from `~/.claude/CLAUDE.md`.
|
|
71
77
|
|
|
72
78
|
## License
|
|
73
79
|
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { initiateOAuth } from "./oauth.js";
|
|
3
|
-
import { loadAccessToken, clearAccessToken, getChestnutUrl
|
|
3
|
+
import { loadAccessToken, clearAccessToken, getChestnutUrl } from "./config.js";
|
|
4
4
|
const args = process.argv.slice(2);
|
|
5
5
|
const command = args[0];
|
|
6
6
|
async function main() {
|
|
@@ -24,24 +24,12 @@ async function main() {
|
|
|
24
24
|
clearAccessToken();
|
|
25
25
|
console.log("✓ Logged out successfully");
|
|
26
26
|
break;
|
|
27
|
-
case "config":
|
|
28
|
-
if (args[1] === "set-url" && args[2]) {
|
|
29
|
-
setChestnutUrl(args[2]);
|
|
30
|
-
console.log(`✓ Chestnut URL set to: ${args[2]}`);
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
console.log(`Current Chestnut URL: ${getChestnutUrl()}`);
|
|
34
|
-
console.log("\nTo change URL:");
|
|
35
|
-
console.log(" npx chestnut-mcp config set-url https://your-url.com");
|
|
36
|
-
}
|
|
37
|
-
break;
|
|
38
27
|
default:
|
|
39
28
|
console.log("Chestnut MCP Server");
|
|
40
29
|
console.log("\nCommands:");
|
|
41
30
|
console.log(" auth Authenticate with Chestnut");
|
|
42
31
|
console.log(" status Check authentication status");
|
|
43
32
|
console.log(" logout Clear saved token");
|
|
44
|
-
console.log(" config View/set configuration");
|
|
45
33
|
console.log("\nFor Claude Code integration, add to your config:");
|
|
46
34
|
console.log(JSON.stringify({
|
|
47
35
|
mcpServers: {
|
package/dist/config.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
interface Config {
|
|
2
2
|
accessToken?: string;
|
|
3
|
-
chestnutUrl?: string;
|
|
4
3
|
}
|
|
5
4
|
export declare function loadConfig(): Config;
|
|
6
5
|
export declare function saveConfig(config: Config): void;
|
|
@@ -8,5 +7,4 @@ export declare function loadAccessToken(): string | null;
|
|
|
8
7
|
export declare function saveAccessToken(token: string): void;
|
|
9
8
|
export declare function clearAccessToken(): void;
|
|
10
9
|
export declare function getChestnutUrl(): string;
|
|
11
|
-
export declare function setChestnutUrl(url: string): void;
|
|
12
10
|
export {};
|
package/dist/config.js
CHANGED
|
@@ -36,11 +36,5 @@ export function clearAccessToken() {
|
|
|
36
36
|
saveConfig(config);
|
|
37
37
|
}
|
|
38
38
|
export function getChestnutUrl() {
|
|
39
|
-
|
|
40
|
-
return config.chestnutUrl || "https://chestnut.so";
|
|
41
|
-
}
|
|
42
|
-
export function setChestnutUrl(url) {
|
|
43
|
-
const config = loadConfig();
|
|
44
|
-
config.chestnutUrl = url;
|
|
45
|
-
saveConfig(config);
|
|
39
|
+
return "https://chestnut.so";
|
|
46
40
|
}
|
package/dist/oauth.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import open from "open";
|
|
2
2
|
import { saveAccessToken, getChestnutUrl } from "./config.js";
|
|
3
3
|
import readline from "readline";
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import os from "os";
|
|
4
7
|
export async function initiateOAuth() {
|
|
5
8
|
const chestnutUrl = getChestnutUrl();
|
|
6
9
|
const authUrl = `${chestnutUrl}/integrations/claude_code/authorize`;
|
|
@@ -37,9 +40,18 @@ export async function initiateOAuth() {
|
|
|
37
40
|
saveAccessToken(token);
|
|
38
41
|
console.log("✓ Authenticated successfully with Chestnut!");
|
|
39
42
|
console.log(`Token saved to: ${process.env.HOME}/.chestnut-mcp/config.json\n`);
|
|
43
|
+
// Prompt to configure global Claude instructions
|
|
44
|
+
await configureGlobalClaude();
|
|
40
45
|
}
|
|
41
46
|
else {
|
|
42
|
-
console.log(
|
|
47
|
+
console.log(`❌ Invalid token. Server returned status: ${response.status}`);
|
|
48
|
+
try {
|
|
49
|
+
const body = await response.text();
|
|
50
|
+
console.log(`Response: ${body}`);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
console.log("(Could not read response body)");
|
|
54
|
+
}
|
|
43
55
|
}
|
|
44
56
|
}
|
|
45
57
|
catch (error) {
|
|
@@ -58,3 +70,51 @@ async function promptForToken() {
|
|
|
58
70
|
});
|
|
59
71
|
});
|
|
60
72
|
}
|
|
73
|
+
async function promptForYesNo(question) {
|
|
74
|
+
const rl = readline.createInterface({
|
|
75
|
+
input: process.stdin,
|
|
76
|
+
output: process.stdout,
|
|
77
|
+
});
|
|
78
|
+
return new Promise((resolve) => {
|
|
79
|
+
rl.question(question, (answer) => {
|
|
80
|
+
rl.close();
|
|
81
|
+
const normalized = answer.trim().toLowerCase();
|
|
82
|
+
resolve(normalized === "y" || normalized === "yes");
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
async function configureGlobalClaude() {
|
|
87
|
+
const claudeDir = path.join(os.homedir(), ".claude");
|
|
88
|
+
const claudeMdPath = path.join(claudeDir, "CLAUDE.md");
|
|
89
|
+
const chestnutInstructions = `
|
|
90
|
+
# Chestnut Learning Integration
|
|
91
|
+
When you notice I could benefit from learning something:
|
|
92
|
+
- Proactively use the \`create_pending_course\` MCP tool
|
|
93
|
+
- Examples: using outdated patterns, reinventing features, common mistakes, suboptimal approaches
|
|
94
|
+
- Run it also when I explicitly ask you to suggest a course
|
|
95
|
+
- Keep suggestions relevant and actionable
|
|
96
|
+
`;
|
|
97
|
+
// Check if instructions already exist
|
|
98
|
+
if (fs.existsSync(claudeMdPath)) {
|
|
99
|
+
const content = fs.readFileSync(claudeMdPath, "utf-8");
|
|
100
|
+
if (content.includes("Chestnut Learning Integration")) {
|
|
101
|
+
console.log("ℹ️ Global Claude instructions already configured for Chestnut.");
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
console.log("\n📚 Chestnut can automatically suggest courses when Claude notices learning opportunities.");
|
|
106
|
+
console.log("⚠️ This will be enabled GLOBALLY for all your Claude Code sessions.\n");
|
|
107
|
+
const enableGlobal = await promptForYesNo("Enable automatic course suggestions globally? (y/n): ");
|
|
108
|
+
if (!enableGlobal) {
|
|
109
|
+
console.log("⏭️ Skipped global configuration. You can enable it later in ~/.claude/CLAUDE.md");
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
// Ensure ~/.claude directory exists
|
|
113
|
+
if (!fs.existsSync(claudeDir)) {
|
|
114
|
+
fs.mkdirSync(claudeDir, { recursive: true });
|
|
115
|
+
}
|
|
116
|
+
// Append or create CLAUDE.md
|
|
117
|
+
fs.appendFileSync(claudeMdPath, chestnutInstructions);
|
|
118
|
+
console.log(`✓ Global instructions added to: ${claudeMdPath}`);
|
|
119
|
+
console.log(" Claude will now proactively suggest Chestnut courses across all projects.\n");
|
|
120
|
+
}
|