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
2 changes: 1 addition & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
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.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -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": {
Expand Down
10 changes: 9 additions & 1 deletion src/templates/common/env.example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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
? `
Expand All @@ -19,5 +27,5 @@ OAUTH_AUDIENCE=https://your-mcp-server.com
: '';

return `PORT=3000
${oauthVars}`;
${allowedHostsVar}${oauthVars}`;
}
15 changes: 15 additions & 0 deletions src/templates/common/templates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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');
});
});
});
9 changes: 7 additions & 2 deletions src/templates/sdk/stateful/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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));`;
Expand Down
2 changes: 1 addition & 1 deletion src/templates/sdk/stateful/readme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
10 changes: 8 additions & 2 deletions src/templates/sdk/stateful/templates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand All @@ -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
Expand Down
6 changes: 5 additions & 1 deletion src/templates/sdk/stateless/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
2 changes: 1 addition & 1 deletion src/templates/sdk/stateless/readme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
10 changes: 8 additions & 2 deletions src/templates/sdk/stateless/templates.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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', () => {
Expand All @@ -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
Expand Down