@botuyo/mcp 0.3.13 → 0.3.16

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.
Files changed (34) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +16 -2
  3. package/dist/__tests__/client.spec.d.ts +5 -0
  4. package/dist/__tests__/client.spec.js +139 -0
  5. package/dist/__tests__/client.spec.js.map +1 -0
  6. package/dist/client.d.ts +4 -0
  7. package/dist/client.js +22 -7
  8. package/dist/client.js.map +1 -1
  9. package/dist/commands/__tests__/credentials.spec.d.ts +5 -0
  10. package/dist/commands/__tests__/credentials.spec.js +174 -0
  11. package/dist/commands/__tests__/credentials.spec.js.map +1 -0
  12. package/dist/commands/auth.js +17 -33
  13. package/dist/commands/auth.js.map +1 -1
  14. package/dist/commands/credentials.d.ts +38 -4
  15. package/dist/commands/credentials.js +80 -12
  16. package/dist/commands/credentials.js.map +1 -1
  17. package/dist/commands/login.js +26 -56
  18. package/dist/commands/login.js.map +1 -1
  19. package/dist/commands/switch_tenant.js +11 -36
  20. package/dist/commands/switch_tenant.js.map +1 -1
  21. package/dist/commands/tenants.js +10 -19
  22. package/dist/commands/tenants.js.map +1 -1
  23. package/dist/index.js +13 -9
  24. package/dist/index.js.map +1 -1
  25. package/dist/tools/__tests__/configure_avatar.spec.js +2 -3
  26. package/dist/tools/__tests__/configure_avatar.spec.js.map +1 -1
  27. package/dist/tools/configure_avatar.js +2 -3
  28. package/dist/tools/configure_avatar.js.map +1 -1
  29. package/dist/tools/index.js +3 -0
  30. package/dist/tools/index.js.map +1 -1
  31. package/dist/tools/ingest_knowledge_url.d.ts +4 -0
  32. package/dist/tools/ingest_knowledge_url.js +35 -0
  33. package/dist/tools/ingest_knowledge_url.js.map +1 -0
  34. package/package.json +2 -3
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 BotUyo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -80,7 +80,8 @@ Use `get_agent_status` to check which channels are connected. It returns a direc
80
80
  ## Build from source
81
81
 
82
82
  ```sh
83
- cd packages/mcp
83
+ git clone https://github.com/MarcoAR1/botuyo-mcp.git
84
+ cd botuyo-mcp
84
85
  npm install
85
86
  npm run build
86
87
  ```
@@ -88,6 +89,19 @@ npm run build
88
89
  ## Test with MCP Inspector
89
90
 
90
91
  ```sh
91
- cd packages/mcp
92
92
  BOTUYO_API_KEY=pk_live_... npm run inspect
93
93
  ```
94
+
95
+ ## Contributing
96
+
97
+ We welcome contributions! See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
98
+
99
+ Please note that this project follows a [Code of Conduct](CODE_OF_CONDUCT.md).
100
+
101
+ ## Security
102
+
103
+ To report a vulnerability, see [SECURITY.md](SECURITY.md).
104
+
105
+ ## License
106
+
107
+ [MIT](LICENSE) © BotUyo
@@ -0,0 +1,5 @@
1
+ /**
2
+ * BotuyoApiClient — Unit tests
3
+ * Tests for error handling, 401 detection, ApiError class
4
+ */
5
+ export {};
@@ -0,0 +1,139 @@
1
+ /**
2
+ * BotuyoApiClient — Unit tests
3
+ * Tests for error handling, 401 detection, ApiError class
4
+ */
5
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
6
+ import { BotuyoApiClient, ApiError } from '../client.js';
7
+ // Mock global fetch
8
+ function mockFetch(status, body, ok) {
9
+ const fn = vi.fn().mockResolvedValue({
10
+ status,
11
+ ok: ok ?? (status >= 200 && status < 300),
12
+ text: async () => JSON.stringify(body),
13
+ json: async () => body
14
+ });
15
+ vi.stubGlobal('fetch', fn);
16
+ return fn;
17
+ }
18
+ describe('BotuyoApiClient', () => {
19
+ let client;
20
+ beforeEach(() => {
21
+ vi.restoreAllMocks();
22
+ client = new BotuyoApiClient({ apiUrl: 'http://localhost:8080', token: 'test-token' });
23
+ });
24
+ // ── ApiError class ──────────────────────────────────────────────────
25
+ describe('ApiError', () => {
26
+ it('is an instance of Error', () => {
27
+ const err = new ApiError('test', 401);
28
+ expect(err).toBeInstanceOf(Error);
29
+ expect(err).toBeInstanceOf(ApiError);
30
+ });
31
+ it('stores the HTTP status code', () => {
32
+ const err = new ApiError('Unauthorized', 401);
33
+ expect(err.status).toBe(401);
34
+ expect(err.message).toBe('Unauthorized');
35
+ });
36
+ it('has a name of ApiError', () => {
37
+ const err = new ApiError('test', 500);
38
+ expect(err.name).toBe('ApiError');
39
+ });
40
+ });
41
+ // ── handleResponse / 401 detection ──────────────────────────────────
42
+ describe('401 detection', () => {
43
+ it('throws ApiError with status 401 on unauthorized response', async () => {
44
+ mockFetch(401, { success: false, error: 'Invalid or expired token' });
45
+ try {
46
+ await client.get('/api/v1/mcp/agents');
47
+ expect.fail('should have thrown');
48
+ }
49
+ catch (err) {
50
+ expect(err).toBeInstanceOf(ApiError);
51
+ expect(err.status).toBe(401);
52
+ }
53
+ });
54
+ it('throws ApiError with status 403 on forbidden response', async () => {
55
+ mockFetch(403, { success: false, error: 'Forbidden' });
56
+ try {
57
+ await client.get('/api/v1/mcp/agents');
58
+ expect.fail('should have thrown');
59
+ }
60
+ catch (err) {
61
+ expect(err).toBeInstanceOf(ApiError);
62
+ expect(err.status).toBe(403);
63
+ }
64
+ });
65
+ it('throws ApiError with status 500 on server error', async () => {
66
+ mockFetch(500, { success: false, error: 'Internal error' });
67
+ try {
68
+ await client.get('/api/v1/mcp/agents');
69
+ expect.fail('should have thrown');
70
+ }
71
+ catch (err) {
72
+ expect(err).toBeInstanceOf(ApiError);
73
+ expect(err.status).toBe(500);
74
+ }
75
+ });
76
+ it('does NOT throw on successful 200 responses', async () => {
77
+ mockFetch(200, { success: true, data: { agents: [] } });
78
+ const result = await client.get('/api/v1/mcp/agents');
79
+ expect(result.success).toBe(true);
80
+ });
81
+ });
82
+ // ── verify() ────────────────────────────────────────────────────────
83
+ describe('verify', () => {
84
+ it('returns AuthInfo on successful /api/auth/me', async () => {
85
+ mockFetch(200, {
86
+ success: true,
87
+ data: {
88
+ user: {
89
+ email: 'test@example.com',
90
+ tenantIds: ['t1'],
91
+ roles: [{ tenantId: 't1', role: 'owner' }]
92
+ }
93
+ }
94
+ });
95
+ const info = await client.verify();
96
+ expect(info.email).toBe('test@example.com');
97
+ expect(info.tenantId).toBe('t1');
98
+ expect(info.role).toBe('owner');
99
+ });
100
+ it('throws on 401 from /api/auth/me', async () => {
101
+ mockFetch(401, { success: false, error: 'Token expired' });
102
+ await expect(client.verify()).rejects.toThrow();
103
+ });
104
+ it('caches authInfo after first successful call', async () => {
105
+ const fetchFn = mockFetch(200, {
106
+ success: true,
107
+ data: {
108
+ user: {
109
+ email: 'test@example.com',
110
+ tenantIds: ['t1'],
111
+ roles: [{ tenantId: 't1', role: 'owner' }]
112
+ }
113
+ }
114
+ });
115
+ await client.verify();
116
+ await client.verify();
117
+ expect(fetchFn).toHaveBeenCalledTimes(1);
118
+ });
119
+ });
120
+ // ── Non-JSON responses ──────────────────────────────────────────────
121
+ describe('non-JSON responses', () => {
122
+ it('throws ApiError with status code when response is not JSON', async () => {
123
+ vi.stubGlobal('fetch', vi.fn().mockResolvedValue({
124
+ status: 502,
125
+ ok: false,
126
+ text: async () => '<html>Bad Gateway</html>'
127
+ }));
128
+ try {
129
+ await client.get('/api/v1/mcp/agents');
130
+ expect.fail('should have thrown');
131
+ }
132
+ catch (err) {
133
+ expect(err).toBeInstanceOf(ApiError);
134
+ expect(err.status).toBe(502);
135
+ }
136
+ });
137
+ });
138
+ });
139
+ //# sourceMappingURL=client.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.spec.js","sourceRoot":"","sources":["../../src/__tests__/client.spec.ts"],"names":[],"mappings":"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"}
package/dist/client.d.ts CHANGED
@@ -5,6 +5,10 @@
5
5
  * Uses a JWT token directly (obtained via `npx @botuyo/mcp auth` or `npx @botuyo/mcp login`).
6
6
  * Requires Node 18+ (native fetch).
7
7
  */
8
+ export declare class ApiError extends Error {
9
+ readonly status: number;
10
+ constructor(message: string, status: number);
11
+ }
8
12
  export interface BotuyoClientConfig {
9
13
  apiUrl: string;
10
14
  token: string;
package/dist/client.js CHANGED
@@ -5,6 +5,14 @@
5
5
  * Uses a JWT token directly (obtained via `npx @botuyo/mcp auth` or `npx @botuyo/mcp login`).
6
6
  * Requires Node 18+ (native fetch).
7
7
  */
8
+ export class ApiError extends Error {
9
+ status;
10
+ constructor(message, status) {
11
+ super(message);
12
+ this.name = 'ApiError';
13
+ this.status = status;
14
+ }
15
+ }
8
16
  export class BotuyoApiClient {
9
17
  config;
10
18
  authInfo = null;
@@ -82,10 +90,17 @@ export class BotuyoApiClient {
82
90
  return this.handleResponse(res);
83
91
  }
84
92
  async handleResponse(res) {
85
- const json = await this.parseJson(res);
86
- // Detect expired token
87
- if (res.status === 401) {
88
- throw new Error('Sesión expirada. Ejecutá: npx @botuyo/mcp auth (browser) o npx @botuyo/mcp login (terminal)');
93
+ const text = await res.text();
94
+ let json;
95
+ try {
96
+ json = JSON.parse(text);
97
+ }
98
+ catch {
99
+ throw new ApiError(`HTTP ${res.status}: ${text.slice(0, 200)}`, res.status);
100
+ }
101
+ if (!res.ok) {
102
+ const msg = json.error || `HTTP ${res.status}`;
103
+ throw new ApiError(msg, res.status);
89
104
  }
90
105
  return json;
91
106
  }
@@ -117,14 +132,14 @@ export class BotuyoApiClient {
117
132
  try {
118
133
  const json = JSON.parse(text);
119
134
  if (!res.ok && !json.success) {
120
- throw new Error(json.error || `HTTP ${res.status}`);
135
+ throw new ApiError(json.error || `HTTP ${res.status}`, res.status);
121
136
  }
122
137
  return json;
123
138
  }
124
139
  catch (e) {
125
- if (e instanceof Error && e.message.includes('HTTP'))
140
+ if (e instanceof ApiError)
126
141
  throw e;
127
- throw new Error(`HTTP ${res.status}: ${text.slice(0, 200)}`);
142
+ throw new ApiError(`HTTP ${res.status}: ${text.slice(0, 200)}`, res.status);
128
143
  }
129
144
  }
130
145
  }
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAcH,MAAM,OAAO,eAAe;IAClB,MAAM,CAAoB;IAC1B,QAAQ,GAAoB,IAAI,CAAA;IAExC,YAAY,MAA0B;QACpC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;IAED,gCAAgC;IAChC,QAAQ;QACN,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,CAAA;IAC1B,CAAC;IAED,qDAAqD;IACrD,QAAQ,CAAC,KAAa;QACpB,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,CAAA;QACvC,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAA,CAAC,yBAAyB;IAChD,CAAC;IAED,uEAAuE;IACvE,KAAK,CAAC,MAAM;QACV,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC,QAAQ,CAAA;QAEvC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,cAAc,EAAE;YAC3D,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE;SAC1D,CAAC,CAAA;QAEF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;QACtC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CAAC,+BAA+B,IAAI,CAAC,KAAK,IAAI,eAAe,2EAA2E,CAAC,CAAA;QAC1J,CAAC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAA;QAC3B,IAAI,CAAC,QAAQ,GAAG;YACd,QAAQ,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE;YACnC,UAAU,EAAE,EAAE,EAAE,oCAAoC;YACpD,IAAI,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,IAAI,QAAQ;YACvC,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAA;QAED,OAAO,IAAI,CAAC,QAAQ,CAAA;IACtB,CAAC;IAED,wCAAwC;IACxC,KAAK,CAAC,GAAG,CAAU,IAAY;QAC7B,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,EAAE,EAAE;YACtD,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE;SAC1D,CAAC,CAAA;QACF,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAA;IACjC,CAAC;IAED,yCAAyC;IACzC,KAAK,CAAC,IAAI,CAAU,IAAY,EAAE,IAAa;QAC7C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,EAAE,EAAE;YACtD,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;gBAC5C,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAA;QACF,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAA;IACjC,CAAC;IAED,wCAAwC;IACxC,KAAK,CAAC,GAAG,CAAU,IAAY,EAAE,IAAa;QAC5C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,EAAE,EAAE;YACtD,MAAM,EAAE,KAAK;YACb,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;gBAC5C,cAAc,EAAE,kBAAkB;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAA;QACF,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAA;IACjC,CAAC;IAED,2CAA2C;IAC3C,KAAK,CAAC,MAAM,CAAU,IAAY;QAChC,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,EAAE,EAAE;YACtD,MAAM,EAAE,QAAQ;YAChB,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;aAC7C;SACF,CAAC,CAAA;QACF,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAA;IACjC,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,GAAa;QACxC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;QAEtC,uBAAuB;QACvB,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,6FAA6F,CAAC,CAAA;QAChH,CAAC;QAED,OAAO,IAAI,CAAA;IACb,CAAC;IAED,wDAAwD;IACxD,KAAK,CAAC,WAAW,CAAC,UAAkB,EAAE,QAAgB,EAAE,QAAgB;QACtE,+EAA+E;QAC/E,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAA;QAEhC,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,CAAC,CAAC,CAAA;QACnD,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAA;QAC/B,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAA;QACvC,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;QACrC,QAAQ,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;QAE1C,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,mBAAmB,EAAE;YAChE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE;gBAC5C,6EAA6E;aAC9E;YACD,IAAI,EAAE,QAAQ;SACf,CAAC,CAAA;QAEF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAA;QACtC,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CAAC,kBAAkB,IAAI,CAAC,KAAK,IAAI,eAAe,EAAE,CAAC,CAAA;QACpE,CAAC;QAED,OAAO,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,GAAG,CAAA;IACnC,CAAC;IAEO,KAAK,CAAC,SAAS,CAAC,GAAa;QACnC,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;QAC7B,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YAC7B,IAAI,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC7B,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,QAAQ,GAAG,CAAC,MAAM,EAAE,CAAC,CAAA;YACrD,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,IAAI,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;gBAAE,MAAM,CAAC,CAAA;YAC7D,MAAM,IAAI,KAAK,CAAC,QAAQ,GAAG,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAA;QAC9D,CAAC;IACH,CAAC;CACF"}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * credentials.ts — Unit tests
3
+ * Tests for apiUrl persistence, resolveApiUrl, and checkExistingSession
4
+ */
5
+ export {};
@@ -0,0 +1,174 @@
1
+ /**
2
+ * credentials.ts — Unit tests
3
+ * Tests for apiUrl persistence, resolveApiUrl, and checkExistingSession
4
+ */
5
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
6
+ import { join } from 'path';
7
+ import { homedir } from 'os';
8
+ // We'll mock fs/promises to avoid touching the real filesystem
9
+ vi.mock('fs/promises', () => ({
10
+ readFile: vi.fn(),
11
+ writeFile: vi.fn(),
12
+ mkdir: vi.fn(),
13
+ unlink: vi.fn()
14
+ }));
15
+ // Import after mocking
16
+ import { readFile, writeFile } from 'fs/promises';
17
+ import { readCredentials, saveCredentials, resolveToken, resolveApiUrl, checkExistingSession } from '../credentials.js';
18
+ const CREDS_PATH = join(homedir(), '.botuyo', 'credentials.json');
19
+ function makeCreds(overrides = {}) {
20
+ return {
21
+ token: 'test-jwt-token',
22
+ tenantId: 'tenant-123',
23
+ tenantName: 'My Tenant',
24
+ role: 'owner',
25
+ email: 'user@test.com',
26
+ savedAt: new Date().toISOString(),
27
+ expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(),
28
+ apiUrl: 'http://localhost:8080',
29
+ ...overrides
30
+ };
31
+ }
32
+ describe('credentials', () => {
33
+ beforeEach(() => {
34
+ vi.resetAllMocks();
35
+ // Clean env vars between tests
36
+ delete process.env.BOTUYO_TOKEN;
37
+ delete process.env.BOTUYO_API_URL;
38
+ });
39
+ // ── apiUrl persistence ──────────────────────────────────────────────
40
+ describe('apiUrl in credentials', () => {
41
+ it('saveCredentials includes apiUrl in stored JSON', async () => {
42
+ const creds = makeCreds({ apiUrl: 'http://localhost:8080' });
43
+ await saveCredentials(creds);
44
+ expect(writeFile).toHaveBeenCalledWith(CREDS_PATH, expect.stringContaining('"apiUrl": "http://localhost:8080"'), 'utf8');
45
+ });
46
+ it('readCredentials returns apiUrl from stored JSON', async () => {
47
+ const creds = makeCreds({ apiUrl: 'https://api.botuyo.com' });
48
+ vi.mocked(readFile).mockResolvedValue(JSON.stringify(creds));
49
+ const result = await readCredentials();
50
+ expect(result?.apiUrl).toBe('https://api.botuyo.com');
51
+ });
52
+ it('readCredentials returns null apiUrl for legacy credentials without apiUrl', async () => {
53
+ // Simulate old credentials.json that doesn't have apiUrl
54
+ const legacy = {
55
+ token: 'old-token',
56
+ tenantId: 't1',
57
+ tenantName: 'T1',
58
+ role: 'owner',
59
+ email: 'a@b.com',
60
+ savedAt: new Date().toISOString(),
61
+ expiresAt: new Date(Date.now() + 86400000).toISOString()
62
+ };
63
+ vi.mocked(readFile).mockResolvedValue(JSON.stringify(legacy));
64
+ const result = await readCredentials();
65
+ expect(result).not.toBeNull();
66
+ expect(result?.apiUrl).toBeUndefined();
67
+ });
68
+ });
69
+ // ── resolveApiUrl ───────────────────────────────────────────────────
70
+ describe('resolveApiUrl', () => {
71
+ it('returns BOTUYO_API_URL env var when set (highest priority)', async () => {
72
+ process.env.BOTUYO_API_URL = 'https://env-override.com';
73
+ vi.mocked(readFile).mockResolvedValue(JSON.stringify(makeCreds({ apiUrl: 'http://localhost:8080' })));
74
+ const url = await resolveApiUrl();
75
+ expect(url).toBe('https://env-override.com');
76
+ });
77
+ it('returns apiUrl from credentials when env var is not set', async () => {
78
+ vi.mocked(readFile).mockResolvedValue(JSON.stringify(makeCreds({ apiUrl: 'http://localhost:8080' })));
79
+ const url = await resolveApiUrl();
80
+ expect(url).toBe('http://localhost:8080');
81
+ });
82
+ it('returns default https://api.botuyo.com when no env var and no credentials', async () => {
83
+ vi.mocked(readFile).mockRejectedValue(new Error('ENOENT'));
84
+ const url = await resolveApiUrl();
85
+ expect(url).toBe('https://api.botuyo.com');
86
+ });
87
+ it('returns default when credentials exist but apiUrl is missing (legacy)', async () => {
88
+ const legacy = { token: 'x', tenantId: 'y', tenantName: 'z', role: 'a', email: 'b', savedAt: 'c', expiresAt: 'd' };
89
+ vi.mocked(readFile).mockResolvedValue(JSON.stringify(legacy));
90
+ const url = await resolveApiUrl();
91
+ expect(url).toBe('https://api.botuyo.com');
92
+ });
93
+ });
94
+ // ── checkExistingSession ────────────────────────────────────────────
95
+ describe('checkExistingSession', () => {
96
+ it('returns null when no credentials exist', async () => {
97
+ vi.mocked(readFile).mockRejectedValue(new Error('ENOENT'));
98
+ const result = await checkExistingSession('http://localhost:8080', false);
99
+ expect(result).toBeNull();
100
+ });
101
+ it('returns null and clears when credentials are locally expired', async () => {
102
+ const expired = makeCreds({ expiresAt: new Date(Date.now() - 1000).toISOString() });
103
+ vi.mocked(readFile).mockResolvedValue(JSON.stringify(expired));
104
+ const result = await checkExistingSession('http://localhost:8080', false);
105
+ expect(result).toBeNull();
106
+ });
107
+ it('returns credentials when valid and not forced', async () => {
108
+ const valid = makeCreds();
109
+ vi.mocked(readFile).mockResolvedValue(JSON.stringify(valid));
110
+ // Mock global fetch for server verification
111
+ const mockFetch = vi.fn().mockResolvedValue({
112
+ ok: true,
113
+ json: async () => ({ success: true })
114
+ });
115
+ vi.stubGlobal('fetch', mockFetch);
116
+ const result = await checkExistingSession('http://localhost:8080', false);
117
+ expect(result).not.toBeNull();
118
+ expect(result?.token).toBe('test-jwt-token');
119
+ vi.unstubAllGlobals();
120
+ });
121
+ it('returns null when --force is true even if credentials are valid', async () => {
122
+ const valid = makeCreds();
123
+ vi.mocked(readFile).mockResolvedValue(JSON.stringify(valid));
124
+ const result = await checkExistingSession('http://localhost:8080', true);
125
+ expect(result).toBeNull();
126
+ });
127
+ it('returns null when server rejects the token (401)', async () => {
128
+ const valid = makeCreds();
129
+ vi.mocked(readFile).mockResolvedValue(JSON.stringify(valid));
130
+ const mockFetch = vi.fn().mockResolvedValue({
131
+ ok: false,
132
+ json: async () => ({ success: false, error: 'Invalid token' })
133
+ });
134
+ vi.stubGlobal('fetch', mockFetch);
135
+ const result = await checkExistingSession('http://localhost:8080', false);
136
+ expect(result).toBeNull();
137
+ vi.unstubAllGlobals();
138
+ });
139
+ it('returns credentials when server is unreachable (network error = assume valid)', async () => {
140
+ const valid = makeCreds();
141
+ vi.mocked(readFile).mockResolvedValue(JSON.stringify(valid));
142
+ const mockFetch = vi.fn().mockRejectedValue(new Error('ECONNREFUSED'));
143
+ vi.stubGlobal('fetch', mockFetch);
144
+ const result = await checkExistingSession('http://localhost:8080', false);
145
+ expect(result).not.toBeNull();
146
+ vi.unstubAllGlobals();
147
+ });
148
+ });
149
+ // ── resolveToken (existing, ensure no regression) ──────────────────
150
+ describe('resolveToken', () => {
151
+ it('returns BOTUYO_TOKEN env var when set', async () => {
152
+ process.env.BOTUYO_TOKEN = 'env-token';
153
+ const token = await resolveToken();
154
+ expect(token).toBe('env-token');
155
+ });
156
+ it('returns token from credentials when env var is not set', async () => {
157
+ vi.mocked(readFile).mockResolvedValue(JSON.stringify(makeCreds()));
158
+ const token = await resolveToken();
159
+ expect(token).toBe('test-jwt-token');
160
+ });
161
+ it('returns null when no credentials and no env var', async () => {
162
+ vi.mocked(readFile).mockRejectedValue(new Error('ENOENT'));
163
+ const token = await resolveToken();
164
+ expect(token).toBeNull();
165
+ });
166
+ it('returns null and clears when credentials are expired', async () => {
167
+ const expired = makeCreds({ expiresAt: new Date(Date.now() - 1000).toISOString() });
168
+ vi.mocked(readFile).mockResolvedValue(JSON.stringify(expired));
169
+ const token = await resolveToken();
170
+ expect(token).toBeNull();
171
+ });
172
+ });
173
+ });
174
+ //# sourceMappingURL=credentials.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"credentials.spec.js","sourceRoot":"","sources":["../../../src/commands/__tests__/credentials.spec.ts"],"names":[],"mappings":"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"}
@@ -17,31 +17,23 @@
17
17
  import http from 'http';
18
18
  import { URL } from 'url';
19
19
  import { execSync } from 'child_process';
20
- import { readCredentials, saveCredentials, clearCredentials, verifyTokenWithServer } from './credentials.js';
20
+ import { saveCredentials, checkExistingSession, resolveApiUrl, resolveTenantName } from './credentials.js';
21
21
  import os from 'os';
22
22
  const ADMIN_URL = process.env.BOTUYO_ADMIN_URL || 'https://botuyo.com';
23
- const API_URL = process.env.BOTUYO_API_URL || 'https://api.botuyo.com';
24
23
  export async function runAuth(args) {
25
24
  console.log('\n🤖 BotUyo MCP — Autenticación por Browser\n');
26
- const existing = await readCredentials();
27
- if (existing && !args.includes('--force')) {
28
- const localExpired = existing.expiresAt && new Date(existing.expiresAt) < new Date();
29
- if (localExpired) {
30
- await clearCredentials();
31
- console.log('⚠️ Tu sesión expiró. Vamos a re-autenticarte.\n');
32
- }
33
- else {
34
- // Verify token is still valid on server
35
- const valid = await verifyTokenWithServer(existing.token, API_URL);
36
- if (valid) {
37
- console.log(`✅ Ya estás autenticado como: ${existing.email || 'usuario'}`);
38
- console.log(` Tenant: ${existing.tenantName} (${existing.role})`);
39
- console.log('\n Usá --force para re-autenticarte.');
40
- console.log(' O usá `npx @botuyo/mcp login` para login por terminal.\n');
41
- return;
42
- }
43
- console.log('⚠️ Tu sesión ya no es válida en el servidor. Vamos a re-autenticarte.\n');
44
- }
25
+ const API_URL = process.env.BOTUYO_API_URL || await resolveApiUrl();
26
+ const force = args.includes('--force');
27
+ const existing = await checkExistingSession(API_URL, force);
28
+ if (existing) {
29
+ console.log(`✅ Ya estás autenticado como: ${existing.email || 'usuario'}`);
30
+ console.log(` Tenant: ${existing.tenantName} (${existing.role})`);
31
+ console.log('\n Usá --force para re-autenticarte.');
32
+ console.log(' O usá `npx @botuyo/mcp login` para login por terminal.\n');
33
+ return;
34
+ }
35
+ if (!force) {
36
+ console.log('⚠️ Sesión expirada o inválida. Vamos a re-autenticarte.\n');
45
37
  }
46
38
  // Start local callback server
47
39
  const { port, waitForCode } = await startCallbackServer();
@@ -75,20 +67,12 @@ export async function runAuth(args) {
75
67
  role: tokenData.data.role || 'viewer',
76
68
  email: tokenData.data.callerEmail || '',
77
69
  savedAt: new Date().toISOString(),
78
- expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString() // 7 days
70
+ expiresAt: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString(), // 7 days
71
+ apiUrl: API_URL
79
72
  };
80
- // Resolve the real tenant name via API (OAuth response often only has the ID)
73
+ // Resolve the real tenant name via shared helper
81
74
  if (creds.tenantName === creds.tenantId) {
82
- try {
83
- const tRes = await fetch(`${API_URL}/api/tenants/${creds.tenantId}`, {
84
- headers: { Authorization: `Bearer ${creds.token}` }
85
- });
86
- const tData = (await tRes.json());
87
- const name = tData.data?.name || tData.data?.tenant?.name;
88
- if (name)
89
- creds.tenantName = name;
90
- }
91
- catch { /* keep ID as fallback */ }
75
+ creds.tenantName = await resolveTenantName(API_URL, creds.token, creds.tenantId);
92
76
  }
93
77
  await saveCredentials(creds);
94
78
  console.log(`\n✅ ¡Autenticado exitosamente!`);
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/commands/auth.ts"],"names":[],"mappings":"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"}