@nexvora/mcp-server 0.3.2 → 0.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.
Files changed (65) 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/package.json +5 -1
  12. package/CHANGELOG.md +0 -208
  13. package/docs/setup/chatgpt-desktop.md +0 -120
  14. package/docs/setup/claude-code.md +0 -152
  15. package/docs/setup/cursor.md +0 -129
  16. package/src/NexvoraClient.ts +0 -328
  17. package/src/RateLimiter.ts +0 -74
  18. package/src/__tests__/NexvoraClient.test.ts +0 -424
  19. package/src/__tests__/RateLimiter.test.ts +0 -151
  20. package/src/__tests__/auth/oauth.test.ts +0 -246
  21. package/src/__tests__/cache.test.ts +0 -64
  22. package/src/__tests__/config.test.ts +0 -98
  23. package/src/__tests__/defineTool.test.ts +0 -223
  24. package/src/__tests__/fixtures/config.json +0 -7
  25. package/src/__tests__/integration/agentstack.integration.test.ts +0 -259
  26. package/src/__tests__/integration/auth_refresh.integration.test.ts +0 -227
  27. package/src/__tests__/integration/consulting.integration.test.ts +0 -213
  28. package/src/__tests__/integration/feed.integration.test.ts +0 -200
  29. package/src/__tests__/integration/helpers.ts +0 -118
  30. package/src/__tests__/integration/knowledge.integration.test.ts +0 -194
  31. package/src/__tests__/integration/rate_limiting.integration.test.ts +0 -207
  32. package/src/__tests__/integration/submit_task.integration.test.ts +0 -120
  33. package/src/__tests__/integration/wallet_observatory.integration.test.ts +0 -240
  34. package/src/__tests__/nexvora_agentstack_answer.test.ts +0 -120
  35. package/src/__tests__/nexvora_agentstack_ask.test.ts +0 -140
  36. package/src/__tests__/nexvora_agentstack_search.test.ts +0 -188
  37. package/src/__tests__/nexvora_consulting_book.test.ts +0 -277
  38. package/src/__tests__/nexvora_consulting_search.test.ts +0 -153
  39. package/src/__tests__/nexvora_feed_post.test.ts +0 -147
  40. package/src/__tests__/nexvora_feed_react.test.ts +0 -98
  41. package/src/__tests__/nexvora_knowledge_search.test.ts +0 -148
  42. package/src/__tests__/nexvora_knowledge_subscribe.test.ts +0 -173
  43. package/src/__tests__/nexvora_observatory.test.ts +0 -125
  44. package/src/__tests__/nexvora_wallet_balance.test.ts +0 -165
  45. package/src/auth/oauth.ts +0 -247
  46. package/src/cache.ts +0 -34
  47. package/src/cli.ts +0 -171
  48. package/src/config.ts +0 -70
  49. package/src/createServer.ts +0 -90
  50. package/src/defineTool.ts +0 -120
  51. package/src/index.ts +0 -36
  52. package/src/server/sse.ts +0 -149
  53. package/src/tools/nexvora_agentstack_answer.ts +0 -62
  54. package/src/tools/nexvora_agentstack_ask.ts +0 -70
  55. package/src/tools/nexvora_agentstack_search.ts +0 -82
  56. package/src/tools/nexvora_consulting_book.ts +0 -130
  57. package/src/tools/nexvora_consulting_search.ts +0 -85
  58. package/src/tools/nexvora_feed_post.ts +0 -69
  59. package/src/tools/nexvora_feed_react.ts +0 -48
  60. package/src/tools/nexvora_knowledge_search.ts +0 -81
  61. package/src/tools/nexvora_knowledge_subscribe.ts +0 -90
  62. package/src/tools/nexvora_observatory.ts +0 -87
  63. package/src/tools/nexvora_submit_task.ts +0 -42
  64. package/src/tools/nexvora_wallet_balance.ts +0 -112
  65. 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
- });