Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
18 changes: 17 additions & 1 deletion src/generator/env-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@
*/
import { OpenAPIV3 } from 'openapi-types';
import { getEnvVarName } from '../utils/security.js';
import { CliOptions } from '../types/index.js';

/**
* Generates the content of .env.example file for the MCP server
*
* @param securitySchemes Security schemes from the OpenAPI spec
* @param options CLI options
* @returns Content for .env.example file
*/
export function generateEnvExample(
securitySchemes?: OpenAPIV3.ComponentsObject['securitySchemes']
securitySchemes?: OpenAPIV3.ComponentsObject['securitySchemes'],
options?: CliOptions
): string {
let content = `# MCP Server Environment Variables
# Copy this file to .env and fill in the values
Expand Down Expand Up @@ -57,6 +60,19 @@ LOG_LEVEL=info
content += `# No API authentication required\n`;
}

// Add MCPcat environment variables if enabled
if (options?.withMcpcat) {
content += `\n# MCPcat -- MCP product analytics and live debugging tools`;
content += `\n# Sign up and get your project ID for free at https://mcpcat.io\n`;
content += `MCPCAT_PROJECT_ID=proj_0000000 # Replace with your MCPcat project ID\n`;
}

// Add OpenTelemetry environment variables if enabled
if (options?.withOtel) {
content += `\n# OpenTelemetry Configuration for logging and traces\n`;
content += `OTLP_ENDPOINT=http://localhost:4318/v1/traces # OTLP collector endpoint\n`;
}

content += `\n# Add any other environment variables your API might need\n`;

return content;
Expand Down
9 changes: 7 additions & 2 deletions src/generator/package-json.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
import { CliOptions } from '../types/index.js';

/**
* Generates the content of package.json for the MCP server
*
* @param serverName Server name
* @param serverVersion Server version
* @param transportType Type of transport to use (stdio, web, or streamable-http)
* @param options CLI options
* @returns JSON string for package.json
*/
export function generatePackageJson(
serverName: string,
serverVersion: string,
transportType: string = 'stdio'
options: CliOptions
): string {
const transportType = options.transport || 'stdio';
const includeWebDeps = transportType === 'web' || transportType === 'streamable-http';
const includeMcpcat = options.withMcpcat || options.withOtel;

Comment on lines 11 to 19
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Restore backward-compatible generatePackageJson signature

Previously this helper accepted either two args (defaulting transport to 'stdio') or an explicit transport string. Making the third argument mandatory—and typing it as the full CliOptions—breaks existing programmatic consumers who relied on the old call shape. Please keep the third parameter optional and scoped to the properties this function actually uses so downstream builds keep compiling.

-export function generatePackageJson(
-  serverName: string,
-  serverVersion: string,
-  options: CliOptions
-): string {
-  const transportType = options.transport || 'stdio';
+export function generatePackageJson(
+  serverName: string,
+  serverVersion: string,
+  options: Pick<CliOptions, 'transport' | 'withMcpcat' | 'withOtel'> = {}
+): string {
+  const transportType = options.transport ?? 'stdio';
   const includeWebDeps = transportType === 'web' || transportType === 'streamable-http';
-  const includeMcpcat = options.withMcpcat || options.withOtel;
+  const includeMcpcat = Boolean(options.withMcpcat || options.withOtel);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function generatePackageJson(
serverName: string,
serverVersion: string,
transportType: string = 'stdio'
options: CliOptions
): string {
const transportType = options.transport || 'stdio';
const includeWebDeps = transportType === 'web' || transportType === 'streamable-http';
const includeMcpcat = options.withMcpcat || options.withOtel;
export function generatePackageJson(
serverName: string,
serverVersion: string,
options: Pick<CliOptions, 'transport' | 'withMcpcat' | 'withOtel'> = {}
): string {
const transportType = options.transport ?? 'stdio';
const includeWebDeps = transportType === 'web' || transportType === 'streamable-http';
const includeMcpcat = Boolean(options.withMcpcat || options.withOtel);

const packageData: any = {
name: serverName,
Expand All @@ -36,6 +40,7 @@ export function generatePackageJson(
dotenv: '^16.4.5',
zod: '^3.24.3',
'json-schema-to-zod': '^2.6.1',
...(includeMcpcat ? { mcpcat: '^0.1.5' } : {}),
},
devDependencies: {
'@types/node': '^22.15.2',
Expand Down
46 changes: 46 additions & 0 deletions src/generator/server-code.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,46 @@ import {
} from '../utils/code-gen.js';
import { generateExecuteApiToolFunction } from '../utils/security.js';

/**
* Generates MCPcat tracking code based on options
*/
function generateMcpcatTracking(options: CliOptions): string {
if (!options.withMcpcat && !options.withOtel) {
return '';
}

let trackingCode = '\n// MCPcat Product analytics and OpenTelemetry exporters\n';

if (options.withMcpcat && options.withOtel) {
// Both flags enabled
trackingCode += `mcpcat.track(server, process.env.MCPCAT_PROJECT_ID || null, {
exporters: {
otlp: {
type: "otlp",
endpoint: process.env.OTLP_ENDPOINT || "http://localhost:4318/v1/traces"
}
}
});`;
} else if (options.withMcpcat) {
// Only MCPcat enabled
trackingCode += `mcpcat.track(server, process.env.MCPCAT_PROJECT_ID || null);`;
} else if (options.withOtel) {
// Only OTEL enabled
trackingCode += `mcpcat.track(server, null, {
enableToolCallContext: false,
enableReportMissing: false,
exporters: {
otlp: {
type: "otlp",
endpoint: process.env.OTLP_ENDPOINT || "http://localhost:4318/v1/traces"
}
}
});`;
}

return trackingCode + '\n';
}

/**
* Generates the TypeScript code for the MCP server
*
Expand Down Expand Up @@ -80,6 +120,10 @@ export function generateMcpServerCode(
}`;
break;
}
let mcpcatImport = '';
if (options.withMcpcat || options.withOtel) {
mcpcatImport = `import * as mcpcat from "mcpcat";`;
}

// Generate the full server code
return `#!/usr/bin/env node
Expand All @@ -101,6 +145,7 @@ import {
type CallToolResult,
type CallToolRequest
} from "@modelcontextprotocol/sdk/types.js";${transportImport}
${mcpcatImport}

import { z, ZodError } from 'zod';
import { jsonSchemaToZod } from 'json-schema-to-zod';
Expand Down Expand Up @@ -156,6 +201,7 @@ ${listToolsHandlerCode}
${callToolHandlerCode}
${executeApiToolFunctionCode}

${generateMcpcatTracking(options)}
/**
* Main function to start the server
*/
Expand Down
9 changes: 6 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ import { normalizeBoolean } from './utils/helpers.js';
import pkg from '../package.json' with { type: 'json' };

// Export programmatic API
export { getToolsFromOpenApi, McpToolDefinition, GetToolsOptions } from './api.js';
export { getToolsFromOpenApi } from './api.js';
export type { McpToolDefinition, GetToolsOptions } from './api.js';

// Configure CLI
const program = new Command();
Expand Down Expand Up @@ -87,6 +88,8 @@ program
true
)
.option('--force', 'Overwrite existing files without prompting')
.option('--with-mcpcat', 'Enable MCPcat MCP product analytics')
.option('--with-otel', 'Enable OpenTelemetry (OTLP) logging')
.version(pkg.version) // Match package.json version
.action((options) => {
runGenerator(options).catch((error) => {
Expand Down Expand Up @@ -161,7 +164,7 @@ async function runGenerator(options: CliOptions & { force?: boolean }) {
const packageJsonContent = generatePackageJson(
serverName,
serverVersion,
options.transport as TransportType
options
);

console.error('Generating tsconfig.json...');
Expand All @@ -180,7 +183,7 @@ async function runGenerator(options: CliOptions & { force?: boolean }) {
const jestConfigContent = generateJestConfig();

console.error('Generating .env.example file...');
const envExampleContent = generateEnvExample(api.components?.securitySchemes);
const envExampleContent = generateEnvExample(api.components?.securitySchemes, options);

console.error('Generating OAuth2 documentation...');
const oauth2DocsContent = generateOAuth2Docs(api.components?.securitySchemes);
Expand Down
4 changes: 4 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ export interface CliOptions {
* false = exclude by default unless x-mcp explicitly enables.
*/
defaultInclude?: boolean;
/** Enable MCPcat analytics tracking */
withMcpcat?: boolean;
/** Enable OpenTelemetry (OTLP) exporters */
withOtel?: boolean;
}

/**
Expand Down