Skip to content

Commit 3af7eda

Browse files
authored
Repo checklist (#34)
* feat: opensource checklist * ci: add license checks * Check node version * ci: try fixing * ci: fix pipeline * chore: include notice in distribution
1 parent 6cd53d6 commit 3af7eda

File tree

8 files changed

+7157
-10
lines changed

8 files changed

+7157
-10
lines changed

.buildkite/default-pipeline.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
---
22
# $yaml-language-server: $schema=https://raw.githubusercontent.com/buildkite/pipeline-schema/main/schema.json
33
steps:
4+
- label: "Check License"
5+
command: "npm install && npm run license-checker && npm run license-header"
6+
47
- label: "Build"
58
command: "npm install && npm run build"

NOTICE.txt

Lines changed: 6680 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,10 @@ POST /_security/api_key
183183
}
184184
```
185185

186+
## License
187+
188+
This project is licensed under the Apache License 2.0.
189+
186190
## Troubleshooting
187191

188192
* Ensure your MCP configuration is correct.

index.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
#!/usr/bin/env node
22

3+
/*
4+
* Copyright Elasticsearch B.V. and contributors
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
38
import { z } from "zod";
49
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
510
import { Client, estypes, ClientOptions } from "@elastic/elasticsearch";
@@ -52,7 +57,7 @@ const ConfigSchema = z
5257
if (data.apiKey) {
5358
return true;
5459
}
55-
60+
5661
// No auth is also valid (for local development)
5762
return true;
5863
},
@@ -360,7 +365,9 @@ export async function createElasticsearchMcpServer(
360365

361366
const metadataFragment = {
362367
type: "text" as const,
363-
text: `Found ${shardsInfo.length} shards${index ? ` for index ${index}` : ""}`,
368+
text: `Found ${shardsInfo.length} shards${
369+
index ? ` for index ${index}` : ""
370+
}`,
364371
};
365372

366373
return {

package.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,32 @@
2020
"mcp-server"
2121
],
2222
"files": [
23-
"dist"
23+
"dist",
24+
"NOTICE.txt",
25+
"LICENSE",
26+
"README.md"
2427
],
2528
"scripts": {
2629
"build": "tsc && shx chmod +x dist/*.js",
2730
"prepare": "npm run build",
2831
"watch": "tsc --watch",
2932
"start": "node dist/index.js",
3033
"inspector": "npx @modelcontextprotocol/inspector node dist/index.js",
31-
"test": "npm run build"
34+
"test": "npm run build",
35+
"license-checker": "license-checker --production --onlyAllow='MIT;Apache-2.0;Apache1.1;ISC;BSD-3-Clause;BSD-2-Clause;0BSD'",
36+
"license-header": "./scripts/check-spdx",
37+
"generate-notice": "node ./scripts/generate-notice.js"
3238
},
3339
"dependencies": {
3440
"@elastic/elasticsearch": "^8.17.1",
3541
"@modelcontextprotocol/sdk": "1.8.0"
3642
},
43+
"engines": {
44+
"node": ">=18"
45+
},
3746
"devDependencies": {
3847
"@types/node": "22.13.15",
48+
"license-checker": "^25.0.1",
3949
"shx": "0.4.0",
4050
"typescript": "5.8.2"
4151
},

scripts/check-spdx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/usr/bin/env bash
2+
3+
# Copyright Elasticsearch B.V. and contributors
4+
# SPDX-License-Identifier: Apache-2.0
5+
6+
the_exit=0
7+
8+
check_file() {
9+
if grep -q "Copyright Elasticsearch B.V. and contributors" "$1" && \
10+
grep -q "SPDX-License-Identifier: Apache-2.0" "$1"; then
11+
echo "Correct: $1"
12+
else
13+
echo "Incorrect: $1"
14+
the_exit=1
15+
fi
16+
}
17+
18+
echo "SPDX license header check"
19+
for file in $(git ls-files | grep -E '\.(ts|js|mjs)$'); do
20+
check_file "$file"
21+
done
22+
23+
exit "$the_exit"

scripts/generate-notice.js

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#!/usr/bin/env node
2+
3+
/*
4+
* Copyright Elasticsearch B.V. and contributors
5+
* SPDX-License-Identifier: Apache-2.0
6+
*/
7+
8+
import { exec } from "child_process";
9+
import fs from "fs/promises";
10+
import path from "path";
11+
import { fileURLToPath } from "url";
12+
13+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
14+
15+
// Execute license-checker command
16+
const generateNotice = () => {
17+
return new Promise((resolve, reject) => {
18+
exec("npx license-checker --json --production", (error, stdout) => {
19+
if (error) {
20+
return reject(error);
21+
}
22+
resolve(JSON.parse(stdout));
23+
});
24+
});
25+
};
26+
27+
async function createNoticeFile() {
28+
// Custom header for notice file
29+
let noticeContent = `Elasticsearch MCP Server
30+
Copyright 2025 Elasticsearch B.V.
31+
32+
The Elasticsearch MCP Server contains the following third-party dependencies:
33+
34+
`;
35+
36+
try {
37+
const licenses = await generateNotice();
38+
39+
for (const [pkgNameVer, info] of Object.entries(licenses)) {
40+
const pkgName =
41+
pkgNameVer.split("@")[0] === ""
42+
? "@" + pkgNameVer.split("@")[1]
43+
: pkgNameVer.split("@")[0];
44+
45+
// Extract version from the pkgNameVer string
46+
let version;
47+
if (pkgNameVer.split("@")[0] === "") {
48+
// Handle scoped packages (@organization/[email protected])
49+
const parts = pkgNameVer.split("@");
50+
if (parts.length >= 3) {
51+
version = parts[2];
52+
}
53+
} else {
54+
// Handle regular packages ([email protected])
55+
const parts = pkgNameVer.split("@");
56+
if (parts.length >= 2) {
57+
version = parts[1];
58+
}
59+
}
60+
61+
// Use extracted version if available, otherwise fall back to info.version
62+
const displayVersion = version || info.version || "";
63+
64+
noticeContent += `\n-------------------------------------------------------------------\n`;
65+
noticeContent += `Package: ${pkgName}\n`;
66+
noticeContent += `Version: ${displayVersion}\n`;
67+
noticeContent += `License: ${info.licenses || "Unknown"}\n`;
68+
69+
if (info.publisher) {
70+
noticeContent += `Author: ${info.publisher}\n`;
71+
}
72+
73+
noticeContent += `\n`;
74+
75+
// Include license text if available
76+
if (info.licenseFile && typeof info.licenseFile === "string") {
77+
try {
78+
const licenseText = await fs.readFile(info.licenseFile, "utf-8");
79+
noticeContent += `${licenseText.trim()}\n`;
80+
} catch (err) {
81+
noticeContent += `License text not available.\n`;
82+
}
83+
} else {
84+
noticeContent += `License text not available.\n`;
85+
}
86+
}
87+
88+
// Write the NOTICE.txt file in the repo root
89+
await fs.writeFile(
90+
path.join(__dirname, "..", "NOTICE.txt"),
91+
noticeContent,
92+
"utf-8"
93+
);
94+
console.log("NOTICE.txt file has been generated successfully.");
95+
} catch (error) {
96+
console.error("Error generating NOTICE.txt:", error);
97+
}
98+
}
99+
100+
createNoticeFile();

0 commit comments

Comments
 (0)