@esaio/esa-mcp-server 0.2.1 → 0.2.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 (78) hide show
  1. package/README.en.md +1 -1
  2. package/README.md +1 -1
  3. package/bin/index.js +1 -1
  4. package/package.json +20 -2
  5. package/.dockerignore +0 -36
  6. package/.github/dependabot.yml +0 -23
  7. package/.github/workflows/docker-publish.yml +0 -120
  8. package/.github/workflows/main.yml +0 -41
  9. package/CLAUDE.md +0 -94
  10. package/Dockerfile +0 -34
  11. package/biome.json +0 -57
  12. package/src/__tests__/fixtures/mock-comment.ts +0 -90
  13. package/src/__tests__/fixtures/mock-post.ts +0 -79
  14. package/src/__tests__/index.test.ts +0 -216
  15. package/src/api_client/__tests__/index.test.ts +0 -149
  16. package/src/api_client/__tests__/middleware.test.ts +0 -120
  17. package/src/api_client/__tests__/with-context.test.ts +0 -98
  18. package/src/api_client/index.ts +0 -29
  19. package/src/api_client/middleware.ts +0 -21
  20. package/src/api_client/with-context.ts +0 -26
  21. package/src/config/__tests__/index.test.ts +0 -65
  22. package/src/config/index.ts +0 -20
  23. package/src/context/mcp-context.ts +0 -1
  24. package/src/context/stdio-context.ts +0 -6
  25. package/src/errors/missing-team-name-error.ts +0 -8
  26. package/src/formatters/__tests__/mcp-response.test.ts +0 -106
  27. package/src/formatters/mcp-response.ts +0 -95
  28. package/src/generated/api-types.ts +0 -2968
  29. package/src/i18n/__tests__/index.test.ts +0 -53
  30. package/src/i18n/index.ts +0 -39
  31. package/src/index.ts +0 -47
  32. package/src/locales/en.json +0 -13
  33. package/src/locales/ja.json +0 -13
  34. package/src/prompts/__tests__/index.test.ts +0 -48
  35. package/src/prompts/__tests__/summarize-post.test.ts +0 -291
  36. package/src/prompts/index.ts +0 -21
  37. package/src/prompts/summarize-post.ts +0 -94
  38. package/src/resources/__tests__/index.test.ts +0 -50
  39. package/src/resources/__tests__/recent-posts-list.test.ts +0 -92
  40. package/src/resources/__tests__/recent-posts.test.ts +0 -270
  41. package/src/resources/index.ts +0 -33
  42. package/src/resources/recent-posts-list.ts +0 -22
  43. package/src/resources/recent-posts.ts +0 -45
  44. package/src/schemas/team-name-schema.ts +0 -19
  45. package/src/tools/__tests__/attachments.test.ts +0 -460
  46. package/src/tools/__tests__/categories.test.ts +0 -402
  47. package/src/tools/__tests__/comments.test.ts +0 -970
  48. package/src/tools/__tests__/helps.test.ts +0 -222
  49. package/src/tools/__tests__/index.test.ts +0 -48
  50. package/src/tools/__tests__/post-actions.test.ts +0 -445
  51. package/src/tools/__tests__/posts.test.ts +0 -917
  52. package/src/tools/__tests__/search.test.ts +0 -339
  53. package/src/tools/__tests__/teams.test.ts +0 -615
  54. package/src/tools/attachments.ts +0 -167
  55. package/src/tools/categories.ts +0 -153
  56. package/src/tools/comments.ts +0 -258
  57. package/src/tools/helps.ts +0 -50
  58. package/src/tools/index.ts +0 -351
  59. package/src/tools/post-actions.ts +0 -132
  60. package/src/tools/posts.ts +0 -179
  61. package/src/tools/search.ts +0 -98
  62. package/src/tools/teams.ts +0 -157
  63. package/src/transformers/__tests__/category-transformer.test.ts +0 -161
  64. package/src/transformers/__tests__/comment-transformer.test.ts +0 -129
  65. package/src/transformers/__tests__/post-name-normalizer.test.ts +0 -53
  66. package/src/transformers/__tests__/post-transformer.test.ts +0 -70
  67. package/src/transformers/__tests__/query-normalizer.test.ts +0 -98
  68. package/src/transformers/__tests__/team-name-normalizer.test.ts +0 -21
  69. package/src/transformers/category-transformer.ts +0 -36
  70. package/src/transformers/comment-transformer.ts +0 -34
  71. package/src/transformers/post-name-normalizer.ts +0 -30
  72. package/src/transformers/post-transformer.ts +0 -38
  73. package/src/transformers/query-normalizer.ts +0 -36
  74. package/src/transformers/team-name-normalizer.ts +0 -7
  75. package/tsconfig.build.json +0 -4
  76. package/tsconfig.json +0 -30
  77. package/tsdown.config.ts +0 -13
  78. package/vitest.config.ts +0 -24
@@ -1,339 +0,0 @@
1
- import { beforeEach, describe, expect, it, vi } from "vitest";
2
- import {
3
- createExpectedTransformed,
4
- createMockPost,
5
- createNullBodyPost,
6
- createWipPost,
7
- } from "../../__tests__/fixtures/mock-post.js";
8
- import type { createEsaClient } from "../../api_client/index.js";
9
- import { searchPosts } from "../search.js";
10
-
11
- describe("searchPosts", () => {
12
- const mockClient = {
13
- GET: vi.fn(),
14
- } as unknown as ReturnType<typeof createEsaClient> & {
15
- GET: ReturnType<typeof vi.fn>;
16
- };
17
-
18
- beforeEach(() => {
19
- vi.clearAllMocks();
20
- });
21
-
22
- it("should return posts successfully", async () => {
23
- const mockPost1 = createMockPost();
24
- const mockPost2 = createWipPost({
25
- number: 456,
26
- name: "wip-post.md",
27
- full_name: "dev/wip-post.md",
28
- });
29
-
30
- mockClient.GET.mockResolvedValue({
31
- data: {
32
- posts: [mockPost1, mockPost2],
33
- prev_page: null,
34
- next_page: 2,
35
- total_count: 42,
36
- page: 1,
37
- per_page: 20,
38
- max_per_page: 100,
39
- },
40
- error: undefined,
41
- response: {
42
- ok: true,
43
- status: 200,
44
- } as Response,
45
- });
46
-
47
- const result = await searchPosts(mockClient, {
48
- query: "test",
49
- teamName: "test-team",
50
- });
51
-
52
- expect(mockClient.GET).toHaveBeenCalledWith("/v1/teams/{team_name}/posts", {
53
- params: {
54
- path: { team_name: "test-team" },
55
- query: {
56
- q: "test",
57
- sort: undefined,
58
- order: undefined,
59
- page: undefined,
60
- per_page: undefined,
61
- include: undefined,
62
- },
63
- },
64
- });
65
-
66
- const expectedResponse = [
67
- createExpectedTransformed(mockPost1),
68
- createExpectedTransformed(mockPost2),
69
- ];
70
-
71
- expect(result).toEqual({
72
- content: [
73
- {
74
- type: "text",
75
- text: JSON.stringify(expectedResponse, null, 2),
76
- },
77
- ],
78
- });
79
- });
80
-
81
- it("should handle search with all parameters", async () => {
82
- const mockPost = createMockPost();
83
-
84
- mockClient.GET.mockResolvedValue({
85
- data: {
86
- posts: [mockPost],
87
- prev_page: 1,
88
- next_page: 3,
89
- total_count: 100,
90
- page: 2,
91
- per_page: 10,
92
- max_per_page: 100,
93
- },
94
- error: undefined,
95
- response: {
96
- ok: true,
97
- status: 200,
98
- } as Response,
99
- });
100
-
101
- const result = await searchPosts(mockClient, {
102
- query: "tag:release",
103
- teamName: "test-team",
104
- sort: "updated",
105
- order: "desc",
106
- page: 2,
107
- perPage: 10,
108
- include: "comments",
109
- });
110
-
111
- expect(mockClient.GET).toHaveBeenCalledWith("/v1/teams/{team_name}/posts", {
112
- params: {
113
- path: { team_name: "test-team" },
114
- query: {
115
- q: "tag:release",
116
- sort: "updated",
117
- order: "desc",
118
- page: 2,
119
- per_page: 10,
120
- include: "comments",
121
- },
122
- },
123
- });
124
-
125
- const expectedResponse = [createExpectedTransformed(mockPost)];
126
- expect(result).toEqual({
127
- content: [
128
- {
129
- type: "text",
130
- text: JSON.stringify(expectedResponse, null, 2),
131
- },
132
- ],
133
- });
134
- });
135
-
136
- it("should handle empty search results", async () => {
137
- mockClient.GET.mockResolvedValue({
138
- data: {
139
- posts: [],
140
- prev_page: null,
141
- next_page: null,
142
- total_count: 0,
143
- page: 1,
144
- per_page: 20,
145
- max_per_page: 100,
146
- },
147
- error: undefined,
148
- response: {
149
- ok: true,
150
- status: 200,
151
- } as Response,
152
- });
153
-
154
- const result = await searchPosts(mockClient, {
155
- query: "nonexistent",
156
- teamName: "test-team",
157
- });
158
-
159
- expect(result).toEqual({
160
- content: [
161
- {
162
- type: "text",
163
- text: JSON.stringify([], null, 2),
164
- },
165
- ],
166
- });
167
- });
168
-
169
- it("should handle multiple posts with various states", async () => {
170
- const shippedPost = createMockPost();
171
- const wipPost = createWipPost();
172
- const nullBodyPost = createNullBodyPost();
173
-
174
- mockClient.GET.mockResolvedValue({
175
- data: {
176
- posts: [shippedPost, wipPost, nullBodyPost],
177
- prev_page: null,
178
- next_page: null,
179
- total_count: 3,
180
- page: 1,
181
- per_page: 20,
182
- max_per_page: 100,
183
- },
184
- error: undefined,
185
- response: {
186
- ok: true,
187
- status: 200,
188
- } as Response,
189
- });
190
-
191
- const result = await searchPosts(mockClient, {
192
- query: "",
193
- teamName: "test-team",
194
- });
195
-
196
- const parsedResult = JSON.parse(result.content[0].text as string);
197
- expect(parsedResult).toHaveLength(3);
198
- expect(parsedResult[0].wip).toBe("Shipped");
199
- expect(parsedResult[1].wip).toBe("WIP");
200
- expect(parsedResult[2].body_md).toBe(undefined);
201
- });
202
-
203
- it("should handle API errors", async () => {
204
- const mockError = {
205
- error: "unauthorized",
206
- message: "Invalid access token",
207
- };
208
-
209
- mockClient.GET.mockResolvedValue({
210
- data: undefined,
211
- error: mockError,
212
- response: {
213
- ok: false,
214
- status: 401,
215
- } as Response,
216
- });
217
-
218
- const result = await searchPosts(mockClient, {
219
- query: "test",
220
- teamName: "test-team",
221
- });
222
-
223
- expect(result).toEqual({
224
- content: [
225
- {
226
- type: "text",
227
- text: `Error: ${JSON.stringify(mockError, null, 2)}`,
228
- },
229
- ],
230
- });
231
- });
232
-
233
- it("should handle network errors", async () => {
234
- const networkError = new Error("Network connection failed");
235
-
236
- mockClient.GET.mockRejectedValue(networkError);
237
-
238
- const result = await searchPosts(mockClient, {
239
- query: "test",
240
- teamName: "test-team",
241
- });
242
-
243
- expect(result).toEqual({
244
- content: [
245
- {
246
- type: "text",
247
- text: "Error: Network connection failed",
248
- },
249
- ],
250
- });
251
- });
252
-
253
- it("should handle non-Error exceptions", async () => {
254
- mockClient.GET.mockRejectedValue("Unexpected error");
255
-
256
- const result = await searchPosts(mockClient, {
257
- query: "test",
258
- teamName: "test-team",
259
- });
260
-
261
- expect(result).toEqual({
262
- content: [
263
- {
264
- type: "text",
265
- text: "Error: Unexpected error",
266
- },
267
- ],
268
- });
269
- });
270
-
271
- it("should throw MissingTeamNameError when teamName is empty", async () => {
272
- const result = await searchPosts(mockClient, {
273
- query: "test",
274
- teamName: "",
275
- });
276
-
277
- expect(result).toEqual({
278
- content: [
279
- {
280
- type: "text",
281
- text: "Error: Missing required parameter 'teamName'. Use esa_get_teams to list available teams, then retry with teamName specified.",
282
- },
283
- ],
284
- });
285
-
286
- expect(mockClient.GET).not.toHaveBeenCalled();
287
- });
288
-
289
- it("should handle complex search queries", async () => {
290
- const mockPost = createMockPost();
291
-
292
- mockClient.GET.mockResolvedValue({
293
- data: {
294
- posts: [mockPost],
295
- prev_page: null,
296
- next_page: null,
297
- total_count: 1,
298
- page: 1,
299
- per_page: 20,
300
- max_per_page: 100,
301
- },
302
- error: undefined,
303
- response: {
304
- ok: true,
305
- status: 200,
306
- } as Response,
307
- });
308
-
309
- const result = await searchPosts(mockClient, {
310
- query: "category:dev wip:false keyword:API",
311
- teamName: "test-team",
312
- sort: "best_match",
313
- });
314
-
315
- expect(mockClient.GET).toHaveBeenCalledWith("/v1/teams/{team_name}/posts", {
316
- params: {
317
- path: { team_name: "test-team" },
318
- query: {
319
- q: "category:dev wip:false keyword:API",
320
- sort: "best_match",
321
- order: undefined,
322
- page: undefined,
323
- per_page: undefined,
324
- include: undefined,
325
- },
326
- },
327
- });
328
-
329
- const expectedResponse = [createExpectedTransformed(mockPost)];
330
- expect(result).toEqual({
331
- content: [
332
- {
333
- type: "text",
334
- text: JSON.stringify(expectedResponse, null, 2),
335
- },
336
- ],
337
- });
338
- });
339
- });