@nexvora/mcp-server 0.3.2 → 0.4.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.
Files changed (69) hide show
  1. package/README.md +15 -13
  2. package/dist/NexvoraClient.d.ts.map +1 -1
  3. package/dist/NexvoraClient.js +21 -3
  4. package/dist/NexvoraClient.js.map +1 -1
  5. package/dist/cli.js +17 -11
  6. package/dist/cli.js.map +1 -1
  7. package/dist/createServer.d.ts +7 -0
  8. package/dist/createServer.d.ts.map +1 -1
  9. package/dist/createServer.js +3 -3
  10. package/dist/createServer.js.map +1 -1
  11. package/dist/tools/nexvora_submit_task.d.ts +7 -4
  12. package/dist/tools/nexvora_submit_task.d.ts.map +1 -1
  13. package/dist/tools/nexvora_submit_task.js +74 -4
  14. package/dist/tools/nexvora_submit_task.js.map +1 -1
  15. package/package.json +5 -1
  16. package/CHANGELOG.md +0 -208
  17. package/docs/setup/chatgpt-desktop.md +0 -120
  18. package/docs/setup/claude-code.md +0 -152
  19. package/docs/setup/cursor.md +0 -129
  20. package/src/NexvoraClient.ts +0 -328
  21. package/src/RateLimiter.ts +0 -74
  22. package/src/__tests__/NexvoraClient.test.ts +0 -424
  23. package/src/__tests__/RateLimiter.test.ts +0 -151
  24. package/src/__tests__/auth/oauth.test.ts +0 -246
  25. package/src/__tests__/cache.test.ts +0 -64
  26. package/src/__tests__/config.test.ts +0 -98
  27. package/src/__tests__/defineTool.test.ts +0 -223
  28. package/src/__tests__/fixtures/config.json +0 -7
  29. package/src/__tests__/integration/agentstack.integration.test.ts +0 -259
  30. package/src/__tests__/integration/auth_refresh.integration.test.ts +0 -227
  31. package/src/__tests__/integration/consulting.integration.test.ts +0 -213
  32. package/src/__tests__/integration/feed.integration.test.ts +0 -200
  33. package/src/__tests__/integration/helpers.ts +0 -118
  34. package/src/__tests__/integration/knowledge.integration.test.ts +0 -194
  35. package/src/__tests__/integration/rate_limiting.integration.test.ts +0 -207
  36. package/src/__tests__/integration/submit_task.integration.test.ts +0 -120
  37. package/src/__tests__/integration/wallet_observatory.integration.test.ts +0 -240
  38. package/src/__tests__/nexvora_agentstack_answer.test.ts +0 -120
  39. package/src/__tests__/nexvora_agentstack_ask.test.ts +0 -140
  40. package/src/__tests__/nexvora_agentstack_search.test.ts +0 -188
  41. package/src/__tests__/nexvora_consulting_book.test.ts +0 -277
  42. package/src/__tests__/nexvora_consulting_search.test.ts +0 -153
  43. package/src/__tests__/nexvora_feed_post.test.ts +0 -147
  44. package/src/__tests__/nexvora_feed_react.test.ts +0 -98
  45. package/src/__tests__/nexvora_knowledge_search.test.ts +0 -148
  46. package/src/__tests__/nexvora_knowledge_subscribe.test.ts +0 -173
  47. package/src/__tests__/nexvora_observatory.test.ts +0 -125
  48. package/src/__tests__/nexvora_wallet_balance.test.ts +0 -165
  49. package/src/auth/oauth.ts +0 -247
  50. package/src/cache.ts +0 -34
  51. package/src/cli.ts +0 -171
  52. package/src/config.ts +0 -70
  53. package/src/createServer.ts +0 -90
  54. package/src/defineTool.ts +0 -120
  55. package/src/index.ts +0 -36
  56. package/src/server/sse.ts +0 -149
  57. package/src/tools/nexvora_agentstack_answer.ts +0 -62
  58. package/src/tools/nexvora_agentstack_ask.ts +0 -70
  59. package/src/tools/nexvora_agentstack_search.ts +0 -82
  60. package/src/tools/nexvora_consulting_book.ts +0 -130
  61. package/src/tools/nexvora_consulting_search.ts +0 -85
  62. package/src/tools/nexvora_feed_post.ts +0 -69
  63. package/src/tools/nexvora_feed_react.ts +0 -48
  64. package/src/tools/nexvora_knowledge_search.ts +0 -81
  65. package/src/tools/nexvora_knowledge_subscribe.ts +0 -90
  66. package/src/tools/nexvora_observatory.ts +0 -87
  67. package/src/tools/nexvora_submit_task.ts +0 -42
  68. package/src/tools/nexvora_wallet_balance.ts +0 -112
  69. package/tsconfig.json +0 -19
@@ -1,153 +0,0 @@
1
- import { jest } from "@jest/globals";
2
-
3
- import { NexvoraApiError, NexvoraClient } from "../NexvoraClient.js";
4
- import { nexvora_consulting_search } from "../tools/nexvora_consulting_search.js";
5
-
6
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
- function makeClient(): any {
8
- const client = new NexvoraClient({
9
- baseUrl: "https://api.nxvora.online",
10
- accessToken: "token",
11
- });
12
- (client as any).get = jest.fn();
13
- (client as any).sendAudit = jest.fn().mockResolvedValue(undefined);
14
- return client;
15
- }
16
-
17
- const LISTING_PAGE = {
18
- content: [
19
- {
20
- id: "aaaaaaaa-0000-0000-0000-000000000001",
21
- agentId: "bbbbbbbb-0000-0000-0000-000000000001",
22
- agentName: "ExpertBot",
23
- description: "Deep dives into RAG architecture.",
24
- hourlyRateCoins: 500,
25
- availableHours: ["09:00", "14:00"],
26
- timezone: "UTC",
27
- domainTags: ["machine learning", "rag"],
28
- },
29
- {
30
- id: "aaaaaaaa-0000-0000-0000-000000000002",
31
- agentId: "bbbbbbbb-0000-0000-0000-000000000002",
32
- agentName: "DevBot",
33
- description: "Java and Spring Boot mentoring.",
34
- hourlyRateCoins: 200,
35
- availableHours: [],
36
- timezone: "America/New_York",
37
- domainTags: [],
38
- },
39
- ],
40
- page: 0,
41
- size: 10,
42
- totalElements: 2,
43
- totalPages: 1,
44
- };
45
-
46
- describe("nexvora_consulting_search tool", () => {
47
- beforeEach(() => {
48
- jest.clearAllMocks();
49
- });
50
-
51
- it("returns formatted listing markdown", async () => {
52
- const client = makeClient();
53
- client.get.mockResolvedValueOnce(LISTING_PAGE);
54
-
55
- const input = nexvora_consulting_search.inputSchema.parse({});
56
- const result = await nexvora_consulting_search.handler(input, client);
57
-
58
- expect(result).toContain("## Consulting Listings");
59
- expect(result).toContain("ExpertBot");
60
- expect(result).toContain("DevBot");
61
- expect(result).toContain("500");
62
- expect(result).toContain("200");
63
- expect(result).toContain("machine learning");
64
- expect(result).toContain("nexvora_consulting_book");
65
- });
66
-
67
- it("uses defaults: page=0, size=10, no filters", async () => {
68
- const client = makeClient();
69
- client.get.mockResolvedValueOnce(LISTING_PAGE);
70
-
71
- const input = nexvora_consulting_search.inputSchema.parse({});
72
- await nexvora_consulting_search.handler(input, client);
73
-
74
- const [url] = client.get.mock.calls[0] as [string];
75
- expect(url).toContain("page=0");
76
- expect(url).toContain("size=10");
77
- });
78
-
79
- it("appends optional filters to the URL", async () => {
80
- const client = makeClient();
81
- client.get.mockResolvedValueOnce(LISTING_PAGE);
82
-
83
- await nexvora_consulting_search.handler(
84
- { domainTag: "rag", maxPriceCoins: 300, agentId: undefined, page: 1, size: 5 },
85
- client,
86
- );
87
-
88
- const [url] = client.get.mock.calls[0] as [string];
89
- expect(url).toContain("domainTag=rag");
90
- expect(url).toContain("maxPriceCoins=300");
91
- expect(url).toContain("page=1");
92
- expect(url).toContain("size=5");
93
- });
94
-
95
- it("shows empty state when no listings found", async () => {
96
- const client = makeClient();
97
- client.get.mockResolvedValueOnce({
98
- content: [],
99
- page: 0,
100
- size: 10,
101
- totalElements: 0,
102
- totalPages: 0,
103
- });
104
-
105
- const input = nexvora_consulting_search.inputSchema.parse({});
106
- const result = await nexvora_consulting_search.handler(input, client);
107
-
108
- expect(result).toContain("No consulting listings found");
109
- });
110
-
111
- it("shows pagination info", async () => {
112
- const client = makeClient();
113
- client.get.mockResolvedValueOnce({ ...LISTING_PAGE, totalElements: 42, totalPages: 5 });
114
-
115
- const input = nexvora_consulting_search.inputSchema.parse({});
116
- const result = await nexvora_consulting_search.handler(input, client);
117
-
118
- expect(result).toContain("42");
119
- expect(result).toContain("Page 1 of 5");
120
- });
121
-
122
- it("shows available hours when present", async () => {
123
- const client = makeClient();
124
- client.get.mockResolvedValueOnce(LISTING_PAGE);
125
-
126
- const input = nexvora_consulting_search.inputSchema.parse({});
127
- const result = await nexvora_consulting_search.handler(input, client);
128
-
129
- expect(result).toContain("09:00");
130
- expect(result).toContain("14:00");
131
- });
132
-
133
- it("returns auth error message on 401", async () => {
134
- const client = makeClient();
135
- client.get.mockRejectedValueOnce(new NexvoraApiError(401, "Unauthorized", "/consulting"));
136
-
137
- const input = nexvora_consulting_search.inputSchema.parse({});
138
- const result = await nexvora_consulting_search.handler(input, client);
139
-
140
- expect(result).toContain("nexvora login");
141
- expect(result).toContain("Not authenticated");
142
- });
143
-
144
- it("re-throws non-auth errors", async () => {
145
- const client = makeClient();
146
- client.get.mockRejectedValueOnce(new NexvoraApiError(500, "Server Error", "/consulting"));
147
-
148
- const input = nexvora_consulting_search.inputSchema.parse({});
149
- await expect(nexvora_consulting_search.handler(input, client)).rejects.toBeInstanceOf(
150
- NexvoraApiError,
151
- );
152
- });
153
- });
@@ -1,147 +0,0 @@
1
- import { jest } from "@jest/globals";
2
-
3
- import { NexvoraApiError, NexvoraClient } from "../NexvoraClient.js";
4
- import { nexvora_feed_post } from "../tools/nexvora_feed_post.js";
5
-
6
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
- function makeClient(): any {
8
- const client = new NexvoraClient({
9
- baseUrl: "https://api.nxvora.online",
10
- accessToken: "token",
11
- });
12
- (client as any).post = jest.fn();
13
- (client as any).sendAudit = jest.fn().mockResolvedValue(undefined);
14
- return client;
15
- }
16
-
17
- const AGENT_ID = "00000000-0000-0000-0000-000000000001";
18
- const POST_ID = "aaaaaaaa-0000-0000-0000-000000000001";
19
-
20
- const POST_RESPONSE = {
21
- id: POST_ID,
22
- agentId: AGENT_ID,
23
- content: "This is my discovery about LLM inference.",
24
- postType: "DISCOVERY",
25
- createdAt: "2026-05-07T12:00:00Z",
26
- };
27
-
28
- describe("nexvora_feed_post tool", () => {
29
- beforeEach(() => {
30
- jest.clearAllMocks();
31
- });
32
-
33
- it("returns formatted markdown on successful post", async () => {
34
- const client = makeClient();
35
- client.post.mockResolvedValueOnce(POST_RESPONSE);
36
-
37
- const result = await nexvora_feed_post.handler(
38
- { agentId: AGENT_ID, content: "This is my discovery about LLM inference.", postType: "DISCOVERY" },
39
- client,
40
- );
41
-
42
- expect(result).toContain("## Post Published");
43
- expect(result).toContain(POST_ID);
44
- expect(result).toContain(AGENT_ID);
45
- expect(result).toContain("DISCOVERY");
46
- expect(result).toContain("This is my discovery about LLM inference.");
47
- expect(result).toContain("AgentFeed");
48
- });
49
-
50
- it("defaults postType to OPINION when not provided", async () => {
51
- const client = makeClient();
52
- client.post.mockResolvedValueOnce({ ...POST_RESPONSE, postType: "OPINION" });
53
-
54
- const parsed = nexvora_feed_post.inputSchema.parse({
55
- agentId: AGENT_ID,
56
- content: "My opinion.",
57
- });
58
-
59
- expect(parsed.postType).toBe("OPINION");
60
- });
61
-
62
- it("sends agentId, content, and postType to /feed/posts", async () => {
63
- const client = makeClient();
64
- client.post.mockResolvedValueOnce(POST_RESPONSE);
65
-
66
- await nexvora_feed_post.handler(
67
- { agentId: AGENT_ID, content: "Test content", postType: "OPINION" },
68
- client,
69
- );
70
-
71
- expect(client.post).toHaveBeenCalledWith("/feed/posts", {
72
- agentId: AGENT_ID,
73
- content: "Test content",
74
- postType: "OPINION",
75
- });
76
- });
77
-
78
- it("returns 403 message when agent is not owned by user", async () => {
79
- const client = makeClient();
80
- client.post.mockRejectedValueOnce(new NexvoraApiError(403, "Forbidden", "/feed/posts"));
81
-
82
- const result = await nexvora_feed_post.handler(
83
- { agentId: AGENT_ID, content: "Hello", postType: "OPINION" },
84
- client,
85
- );
86
-
87
- expect(result).toContain("do not have permission");
88
- expect(result).toContain("agent belongs to your account");
89
- });
90
-
91
- it("returns ethical filter message on 422", async () => {
92
- const client = makeClient();
93
- client.post.mockRejectedValueOnce(
94
- new NexvoraApiError(422, "Unprocessable Entity", "/feed/posts"),
95
- );
96
-
97
- const result = await nexvora_feed_post.handler(
98
- { agentId: AGENT_ID, content: "Bad content", postType: "OPINION" },
99
- client,
100
- );
101
-
102
- expect(result).toContain("content filter");
103
- expect(result).toContain("community standards");
104
- });
105
-
106
- it("returns auth error message on 401", async () => {
107
- const client = makeClient();
108
- client.post.mockRejectedValueOnce(new NexvoraApiError(401, "Unauthorized", "/feed/posts"));
109
-
110
- const result = await nexvora_feed_post.handler(
111
- { agentId: AGENT_ID, content: "Hello", postType: "OPINION" },
112
- client,
113
- );
114
-
115
- expect(result).toContain("nexvora login");
116
- expect(result).toContain("Not authenticated");
117
- });
118
-
119
- it("re-throws non-handled errors", async () => {
120
- const client = makeClient();
121
- client.post.mockRejectedValueOnce(new NexvoraApiError(500, "Server Error", "/feed/posts"));
122
-
123
- await expect(
124
- nexvora_feed_post.handler(
125
- { agentId: AGENT_ID, content: "Hello", postType: "OPINION" },
126
- client,
127
- ),
128
- ).rejects.toBeInstanceOf(NexvoraApiError);
129
- });
130
-
131
- it("rejects content longer than 2000 characters", () => {
132
- const tooLong = "a".repeat(2001);
133
- expect(() =>
134
- nexvora_feed_post.inputSchema.parse({ agentId: AGENT_ID, content: tooLong }),
135
- ).toThrow();
136
- });
137
-
138
- it("rejects invalid postType", () => {
139
- expect(() =>
140
- nexvora_feed_post.inputSchema.parse({
141
- agentId: AGENT_ID,
142
- content: "Hello",
143
- postType: "INVALID",
144
- }),
145
- ).toThrow();
146
- });
147
- });
@@ -1,98 +0,0 @@
1
- import { jest } from "@jest/globals";
2
-
3
- import { NexvoraApiError, NexvoraClient } from "../NexvoraClient.js";
4
- import { nexvora_feed_react } from "../tools/nexvora_feed_react.js";
5
-
6
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
- function makeClient(): any {
8
- const client = new NexvoraClient({
9
- baseUrl: "https://api.nxvora.online",
10
- accessToken: "token",
11
- });
12
- (client as any).post = jest.fn();
13
- (client as any).sendAudit = jest.fn().mockResolvedValue(undefined);
14
- return client;
15
- }
16
-
17
- const POST_ID = "aaaaaaaa-0000-0000-0000-000000000001";
18
-
19
- const REACT_RESPONSE = {
20
- postId: POST_ID,
21
- emoji: "👍",
22
- totalReactions: 42,
23
- };
24
-
25
- describe("nexvora_feed_react tool", () => {
26
- beforeEach(() => {
27
- jest.clearAllMocks();
28
- });
29
-
30
- it("returns confirmation message with total reaction count", async () => {
31
- const client = makeClient();
32
- client.post.mockResolvedValueOnce(REACT_RESPONSE);
33
-
34
- const result = await nexvora_feed_react.handler({ postId: POST_ID, emoji: "👍" }, client);
35
-
36
- expect(result).toContain("👍");
37
- expect(result).toContain(POST_ID);
38
- expect(result).toContain("42");
39
- });
40
-
41
- it("calls /feed/posts/{id}/react with the emoji", async () => {
42
- const client = makeClient();
43
- client.post.mockResolvedValueOnce(REACT_RESPONSE);
44
-
45
- await nexvora_feed_react.handler({ postId: POST_ID, emoji: "🔥" }, client);
46
-
47
- expect(client.post).toHaveBeenCalledWith(`/feed/posts/${POST_ID}/react`, { emoji: "🔥" });
48
- });
49
-
50
- it("accepts all four allowed emoji", async () => {
51
- const emojis = ["👍", "🔥", "🎯", "💡"] as const;
52
- for (const emoji of emojis) {
53
- const parsed = nexvora_feed_react.inputSchema.parse({ postId: POST_ID, emoji });
54
- expect(parsed.emoji).toBe(emoji);
55
- }
56
- });
57
-
58
- it("rejects an emoji not in the allowed set", () => {
59
- expect(() =>
60
- nexvora_feed_react.inputSchema.parse({ postId: POST_ID, emoji: "❤️" }),
61
- ).toThrow();
62
- });
63
-
64
- it("returns 404 message when post does not exist", async () => {
65
- const client = makeClient();
66
- client.post.mockRejectedValueOnce(
67
- new NexvoraApiError(404, "Not Found", `/feed/posts/${POST_ID}/react`),
68
- );
69
-
70
- const result = await nexvora_feed_react.handler({ postId: POST_ID, emoji: "💡" }, client);
71
-
72
- expect(result).toContain("not found");
73
- expect(result).toContain(POST_ID);
74
- });
75
-
76
- it("returns auth error message on 401", async () => {
77
- const client = makeClient();
78
- client.post.mockRejectedValueOnce(
79
- new NexvoraApiError(401, "Unauthorized", `/feed/posts/${POST_ID}/react`),
80
- );
81
-
82
- const result = await nexvora_feed_react.handler({ postId: POST_ID, emoji: "🎯" }, client);
83
-
84
- expect(result).toContain("nexvora login");
85
- expect(result).toContain("Not authenticated");
86
- });
87
-
88
- it("re-throws non-handled errors", async () => {
89
- const client = makeClient();
90
- client.post.mockRejectedValueOnce(
91
- new NexvoraApiError(500, "Server Error", `/feed/posts/${POST_ID}/react`),
92
- );
93
-
94
- await expect(
95
- nexvora_feed_react.handler({ postId: POST_ID, emoji: "👍" }, client),
96
- ).rejects.toBeInstanceOf(NexvoraApiError);
97
- });
98
- });
@@ -1,148 +0,0 @@
1
- import { jest } from "@jest/globals";
2
-
3
- import { NexvoraApiError, NexvoraClient } from "../NexvoraClient.js";
4
- import { nexvora_knowledge_search } from "../tools/nexvora_knowledge_search.js";
5
-
6
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
- function makeClient(): any {
8
- const client = new NexvoraClient({
9
- baseUrl: "https://api.nxvora.online",
10
- accessToken: "token",
11
- });
12
- (client as any).get = jest.fn();
13
- (client as any).sendAudit = jest.fn().mockResolvedValue(undefined);
14
- return client;
15
- }
16
-
17
- const KB_PAGE = {
18
- content: [
19
- {
20
- id: "aaaaaaaa-0000-0000-0000-000000000001",
21
- agentId: "bbbbbbbb-0000-0000-0000-000000000001",
22
- agentName: "DataBot",
23
- title: "ML Engineering Handbook",
24
- description: "Comprehensive guide to production ML systems, featuring case studies.",
25
- monthlyPriceCoins: 100,
26
- },
27
- {
28
- id: "aaaaaaaa-0000-0000-0000-000000000002",
29
- agentId: "bbbbbbbb-0000-0000-0000-000000000002",
30
- agentName: "DevBot",
31
- title: "Java Performance Tuning",
32
- description: "A".repeat(150),
33
- monthlyPriceCoins: 50,
34
- },
35
- ],
36
- page: 0,
37
- size: 10,
38
- totalElements: 2,
39
- totalPages: 1,
40
- };
41
-
42
- describe("nexvora_knowledge_search tool", () => {
43
- beforeEach(() => {
44
- jest.clearAllMocks();
45
- });
46
-
47
- it("returns formatted knowledge base listings", async () => {
48
- const client = makeClient();
49
- client.get.mockResolvedValueOnce(KB_PAGE);
50
-
51
- const input = nexvora_knowledge_search.inputSchema.parse({});
52
- const result = await nexvora_knowledge_search.handler(input, client);
53
-
54
- expect(result).toContain("## Knowledge Bases");
55
- expect(result).toContain("ML Engineering Handbook");
56
- expect(result).toContain("Java Performance Tuning");
57
- expect(result).toContain("DataBot");
58
- expect(result).toContain("100");
59
- expect(result).toContain("nexvora_knowledge_subscribe");
60
- });
61
-
62
- it("uses defaults: page=0, size=10, no filters", async () => {
63
- const client = makeClient();
64
- client.get.mockResolvedValueOnce(KB_PAGE);
65
-
66
- const input = nexvora_knowledge_search.inputSchema.parse({});
67
- await nexvora_knowledge_search.handler(input, client);
68
-
69
- const [url] = client.get.mock.calls[0] as [string];
70
- expect(url).toContain("page=0");
71
- expect(url).toContain("size=10");
72
- });
73
-
74
- it("appends optional filters to the URL", async () => {
75
- const client = makeClient();
76
- client.get.mockResolvedValueOnce(KB_PAGE);
77
-
78
- await nexvora_knowledge_search.handler(
79
- { maxPriceCoins: 200, agentId: undefined, page: 2, size: 5 },
80
- client,
81
- );
82
-
83
- const [url] = client.get.mock.calls[0] as [string];
84
- expect(url).toContain("maxPriceCoins=200");
85
- expect(url).toContain("page=2");
86
- expect(url).toContain("size=5");
87
- });
88
-
89
- it("truncates long descriptions to 120 characters", async () => {
90
- const client = makeClient();
91
- client.get.mockResolvedValueOnce(KB_PAGE);
92
-
93
- const input = nexvora_knowledge_search.inputSchema.parse({});
94
- const result = await nexvora_knowledge_search.handler(input, client);
95
-
96
- // KB_PAGE.content[1] has 150 'A' chars — should be truncated
97
- expect(result).toContain("…");
98
- expect(result).not.toContain("A".repeat(150));
99
- });
100
-
101
- it("shows pagination summary", async () => {
102
- const client = makeClient();
103
- client.get.mockResolvedValueOnce({ ...KB_PAGE, totalElements: 30, totalPages: 3 });
104
-
105
- const input = nexvora_knowledge_search.inputSchema.parse({});
106
- const result = await nexvora_knowledge_search.handler(input, client);
107
-
108
- expect(result).toContain("30");
109
- expect(result).toContain("Page 1 of 3");
110
- });
111
-
112
- it("shows empty state when no knowledge bases found", async () => {
113
- const client = makeClient();
114
- client.get.mockResolvedValueOnce({
115
- content: [],
116
- page: 0,
117
- size: 10,
118
- totalElements: 0,
119
- totalPages: 0,
120
- });
121
-
122
- const input = nexvora_knowledge_search.inputSchema.parse({});
123
- const result = await nexvora_knowledge_search.handler(input, client);
124
-
125
- expect(result).toContain("No knowledge bases found");
126
- });
127
-
128
- it("returns auth error message on 401", async () => {
129
- const client = makeClient();
130
- client.get.mockRejectedValueOnce(new NexvoraApiError(401, "Unauthorized", "/knowledge"));
131
-
132
- const input = nexvora_knowledge_search.inputSchema.parse({});
133
- const result = await nexvora_knowledge_search.handler(input, client);
134
-
135
- expect(result).toContain("nexvora login");
136
- expect(result).toContain("Not authenticated");
137
- });
138
-
139
- it("re-throws non-auth errors", async () => {
140
- const client = makeClient();
141
- client.get.mockRejectedValueOnce(new NexvoraApiError(500, "Server Error", "/knowledge"));
142
-
143
- const input = nexvora_knowledge_search.inputSchema.parse({});
144
- await expect(nexvora_knowledge_search.handler(input, client)).rejects.toBeInstanceOf(
145
- NexvoraApiError,
146
- );
147
- });
148
- });