MCP Framework

Server Configuration

Configuration options and best practices for MCP Framework servers

Server Configuration

The MCP Framework provides extensive configuration options for customizing your server's behavior. This guide covers all available configuration options and best practices.

Basic Configuration

When creating a new MCP server, you can provide configuration options:

import { MCPServer } from "@modelcontextprotocol/mcp-framework";

const server = new MCPServer({
  name: "my-mcp-server",        // Server name
  version: "1.0.0",            // Server version
  basePath: "./dist",          // Base path for tools/prompts/resources
  transport: {                 // Transport configuration
    type: "sse",
    options: {
      // Transport-specific options
    }
  }
});

Server Name and Version

The server name and version are used to identify your MCP server:

const server = new MCPServer({
  name: "my-mcp-server",     // Default: package.json name or "unnamed-mcp-server"
  version: "1.0.0"          // Default: package.json version or "0.0.0"
});

If not provided, the server will attempt to read these values from your project's package.json file.

Base Path

The basePath option specifies where the server should look for tools, prompts, and resources:

const server = new MCPServer({
  basePath: "./dist"  // Default: join(process.cwd(), 'dist')
});

The server will look for:

  • Tools in ${basePath}/tools
  • Prompts in ${basePath}/prompts
  • Resources in ${basePath}/resources

Transport Configuration

The transport configuration determines how clients will communicate with your server:

const server = new MCPServer({
  transport: {
    type: "sse",              // "sse" or "stdio"
    options: {
      // Transport-specific options
      port: 8080,
      endpoint: "/sse",
      // ... other options
    }
  }
});

See the transport-specific documentation for detailed configuration options:

Server Capabilities

The server automatically detects and enables capabilities based on your project structure:

interface ServerCapabilities {
  tools?: {
    enabled: true;
  };
  schemas?: {
    enabled: true;
  };
  prompts?: {
    enabled: true;
  };
  resources?: {
    enabled: true;
  };
}
  • Tools capability is always enabled
  • Prompts capability is enabled if prompts are found in the prompts directory
  • Resources capability is enabled if resources are found in the resources directory

Server Lifecycle

Starting the Server

await server.start();

The start process:

  1. Loads tools, prompts, and resources
  2. Detects capabilities
  3. Sets up request handlers
  4. Initializes the transport
  5. Starts listening for connections

Stopping the Server

await server.stop();

The stop process:

  1. Closes active connections
  2. Stops the transport
  3. Cleans up resources
  4. Exits gracefully

The server also handles SIGINT signals (Ctrl+C) for graceful shutdown.

Logging

Framework Logging

The server uses a built-in logger that can be imported and configured:

import { logger } from "@modelcontextprotocol/mcp-framework";

// Log levels: debug, info, warn, error
logger.debug("Debug message");
logger.info("Info message");
logger.warn("Warning message");
logger.error("Error message");

This is the framework's internal logging system, controlled via environment variables (MCP_ENABLE_FILE_LOGGING, MCP_LOG_DIRECTORY, MCP_DEBUG_CONSOLE). It writes to stderr and optionally to log files.

Best Practices

  1. Project Structure

    • Keep tools, prompts, and resources in separate directories
    • Use TypeScript for better type safety
    • Follow the naming conventions for each component
  2. Configuration

    • Use environment variables for sensitive values
    • Set appropriate base paths for your deployment
    • Configure proper authentication in production
  3. Error Handling

    • Implement proper error handling in your tools
    • Use the logger for debugging and monitoring
    • Handle transport errors appropriately
  4. Security

    • Enable authentication in production
    • Use HTTPS for SSE transport
    • Set appropriate CORS settings
    • Implement rate limiting
  5. Performance

    • Keep message sizes reasonable
    • Implement proper cleanup in tools
    • Monitor server resources

MCP Protocol Logging

The server can declare the MCP logging capability, which allows tools to send structured log messages to connected clients over the transport:

const server = new MCPServer({
  logging: true,  // Enable MCP protocol logging capability
  // ...
});

When enabled:

  • The server declares the logging capability during initialization, signaling to clients that it supports the MCP logging protocol.
  • Clients can control the minimum log level by sending logging/setLevel requests.
  • Tools can send log messages to the client via this.log(level, data) inside the execute method.
  • Log levels follow RFC 5424 severity: debug, info, notice, warning, error, critical, alert, emergency.
  • The default threshold is warning -- only messages at warning level and above are sent to the client until it explicitly changes the level via logging/setLevel.

MCP protocol logging is separate from the framework's internal file/stderr logging. Framework logs (via the logger import) go to stderr and log files. MCP protocol logs (via this.log() in tools) are sent to the connected client over the MCP transport.

Tasks (Experimental)

Enable asynchronous tool execution with polling and deferred result retrieval:

const server = new MCPServer({
  tasks: {
    enabled: true,
    defaultTtl: 300000,        // Task lifetime in ms (default: 5 minutes)
    defaultPollInterval: 5000,  // Suggested poll interval in ms (default: 5 seconds)
    maxTasks: 100,              // Maximum concurrent tasks (default: 100)
  },
});

When enabled:

  • The server declares the tasks capability with list, cancel, and requests.tools.call support
  • Tools opt in via execution: { taskSupport: 'optional' } on the tool class
  • When a client includes a task field in tools/call, the server creates a task, executes the tool in the background, and immediately returns a task ID
  • Clients poll via tasks/get and retrieve results via tasks/result
  • Tasks expire after the configured TTL

This is an experimental feature from MCP specification 2025-11-25. See Advanced Tool Features for tool-side configuration.

Example Configuration

Here's a complete example with all configuration options:

import { MCPServer, APIKeyAuthProvider } from "mcp-framework";

const server = new MCPServer({
  name: "my-mcp-server",
  version: "1.0.0",
  basePath: "./dist",
  logging: true,  // Enable protocol logging
  tasks: {        // Enable async tasks (experimental)
    enabled: true,
    defaultTtl: 300000,
    maxTasks: 100,
  },
  transport: {
    type: "http-stream",
    options: {
      port: 8080,
      host: "127.0.0.1",      // Default: localhost only (use "0.0.0.0" for Docker)
      endpoint: "/mcp",
      responseMode: "stream",
      cors: {
        allowedOrigins: ["http://localhost:3000"],  // Origin validation
        allowMethods: "GET, POST, DELETE, OPTIONS",
        allowHeaders: "Content-Type, Authorization, x-api-key, Mcp-Session-Id",
        exposeHeaders: "Content-Type, Authorization, Mcp-Session-Id",
        maxAge: "86400"
      },
      auth: {
        provider: new APIKeyAuthProvider({
          keys: ["your-api-key"]
        }),
        endpoints: {
          sse: true,
          messages: true
        }
      }
    }
  }
});

// Start the server
await server.start();

// Handle shutdown
process.on('SIGINT', async () => {
  await server.stop();
});