锅炉板MCP服务器
用于在TypeScript中开发自定义模型上下文协议(MCP)服务器的生产就绪基础。提供完整的分层架构模式、工作示例实现和全面的开发人员基础设施,将AI助手与外部API和数据源连接起来。
](https://www.npmjs.com/package/@aashari/boilerplate-mcp-server) 
最新更新(2026年2月):更新到MCP SDK 1.26.0和Zod 4.3.6,并继续更新 registerTool 模式和可流式传输的HTTP改进。看 docs/MODERNIZATION.md 了解详情。特性
- 安全第一:DNS重新绑定保护,仅限本地主机绑定,安全错误处理
- 双重运输支持:STDIO和流式HTTP传输,具有自动回退功能
- 分层架构:CLI、工具、资源、提示、控制器、服务和实用程序之间的清晰分离
- 类型安全:使用Zod v4.3.6模式验证的完整TypeScript实现
- 所有MCP图元:工具、资源和提示(附示例)
- 资源链接模式:用于大型响应的令牌高效资源引用
- TOON输出格式:面向令牌的对象表示法,令牌比JSON少30-60%
- JMESPath过滤:从响应中仅提取所需字段以降低令牌成本
- 原始响应记录:自动记录对的大型API响应 `/tmp/mcp/
/` 带截断制导
- 现代SDK:使用MCP SDK v1.26.0
registerToolAPI模式(已准备好进行v2迁移) - 完整的IP地址示例:用于IP地理定位的工具、资源、提示和CLI命令
- 综合测试:具有覆盖率报告的单元和集成测试(47个测试通过)
- 生产工具:ESLint、Prettier、语义发布和MCP检查器集成
- 错误处理:结构化错误处理
isError字段和上下文日志记录 - 安全文档:完成 安全.md 带有身份验证实施指南
什么是MCP?
模型上下文协议(MCP)是一个开放标准,用于将人工智能系统安全地连接到外部工具和数据源。该样板文件采用一种干净、分层的体系结构来实现MCP规范,该体系结构可以扩展为为任何API或数据源构建自定义MCP服务器。
先决条件
- Node.js (>=20.x): 下载
- Git:用于版本控制
快速开始
# Clone the repository
git clone https://github.com/aashari/boilerplate-mcp-server.git
cd boilerplate-mcp-server
# Install dependencies
npm install
# Build the project
npm run build
# Run in different modes:
# 1. CLI Mode - Execute commands directly
npm run cli -- get-ip-details 8.8.8.8
npm run cli -- get-ip-details # Get your current IP
npm run cli -- get-ip-details 1.1.1.1 -e # With extended data
npm run cli -- get-ip-details 8.8.8.8 --jq "{ip: query, country: country}" # JMESPath filter
npm run cli -- get-ip-details 8.8.8.8 -o json # JSON output
# 2. STDIO Transport - For AI assistant integration (Claude Desktop, Cursor)
npm run mcp:stdio
# 3. HTTP Transport - For web-based integrations
npm run mcp:http
# 4. Development with MCP Inspector
npm run mcp:inspect # Auto-opens browser with debugging UI运输方式
STDIO传输
- 通过stdin/stdout进行JSON-RPC通信
- Claude Desktop、Cursor AI和其他本地AI助手使用
- 运行方式:
TRANSPORT_MODE=stdio node dist/index.js
可流式HTTP传输
- 基于HTTP的传输,带有服务器发送事件(SSE)
- 支持多个并发连接和web集成
- 默认情况下在端口3000上运行(可通过配置
PORT任何人) - MCP端点:
http://localhost:3000/mcp - 健康检查:
http://localhost:3000/→ 返回服务器版本 - 运行方式:
TRANSPORT_MODE=http node dist/index.js
安全🔒
此样板实施了生产就绪的安全措施:
✅ 内置保护
- DNS重新绑定保护:Origin标头验证可防止恶意网站访问您的localhost服务器
- 仅本地主机绑定:服务器显式绑定到
127.0.0.1(无法从网络访问) - 安全错误处理:错误响应包括
isError: true标记并不要泄露敏感信息
🔐 安全最佳实践
📖 完整的安全文件: 安全.md
🔍 安全审计报告: 文件/审计-2025-01-13.1.md
输出格式
TOON格式(默认)
TOON(面向令牌的对象表示法)是一种针对LLM优化的人类可读格式,与JSON相比,令牌使用量减少了30-60%:
status: success
query: 8.8.8.8
country: United States
city: Ashburn
lat: 39.03
lon: -77.5JSON格式
标准JSON输出 --output-format json 已指定:
{
"status": "success",
"query": "8.8.8.8",
"country": "United States",
"city": "Ashburn"
}JMESPath过滤
使用 --jq 仅提取所需字段,降低令牌成本:
# Extract specific fields
npm run cli -- get-ip-details 8.8.8.8 --jq "{ip: query, country: country}"
# Output:
# ip: 8.8.8.8
# country: United States
# Nested structure
npm run cli -- get-ip-details 8.8.8.8 --jq "{location: {city: city, coords: {lat: lat, lon: lon}}}"看 JMESPath文档 更多过滤器示例。
架构概述
Project Structure (Click to expand)
src/
├── cli/ # Command-line interfaces
│ ├── index.ts # CLI entry point with Commander setup
│ └── ipaddress.cli.ts # IP address CLI commands
├── controllers/ # Business logic orchestration
│ ├── ipaddress.controller.ts # IP lookup business logic
│ └── ipaddress.formatter.ts # Response formatting
├── services/ # External API interactions
│ ├── vendor.ip-api.com.service.ts # ip-api.com service
│ └── vendor.ip-api.com.types.ts # Service type definitions
├── tools/ # MCP tool definitions (AI interface)
│ ├── ipaddress.tool.ts # IP lookup tool (inline content)
│ ├── ipaddress-link.tool.ts # IP lookup with ResourceLink pattern
│ └── ipaddress.types.ts # Tool argument schemas
├── resources/ # MCP resource definitions
│ └── ipaddress.resource.ts # IP lookup resource (URI: ip://address)
├── prompts/ # MCP prompt definitions
│ └── analysis.prompt.ts # IP analysis prompt templates
├── types/ # Global type definitions
│ └── common.types.ts # Shared interfaces (ControllerResponse, etc.)
├── utils/ # Shared utilities
│ ├── logger.util.ts # Contextual logging system
│ ├── error.util.ts # MCP-specific error formatting
│ ├── error-handler.util.ts # Error handling utilities
│ ├── config.util.ts # Environment configuration
│ ├── constants.util.ts # Version and package constants
│ ├── formatter.util.ts # Markdown formatting and response truncation
│ ├── toon.util.ts # TOON format encoding
│ ├── jq.util.ts # JMESPath filtering
│ ├── response.util.ts # Raw API response logging
│ └── transport.util.ts # HTTP transport utilities
└── index.ts # Server entry point (dual transport)分层架构
样板遵循一个干净、分层的架构,有6个不同的层,可以促进可维护性和明确的关注点分离:
1.CLI层(src/cli/)
- 目的:用于直接工具使用和测试的命令行界面
- 实施:基于命令的参数解析和上下文错误处理
- 示例:
get-ip-details [ipAddress] --include-extended-data --no-use-https - 模式:注册命令→ 解析参数→ 呼叫控制器→ 处理错误
2.工具层(src/tools/)
- 目的:人工智能助手可以调用的MCP工具定义
- 实施:使用结构化响应进行Zod模式验证
- 示例:
ip_get_details具有可选IP地址和配置选项的工具 - 模式:定义架构→ 验证参数→ 呼叫控制器→ 格式化MCP响应
3.资源层(src/resources/)
- 目的:MCP资源提供可通过URI访问的上下文数据
- 实施:用途
registerResourceAPIResourceTemplate用于参数化URI - 示例:
ip://{ipAddress}提供IP地理定位数据的资源模板 - 模式:注册URI模板→ 提取变量→ 返回格式化内容
4.控制器层(src/controllers/)
- 目的:具有全面错误处理功能的业务逻辑编排
- 实施:选项验证、回退逻辑、响应格式
- 示例:具有HTTPS回退的IP查找、测试环境检测、API令牌验证
- 模式:验证输入→ 应用默认值→ 呼叫服务→ 格式化响应
5.服务层(src/services/)
- 目的:使用最少的业务逻辑直接进行外部API交互
- 实施:具有结构化错误处理的HTTP传输实用程序
- 示例:带有身份验证和字段选择的ip-api.com api调用
- 模式:生成请求→ 进行API调用→ 验证响应→ 返回原始数据
6.实用程序层(src/utils/)
- 目的:跨所有层共享功能
- 关键组件:
- logger.util.ts:上下文日志记录(文件:方法上下文) - error.util.ts:MCP特定错误格式化 - error-handler.util.ts:错误处理和上下文构建 - transport.util.ts:具有重试逻辑的HTTP/API实用程序 - config.util.ts:环境配置管理 - constants.util.ts:版本和包常量 - formatter.util.ts:Markdown格式和响应截断 - toon.util.ts:TOON格式编码(令牌高效输出) - jq.util.ts:用于响应转换的JMESPath过滤 - response.util.ts:原始API响应日志记录到 /tmp/mcp/ /
开发者指南
开发脚本
# Build and Clean
npm run build # Build TypeScript to dist/
npm run clean # Remove dist/ and coverage/
npm run prepare # Build + ensure executable permissions (for npm publish)
# CLI Testing
npm run cli -- get-ip-details 8.8.8.8 # Test specific IP
npm run cli -- get-ip-details --include-extended-data # Test with extended data
npm run cli -- get-ip-details --no-use-https # Test with HTTP
# MCP Server Modes
npm run mcp:stdio # STDIO transport for AI assistants
npm run mcp:http # HTTP transport on port 3000
npm run mcp:inspect # HTTP + auto-open MCP Inspector
# Testing
npm test # Run all tests (Jest)
npm run test:coverage # Generate coverage report
npm run test:cli # Run CLI-specific tests
# Code Quality
npm run lint # ESLint with TypeScript rules
npm run format # Prettier formatting环境变量
核心配置
TRANSPORT_MODE:运输方式(stdio|http,默认值:stdio)PORT:HTTP服务器端口(默认值:3000)DEBUG:启用调试日志记录(true|false,默认值:false)NODE_ENV:节点环境(development|production,默认值:development)
IP API配置
IPAPI_API_TOKEN:ip-API.com扩展数据的API令牌(可选,可用免费层)
示例 .env 文件
# Core configuration
TRANSPORT_MODE=http
PORT=3000
DEBUG=true
NODE_ENV=development
# External API Keys
IPAPI_API_TOKEN=your_token_here调试工具
- MCP检查员:用于测试MCP工具的可视化工具
- 使用以下命令运行服务器 npm run mcp:inspect - 打开终端中显示的URL - 以交互方式测试您的工具
- 调试日志记录:启用
DEBUG=true环境变量
- 原始响应记录:自动记录大型API响应(>40000个字符)
- 响应已保存到 /tmp/mcp/ / 目录 - 文件名格式: -.txt - 包括请求详细信息、响应数据和性能指标 - 截断的响应包括访问完整原始文件的指导
Configuration (Click to expand)
创建 ~/.mcp/configs.json:
{
"boilerplate": {
"environments": {
"DEBUG": "true",
"TRANSPORT_MODE": "http",
"PORT": "3000"
}
}
}构建自定义工具
Step-by-Step Tool Implementation Guide (Click to expand)
1.定义服务层
在中创建新服务 src/services/ 遵循供应商特定的命名模式:
// src/services/vendor.example-api.service.ts
import { Logger } from '../utils/logger.util.js';
import { fetchApi } from '../utils/transport.util.js';
import { ExampleApiResponse, ExampleApiRequestOptions } from './vendor.example-api.types.js';
import { createApiError, McpError } from '../utils/error.util.js';
const serviceLogger = Logger.forContext('services/vendor.example-api.service.ts');
async function get(
param?: string,
options: ExampleApiRequestOptions = {}
): Promise {
const methodLogger = serviceLogger.forMethod('get');
methodLogger.debug(`Calling Example API with param: ${param}`);
try {
const url = `https://api.example.com/${param || 'default'}`;
const rawData = await fetchApi(url, {
headers: options.apiKey ? { 'Authorization': `Bearer ${options.apiKey}` } : {}
});
methodLogger.debug('Received successful response from Example API');
return rawData;
} catch (error) {
methodLogger.error('Service error fetching data', error);
if (error instanceof McpError) {
throw error;
}
throw createApiError(
'Unexpected service error while fetching data',
undefined,
error
);
}
}
export default { get };2.创建控制器
在中添加控制器 src/controllers/ 处理带有错误上下文的业务逻辑:
// src/controllers/example.controller.ts
import { Logger } from '../utils/logger.util.js';
import exampleService from '../services/vendor.example-api.service.js';
import { formatExample } from './example.formatter.js';
import { handleControllerError, buildErrorContext } from '../utils/error-handler.util.js';
import { ControllerResponse } from '../types/common.types.js';
import { config } from '../utils/config.util.js';
const logger = Logger.forContext('controllers/example.controller.ts');
export interface GetDataOptions {
param?: string;
includeMetadata?: boolean;
}
async function getData(
options: GetDataOptions = {}
): Promise {
const methodLogger = logger.forMethod('getData');
methodLogger.debug(`Getting data for param: ${options.param || 'default'}`, options);
try {
// Apply business logic and defaults
const apiKey = config.get('EXAMPLE_API_TOKEN');
// Call service layer
const data = await exampleService.get(options.param, {
apiKey,
includeMetadata: options.includeMetadata ?? false
});
// Format response
const formattedContent = formatExample(data);
return { content: formattedContent };
} catch (error) {
throw handleControllerError(
error,
buildErrorContext(
'ExampleData',
'getData',
'controllers/example.controller.ts@getData',
options.param || 'default',
{ options }
)
);
}
}
export default { getData };3.实施MCP工具
在中创建工具定义 src/tools/ 遵循注册模式:
// src/tools/example.tool.ts
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import { z } from 'zod';
import { Logger } from '../utils/logger.util.js';
import { formatErrorForMcpTool } from '../utils/error.util.js';
import exampleController from '../controllers/example.controller.js';
const logger = Logger.forContext('tools/example.tool.ts');
// Define Zod schema for tool arguments
const GetDataSchema = z.object({
param: z.string().optional().describe('Optional parameter for the API call'),
includeMetadata: z.boolean().optional().default(false)
.describe('Whether to include additional metadata in the response')
});
async function handleGetData(args: Record) {
const methodLogger = logger.forMethod('handleGetData');
try {
methodLogger.debug('Tool example_get_data called', args);
// Validate arguments with Zod
const validatedArgs = GetDataSchema.parse(args);
// Call controller
const result = await exampleController.getData({
param: validatedArgs.param,
includeMetadata: validatedArgs.includeMetadata
});
// Return MCP-formatted response
return {
content: [
{
type: 'text' as const,
text: result.content
}
]
};
} catch (error) {
methodLogger.error('Tool example_get_data failed', error);
return formatErrorForMcpTool(error);
}
}
// Registration function using the modern registerTool API (SDK v1.23.0)
function registerTools(server: McpServer) {
const registerLogger = logger.forMethod('registerTools');
registerLogger.debug('Registering example tools...');
// SDK best practices: 'title' for UI display name, 'description' for detailed info
server.registerTool(
'example_get_data',
{
title: 'Get Example Data', // Display name for UI (e.g., 'Get Example Data')
description: `Gets data from the Example API with optional parameter.
Use this tool to fetch example data. Returns formatted data as Markdown.`,
inputSchema: GetDataSchema,
},
handleGetData
);
registerLogger.debug('Example tools registered successfully');
}
export default { registerTools };4.添加CLI支持
在中创建CLI命令 src/cli/ 遵循指挥官模式:
// src/cli/example.cli.ts
import { Command } from 'commander';
import { Logger } from '../utils/logger.util.js';
import exampleController from '../controllers/example.controller.js';
import { handleCliError } from '../utils/error.util.js';
const logger = Logger.forContext('cli/example.cli.ts');
function register(program: Command) {
const methodLogger = logger.forMethod('register');
methodLogger.debug('Registering example CLI commands...');
program
.command('get-data')
.description('Gets data from the Example API')
.argument('[param]', 'Optional parameter for the API call')
.option('-m, --include-metadata', 'Include additional metadata in response')
.action(async (param, options) => {
const actionLogger = logger.forMethod('action:get-data');
try {
actionLogger.debug('CLI get-data called', { param, options });
const result = await exampleController.getData({
param,
includeMetadata: options.includeMetadata || false
});
console.log(result.content);
} catch (error) {
handleCliError(error);
}
});
methodLogger.debug('Example CLI commands registered successfully');
}
export default { register };5.注册组件
更新入口点以注册新组件:
// 1. Register CLI in src/cli/index.ts
import exampleCli from './example.cli.js';
export async function runCli(args: string[]) {
// ... existing setup code ...
// Register CLI commands
exampleCli.register(program); // Add this line
// ... rest of function
}
// 2. Register Tools in src/index.ts
import exampleTools from './tools/example.tool.js';
// In the startServer function, after existing registrations:
exampleTools.registerTools(serverInstance);6.添加MCP资源(可选)
在中创建资源 src/resources/ 使用现代 registerResource API
// src/resources/example.resource.ts
import { McpServer, ResourceTemplate } from '@modelcontextprotocol/sdk/server/mcp.js';
import { Logger } from '../utils/logger.util.js';
import exampleController from '../controllers/example.controller.js';
import { formatErrorForMcpResource } from '../utils/error.util.js';
const logger = Logger.forContext('resources/example.resource.ts');
function registerResources(server: McpServer) {
const registerLogger = logger.forMethod('registerResources');
registerLogger.debug('Registering example resources...');
// Use registerResource with ResourceTemplate for parameterized URIs (SDK v1.23.0)
server.registerResource(
'example-data',
new ResourceTemplate('example://{param}', { list: undefined }),
{
title: 'Example Data', // Display name for UI
description: 'Retrieve example data by parameter'
},
async (uri, variables) => {
const methodLogger = logger.forMethod('exampleResource');
try {
// Extract parameter from template variables
const param = variables.param as string | undefined;
methodLogger.debug('Example resource called', { uri: uri.href, param });
const result = await exampleController.getData({ param });
return {
contents: [
{
uri: uri.href,
text: result.content,
mimeType: 'text/markdown'
}
]
};
} catch (error) {
methodLogger.error('Resource error', error);
return formatErrorForMcpResource(error, uri.href);
}
}
);
registerLogger.debug('Example resources registered successfully');
}
export default { registerResources };IP地址示例实现
样板包括一个完整的IP地址地理定位示例,演示了所有层:
可用工具和命令
CLI命令:
npm run cli -- get-ip-details # Get current public IP (TOON format)
npm run cli -- get-ip-details 8.8.8.8 # Get details for specific IP
npm run cli -- get-ip-details 1.1.1.1 -e # Short form with extended data
npm run cli -- get-ip-details 1.1.1.1 --include-extended-data # Long form with extended data
npm run cli -- get-ip-details 8.8.8.8 --no-use-https # Force HTTP (for free tier)
npm run cli -- get-ip-details 8.8.8.8 -o json # JSON output (short form)
npm run cli -- get-ip-details 8.8.8.8 --output-format json # JSON output (long form)
npm run cli -- get-ip-details 8.8.8.8 --jq "{ip: query, country: country}" # JMESPath filtered outputMCP工具:
ip_get_details-AI助手的IP地理定位查找ip_get_details_link-资源感知客户端的相同查找+资源链接输出
这两个工具共享相同的参数:
ipAddress(可选):要查找的IP地址(省略当前设备的公共IP)includeExtendedData(可选,默认值:false):包括ASN、主机、组织数据(需要API令牌)useHttps(可选,默认值:true):对API调用使用HTTPSjq(可选):用于过滤/转换响应的JMESPath表达式outputFormat(可选,默认值:"toon"):输出格式-“toon”或“json”
输出行为:
ip_get_details:返回一个text内容块ip_get_details_link:首先返回相同的结果text块加aresource_link挡块(ip://)
MCP资源:
ip://{ipAddress}-IP详细信息资源模板(例如。,ip://8.8.8.8,ip://1.1.1.1)
- 以Markdown格式返回IP地理位置数据 - 默认情况下使用TOON格式以提高令牌效率
演示的功能
- TOON输出:令牌高效格式(令牌比JSON少30-60%)
- JMESPath过滤:仅提取所需字段以降低成本
- 回退逻辑:HTTPS→ 免费层用户的HTTP回退
- 环境检测:测试与生产中的不同行为
- API代币支持:扩展数据(ASN、移动检测等)的可选令牌
- 错误处理:私有/保留IP地址的结构化错误
配置选项
# Optional - for extended data features
IPAPI_API_TOKEN=your_token_from_ip-api.com
# Development
DEBUG=true # Enable detailed logging
TRANSPORT_MODE=http # Use HTTP transport
PORT=3001 # Custom port发布您的MCP服务器
- 自定义套餐详细信息:
{
"name": "your-mcp-server-name",
"version": "1.0.0",
"description": "Your custom MCP server",
"author": "Your Name",
"keywords": ["mcp", "your-domain", "ai-integration"]
}- 更新文档: 用您的用例替换IP地址示例
- 彻底测试:
npm run build && npm test
npm run cli -- your-command
npm run mcp:stdio # Test with MCP Inspector- 发布: 推动传统承诺
main并让语义发布通过GitHub Actions自动发布(OIDC可信发布)。
测试策略
样板包括全面的测试基础设施:
测试结构
tests/ # Not present - tests are in src/
src/
├── **/*.test.ts # Co-located with source files
├── utils/ # Utility function tests
├── controllers/ # Business logic tests
├── services/ # API integration tests
└── cli/ # CLI command tests测试最佳实践
- 单元测试:测试实用程序和纯函数(
*.util.test.ts) - 控制器测试:使用模拟服务调用测试业务逻辑
- 服务测试:测试API与真实/模拟HTTP调用的集成
- CLI测试:测试命令解析和执行
- 测试环境检测:控制器中的自动测试模式处理
运行测试
npm test # Run all tests
npm run test:coverage # Generate coverage report
npm run test:cli # CLI-specific tests only覆盖目标
- 目标:测试覆盖率>80%
- 专注于业务逻辑(控制器)和实用程序
- 适当模拟外部服务
许可证
MCP SDK v2准备
⚠️ 备注:MCP SDK v2正在开发中(预计2026年第一季度稳定)。此样板已准备好进行迁移,只需进行最小的更改。
关键v2更改:
- 包裹拆分:
@modelcontextprotocol/server和@modelcontextprotocol/client - Express、Hono、Node.js HTTP的可选中间件包
- 相同的核心API模式(这个样板已经使用了现代API)
看 现代化.md 获取详细的迁移指南和时间表。
资源和文件
MCP协议资源
实施参考
您的MCP服务器生态系统
- 所有@aashari MCP服务器 -NPM包
- -源代码

