From 288663f8505b6cbf478b8b0e8af7ca3de09629b6 Mon Sep 17 00:00:00 2001 From: Ali Ibrahim Jr <48456829+IBJunior@users.noreply.github.com> Date: Sat, 21 Feb 2026 02:38:26 +0100 Subject: [PATCH 1/3] fix: add allowed hosts configuration to SDK templates --- CLAUDE.md | 2 +- src/templates/sdk/stateful/index.ts | 9 +++++++-- src/templates/sdk/stateful/readme.ts | 2 +- src/templates/sdk/stateful/templates.test.ts | 10 ++++++++-- src/templates/sdk/stateless/index.ts | 6 +++++- src/templates/sdk/stateless/readme.ts | 2 +- src/templates/sdk/stateless/templates.test.ts | 10 ++++++++-- 7 files changed, 31 insertions(+), 10 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index d147b91..c93fa17 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -137,7 +137,7 @@ Features: - Example tool (`start-notification-stream`) - Example resource (`greeting-resource`) - TypeScript configuration -- Environment variable support for PORT +- Environment variable support for PORT and ALLOWED_HOSTS #### sdk/stateful diff --git a/src/templates/sdk/stateful/index.ts b/src/templates/sdk/stateful/index.ts index 94ddee3..51bc379 100644 --- a/src/templates/sdk/stateful/index.ts +++ b/src/templates/sdk/stateful/index.ts @@ -18,14 +18,19 @@ import { getOAuthMetadataUrl, validateOAuthConfig, } from './auth.js';` - : `import { type Request, type Response } from 'express'; + : `import 'dotenv/config'; +import { type Request, type Response } from 'express'; import { randomUUID } from 'node:crypto'; import { createMcpExpressApp } from '@modelcontextprotocol/sdk/server/express.js'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js'; import { getServer } from './server.js';`; - const appSetup = `const app = createMcpExpressApp(); + const appSetup = `const allowedHosts = process.env.ALLOWED_HOSTS?.split(',') ?? []; + +const app = createMcpExpressApp({ + allowedHosts: ['localhost', '127.0.0.1', '[::1]', ...allowedHosts], +}); // Health check endpoint for container orchestration app.get('/health', (_, res) => res.sendStatus(200));`; diff --git a/src/templates/sdk/stateful/readme.ts b/src/templates/sdk/stateful/readme.ts index aa0fcfd..cf8a409 100644 --- a/src/templates/sdk/stateful/readme.ts +++ b/src/templates/sdk/stateful/readme.ts @@ -143,7 +143,7 @@ ${commands.build} ${commands.start} \`\`\` -The server will start on port 3000 by default. You can change this by setting the \`PORT\` environment variable. +The server will start on port 3000 by default. You can change this by setting the \`PORT\` environment variable. To allow additional hosts (e.g. when deploying behind a reverse proxy), set \`ALLOWED_HOSTS\` as a comma-separated list. ## Testing with MCP Inspector diff --git a/src/templates/sdk/stateful/templates.test.ts b/src/templates/sdk/stateful/templates.test.ts index 68eab54..ca5548b 100644 --- a/src/templates/sdk/stateful/templates.test.ts +++ b/src/templates/sdk/stateful/templates.test.ts @@ -44,7 +44,7 @@ describe('sdk/stateful templates', () => { it('should use createMcpExpressApp', () => { const template = getIndexTemplate(); expect(template).toContain('createMcpExpressApp'); - expect(template).toContain('const app = createMcpExpressApp()'); + expect(template).toContain('const app = createMcpExpressApp({'); }); it('should configure /mcp endpoint', () => { @@ -56,7 +56,13 @@ describe('sdk/stateful templates', () => { it('should use PORT from environment variable', () => { const template = getIndexTemplate(); - expect(template).toContain('process.env.PORT || 3000'); + expect(template).toContain('process.env.PORT'); + }); + + it('should pass allowedHosts to createMcpExpressApp', () => { + const template = getIndexTemplate(); + expect(template).toContain('allowedHosts'); + expect(template).toContain("ALLOWED_HOSTS?.split(',')"); }); // Stateful-specific tests diff --git a/src/templates/sdk/stateless/index.ts b/src/templates/sdk/stateless/index.ts index b470567..63f639e 100644 --- a/src/templates/sdk/stateless/index.ts +++ b/src/templates/sdk/stateless/index.ts @@ -10,7 +10,11 @@ import { createMcpExpressApp } from '@modelcontextprotocol/sdk/server/express.js import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import { getServer } from './server.js'; -const app = createMcpExpressApp(); +const allowedHosts = process.env.ALLOWED_HOSTS?.split(',') ?? []; + +const app = createMcpExpressApp({ + allowedHosts: ['localhost', '127.0.0.1', '[::1]', ...allowedHosts], +}); // Health check endpoint for container orchestration app.get('/health', (_, res) => res.sendStatus(200)); diff --git a/src/templates/sdk/stateless/readme.ts b/src/templates/sdk/stateless/readme.ts index cd711fd..0aa3244 100644 --- a/src/templates/sdk/stateless/readme.ts +++ b/src/templates/sdk/stateless/readme.ts @@ -49,7 +49,7 @@ ${commands.build} ${commands.start} \`\`\` -The server will start on port 3000 by default. You can change this by setting the \`PORT\` environment variable. +The server will start on port 3000 by default. You can change this by setting the \`PORT\` environment variable. To allow additional hosts (e.g. when deploying behind a reverse proxy), set \`ALLOWED_HOSTS\` as a comma-separated list. ## Testing with MCP Inspector diff --git a/src/templates/sdk/stateless/templates.test.ts b/src/templates/sdk/stateless/templates.test.ts index dc0bc6a..d353a7b 100644 --- a/src/templates/sdk/stateless/templates.test.ts +++ b/src/templates/sdk/stateless/templates.test.ts @@ -44,7 +44,7 @@ describe('sdk/stateless templates', () => { it('should use createMcpExpressApp', () => { const template = getIndexTemplate(); expect(template).toContain('createMcpExpressApp'); - expect(template).toContain('const app = createMcpExpressApp()'); + expect(template).toContain('const app = createMcpExpressApp({'); }); it('should configure /mcp endpoint', () => { @@ -56,7 +56,13 @@ describe('sdk/stateless templates', () => { it('should use PORT from environment variable', () => { const template = getIndexTemplate(); - expect(template).toContain('process.env.PORT || 3000'); + expect(template).toContain('process.env.PORT'); + }); + + it('should pass allowedHosts to createMcpExpressApp', () => { + const template = getIndexTemplate(); + expect(template).toContain('allowedHosts'); + expect(template).toContain("ALLOWED_HOSTS?.split(',')"); }); // Stateless-specific tests From d12161e3cacd1de1235e3863615c0c91534823d5 Mon Sep 17 00:00:00 2001 From: Ali Ibrahim Jr <48456829+IBJunior@users.noreply.github.com> Date: Sat, 21 Feb 2026 02:46:27 +0100 Subject: [PATCH 2/3] update .env.example and bump version to 0.5.3 --- package.json | 2 +- src/templates/common/env.example.ts | 10 +++++++++- src/templates/common/templates.test.ts | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index fe23bda..60a0d60 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@agentailor/create-mcp-server", - "version": "0.5.2", + "version": "0.5.3", "description": "Create a new MCP (Model Context Protocol) server project", "type": "module", "bin": { diff --git a/src/templates/common/env.example.ts b/src/templates/common/env.example.ts index 166c64d..ab092a5 100644 --- a/src/templates/common/env.example.ts +++ b/src/templates/common/env.example.ts @@ -2,6 +2,14 @@ import type { CommonTemplateOptions } from './types.js'; export function getEnvExampleTemplate(options?: CommonTemplateOptions): string { const withOAuth = options?.withOAuth ?? false; + const isSdk = options?.framework === 'sdk' || !options?.framework; + + const allowedHostsVar = isSdk + ? ` +# Comma-separated list of additional allowed hosts (for deployment behind reverse proxies) +# ALLOWED_HOSTS=my-server.example.com,my-server.us-central1.run.app +` + : ''; const oauthVars = withOAuth ? ` @@ -19,5 +27,5 @@ OAUTH_AUDIENCE=https://your-mcp-server.com : ''; return `PORT=3000 -${oauthVars}`; +${allowedHostsVar}${oauthVars}`; } diff --git a/src/templates/common/templates.test.ts b/src/templates/common/templates.test.ts index 0fd9d8c..54c5733 100644 --- a/src/templates/common/templates.test.ts +++ b/src/templates/common/templates.test.ts @@ -105,5 +105,20 @@ describe('common templates', () => { const template = getEnvExampleTemplate(); expect(template).toContain('PORT='); }); + + it('should include ALLOWED_HOSTS hint for SDK framework', () => { + const template = getEnvExampleTemplate({ framework: 'sdk' }); + expect(template).toContain('ALLOWED_HOSTS'); + }); + + it('should include ALLOWED_HOSTS hint by default (no framework specified)', () => { + const template = getEnvExampleTemplate(); + expect(template).toContain('ALLOWED_HOSTS'); + }); + + it('should NOT include ALLOWED_HOSTS for FastMCP framework', () => { + const template = getEnvExampleTemplate({ framework: 'fastmcp' }); + expect(template).not.toContain('ALLOWED_HOSTS'); + }); }); }); From 1bf0b5696fb08be033d429ea32ed7d68bd881899 Mon Sep 17 00:00:00 2001 From: Ali Ibrahim Jr <48456829+IBJunior@users.noreply.github.com> Date: Sat, 21 Feb 2026 02:48:39 +0100 Subject: [PATCH 3/3] update package-lock.json --- package-lock.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index a27e51c..1d152f8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@agentailor/create-mcp-server", - "version": "0.5.2", + "version": "0.5.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@agentailor/create-mcp-server", - "version": "0.5.2", + "version": "0.5.3", "license": "MIT", "dependencies": { "commander": "^14.0.3",