Skip to content

Commit 5ab09b9

Browse files
committed
**chore: update Jira server integration and clean up code**
**detailed description** - **Update .gitignore**: - Add `demo-jira.js` and `olds` to ignore unnecessary files. - **Refactor README.md**: - Remove TypeScript SDK mention as it is no longer required. - Update command in JSON example from `npx` to `node`. - Change file path from `.ts` to `.js` for the server generator. - **Modify creator-server.js**: - Clean up commented-out code to improve readability. - Remove unused resource template and other unnecessary comments. - Ensure the server uses the correct API and adheres to the latest standards. - **Remove deprecated jira-server.js**: - Delete the old server code that is no longer in use to avoid confusion. - **Enhance error handling**: - Improve error messages and handling mechanisms throughout the server code. - **General code cleanup**: - Clean up formatting issues and ensure consistent code style. - Organize functions and improve readability for better maintainability.
1 parent 701ecdd commit 5ab09b9

File tree

6 files changed

+785
-2391
lines changed

6 files changed

+785
-2391
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,5 @@ Thumbs.db
4747
READMEFORME.md
4848

4949
google_auth.json
50+
demo-jira.js
51+
olds

README.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ The MCP Server Creator helps you create, manage, and register custom MCP servers
1717

1818
- [Node.js](https://nodejs.org/) (v16 or later)
1919
- [Claude Desktop](https://claude.ai/desktop) installed
20-
- TypeScript SDK for Model Context Protocol
2120

2221
### Installation
2322

@@ -45,10 +44,9 @@ The MCP Server Creator helps you create, manage, and register custom MCP servers
4544
{
4645
"mcpServers": {
4746
"serverGenerator": {
48-
"command": "npx",
47+
"command": "node",
4948
"args": [
50-
"tsx",
51-
"/Users/username/Documents/GitHub/mcprotocol/creator-server.ts"
49+
"/Users/username/Documents/GitHub/mcprotocol/creator-server.js"
5250
]
5351
}
5452
}

creator-server.js

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// creator-server.ts
21
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
32
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
43
import { TEMPLATE_MCP_SERVER } from "./template.js";
@@ -34,15 +33,6 @@ const server = new McpServer({
3433

3534
const execAsync = promisify(exec);
3635

37-
server.resource("template", "mcp-template://default", async (uri) => ({
38-
contents: [
39-
{
40-
uri: uri.href,
41-
text: TEMPLATE_MCP_SERVER,
42-
},
43-
],
44-
}));
45-
4636
server.prompt("system prompt", {}, () => ({
4737
messages: [
4838
{
@@ -286,9 +276,6 @@ server.tool(
286276
};
287277
}
288278

289-
// This is the critical step: We write the file to disk FIRST, before doing anything else.
290-
// This ensures that even if the context window limit is reached during the conversation,
291-
// the file has already been saved and can be accessed in a new conversation.
292279
console.log(
293280
`[createMcpServer] Writing server "${serverName}" to file: ${filePath}`
294281
);
@@ -311,7 +298,6 @@ server.tool(
311298
}
312299
}
313300

314-
// Add line numbers to the code for better reference
315301
const lines = serverCode.split("\n");
316302
const numberedLines = lines.map(
317303
(line, index) => `${(index + 1).toString().padStart(4, " ")}| ${line}`
@@ -569,15 +555,13 @@ server.tool(
569555
};
570556
}
571557

572-
// For full update, just replace the entire file
573558
if (updateType === "full") {
574559
await fs.writeFile(filePath, code);
575560

576561
const updateDetails = description
577562
? `\nUpdate details: ${description}`
578563
: "";
579564

580-
// Add line numbers to the updated content
581565
const updatedLines = code.split("\n");
582566
const numberedLines = updatedLines.map(
583567
(line, index) => `${(index + 1).toString().padStart(4, " ")}| ${line}`
@@ -594,11 +578,9 @@ server.tool(
594578
};
595579
}
596580

597-
// For section or add updates, read the current file
598581
const serverCode = await fs.readFile(filePath, "utf-8");
599582
const lines = serverCode.split("\n");
600583

601-
// Handle section update
602584
if (updateType === "section") {
603585
if (!startLine || !endLine) {
604586
return {
@@ -612,7 +594,6 @@ server.tool(
612594
};
613595
}
614596

615-
// Validate line numbers
616597
if (startLine > lines.length || endLine > lines.length) {
617598
return {
618599
content: [
@@ -668,7 +649,6 @@ server.tool(
668649
};
669650
}
670651

671-
// Handle add update
672652
if (updateType === "add") {
673653
if (!insertAfterLine) {
674654
return {
@@ -682,7 +662,6 @@ server.tool(
682662
};
683663
}
684664

685-
// Validate line number
686665
if (insertAfterLine > lines.length) {
687666
return {
688667
content: [
@@ -695,23 +674,18 @@ server.tool(
695674
};
696675
}
697676

698-
// Split the new code into lines
699677
const newLines = code.split("\n");
700678

701-
// Insert the new code after the specified line
702679
const updatedLines = [
703680
...lines.slice(0, insertAfterLine),
704681
...newLines,
705682
...lines.slice(insertAfterLine),
706683
];
707684

708-
// Join the lines back together
709685
const updatedCode = updatedLines.join("\n");
710686

711-
// Write the updated code back to the file
712687
await fs.writeFile(filePath, updatedCode);
713688

714-
// Add line numbers to the updated content
715689
const numberedLines = updatedLines.map(
716690
(line, index) => `${(index + 1).toString().padStart(4, " ")}| ${line}`
717691
);
@@ -731,7 +705,6 @@ server.tool(
731705
};
732706
}
733707

734-
// This should never happen due to zod validation, but just in case
735708
return {
736709
content: [
737710
{
@@ -790,7 +763,6 @@ server.tool(
790763

791764
const serverCode = await fs.readFile(filePath, "utf-8");
792765

793-
// Add line numbers to the code for better reference
794766
const lines = serverCode.split("\n");
795767
const numberedLines = lines.map(
796768
(line, index) => `${(index + 1).toString().padStart(4, " ")}| ${line}`
@@ -845,11 +817,9 @@ server.tool(
845817
};
846818
}
847819

848-
// Use the project directory where the server.js file is located
849820
const projectDir = CURRENT_DIR;
850821
log(`Project directory: ${projectDir}`);
851822

852-
// Check if package.json exists in the project directory, and create one if it doesn't
853823
const packageJsonPath = path.join(projectDir, "package.json");
854824
let packageJson;
855825

@@ -867,24 +837,20 @@ server.tool(
867837
devDependencies: {},
868838
};
869839

870-
// Write the initial package.json
871840
await fs.writeFile(
872841
packageJsonPath,
873842
JSON.stringify(packageJson, null, 2)
874843
);
875844
}
876845

877-
// Ensure dependencies object exists
878846
if (!packageJson.dependencies) {
879847
packageJson.dependencies = {};
880848
}
881849

882-
// Ensure devDependencies object exists
883850
if (!packageJson.devDependencies) {
884851
packageJson.devDependencies = {};
885852
}
886853

887-
// Filter out already installed dependencies
888854
const missingDependencies = dependencies.filter(
889855
(dep) => !packageJson.dependencies[dep.split("@")[0]]
890856
);
@@ -900,20 +866,17 @@ server.tool(
900866
};
901867
}
902868

903-
// Prepare dependency strings
904869
const dependencyString = missingDependencies.join(" ");
905870

906871
log(
907872
`Installing dependencies in directory ${projectDir}: ${dependencyString}`
908873
);
909874

910875
try {
911-
// Change to the project directory before running npm
912876
const originalDir = process.cwd();
913877
process.chdir(projectDir);
914878
log(`Changed working directory to: ${projectDir}`);
915879

916-
// Install regular dependencies
917880
const { stdout, stderr } = await execAsync(
918881
`npm install ${dependencyString} --save`
919882
);
@@ -924,7 +887,6 @@ server.tool(
924887

925888
log(`Regular dependencies installation output: ${stdout}`);
926889

927-
// Try to install type definitions as dev dependencies
928890
log(`Checking for TypeScript type definitions...`);
929891
let installedTypes = [];
930892

@@ -933,13 +895,11 @@ server.tool(
933895
const typePackage = `@types/${basePackage}`;
934896

935897
try {
936-
// Check if type package exists
937898
log(`Checking if ${typePackage} exists...`);
938899
const { stdout: typeVersionOutput } = await execAsync(
939900
`npm view ${typePackage} version`
940901
);
941902

942-
// If we reach here, the package exists, so install it
943903
if (typeVersionOutput && typeVersionOutput.trim()) {
944904
log(`Installing ${typePackage} as dev dependency...`);
945905
await execAsync(`npm install ${typePackage} --save-dev`);
@@ -950,18 +910,15 @@ server.tool(
950910
}
951911
}
952912

953-
// Return to original directory
954913
process.chdir(originalDir);
955914
log(`Returned to original directory: ${originalDir}`);
956915

957-
// Read the updated package.json to confirm what was installed
958916
const updatedPackageJsonContent = await fs.readFile(
959917
packageJsonPath,
960918
"utf-8"
961919
);
962920
const updatedPackageJson = JSON.parse(updatedPackageJsonContent);
963921

964-
// Get the list of successfully installed dependencies
965922
const installedDeps = Object.keys(
966923
updatedPackageJson.dependencies || {}
967924
).filter((key) =>
@@ -989,7 +946,6 @@ server.tool(
989946
],
990947
};
991948
} catch (installError) {
992-
// Ensure we change back to original directory if there was an error
993949
try {
994950
const currentDir = process.cwd();
995951
if (currentDir !== originalDir) {
@@ -1033,7 +989,6 @@ server.tool(
1033989
}
1034990
);
1035991

1036-
// Helper function to recursively copy directories
1037992
async function copyRecursive(src, dest) {
1038993
const stats = await fs.stat(src);
1039994

@@ -1051,28 +1006,24 @@ async function copyRecursive(src, dest) {
10511006
}
10521007
}
10531008

1054-
// Tool to analyze server dependencies
10551009
server.tool(
10561010
"analyzeServerDependencies",
10571011
{
10581012
serverName: z.string().min(1),
10591013
},
10601014
async ({ serverName }) => {
10611015
try {
1062-
// Strip .js extension if it's already included in the serverName
10631016
const nameWithoutExtension = serverName.endsWith(".js")
10641017
? serverName.slice(0, -3)
10651018
: serverName;
10661019

1067-
// Sanitize the server name for use as a filename
10681020
const sanitizedName = nameWithoutExtension.replace(
10691021
/[^a-zA-Z0-9-_]/g,
10701022
"_"
10711023
);
10721024
const filename = `${sanitizedName}.js`;
10731025
const filePath = path.join(SERVERS_DIR, filename);
10741026

1075-
// Check if the server exists
10761027
const exists = await fileExists(filePath);
10771028
if (!exists) {
10781029
return {
@@ -1086,10 +1037,8 @@ server.tool(
10861037
};
10871038
}
10881039

1089-
// Read the server file content
10901040
const serverCode = await fs.readFile(filePath, "utf-8");
10911041

1092-
// Simple regex to find import statements
10931042
const importRegex = /import\s+(?:[\w\s{},*]+from\s+)?['"]([^'"]+)['"]/g;
10941043
const imports = [];
10951044
let match;
@@ -1098,7 +1047,6 @@ server.tool(
10981047
imports.push(match[1]);
10991048
}
11001049

1101-
// Filter out built-in Node.js modules and SDK imports
11021050
const nodeBuiltins = [
11031051
"fs",
11041052
"path",
@@ -1112,7 +1060,6 @@ server.tool(
11121060
const sdkImports = ["@modelcontextprotocol/sdk"];
11131061

11141062
const externalDependencies = imports.filter((imp) => {
1115-
// Check if it's not a relative import, built-in module, or SDK import
11161063
const isRelative =
11171064
imp.startsWith("./") || imp.startsWith("../") || imp.startsWith("/");
11181065
const isBuiltin = nodeBuiltins.some(
@@ -1125,18 +1072,15 @@ server.tool(
11251072
return !isRelative && !isBuiltin && !isSdk;
11261073
});
11271074

1128-
// Extract package names (remove trailing paths)
11291075
const packageNames = externalDependencies.map((dep) => {
11301076
const parts = dep.split("/");
11311077
if (dep.startsWith("@")) {
1132-
// Handle scoped packages like @org/package
11331078
return `${parts[0]}/${parts[1]}`;
11341079
} else {
11351080
return parts[0];
11361081
}
11371082
});
11381083

1139-
// Remove duplicates
11401084
const uniquePackages = [...new Set(packageNames)];
11411085

11421086
return {
@@ -1200,13 +1144,10 @@ server.tool(
12001144
};
12011145
}
12021146

1203-
// Run the server using Node.js and capture stdout/stderr
12041147
const { spawn } = await import("child_process");
12051148

1206-
// Run without passing environment variables
12071149
const nodeProcess = spawn("node", [filePath], {
12081150
stdio: ["pipe", "pipe", "pipe"],
1209-
// Not passing environment variables
12101151
});
12111152

12121153
let stdout = "";
@@ -1222,12 +1163,10 @@ server.tool(
12221163
hasError = true;
12231164
});
12241165

1225-
// Set a timeout to kill the process after the specified time
12261166
const timeoutId = setTimeout(() => {
12271167
nodeProcess.kill();
12281168
}, timeout);
12291169

1230-
// Wait for the process to exit or timeout
12311170
await new Promise((resolve) => {
12321171
nodeProcess.on("exit", (code) => {
12331172
clearTimeout(timeoutId);
@@ -1238,7 +1177,6 @@ server.tool(
12381177
});
12391178
});
12401179

1241-
// Prepare the response
12421180
let resultText = "";
12431181
if (hasError) {
12441182
resultText = `Server "${nameWithoutExtension}" encountered errors during execution:\n\n`;
@@ -1308,7 +1246,6 @@ async function registerServerWithClaude(serverName, serverPath) {
13081246
config.mcpServers = {};
13091247
}
13101248

1311-
// Create server entry with command, args, and empty env object for future environment variables
13121249
config.mcpServers[serverName] = {
13131250
command: "node",
13141251
args: [serverPath],

0 commit comments

Comments
 (0)