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