@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.
- package/README.en.md +1 -1
- package/README.md +1 -1
- package/bin/index.js +1 -1
- package/package.json +20 -2
- package/.dockerignore +0 -36
- package/.github/dependabot.yml +0 -23
- package/.github/workflows/docker-publish.yml +0 -120
- package/.github/workflows/main.yml +0 -41
- package/CLAUDE.md +0 -94
- package/Dockerfile +0 -34
- package/biome.json +0 -57
- package/src/__tests__/fixtures/mock-comment.ts +0 -90
- package/src/__tests__/fixtures/mock-post.ts +0 -79
- package/src/__tests__/index.test.ts +0 -216
- package/src/api_client/__tests__/index.test.ts +0 -149
- package/src/api_client/__tests__/middleware.test.ts +0 -120
- package/src/api_client/__tests__/with-context.test.ts +0 -98
- package/src/api_client/index.ts +0 -29
- package/src/api_client/middleware.ts +0 -21
- package/src/api_client/with-context.ts +0 -26
- package/src/config/__tests__/index.test.ts +0 -65
- package/src/config/index.ts +0 -20
- package/src/context/mcp-context.ts +0 -1
- package/src/context/stdio-context.ts +0 -6
- package/src/errors/missing-team-name-error.ts +0 -8
- package/src/formatters/__tests__/mcp-response.test.ts +0 -106
- package/src/formatters/mcp-response.ts +0 -95
- package/src/generated/api-types.ts +0 -2968
- package/src/i18n/__tests__/index.test.ts +0 -53
- package/src/i18n/index.ts +0 -39
- package/src/index.ts +0 -47
- package/src/locales/en.json +0 -13
- package/src/locales/ja.json +0 -13
- package/src/prompts/__tests__/index.test.ts +0 -48
- package/src/prompts/__tests__/summarize-post.test.ts +0 -291
- package/src/prompts/index.ts +0 -21
- package/src/prompts/summarize-post.ts +0 -94
- package/src/resources/__tests__/index.test.ts +0 -50
- package/src/resources/__tests__/recent-posts-list.test.ts +0 -92
- package/src/resources/__tests__/recent-posts.test.ts +0 -270
- package/src/resources/index.ts +0 -33
- package/src/resources/recent-posts-list.ts +0 -22
- package/src/resources/recent-posts.ts +0 -45
- package/src/schemas/team-name-schema.ts +0 -19
- package/src/tools/__tests__/attachments.test.ts +0 -460
- package/src/tools/__tests__/categories.test.ts +0 -402
- package/src/tools/__tests__/comments.test.ts +0 -970
- package/src/tools/__tests__/helps.test.ts +0 -222
- package/src/tools/__tests__/index.test.ts +0 -48
- package/src/tools/__tests__/post-actions.test.ts +0 -445
- package/src/tools/__tests__/posts.test.ts +0 -917
- package/src/tools/__tests__/search.test.ts +0 -339
- package/src/tools/__tests__/teams.test.ts +0 -615
- package/src/tools/attachments.ts +0 -167
- package/src/tools/categories.ts +0 -153
- package/src/tools/comments.ts +0 -258
- package/src/tools/helps.ts +0 -50
- package/src/tools/index.ts +0 -351
- package/src/tools/post-actions.ts +0 -132
- package/src/tools/posts.ts +0 -179
- package/src/tools/search.ts +0 -98
- package/src/tools/teams.ts +0 -157
- package/src/transformers/__tests__/category-transformer.test.ts +0 -161
- package/src/transformers/__tests__/comment-transformer.test.ts +0 -129
- package/src/transformers/__tests__/post-name-normalizer.test.ts +0 -53
- package/src/transformers/__tests__/post-transformer.test.ts +0 -70
- package/src/transformers/__tests__/query-normalizer.test.ts +0 -98
- package/src/transformers/__tests__/team-name-normalizer.test.ts +0 -21
- package/src/transformers/category-transformer.ts +0 -36
- package/src/transformers/comment-transformer.ts +0 -34
- package/src/transformers/post-name-normalizer.ts +0 -30
- package/src/transformers/post-transformer.ts +0 -38
- package/src/transformers/query-normalizer.ts +0 -36
- package/src/transformers/team-name-normalizer.ts +0 -7
- package/tsconfig.build.json +0 -4
- package/tsconfig.json +0 -30
- package/tsdown.config.ts +0 -13
- package/vitest.config.ts +0 -24
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { normalizeSearchQuery } from "../query-normalizer.js";
|
|
3
|
-
|
|
4
|
-
describe("normalizeSearchQuery", () => {
|
|
5
|
-
describe("wildcard normalization", () => {
|
|
6
|
-
it("should convert * to empty string", () => {
|
|
7
|
-
expect(normalizeSearchQuery("*")).toBe("");
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
it("should not convert * when part of a larger query", () => {
|
|
11
|
-
expect(normalizeSearchQuery("user:* tag:release")).toBe(
|
|
12
|
-
"user:* tag:release",
|
|
13
|
-
);
|
|
14
|
-
});
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
describe("date syntax normalization", () => {
|
|
18
|
-
it("should convert after: to created:>", () => {
|
|
19
|
-
expect(normalizeSearchQuery("after:2025-08-16")).toBe(
|
|
20
|
-
"created:>2025-08-16",
|
|
21
|
-
);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it("should convert before: to created:<", () => {
|
|
25
|
-
expect(normalizeSearchQuery("before:2025-08-16")).toBe(
|
|
26
|
-
"created:<2025-08-16",
|
|
27
|
-
);
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("should convert since: to created:>", () => {
|
|
31
|
-
expect(normalizeSearchQuery("since:2025-08-16")).toBe(
|
|
32
|
-
"created:>2025-08-16",
|
|
33
|
-
);
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
it("should convert until: to created:<", () => {
|
|
37
|
-
expect(normalizeSearchQuery("until:2025-08-16")).toBe(
|
|
38
|
-
"created:<2025-08-16",
|
|
39
|
-
);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("should handle case-insensitive matching", () => {
|
|
43
|
-
expect(normalizeSearchQuery("AFTER:2025-08-16")).toBe(
|
|
44
|
-
"created:>2025-08-16",
|
|
45
|
-
);
|
|
46
|
-
expect(normalizeSearchQuery("After:2025-08-16")).toBe(
|
|
47
|
-
"created:>2025-08-16",
|
|
48
|
-
);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it("should handle multiple date patterns in one query", () => {
|
|
52
|
-
expect(
|
|
53
|
-
normalizeSearchQuery(
|
|
54
|
-
"user:fukayatsu after:2025-08-16 before:2025-08-22",
|
|
55
|
-
),
|
|
56
|
-
).toBe("user:fukayatsu created:>2025-08-16 created:<2025-08-22");
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("should not convert partial matches", () => {
|
|
60
|
-
expect(normalizeSearchQuery("notafter:2025-08-16")).toBe(
|
|
61
|
-
"notafter:2025-08-16",
|
|
62
|
-
);
|
|
63
|
-
expect(normalizeSearchQuery("after:notadate")).toBe("after:notadate");
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
it("should handle complex queries with mixed syntax", () => {
|
|
67
|
-
expect(
|
|
68
|
-
normalizeSearchQuery(
|
|
69
|
-
"user:fukayatsu after:2025-08-01 tag:release wip:false",
|
|
70
|
-
),
|
|
71
|
-
).toBe("user:fukayatsu created:>2025-08-01 tag:release wip:false");
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
describe("no transformation needed", () => {
|
|
76
|
-
it("should not modify valid esa syntax", () => {
|
|
77
|
-
expect(normalizeSearchQuery("created:>2025-08-16")).toBe(
|
|
78
|
-
"created:>2025-08-16",
|
|
79
|
-
);
|
|
80
|
-
expect(normalizeSearchQuery("updated:<2025-08-16")).toBe(
|
|
81
|
-
"updated:<2025-08-16",
|
|
82
|
-
);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
it("should preserve normal search queries", () => {
|
|
86
|
-
expect(normalizeSearchQuery("user:fukayatsu tag:release")).toBe(
|
|
87
|
-
"user:fukayatsu tag:release",
|
|
88
|
-
);
|
|
89
|
-
expect(normalizeSearchQuery("category:dev wip:false")).toBe(
|
|
90
|
-
"category:dev wip:false",
|
|
91
|
-
);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it("should handle empty string", () => {
|
|
95
|
-
expect(normalizeSearchQuery("")).toBe("");
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
});
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { normalizeTeamName } from "../team-name-normalizer.js";
|
|
3
|
-
|
|
4
|
-
describe("normalizeTeamName", () => {
|
|
5
|
-
it("should extract team name from URL-like input", () => {
|
|
6
|
-
expect(normalizeTeamName("docs.example.com")).toBe("docs");
|
|
7
|
-
expect(normalizeTeamName("my-team.example.com")).toBe("my-team");
|
|
8
|
-
expect(normalizeTeamName("company.example.com")).toBe("company");
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it("should leave normal team names unchanged", () => {
|
|
12
|
-
expect(normalizeTeamName("docs")).toBe("docs");
|
|
13
|
-
expect(normalizeTeamName("my-team")).toBe("my-team");
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
it("should handle edge cases", () => {
|
|
17
|
-
expect(normalizeTeamName("")).toBe("");
|
|
18
|
-
expect(normalizeTeamName(".")).toBe("");
|
|
19
|
-
expect(normalizeTeamName("team.")).toBe("team");
|
|
20
|
-
});
|
|
21
|
-
});
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import type { components } from "../generated/api-types.js";
|
|
2
|
-
|
|
3
|
-
export function transformCategory(category: components["schemas"]["Category"]) {
|
|
4
|
-
return {
|
|
5
|
-
full_name: category.full_name,
|
|
6
|
-
count: category.count,
|
|
7
|
-
has_child: category.has_child || false,
|
|
8
|
-
};
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function transformCategoryList(
|
|
12
|
-
categoryList: components["schemas"]["CategoryList"],
|
|
13
|
-
) {
|
|
14
|
-
return {
|
|
15
|
-
current_category: categoryList.current_category,
|
|
16
|
-
categories: categoryList.categories?.map(transformCategory) || [],
|
|
17
|
-
parent_categories: categoryList.parent_categories?.map(
|
|
18
|
-
(parentCategory) => ({
|
|
19
|
-
current_category: parentCategory.current_category,
|
|
20
|
-
categories: parentCategory.categories?.map(transformCategory) || [],
|
|
21
|
-
}),
|
|
22
|
-
),
|
|
23
|
-
readme: categoryList.readme,
|
|
24
|
-
no_category: categoryList.no_category
|
|
25
|
-
? transformCategory(categoryList.no_category)
|
|
26
|
-
: undefined,
|
|
27
|
-
descendant_posts: categoryList.descendant_posts,
|
|
28
|
-
posts: categoryList.posts,
|
|
29
|
-
total_count: categoryList.total_count,
|
|
30
|
-
per_page: categoryList.per_page,
|
|
31
|
-
page: categoryList.page,
|
|
32
|
-
prev_page: categoryList.prev_page,
|
|
33
|
-
next_page: categoryList.next_page,
|
|
34
|
-
max_per_page: categoryList.max_per_page,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
import type { components } from "../generated/api-types.js";
|
|
2
|
-
|
|
3
|
-
export interface CommentTransformOptions {
|
|
4
|
-
truncateBody?: number;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function transformComment(
|
|
8
|
-
comment: components["schemas"]["Comment"],
|
|
9
|
-
options: CommentTransformOptions = {},
|
|
10
|
-
) {
|
|
11
|
-
const { truncateBody } = options;
|
|
12
|
-
|
|
13
|
-
let bodyMd = comment.body_md;
|
|
14
|
-
if (truncateBody && bodyMd && bodyMd.length > truncateBody) {
|
|
15
|
-
bodyMd = `${bodyMd.slice(0, truncateBody)}...`;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return {
|
|
19
|
-
id: comment.id,
|
|
20
|
-
post_number: comment.post_number,
|
|
21
|
-
url: comment.url,
|
|
22
|
-
body_md: bodyMd,
|
|
23
|
-
created_at: comment.created_at,
|
|
24
|
-
updated_at: comment.updated_at,
|
|
25
|
-
created_by: comment.created_by,
|
|
26
|
-
stats: {
|
|
27
|
-
stargazers_count: comment.stargazers_count,
|
|
28
|
-
star: comment.star,
|
|
29
|
-
},
|
|
30
|
-
stargazers: comment.stargazers,
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export type TransformedComment = ReturnType<typeof transformComment>;
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
export interface PostNameParts {
|
|
2
|
-
name?: string;
|
|
3
|
-
category?: string;
|
|
4
|
-
}
|
|
5
|
-
|
|
6
|
-
export function normalizePostName(
|
|
7
|
-
name?: string,
|
|
8
|
-
category?: string,
|
|
9
|
-
): PostNameParts {
|
|
10
|
-
if (!name) {
|
|
11
|
-
return { name, category };
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
if (category !== undefined) {
|
|
15
|
-
return { name, category };
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
if (name.includes("/")) {
|
|
19
|
-
const parts = name.split("/");
|
|
20
|
-
const extractedName = parts.pop();
|
|
21
|
-
const extractedCategory = parts.join("/");
|
|
22
|
-
|
|
23
|
-
return {
|
|
24
|
-
name: extractedName || undefined,
|
|
25
|
-
category: extractedCategory,
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return { name, category };
|
|
30
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import type { components } from "../generated/api-types.js";
|
|
2
|
-
|
|
3
|
-
export interface PostTransformOptions {
|
|
4
|
-
truncateBody?: number;
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export function transformPost(
|
|
8
|
-
post: components["schemas"]["Post"],
|
|
9
|
-
options: PostTransformOptions = {},
|
|
10
|
-
) {
|
|
11
|
-
const { truncateBody } = options;
|
|
12
|
-
|
|
13
|
-
let bodyMd = post.body_md;
|
|
14
|
-
if (truncateBody && bodyMd && bodyMd.length > truncateBody) {
|
|
15
|
-
bodyMd = `${bodyMd.slice(0, truncateBody)}...`;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
return {
|
|
19
|
-
url: post.url,
|
|
20
|
-
wip: post.wip ? "WIP" : ("Shipped" as const),
|
|
21
|
-
kind: post.kind,
|
|
22
|
-
category_and_title_and_tags: post.full_name,
|
|
23
|
-
body_md: bodyMd,
|
|
24
|
-
created_at: post.created_at,
|
|
25
|
-
updated_at: post.updated_at,
|
|
26
|
-
created_by: post.created_by,
|
|
27
|
-
updated_by: post.updated_by,
|
|
28
|
-
stats: {
|
|
29
|
-
tasks_count: post.tasks_count,
|
|
30
|
-
done_tasks_count: post.done_tasks_count,
|
|
31
|
-
comments_count: post.comments_count,
|
|
32
|
-
stargazers_count: post.stargazers_count,
|
|
33
|
-
watchers_count: post.watchers_count,
|
|
34
|
-
},
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export type TransformedPost = ReturnType<typeof transformPost>;
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
export function normalizeSearchQuery(query: string): string {
|
|
2
|
-
let normalized = query;
|
|
3
|
-
|
|
4
|
-
// Convert wildcard "*" to empty string (for "all posts" queries)
|
|
5
|
-
if (normalized === "*") {
|
|
6
|
-
normalized = "";
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
// Convert common date syntax patterns from other services to esa format
|
|
10
|
-
// GitHub/Gmail style: after:YYYY-MM-DD -> created:>YYYY-MM-DD
|
|
11
|
-
normalized = normalized.replace(
|
|
12
|
-
/\bafter:(\d{4}-\d{2}-\d{2})\b/gi,
|
|
13
|
-
"created:>$1",
|
|
14
|
-
);
|
|
15
|
-
|
|
16
|
-
// GitHub/Gmail style: before:YYYY-MM-DD -> created:<YYYY-MM-DD
|
|
17
|
-
normalized = normalized.replace(
|
|
18
|
-
/\bbefore:(\d{4}-\d{2}-\d{2})\b/gi,
|
|
19
|
-
"created:<$1",
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
// Alternative patterns that might be used
|
|
23
|
-
// since:YYYY-MM-DD -> created:>YYYY-MM-DD
|
|
24
|
-
normalized = normalized.replace(
|
|
25
|
-
/\bsince:(\d{4}-\d{2}-\d{2})\b/gi,
|
|
26
|
-
"created:>$1",
|
|
27
|
-
);
|
|
28
|
-
|
|
29
|
-
// until:YYYY-MM-DD -> created:<YYYY-MM-DD
|
|
30
|
-
normalized = normalized.replace(
|
|
31
|
-
/\buntil:(\d{4}-\d{2}-\d{2})\b/gi,
|
|
32
|
-
"created:<$1",
|
|
33
|
-
);
|
|
34
|
-
|
|
35
|
-
return normalized;
|
|
36
|
-
}
|
package/tsconfig.build.json
DELETED
package/tsconfig.json
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2022",
|
|
4
|
-
"module": "NodeNext",
|
|
5
|
-
"lib": ["ES2022"],
|
|
6
|
-
"moduleResolution": "nodenext",
|
|
7
|
-
"outDir": "./bin",
|
|
8
|
-
"rootDir": "./src",
|
|
9
|
-
"strict": true,
|
|
10
|
-
"esModuleInterop": true,
|
|
11
|
-
"skipLibCheck": true,
|
|
12
|
-
"forceConsistentCasingInFileNames": true,
|
|
13
|
-
"resolveJsonModule": true,
|
|
14
|
-
"declaration": true,
|
|
15
|
-
"declarationMap": true,
|
|
16
|
-
"sourceMap": true,
|
|
17
|
-
"removeComments": true,
|
|
18
|
-
"noImplicitAny": true,
|
|
19
|
-
"strictNullChecks": true,
|
|
20
|
-
"strictFunctionTypes": true,
|
|
21
|
-
"noImplicitThis": true,
|
|
22
|
-
"noUnusedLocals": true,
|
|
23
|
-
"noUnusedParameters": true,
|
|
24
|
-
"noImplicitReturns": true,
|
|
25
|
-
"noFallthroughCasesInSwitch": true,
|
|
26
|
-
"allowSyntheticDefaultImports": true,
|
|
27
|
-
"isolatedModules": true
|
|
28
|
-
},
|
|
29
|
-
"include": ["src/**/*"]
|
|
30
|
-
}
|
package/tsdown.config.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "tsdown";
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
entry: "src/index.ts",
|
|
5
|
-
outDir: "bin",
|
|
6
|
-
format: "es",
|
|
7
|
-
platform: "node",
|
|
8
|
-
target: "node20",
|
|
9
|
-
clean: true,
|
|
10
|
-
dts: false,
|
|
11
|
-
tsconfig: "tsconfig.build.json",
|
|
12
|
-
minify: true,
|
|
13
|
-
});
|
package/vitest.config.ts
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { defineConfig } from "vitest/config";
|
|
2
|
-
|
|
3
|
-
export default defineConfig({
|
|
4
|
-
test: {
|
|
5
|
-
globals: false,
|
|
6
|
-
environment: "node",
|
|
7
|
-
include: ["**/__tests__/**/*.{test,spec}.{js,ts,jsx,tsx}"],
|
|
8
|
-
coverage: {
|
|
9
|
-
provider: "v8",
|
|
10
|
-
reporter: ["text", "json", "html"],
|
|
11
|
-
exclude: [
|
|
12
|
-
"node_modules/",
|
|
13
|
-
"bin/",
|
|
14
|
-
"**/*.config.ts",
|
|
15
|
-
"**/*.config.js",
|
|
16
|
-
"**/context/**",
|
|
17
|
-
"**/generated/**",
|
|
18
|
-
],
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
resolve: {
|
|
22
|
-
extensions: [".ts", ".js"],
|
|
23
|
-
},
|
|
24
|
-
});
|