@ainote/mcp 1.3.1 → 1.3.3

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/lib/cli/logout.js CHANGED
@@ -1,39 +1,39 @@
1
- /**
2
- * `ainote-mcp logout` — revoke server-side tokens and clear local credentials.
3
- */
4
- import process from 'node:process';
5
- import axios from 'axios';
6
- import { getCredentials, clearCredentials } from '../auth/token-store.js';
7
-
8
- const DEFAULT_API_URL = 'https://ainote-5muq.onrender.com';
9
-
10
- export async function run() {
11
- const apiUrl = (process.env.AINOTE_API_URL || DEFAULT_API_URL).replace(/\/+$/, '');
12
-
13
- const creds = await getCredentials(apiUrl);
14
-
15
- if (!creds) {
16
- console.log(' No credentials found. Already logged out.');
17
- return;
18
- }
19
-
20
- if (creds.refreshToken) {
21
- try {
22
- await axios.post(
23
- `${apiUrl}/api/auth/token/revoke`,
24
- { refresh_token: creds.refreshToken },
25
- {
26
- headers: { 'Content-Type': 'application/json' },
27
- timeout: 10000,
28
- validateStatus: () => true
29
- }
30
- );
31
- } catch (err) {
32
- // Server-side revoke is best-effort. Continue with local clear.
33
- process.stderr.write(`[ainote-mcp] Server revoke failed (continuing): ${err.message}\n`);
34
- }
35
- }
36
-
37
- await clearCredentials(apiUrl);
38
- console.log(' Logged out.');
39
- }
1
+ /**
2
+ * `ainote-mcp logout` — revoke server-side tokens and clear local credentials.
3
+ */
4
+ import process from 'node:process';
5
+ import axios from 'axios';
6
+ import { getCredentials, clearCredentials } from '../auth/token-store.js';
7
+
8
+ const DEFAULT_API_URL = 'https://ainote-5muq.onrender.com';
9
+
10
+ export async function run() {
11
+ const apiUrl = (process.env.AINOTE_API_URL || DEFAULT_API_URL).replace(/\/+$/, '');
12
+
13
+ const creds = await getCredentials(apiUrl);
14
+
15
+ if (!creds) {
16
+ console.log(' No credentials found. Already logged out.');
17
+ return;
18
+ }
19
+
20
+ if (creds.refreshToken) {
21
+ try {
22
+ await axios.post(
23
+ `${apiUrl}/api/auth/token/revoke`,
24
+ { refresh_token: creds.refreshToken },
25
+ {
26
+ headers: { 'Content-Type': 'application/json' },
27
+ timeout: 10000,
28
+ validateStatus: () => true
29
+ }
30
+ );
31
+ } catch (err) {
32
+ // Server-side revoke is best-effort. Continue with local clear.
33
+ process.stderr.write(`[ainote-mcp] Server revoke failed (continuing): ${err.message}\n`);
34
+ }
35
+ }
36
+
37
+ await clearCredentials(apiUrl);
38
+ console.log(' Logged out.');
39
+ }
package/lib/cli/signup.js CHANGED
@@ -1,118 +1,118 @@
1
- import * as readline from 'node:readline/promises';
2
- import { stdin as input, stdout as output } from 'node:process';
3
- import axios from 'axios';
4
- import { getConfig } from '../core/config-manager.js';
5
-
6
- /**
7
- * Interactive CLI signup for AI Note MCP.
8
- * Usage: ainote-mcp signup
9
- */
10
- export async function runSignup() {
11
- const config = getConfig();
12
- const rl = readline.createInterface({ input, output });
13
-
14
- console.log('\n AI Note MCP — Sign Up\n');
15
-
16
- try {
17
- const email = await rl.question(' Email: ');
18
- const password = await rl.question(' Password (min 6 chars): ');
19
- const name = await rl.question(' Name (optional, press Enter to skip): ');
20
-
21
- if (!email.trim() || !password.trim()) {
22
- console.error('\n Error: Email and password are required.\n');
23
- process.exit(1);
24
- }
25
-
26
- if (password.trim().length < 6) {
27
- console.error('\n Error: Password must be at least 6 characters.\n');
28
- process.exit(1);
29
- }
30
-
31
- console.log('\n Creating account...');
32
-
33
- const rpcRequest = {
34
- jsonrpc: '2.0',
35
- id: 1,
36
- method: 'tools/call',
37
- params: {
38
- name: 'signup_and_get_key',
39
- arguments: {
40
- email: email.trim(),
41
- password: password.trim(),
42
- ...(name.trim() ? { name: name.trim() } : {})
43
- }
44
- }
45
- };
46
-
47
- const response = await axios.post(`${config.api.url}/api/mcp`, rpcRequest, {
48
- headers: { 'Content-Type': 'application/json' },
49
- timeout: 30000
50
- });
51
-
52
- const data = response.data?.data;
53
-
54
- // Check for JSON-RPC error
55
- if (data?.error) {
56
- console.error(`\n Error: ${data.error.message}`);
57
- if (data.error.data?.suggestion) {
58
- console.log(` Hint: ${data.error.data.suggestion}`);
59
- }
60
- console.log();
61
- process.exit(1);
62
- }
63
-
64
- // Extract MCP key from structured resource data
65
- const content = data?.result?.content;
66
- let mcpKey = null;
67
-
68
- if (Array.isArray(content)) {
69
- for (const item of content) {
70
- if (item.type === 'resource' && item.resource?.text) {
71
- try {
72
- const resourceData = JSON.parse(item.resource.text);
73
- mcpKey = resourceData.mcp_key;
74
- } catch { /* ignore */ }
75
- }
76
- }
77
- }
78
-
79
- if (mcpKey) {
80
- console.log('\n Account created successfully!\n');
81
- console.log(` Your MCP API Key:\n`);
82
- console.log(` ${mcpKey}\n`);
83
- console.log(' Add this to your MCP config:\n');
84
- console.log(' {');
85
- console.log(' "mcpServers": {');
86
- console.log(' "ainote": {');
87
- console.log(' "command": "npx",');
88
- console.log(' "args": ["-y", "@ainote/mcp"],');
89
- console.log(' "env": {');
90
- console.log(` "AINOTE_API_KEY": "${mcpKey}"`);
91
- console.log(' }');
92
- console.log(' }');
93
- console.log(' }');
94
- console.log(' }\n');
95
- console.log(' Then restart Claude Desktop.\n');
96
- } else {
97
- // Fallback: print text content
98
- if (Array.isArray(content)) {
99
- for (const item of content) {
100
- if (item.type === 'text') {
101
- console.log(`\n${item.text}\n`);
102
- }
103
- }
104
- } else {
105
- console.log('\n Account created! Check the response for your API key.\n');
106
- }
107
- }
108
- } catch (error) {
109
- if (error.response?.data) {
110
- console.error(`\n Error: ${JSON.stringify(error.response.data)}\n`);
111
- } else {
112
- console.error(`\n Error: ${error.message}\n`);
113
- }
114
- process.exit(1);
115
- } finally {
116
- rl.close();
117
- }
118
- }
1
+ import * as readline from 'node:readline/promises';
2
+ import { stdin as input, stdout as output } from 'node:process';
3
+ import axios from 'axios';
4
+ import { getConfig } from '../core/config-manager.js';
5
+
6
+ /**
7
+ * Interactive CLI signup for AI Note MCP.
8
+ * Usage: ainote-mcp signup
9
+ */
10
+ export async function runSignup() {
11
+ const config = getConfig();
12
+ const rl = readline.createInterface({ input, output });
13
+
14
+ console.log('\n AI Note MCP — Sign Up\n');
15
+
16
+ try {
17
+ const email = await rl.question(' Email: ');
18
+ const password = await rl.question(' Password (min 6 chars): ');
19
+ const name = await rl.question(' Name (optional, press Enter to skip): ');
20
+
21
+ if (!email.trim() || !password.trim()) {
22
+ console.error('\n Error: Email and password are required.\n');
23
+ process.exit(1);
24
+ }
25
+
26
+ if (password.trim().length < 6) {
27
+ console.error('\n Error: Password must be at least 6 characters.\n');
28
+ process.exit(1);
29
+ }
30
+
31
+ console.log('\n Creating account...');
32
+
33
+ const rpcRequest = {
34
+ jsonrpc: '2.0',
35
+ id: 1,
36
+ method: 'tools/call',
37
+ params: {
38
+ name: 'signup_and_get_key',
39
+ arguments: {
40
+ email: email.trim(),
41
+ password: password.trim(),
42
+ ...(name.trim() ? { name: name.trim() } : {})
43
+ }
44
+ }
45
+ };
46
+
47
+ const response = await axios.post(`${config.api.url}/api/mcp`, rpcRequest, {
48
+ headers: { 'Content-Type': 'application/json' },
49
+ timeout: 30000
50
+ });
51
+
52
+ const data = response.data?.data;
53
+
54
+ // Check for JSON-RPC error
55
+ if (data?.error) {
56
+ console.error(`\n Error: ${data.error.message}`);
57
+ if (data.error.data?.suggestion) {
58
+ console.log(` Hint: ${data.error.data.suggestion}`);
59
+ }
60
+ console.log();
61
+ process.exit(1);
62
+ }
63
+
64
+ // Extract MCP key from structured resource data
65
+ const content = data?.result?.content;
66
+ let mcpKey = null;
67
+
68
+ if (Array.isArray(content)) {
69
+ for (const item of content) {
70
+ if (item.type === 'resource' && item.resource?.text) {
71
+ try {
72
+ const resourceData = JSON.parse(item.resource.text);
73
+ mcpKey = resourceData.mcp_key;
74
+ } catch { /* ignore */ }
75
+ }
76
+ }
77
+ }
78
+
79
+ if (mcpKey) {
80
+ console.log('\n Account created successfully!\n');
81
+ console.log(` Your MCP API Key:\n`);
82
+ console.log(` ${mcpKey}\n`);
83
+ console.log(' Add this to your MCP config:\n');
84
+ console.log(' {');
85
+ console.log(' "mcpServers": {');
86
+ console.log(' "ainote": {');
87
+ console.log(' "command": "npx",');
88
+ console.log(' "args": ["-y", "@ainote/mcp"],');
89
+ console.log(' "env": {');
90
+ console.log(` "AINOTE_API_KEY": "${mcpKey}"`);
91
+ console.log(' }');
92
+ console.log(' }');
93
+ console.log(' }');
94
+ console.log(' }\n');
95
+ console.log(' Then restart Claude Desktop.\n');
96
+ } else {
97
+ // Fallback: print text content
98
+ if (Array.isArray(content)) {
99
+ for (const item of content) {
100
+ if (item.type === 'text') {
101
+ console.log(`\n${item.text}\n`);
102
+ }
103
+ }
104
+ } else {
105
+ console.log('\n Account created! Check the response for your API key.\n');
106
+ }
107
+ }
108
+ } catch (error) {
109
+ if (error.response?.data) {
110
+ console.error(`\n Error: ${JSON.stringify(error.response.data)}\n`);
111
+ } else {
112
+ console.error(`\n Error: ${error.message}\n`);
113
+ }
114
+ process.exit(1);
115
+ } finally {
116
+ rl.close();
117
+ }
118
+ }
package/lib/cli/whoami.js CHANGED
@@ -1,77 +1,77 @@
1
- /**
2
- * `ainote-mcp whoami` — show the currently authenticated user.
3
- *
4
- * Strategy:
5
- * 1. Read credentials from the token store.
6
- * 2. If we have an access_token, hit GET /api/users/me with Bearer auth and
7
- * print the response.
8
- * 3. If the API call fails (404, 401, network) but we have a stored mcp_key,
9
- * print a minimal local-only summary so the user at least sees that
10
- * credentials exist for this host.
11
- */
12
- import process from 'node:process';
13
- import axios from 'axios';
14
- import { getCredentials } from '../auth/token-store.js';
15
-
16
- const DEFAULT_API_URL = 'https://ainote-5muq.onrender.com';
17
-
18
- function summarizeUser(user) {
19
- if (!user || typeof user !== 'object') return null;
20
- const parts = [];
21
- if (user.email) parts.push(user.email);
22
- else if (user.name) parts.push(user.name);
23
- else if (user.id) parts.push(`user #${user.id}`);
24
- return parts.join(' ');
25
- }
26
-
27
- export async function run() {
28
- const apiUrl = (process.env.AINOTE_API_URL || DEFAULT_API_URL).replace(/\/+$/, '');
29
- const creds = await getCredentials(apiUrl);
30
-
31
- if (!creds) {
32
- console.error(' Not logged in. Run `ainote-mcp login`.');
33
- process.exit(1);
34
- return;
35
- }
36
-
37
- let identity = null;
38
-
39
- if (creds.accessToken) {
40
- try {
41
- const response = await axios.get(`${apiUrl}/api/users/me`, {
42
- headers: {
43
- Authorization: `Bearer ${creds.accessToken}`,
44
- Accept: 'application/json'
45
- },
46
- timeout: 15000,
47
- validateStatus: () => true
48
- });
49
- if (response.status >= 200 && response.status < 300) {
50
- const body = response.data || {};
51
- identity = summarizeUser(body.user || body.data || body) || summarizeUser(body);
52
- }
53
- } catch {
54
- // fall through to local-only fallback below
55
- }
56
- }
57
-
58
- if (identity) {
59
- console.log(` Logged in as ${identity}`);
60
- } else {
61
- // Local-only fallback: report what we have.
62
- const host = (() => {
63
- try { return new URL(apiUrl).host; } catch { return apiUrl; }
64
- })();
65
- console.log(` Credentials present for ${host}`);
66
- if (creds.mcpKey) console.log(` MCP key: ${creds.mcpKey.slice(0, 8)}…`);
67
- if (creds.expiresAt) {
68
- const remaining = Math.floor((creds.expiresAt - Date.now()) / 1000);
69
- if (remaining > 0) console.log(` Access token expires in ~${remaining}s`);
70
- else console.log(` Access token expired (refresh on next call).`);
71
- }
72
- if (!creds.accessToken && !creds.mcpKey) {
73
- console.error(' Could not verify identity. Try `ainote-mcp login` again.');
74
- process.exit(1);
75
- }
76
- }
77
- }
1
+ /**
2
+ * `ainote-mcp whoami` — show the currently authenticated user.
3
+ *
4
+ * Strategy:
5
+ * 1. Read credentials from the token store.
6
+ * 2. If we have an access_token, hit GET /api/users/me with Bearer auth and
7
+ * print the response.
8
+ * 3. If the API call fails (404, 401, network) but we have a stored mcp_key,
9
+ * print a minimal local-only summary so the user at least sees that
10
+ * credentials exist for this host.
11
+ */
12
+ import process from 'node:process';
13
+ import axios from 'axios';
14
+ import { getCredentials } from '../auth/token-store.js';
15
+
16
+ const DEFAULT_API_URL = 'https://ainote-5muq.onrender.com';
17
+
18
+ function summarizeUser(user) {
19
+ if (!user || typeof user !== 'object') return null;
20
+ const parts = [];
21
+ if (user.email) parts.push(user.email);
22
+ else if (user.name) parts.push(user.name);
23
+ else if (user.id) parts.push(`user #${user.id}`);
24
+ return parts.join(' ');
25
+ }
26
+
27
+ export async function run() {
28
+ const apiUrl = (process.env.AINOTE_API_URL || DEFAULT_API_URL).replace(/\/+$/, '');
29
+ const creds = await getCredentials(apiUrl);
30
+
31
+ if (!creds) {
32
+ console.error(' Not logged in. Run `ainote-mcp login`.');
33
+ process.exit(1);
34
+ return;
35
+ }
36
+
37
+ let identity = null;
38
+
39
+ if (creds.accessToken) {
40
+ try {
41
+ const response = await axios.get(`${apiUrl}/api/users/me`, {
42
+ headers: {
43
+ Authorization: `Bearer ${creds.accessToken}`,
44
+ Accept: 'application/json'
45
+ },
46
+ timeout: 15000,
47
+ validateStatus: () => true
48
+ });
49
+ if (response.status >= 200 && response.status < 300) {
50
+ const body = response.data || {};
51
+ identity = summarizeUser(body.user || body.data || body) || summarizeUser(body);
52
+ }
53
+ } catch {
54
+ // fall through to local-only fallback below
55
+ }
56
+ }
57
+
58
+ if (identity) {
59
+ console.log(` Logged in as ${identity}`);
60
+ } else {
61
+ // Local-only fallback: report what we have.
62
+ const host = (() => {
63
+ try { return new URL(apiUrl).host; } catch { return apiUrl; }
64
+ })();
65
+ console.log(` Credentials present for ${host}`);
66
+ if (creds.mcpKey) console.log(` MCP key: ${creds.mcpKey.slice(0, 8)}…`);
67
+ if (creds.expiresAt) {
68
+ const remaining = Math.floor((creds.expiresAt - Date.now()) / 1000);
69
+ if (remaining > 0) console.log(` Access token expires in ~${remaining}s`);
70
+ else console.log(` Access token expired (refresh on next call).`);
71
+ }
72
+ if (!creds.accessToken && !creds.mcpKey) {
73
+ console.error(' Could not verify identity. Try `ainote-mcp login` again.');
74
+ process.exit(1);
75
+ }
76
+ }
77
+ }
@@ -1 +1 @@
1
- export * from '../utils/api-client.js';
1
+ export * from '../utils/api-client.js';