Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@agentailor/create-mcp-server",
"version": "0.6.0",
"version": "0.6.1",
"description": "Create a new MCP (Model Context Protocol) server project",
"type": "module",
"bin": {
Expand All @@ -17,7 +17,9 @@
"lint:fix": "eslint src/ --fix",
"format": "prettier --write src/",
"format:check": "prettier --check src/",
"prepublishOnly": "npm run build"
"prepublishOnly": "npm run build",
"update-template-deps": "node scripts/update-template-deps.mjs",
"update-template-deps:dry": "node scripts/update-template-deps.mjs --dry-run"
},
"keywords": [
"mcp",
Expand Down
116 changes: 116 additions & 0 deletions scripts/update-template-deps.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
#!/usr/bin/env node
/**
* Fetches the latest versions of all template dependencies from npm and
* updates the hardcoded version strings in src/templates/common/package.json.ts.
*
* Usage via npm scripts:
* npm run update-template-deps # update in place
* npm run update-template-deps:dry # print changes only, no
* Usage via direct node command:
* node scripts/update-template-deps.mjs # update in place
* node scripts/update-template-deps.mjs --dry-run # print changes only
*/

import { execSync } from 'child_process';
import { readFileSync, writeFileSync } from 'fs';
import { resolve, dirname } from 'path';
import { fileURLToPath } from 'url';

const __dirname = dirname(fileURLToPath(import.meta.url));
const TEMPLATE_FILE = resolve(__dirname, '../src/templates/common/package.json.ts');
const DRY_RUN = process.argv.includes('--dry-run');

const TEMPLATE_PACKAGES = [
'@modelcontextprotocol/sdk',
'@modelcontextprotocol/inspector',
'express',
'fastmcp',
'zod',
'dotenv',
'jose',
'typescript',
'@types/node',
'@types/express',
];

function getLatestVersion(pkg) {
try {
return execSync(`npm view ${pkg} version`, { encoding: 'utf8' }).trim();
} catch (err) {
console.error(` Failed to fetch version for ${pkg}: ${err.message}`);
return null;
}
}

// Escapes special regex characters in a package name (e.g. @, /)
function escapeRegex(str) {
return str.replace(/[.*+?^${}()|[\]\\@/]/g, '\\$&');
}

function updateVersionInContent(content, pkg, newVersion) {
// Pattern 1: quoted key — '@scope/pkg': '^1.0.0' or "@scope/pkg": "^1.0.0"
const quotedKey = new RegExp(
`(['"]${escapeRegex(pkg)}['"]\\s*:\\s*['"])\\^[\\d.]+(['"])`,
'g'
);
// Pattern 2: unquoted key — pkg: '^1.0.0'
const unquotedKey = new RegExp(
`(\\b${escapeRegex(pkg)}\\s*:\\s*['"])\\^[\\d.]+(['"])`,
'g'
);
// Pattern 3: bracket assignment — dependencies['pkg'] = '^1.0.0'
const bracketAssign = new RegExp(
`(\\[['"]${escapeRegex(pkg)}['"]\\]\\s*=\\s*['"])\\^[\\d.]+(['"])`,
'g'
);
return content
.replace(quotedKey, `$1^${newVersion}$2`)
.replace(unquotedKey, `$1^${newVersion}$2`)
.replace(bracketAssign, `$1^${newVersion}$2`);
}

async function main() {
console.log(`Fetching latest versions for ${TEMPLATE_PACKAGES.length} packages...\n`);

let content = readFileSync(TEMPLATE_FILE, 'utf8');
let hasChanges = false;

for (const pkg of TEMPLATE_PACKAGES) {
const newVersion = getLatestVersion(pkg);
if (!newVersion) continue;

// Extract current file version BEFORE comparison or mutation.
// Tries quoted key, unquoted key, and bracket assignment forms.
const oldMatch =
content.match(new RegExp(`['"]${escapeRegex(pkg)}['"]\\s*:\\s*['"]\\^([\\d.]+)['"]`)) ||
content.match(new RegExp(`\\b${escapeRegex(pkg)}\\s*:\\s*['"]\\^([\\d.]+)['"]`)) ||
content.match(new RegExp(`\\[['"]${escapeRegex(pkg)}['"]\\]\\s*=\\s*['"]\\^([\\d.]+)['"]`));
const oldVersion = oldMatch ? oldMatch[1] : '?';

const updated = updateVersionInContent(content, pkg, newVersion);

if (updated === content) {
console.log(` ${pkg}: ^${oldVersion} (up to date)`);
} else {
console.log(` ${pkg}: ^${oldVersion} → ^${newVersion}`);
content = updated;
hasChanges = true;
}
}

console.log();

if (!hasChanges) {
console.log('All packages are already at their latest versions. Nothing to update.');
return;
}

if (DRY_RUN) {
console.log('Dry run — no files were written.');
} else {
writeFileSync(TEMPLATE_FILE, content, 'utf8');
console.log(`Updated: src/templates/common/package.json.ts`);
}
}

main();
16 changes: 8 additions & 8 deletions src/templates/common/package.json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ export function getPackageJsonTemplate(
let devDependencies: Record<string, string>;

const commonDevDependencies = {
typescript: '^5.9.3',
'@modelcontextprotocol/inspector': '^0.20.0',
'@types/node': '^25.3.0',
typescript: '^6.0.2',
'@modelcontextprotocol/inspector': '^0.21.1',
'@types/node': '^25.5.2',
};
const zodDependency = { zod: '^4.3.6' };
const dotEnvDependency = { dotenv: '^17.3.1' };
const dotEnvDependency = { dotenv: '^17.4.1' };

if (framework === 'fastmcp') {
// FastMCP dependencies - simpler setup
dependencies = {
fastmcp: '^3.33.0',
fastmcp: '^3.35.0',
...zodDependency,
...dotEnvDependency,
};
Expand All @@ -33,7 +33,7 @@ export function getPackageJsonTemplate(
} else if (transport === 'stdio') {
// Official SDK stdio - no express needed
dependencies = {
'@modelcontextprotocol/sdk': '^1.26.0',
'@modelcontextprotocol/sdk': '^1.29.0',
...zodDependency,
...dotEnvDependency,
};
Expand All @@ -44,14 +44,14 @@ export function getPackageJsonTemplate(
} else {
// Official SDK HTTP dependencies
dependencies = {
'@modelcontextprotocol/sdk': '^1.26.0',
'@modelcontextprotocol/sdk': '^1.29.0',
express: '^5.2.1',
...zodDependency,
...dotEnvDependency,
};

if (withOAuth) {
dependencies['jose'] = '^6.1.3';
dependencies['jose'] = '^6.2.2';
}

devDependencies = {
Expand Down
1 change: 1 addition & 0 deletions src/templates/common/tsconfig.json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export function getTsconfigTemplate(): string {
skipLibCheck: true,
forceConsistentCasingInFileNames: true,
declaration: true,
types: ['node'],
},
include: ['src/**/*'],
exclude: ['node_modules', 'dist'],
Expand Down
Loading