@pollychrome/joan-mcp 1.0.0
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 +385 -0
- package/bin/joan-mcp +16 -0
- package/dist/auth.d.ts +49 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +264 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli.d.ts +7 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +326 -0
- package/dist/cli.js.map +1 -0
- package/dist/client/api-client.d.ts +86 -0
- package/dist/client/api-client.d.ts.map +1 -0
- package/dist/client/api-client.js +182 -0
- package/dist/client/api-client.js.map +1 -0
- package/dist/client/types.d.ts +270 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +5 -0
- package/dist/client/types.js.map +1 -0
- package/dist/config.d.ts +33 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +71 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +118 -0
- package/dist/index.js.map +1 -0
- package/dist/resources/goals.d.ts +7 -0
- package/dist/resources/goals.d.ts.map +1 -0
- package/dist/resources/goals.js +49 -0
- package/dist/resources/goals.js.map +1 -0
- package/dist/resources/index.d.ts +16 -0
- package/dist/resources/index.d.ts.map +1 -0
- package/dist/resources/index.js +20 -0
- package/dist/resources/index.js.map +1 -0
- package/dist/resources/milestones.d.ts +7 -0
- package/dist/resources/milestones.d.ts.map +1 -0
- package/dist/resources/milestones.js +40 -0
- package/dist/resources/milestones.js.map +1 -0
- package/dist/resources/notes.d.ts +7 -0
- package/dist/resources/notes.d.ts.map +1 -0
- package/dist/resources/notes.js +33 -0
- package/dist/resources/notes.js.map +1 -0
- package/dist/resources/projects.d.ts +7 -0
- package/dist/resources/projects.d.ts.map +1 -0
- package/dist/resources/projects.js +97 -0
- package/dist/resources/projects.js.map +1 -0
- package/dist/resources/tasks.d.ts +7 -0
- package/dist/resources/tasks.d.ts.map +1 -0
- package/dist/resources/tasks.js +36 -0
- package/dist/resources/tasks.js.map +1 -0
- package/dist/tools/goals.d.ts +7 -0
- package/dist/tools/goals.d.ts.map +1 -0
- package/dist/tools/goals.js +114 -0
- package/dist/tools/goals.js.map +1 -0
- package/dist/tools/index.d.ts +16 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +20 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/milestones.d.ts +7 -0
- package/dist/tools/milestones.d.ts.map +1 -0
- package/dist/tools/milestones.js +119 -0
- package/dist/tools/milestones.js.map +1 -0
- package/dist/tools/notes.d.ts +7 -0
- package/dist/tools/notes.d.ts.map +1 -0
- package/dist/tools/notes.js +82 -0
- package/dist/tools/notes.js.map +1 -0
- package/dist/tools/projects.d.ts +7 -0
- package/dist/tools/projects.d.ts.map +1 -0
- package/dist/tools/projects.js +63 -0
- package/dist/tools/projects.js.map +1 -0
- package/dist/tools/tasks.d.ts +7 -0
- package/dist/tools/tasks.d.ts.map +1 -0
- package/dist/tools/tasks.js +125 -0
- package/dist/tools/tasks.js.map +1 -0
- package/dist/utils/converters.d.ts +78 -0
- package/dist/utils/converters.d.ts.map +1 -0
- package/dist/utils/converters.js +79 -0
- package/dist/utils/converters.js.map +1 -0
- package/dist/utils/errors.d.ts +27 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +104 -0
- package/dist/utils/errors.js.map +1 -0
- package/package.json +53 -0
package/dist/auth.js
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth token management for Joan MCP server
|
|
3
|
+
* Handles storing, retrieving, and validating auth tokens
|
|
4
|
+
*/
|
|
5
|
+
import { createServer } from 'node:http';
|
|
6
|
+
import { mkdir, readFile, writeFile, unlink, chmod } from 'node:fs/promises';
|
|
7
|
+
import { homedir } from 'node:os';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
import { randomBytes, createCipheriv, createDecipheriv, scryptSync } from 'node:crypto';
|
|
10
|
+
import { AuthenticationError } from './utils/errors.js';
|
|
11
|
+
const CONFIG_DIR = join(homedir(), '.joan-mcp');
|
|
12
|
+
const CREDENTIALS_FILE = join(CONFIG_DIR, 'credentials.json');
|
|
13
|
+
const ALGORITHM = 'aes-256-gcm';
|
|
14
|
+
/**
|
|
15
|
+
* Get a machine-specific encryption key
|
|
16
|
+
* Uses a combination of factors to create a stable key
|
|
17
|
+
*/
|
|
18
|
+
function getMachineKey() {
|
|
19
|
+
// Use home directory and username as salt - stable across sessions
|
|
20
|
+
const salt = `${homedir()}-${process.env.USER || process.env.USERNAME || 'joan'}`;
|
|
21
|
+
return scryptSync('joan-mcp-local-encryption', salt, 32);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Encrypt a token for storage
|
|
25
|
+
*/
|
|
26
|
+
function encryptToken(token) {
|
|
27
|
+
const key = getMachineKey();
|
|
28
|
+
const iv = randomBytes(16);
|
|
29
|
+
const cipher = createCipheriv(ALGORITHM, key, iv);
|
|
30
|
+
let encrypted = cipher.update(token, 'utf8', 'hex');
|
|
31
|
+
encrypted += cipher.final('hex');
|
|
32
|
+
const authTag = cipher.getAuthTag();
|
|
33
|
+
return {
|
|
34
|
+
encrypted,
|
|
35
|
+
iv: iv.toString('hex'),
|
|
36
|
+
authTag: authTag.toString('hex'),
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Decrypt a stored token
|
|
41
|
+
*/
|
|
42
|
+
function decryptToken(encrypted, iv, authTag) {
|
|
43
|
+
const key = getMachineKey();
|
|
44
|
+
const decipher = createDecipheriv(ALGORITHM, key, Buffer.from(iv, 'hex'));
|
|
45
|
+
decipher.setAuthTag(Buffer.from(authTag, 'hex'));
|
|
46
|
+
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
|
|
47
|
+
decrypted += decipher.final('utf8');
|
|
48
|
+
return decrypted;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Ensure the config directory exists
|
|
52
|
+
*/
|
|
53
|
+
async function ensureConfigDir() {
|
|
54
|
+
try {
|
|
55
|
+
await mkdir(CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (error.code !== 'EEXIST') {
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Store auth token securely
|
|
65
|
+
*/
|
|
66
|
+
export async function storeToken(token, email, expiresAt) {
|
|
67
|
+
await ensureConfigDir();
|
|
68
|
+
const { encrypted, iv, authTag } = encryptToken(token);
|
|
69
|
+
const credentials = {
|
|
70
|
+
token: encrypted,
|
|
71
|
+
iv,
|
|
72
|
+
authTag,
|
|
73
|
+
email,
|
|
74
|
+
expiresAt: expiresAt?.toISOString(),
|
|
75
|
+
createdAt: new Date().toISOString(),
|
|
76
|
+
};
|
|
77
|
+
await writeFile(CREDENTIALS_FILE, JSON.stringify(credentials, null, 2), 'utf8');
|
|
78
|
+
await chmod(CREDENTIALS_FILE, 0o600); // Owner read/write only
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Retrieve stored auth token
|
|
82
|
+
*/
|
|
83
|
+
export async function getStoredToken() {
|
|
84
|
+
try {
|
|
85
|
+
const content = await readFile(CREDENTIALS_FILE, 'utf8');
|
|
86
|
+
const credentials = JSON.parse(content);
|
|
87
|
+
// Check if token is expired
|
|
88
|
+
if (credentials.expiresAt) {
|
|
89
|
+
const expiresAt = new Date(credentials.expiresAt);
|
|
90
|
+
if (expiresAt < new Date()) {
|
|
91
|
+
// Token expired, remove it
|
|
92
|
+
await clearToken();
|
|
93
|
+
return null;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const token = decryptToken(credentials.token, credentials.iv, credentials.authTag);
|
|
97
|
+
return {
|
|
98
|
+
token,
|
|
99
|
+
email: credentials.email,
|
|
100
|
+
expiresAt: credentials.expiresAt ? new Date(credentials.expiresAt) : undefined,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
catch (error) {
|
|
104
|
+
if (error.code === 'ENOENT') {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Clear stored token
|
|
112
|
+
*/
|
|
113
|
+
export async function clearToken() {
|
|
114
|
+
try {
|
|
115
|
+
await unlink(CREDENTIALS_FILE);
|
|
116
|
+
}
|
|
117
|
+
catch (error) {
|
|
118
|
+
if (error.code !== 'ENOENT') {
|
|
119
|
+
throw error;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Get auth token from stored credentials or environment variable
|
|
125
|
+
*/
|
|
126
|
+
export async function getAuthToken() {
|
|
127
|
+
// First, check environment variable
|
|
128
|
+
if (process.env.JOAN_AUTH_TOKEN) {
|
|
129
|
+
return process.env.JOAN_AUTH_TOKEN;
|
|
130
|
+
}
|
|
131
|
+
// Then, check stored credentials
|
|
132
|
+
const stored = await getStoredToken();
|
|
133
|
+
if (stored) {
|
|
134
|
+
return stored.token;
|
|
135
|
+
}
|
|
136
|
+
throw new AuthenticationError('No authentication token found. Run "joan-mcp login" to authenticate or set JOAN_AUTH_TOKEN environment variable.');
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Parse JWT to extract payload (without verification)
|
|
140
|
+
*/
|
|
141
|
+
export function parseJwt(token) {
|
|
142
|
+
try {
|
|
143
|
+
const parts = token.split('.');
|
|
144
|
+
if (parts.length !== 3) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
const payload = JSON.parse(Buffer.from(parts[1], 'base64').toString('utf8'));
|
|
148
|
+
return payload;
|
|
149
|
+
}
|
|
150
|
+
catch {
|
|
151
|
+
return null;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Check if token is expired based on JWT payload
|
|
156
|
+
*/
|
|
157
|
+
export function isTokenExpired(token) {
|
|
158
|
+
const payload = parseJwt(token);
|
|
159
|
+
if (!payload?.exp) {
|
|
160
|
+
return false; // Assume not expired if no exp claim
|
|
161
|
+
}
|
|
162
|
+
return payload.exp * 1000 < Date.now();
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Start local HTTP server for OAuth callback
|
|
166
|
+
* Returns a promise that resolves with the token when received
|
|
167
|
+
*/
|
|
168
|
+
export function startCallbackServer(port) {
|
|
169
|
+
return new Promise((resolve, reject) => {
|
|
170
|
+
const server = createServer((req, res) => {
|
|
171
|
+
const url = new URL(req.url || '/', `http://localhost:${port}`);
|
|
172
|
+
if (url.pathname === '/callback') {
|
|
173
|
+
const token = url.searchParams.get('token');
|
|
174
|
+
const email = url.searchParams.get('email');
|
|
175
|
+
const error = url.searchParams.get('error');
|
|
176
|
+
if (error) {
|
|
177
|
+
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
178
|
+
res.end(`
|
|
179
|
+
<!DOCTYPE html>
|
|
180
|
+
<html>
|
|
181
|
+
<head><title>Authentication Failed</title></head>
|
|
182
|
+
<body style="font-family: system-ui; padding: 40px; text-align: center;">
|
|
183
|
+
<h1 style="color: #dc2626;">Authentication Failed</h1>
|
|
184
|
+
<p>${error}</p>
|
|
185
|
+
<p>You can close this window.</p>
|
|
186
|
+
</body>
|
|
187
|
+
</html>
|
|
188
|
+
`);
|
|
189
|
+
server.close();
|
|
190
|
+
reject(new AuthenticationError(error));
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (!token) {
|
|
194
|
+
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
195
|
+
res.end(`
|
|
196
|
+
<!DOCTYPE html>
|
|
197
|
+
<html>
|
|
198
|
+
<head><title>Authentication Failed</title></head>
|
|
199
|
+
<body style="font-family: system-ui; padding: 40px; text-align: center;">
|
|
200
|
+
<h1 style="color: #dc2626;">Authentication Failed</h1>
|
|
201
|
+
<p>No token received.</p>
|
|
202
|
+
<p>You can close this window.</p>
|
|
203
|
+
</body>
|
|
204
|
+
</html>
|
|
205
|
+
`);
|
|
206
|
+
server.close();
|
|
207
|
+
reject(new AuthenticationError('No token received'));
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
211
|
+
res.end(`
|
|
212
|
+
<!DOCTYPE html>
|
|
213
|
+
<html>
|
|
214
|
+
<head><title>Authentication Successful</title></head>
|
|
215
|
+
<body style="font-family: system-ui; padding: 40px; text-align: center;">
|
|
216
|
+
<h1 style="color: #16a34a;">Authentication Successful!</h1>
|
|
217
|
+
<p>You are now logged in to Joan MCP.</p>
|
|
218
|
+
<p>You can close this window and return to the terminal.</p>
|
|
219
|
+
<script>setTimeout(() => window.close(), 2000);</script>
|
|
220
|
+
</body>
|
|
221
|
+
</html>
|
|
222
|
+
`);
|
|
223
|
+
server.close();
|
|
224
|
+
resolve({ token, email: email || undefined });
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
228
|
+
res.end('Not found');
|
|
229
|
+
}
|
|
230
|
+
});
|
|
231
|
+
server.on('error', reject);
|
|
232
|
+
server.listen(port, 'localhost', () => {
|
|
233
|
+
// Server started
|
|
234
|
+
});
|
|
235
|
+
// Timeout after 5 minutes
|
|
236
|
+
setTimeout(() => {
|
|
237
|
+
server.close();
|
|
238
|
+
reject(new AuthenticationError('Authentication timeout - no response received'));
|
|
239
|
+
}, 5 * 60 * 1000);
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Find an available port for the callback server
|
|
244
|
+
*/
|
|
245
|
+
export async function findAvailablePort(startPort = 9876) {
|
|
246
|
+
return new Promise((resolve, reject) => {
|
|
247
|
+
const server = createServer();
|
|
248
|
+
server.listen(startPort, 'localhost', () => {
|
|
249
|
+
const address = server.address();
|
|
250
|
+
const port = typeof address === 'object' && address ? address.port : startPort;
|
|
251
|
+
server.close(() => resolve(port));
|
|
252
|
+
});
|
|
253
|
+
server.on('error', (err) => {
|
|
254
|
+
if (err.code === 'EADDRINUSE') {
|
|
255
|
+
// Try next port
|
|
256
|
+
findAvailablePort(startPort + 1).then(resolve).catch(reject);
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
reject(err);
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA;;;GAGG"}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* CLI for Joan MCP server
|
|
4
|
+
* Commands: login, logout, status, serve (default)
|
|
5
|
+
*/
|
|
6
|
+
import { spawn } from 'node:child_process';
|
|
7
|
+
import { getStoredToken, storeToken, clearToken, findAvailablePort, startCallbackServer, parseJwt, isTokenExpired, } from './auth.js';
|
|
8
|
+
import { getApiUrl, getMcpAuthUrl, loadConfig } from './config.js';
|
|
9
|
+
import { JoanApiClient } from './client/api-client.js';
|
|
10
|
+
import { startServer } from './index.js';
|
|
11
|
+
const HELP_TEXT = `
|
|
12
|
+
Joan MCP Server - AI assistant integration for Joan productivity app
|
|
13
|
+
|
|
14
|
+
Usage: joan-mcp <command>
|
|
15
|
+
|
|
16
|
+
Commands:
|
|
17
|
+
init Set up Joan MCP (login + configure Claude Code)
|
|
18
|
+
serve Start the MCP server (default)
|
|
19
|
+
login Authenticate with Joan
|
|
20
|
+
logout Clear stored credentials
|
|
21
|
+
status Show current authentication status
|
|
22
|
+
help Show this help message
|
|
23
|
+
|
|
24
|
+
Examples:
|
|
25
|
+
joan-mcp init # First-time setup (recommended)
|
|
26
|
+
joan-mcp login # Opens browser to authenticate
|
|
27
|
+
joan-mcp status # Shows if logged in
|
|
28
|
+
joan-mcp serve # Start MCP server
|
|
29
|
+
joan-mcp # Same as 'joan-mcp serve'
|
|
30
|
+
|
|
31
|
+
Environment Variables:
|
|
32
|
+
JOAN_AUTH_TOKEN JWT token for authentication (alternative to login)
|
|
33
|
+
JOAN_API_URL API base URL (default: production)
|
|
34
|
+
`;
|
|
35
|
+
/**
|
|
36
|
+
* Open a URL in the default browser
|
|
37
|
+
*/
|
|
38
|
+
async function openBrowser(url) {
|
|
39
|
+
const platform = process.platform;
|
|
40
|
+
let command;
|
|
41
|
+
let args;
|
|
42
|
+
switch (platform) {
|
|
43
|
+
case 'darwin':
|
|
44
|
+
command = 'open';
|
|
45
|
+
args = [url];
|
|
46
|
+
break;
|
|
47
|
+
case 'win32':
|
|
48
|
+
command = 'cmd';
|
|
49
|
+
args = ['/c', 'start', url];
|
|
50
|
+
break;
|
|
51
|
+
default:
|
|
52
|
+
// Linux and others
|
|
53
|
+
command = 'xdg-open';
|
|
54
|
+
args = [url];
|
|
55
|
+
}
|
|
56
|
+
return new Promise((resolve, reject) => {
|
|
57
|
+
const child = spawn(command, args, {
|
|
58
|
+
detached: true,
|
|
59
|
+
stdio: 'ignore',
|
|
60
|
+
});
|
|
61
|
+
child.unref();
|
|
62
|
+
child.on('error', reject);
|
|
63
|
+
// Give it a moment to start
|
|
64
|
+
setTimeout(resolve, 500);
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Login command - opens browser for authentication
|
|
69
|
+
*/
|
|
70
|
+
async function login() {
|
|
71
|
+
console.log('Starting authentication flow...');
|
|
72
|
+
// Check if already logged in
|
|
73
|
+
const existing = await getStoredToken();
|
|
74
|
+
if (existing && !isTokenExpired(existing.token)) {
|
|
75
|
+
console.log(`Already logged in as ${existing.email || 'unknown user'}`);
|
|
76
|
+
console.log('Run "joan-mcp logout" first to login with a different account.');
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
// Find available port for callback
|
|
80
|
+
const port = await findAvailablePort();
|
|
81
|
+
console.log(`Callback server listening on port ${port}`);
|
|
82
|
+
// Start callback server
|
|
83
|
+
const callbackPromise = startCallbackServer(port);
|
|
84
|
+
// Open browser to MCP auth page
|
|
85
|
+
const loginUrl = getMcpAuthUrl(port);
|
|
86
|
+
console.log(`Opening browser to: ${loginUrl}`);
|
|
87
|
+
console.log('If the browser does not open, please visit the URL manually.');
|
|
88
|
+
try {
|
|
89
|
+
await openBrowser(loginUrl);
|
|
90
|
+
}
|
|
91
|
+
catch (error) {
|
|
92
|
+
console.log('Could not open browser automatically.');
|
|
93
|
+
console.log(`Please visit: ${loginUrl}`);
|
|
94
|
+
}
|
|
95
|
+
console.log('\nWaiting for authentication...');
|
|
96
|
+
try {
|
|
97
|
+
const { token, email } = await callbackPromise;
|
|
98
|
+
// Parse JWT to get expiration
|
|
99
|
+
const payload = parseJwt(token);
|
|
100
|
+
const expiresAt = payload?.exp ? new Date(payload.exp * 1000) : undefined;
|
|
101
|
+
// Store the token
|
|
102
|
+
await storeToken(token, email, expiresAt);
|
|
103
|
+
console.log('\n✓ Authentication successful!');
|
|
104
|
+
console.log(` Logged in as: ${email || 'unknown'}`);
|
|
105
|
+
if (expiresAt) {
|
|
106
|
+
console.log(` Token expires: ${expiresAt.toLocaleDateString()}`);
|
|
107
|
+
}
|
|
108
|
+
console.log('\nYou can now use joan-mcp with Claude Code or other MCP clients.');
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
console.error('\n✗ Authentication failed:', error.message);
|
|
112
|
+
process.exit(1);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Logout command - clear stored credentials
|
|
117
|
+
*/
|
|
118
|
+
async function logout() {
|
|
119
|
+
await clearToken();
|
|
120
|
+
console.log('Logged out. Stored credentials have been cleared.');
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Status command - show current auth status
|
|
124
|
+
*/
|
|
125
|
+
async function status() {
|
|
126
|
+
// Check environment variable first
|
|
127
|
+
if (process.env.JOAN_AUTH_TOKEN) {
|
|
128
|
+
console.log('Authentication: Using JOAN_AUTH_TOKEN environment variable');
|
|
129
|
+
const payload = parseJwt(process.env.JOAN_AUTH_TOKEN);
|
|
130
|
+
if (payload) {
|
|
131
|
+
console.log(` Email: ${payload.sub || payload.email || 'unknown'}`);
|
|
132
|
+
if (payload.exp) {
|
|
133
|
+
const expDate = new Date(payload.exp * 1000);
|
|
134
|
+
const isExpired = expDate < new Date();
|
|
135
|
+
console.log(` Expires: ${expDate.toLocaleDateString()} ${isExpired ? '(EXPIRED)' : ''}`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
console.log(`\nAPI URL: ${getApiUrl()}`);
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
// Check stored token
|
|
142
|
+
const stored = await getStoredToken();
|
|
143
|
+
if (!stored) {
|
|
144
|
+
console.log('Not logged in.');
|
|
145
|
+
console.log('Run "joan-mcp login" to authenticate.');
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const isExpired = isTokenExpired(stored.token);
|
|
149
|
+
console.log(`Authentication: Logged in${isExpired ? ' (EXPIRED)' : ''}`);
|
|
150
|
+
console.log(` Email: ${stored.email || 'unknown'}`);
|
|
151
|
+
if (stored.expiresAt) {
|
|
152
|
+
console.log(` Expires: ${stored.expiresAt.toLocaleDateString()}`);
|
|
153
|
+
}
|
|
154
|
+
console.log(`\nAPI URL: ${getApiUrl()}`);
|
|
155
|
+
// Verify token by calling API
|
|
156
|
+
if (!isExpired) {
|
|
157
|
+
try {
|
|
158
|
+
const config = await loadConfig();
|
|
159
|
+
const client = new JoanApiClient({
|
|
160
|
+
baseUrl: config.apiUrl,
|
|
161
|
+
authToken: config.authToken,
|
|
162
|
+
});
|
|
163
|
+
const user = await client.getCurrentUser();
|
|
164
|
+
console.log(`\n✓ Token verified with API`);
|
|
165
|
+
console.log(` User ID: ${user.id}`);
|
|
166
|
+
console.log(` Name: ${user.name || 'N/A'}`);
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
console.log(`\n⚠ Could not verify token with API: ${error.message}`);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Serve command - start MCP server
|
|
175
|
+
*/
|
|
176
|
+
async function serve() {
|
|
177
|
+
// This is handled by index.ts
|
|
178
|
+
await startServer();
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Get the path to this CLI script for Claude Code config
|
|
182
|
+
*/
|
|
183
|
+
function getCliPath() {
|
|
184
|
+
// Get the directory where this script is located
|
|
185
|
+
const scriptPath = process.argv[1];
|
|
186
|
+
// If running via tsx, we need to find the actual source file
|
|
187
|
+
if (scriptPath.includes('node_modules/.bin/tsx') || scriptPath.includes('tsx')) {
|
|
188
|
+
// We're running in dev mode, use the src path
|
|
189
|
+
const srcDir = new URL('.', import.meta.url).pathname;
|
|
190
|
+
return `${srcDir}cli.ts`;
|
|
191
|
+
}
|
|
192
|
+
// Running compiled, use the dist path
|
|
193
|
+
return scriptPath;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Configure Claude Code to use Joan MCP
|
|
197
|
+
*/
|
|
198
|
+
async function configureClaudeCode() {
|
|
199
|
+
const { readFile, writeFile, mkdir } = await import('node:fs/promises');
|
|
200
|
+
const { homedir } = await import('node:os');
|
|
201
|
+
const { join, dirname } = await import('node:path');
|
|
202
|
+
const { existsSync } = await import('node:fs');
|
|
203
|
+
const claudeSettingsPath = join(homedir(), '.claude', 'settings.json');
|
|
204
|
+
const cliPath = getCliPath();
|
|
205
|
+
// Determine how to run the CLI
|
|
206
|
+
let command;
|
|
207
|
+
let args;
|
|
208
|
+
if (cliPath.endsWith('.ts')) {
|
|
209
|
+
// Development mode - use npx tsx
|
|
210
|
+
command = 'npx';
|
|
211
|
+
args = ['tsx', cliPath, 'serve'];
|
|
212
|
+
}
|
|
213
|
+
else {
|
|
214
|
+
// Production mode - use node directly
|
|
215
|
+
command = 'node';
|
|
216
|
+
args = [cliPath, 'serve'];
|
|
217
|
+
}
|
|
218
|
+
const joanConfig = {
|
|
219
|
+
command,
|
|
220
|
+
args,
|
|
221
|
+
};
|
|
222
|
+
try {
|
|
223
|
+
let settings = {};
|
|
224
|
+
// Read existing settings if they exist
|
|
225
|
+
if (existsSync(claudeSettingsPath)) {
|
|
226
|
+
const content = await readFile(claudeSettingsPath, 'utf8');
|
|
227
|
+
settings = JSON.parse(content);
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
// Create directory if it doesn't exist
|
|
231
|
+
await mkdir(dirname(claudeSettingsPath), { recursive: true });
|
|
232
|
+
}
|
|
233
|
+
// Add or update mcpServers
|
|
234
|
+
if (!settings.mcpServers) {
|
|
235
|
+
settings.mcpServers = {};
|
|
236
|
+
}
|
|
237
|
+
settings.mcpServers.joan = joanConfig;
|
|
238
|
+
// Write updated settings
|
|
239
|
+
await writeFile(claudeSettingsPath, JSON.stringify(settings, null, 2), 'utf8');
|
|
240
|
+
console.log(`\n✓ Claude Code configured`);
|
|
241
|
+
console.log(` Settings: ${claudeSettingsPath}`);
|
|
242
|
+
console.log(` Command: ${command} ${args.join(' ')}`);
|
|
243
|
+
return true;
|
|
244
|
+
}
|
|
245
|
+
catch (error) {
|
|
246
|
+
console.error(`\n⚠ Could not configure Claude Code automatically: ${error.message}`);
|
|
247
|
+
console.log('\nManual configuration:');
|
|
248
|
+
console.log(`Add this to ${claudeSettingsPath}:`);
|
|
249
|
+
console.log(JSON.stringify({ mcpServers: { joan: joanConfig } }, null, 2));
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Init command - full setup (login + configure Claude Code)
|
|
255
|
+
*/
|
|
256
|
+
async function init() {
|
|
257
|
+
console.log('╔════════════════════════════════════════════╗');
|
|
258
|
+
console.log('║ Joan MCP Server - Setup Wizard ║');
|
|
259
|
+
console.log('╚════════════════════════════════════════════╝\n');
|
|
260
|
+
// Step 1: Check if already logged in
|
|
261
|
+
const existing = await getStoredToken();
|
|
262
|
+
if (existing && !isTokenExpired(existing.token)) {
|
|
263
|
+
console.log(`✓ Already logged in as ${existing.email || 'unknown user'}\n`);
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
// Step 1: Login
|
|
267
|
+
console.log('Step 1/2: Authenticate with Joan\n');
|
|
268
|
+
await login();
|
|
269
|
+
console.log('');
|
|
270
|
+
}
|
|
271
|
+
// Step 2: Configure Claude Code
|
|
272
|
+
console.log('Step 2/2: Configure Claude Code\n');
|
|
273
|
+
await configureClaudeCode();
|
|
274
|
+
// Done!
|
|
275
|
+
console.log('\n╔════════════════════════════════════════════╗');
|
|
276
|
+
console.log('║ Setup Complete! ║');
|
|
277
|
+
console.log('╚════════════════════════════════════════════╝');
|
|
278
|
+
console.log('\nYou can now use Joan with Claude Code:');
|
|
279
|
+
console.log(' • "Show me my projects in Joan"');
|
|
280
|
+
console.log(' • "Create a task for implementing the login feature"');
|
|
281
|
+
console.log(' • "Mark task XYZ as completed"');
|
|
282
|
+
console.log('\nNote: Restart Claude Code for changes to take effect.');
|
|
283
|
+
}
|
|
284
|
+
/**
|
|
285
|
+
* Main CLI entry point
|
|
286
|
+
*/
|
|
287
|
+
async function main() {
|
|
288
|
+
const args = process.argv.slice(2);
|
|
289
|
+
const command = args[0] || 'serve';
|
|
290
|
+
switch (command) {
|
|
291
|
+
case 'init':
|
|
292
|
+
await init();
|
|
293
|
+
break;
|
|
294
|
+
case 'login':
|
|
295
|
+
await login();
|
|
296
|
+
break;
|
|
297
|
+
case 'logout':
|
|
298
|
+
await logout();
|
|
299
|
+
break;
|
|
300
|
+
case 'status':
|
|
301
|
+
await status();
|
|
302
|
+
break;
|
|
303
|
+
case 'serve':
|
|
304
|
+
await serve();
|
|
305
|
+
break;
|
|
306
|
+
case 'help':
|
|
307
|
+
case '--help':
|
|
308
|
+
case '-h':
|
|
309
|
+
console.log(HELP_TEXT);
|
|
310
|
+
break;
|
|
311
|
+
case 'version':
|
|
312
|
+
case '--version':
|
|
313
|
+
case '-v':
|
|
314
|
+
console.log('joan-mcp v1.0.0');
|
|
315
|
+
break;
|
|
316
|
+
default:
|
|
317
|
+
console.error(`Unknown command: ${command}`);
|
|
318
|
+
console.log(HELP_TEXT);
|
|
319
|
+
process.exit(1);
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
main().catch((error) => {
|
|
323
|
+
console.error('Error:', error.message);
|
|
324
|
+
process.exit(1);
|
|
325
|
+
});
|
|
326
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|