Skip to content

MCP Server 设计

这页偏开发者实现视角。

设计原则

  • 单一领域:一个 Server 聚焦一类能力。
  • 最小暴露:只暴露必须的 tool/resource。
  • 明确契约:输入输出字段稳定、可验证。

Tool 设计建议

  • 命名直观,如 get_release_status
  • 参数类型明确,避免"万能字符串"。
  • 返回结构化对象,便于下游评测与日志分析。

Tool 定义示例

typescript
// tool-definition.ts
interface ToolDefinition {
  name: string // 工具名称,如 "get_release_status"
  description: string // 功能描述
  inputSchema: JSONSchema // 输入参数 Schema
  outputSchema: JSONSchema // 输出结构 Schema
  riskLevel: 'low' | 'medium' | 'high' // 风险等级
  timeout?: number // 超时时间(毫秒)
  retryPolicy?: {
    maxRetries: number
    backoffMs: number
  }
}

// 示例:发布状态查询工具
const getReleaseStatusTool: ToolDefinition = {
  name: 'get_release_status',
  description: '查询指定版本的发布状态和健康指标',
  inputSchema: {
    type: 'object',
    properties: {
      version: { type: 'string', pattern: '^\\d+\\.\\d+\\.\\d+$' },
      environment: { type: 'string', enum: ['dev', 'staging', 'prod'] }
    },
    required: ['version', 'environment']
  },
  outputSchema: {
    type: 'object',
    properties: {
      status: { type: 'string', enum: ['pending', 'running', 'success', 'failed', 'rolled_back'] },
      healthScore: { type: 'number', minimum: 0, maximum: 100 },
      metrics: {
        type: 'object',
        properties: {
          errorRate: { type: 'number' },
          latencyP95: { type: 'number' },
          requestCount: { type: 'number' }
        }
      }
    }
  },
  riskLevel: 'low',
  timeout: 5000
}

Tool 实现模板

typescript
// tool-implementation.ts
interface ToolContext {
  logger: Logger
  metrics: MetricsCollector
  config: Config
}

async function executeTool(
  input: unknown,
  context: ToolContext
): Promise<ToolResult> {
  // 1. 参数校验
  const validated = validateInput(input, toolDefinition.inputSchema)

  // 2. 权限检查
  await checkPermissions(context)

  // 3. 执行逻辑
  try {
    const result = await doExecute(validated, context)

    // 4. 输出校验
    validateOutput(result, toolDefinition.outputSchema)

    // 5. 记录日志
    context.logger.info('Tool executed successfully', {
      tool: toolDefinition.name,
      input: validated,
      result
    })

    return { success: true, data: result }
  }
  catch (error) {
    context.logger.error('Tool execution failed', {
      tool: toolDefinition.name,
      input: validated,
      error: error.message
    })

    return {
      success: false,
      error: {
        code: error.code || 'UNKNOWN_ERROR',
        message: error.message,
        retryable: isRetryable(error)
      }
    }
  }
}

Resource 设计建议

  • 支持分页或分段读取。
  • 对高体量内容提供摘要资源。
  • 返回时附带版本和时间戳。

Resource 定义示例

typescript
// resource-definition.ts
interface ResourceDefinition {
  uri: string // 资源 URI,如 "docs://api/v1/spec"
  name: string // 资源名称
  description: string // 资源描述
  mimeType: string // MIME 类型
  pagination?: {
    enabled: boolean
    pageSize: number
    maxItems?: number
  }
  caching?: {
    enabled: boolean
    ttlSeconds: number
  }
}

// 示例:API 文档资源
const apiDocsResource: ResourceDefinition = {
  uri: 'docs://api/v1/spec',
  name: 'API Specification',
  description: 'OpenAPI 3.0 规范文档',
  mimeType: 'application/json',
  pagination: {
    enabled: true,
    pageSize: 100
  },
  caching: {
    enabled: true,
    ttlSeconds: 3600
  }
}

Prompt 设计建议

  • 按任务分类,不按团队分类。
  • 每个 prompt 要有适用边界。
  • 标记风险级别(低/中/高)。

Prompt 定义示例

typescript
// prompt-definition.ts
interface PromptDefinition {
  id: string // Prompt ID
  name: string // 显示名称
  description: string // 用途描述
  template: string // 模板内容
  variables: VariableDef[] // 变量定义
  riskLevel: 'low' | 'medium' | 'high'
  tags: string[] // 分类标签
  examples: PromptExample[]
}

// 示例:代码审查 Prompt
const codeReviewPrompt: PromptDefinition = {
  id: 'code-review',
  name: '代码审查助手',
  description: '对代码进行专业审查,关注正确性、可维护性、安全性',
  template: `
你是一位资深代码审查专家。请对以下代码进行审查:

**代码**
\`\`\`{language}
{code}
\`\`\`

**审查维度**
1. 正确性:逻辑是否正确,边界是否处理
2. 可读性:命名、结构、注释是否清晰
3. 安全性:是否有潜在漏洞
4. 性能:是否有明显性能问题

**输出格式**
{output_format}

**约束**
- 先指出问题,再给建议,不要直接给代码
- 对每个问题标注严重程度(critical/warning/info)
`,
  variables: [
    { name: 'language', type: 'string', required: true },
    { name: 'code', type: 'string', required: true },
    { name: 'output_format', type: 'string', default: 'markdown' }
  ],
  riskLevel: 'low',
  tags: ['development', 'review'],
  examples: [
    {
      input: { language: 'typescript', code: 'function add(a, b) { return a + b }' },
      output: '...'
    }
  ]
}

错误处理建议

  • 错误信息分三层:用户可读、开发可诊断、系统可追踪。
  • 对可重试错误和不可重试错误做区分。

错误处理示例

typescript
// error-handling.ts
enum ErrorCode {
  // 客户端错误(不可重试)
  INVALID_INPUT = 'INVALID_INPUT',
  UNAUTHORIZED = 'UNAUTHORIZED',
  NOT_FOUND = 'NOT_FOUND',

  // 服务端错误(可重试)
  TIMEOUT = 'TIMEOUT',
  RATE_LIMITED = 'RATE_LIMITED',
  SERVICE_UNAVAILABLE = 'SERVICE_UNAVAILABLE',

  // 业务错误
  BUSINESS_RULE_VIOLATION = 'BUSINESS_RULE_VIOLATION',
  RESOURCE_EXHAUSTED = 'RESOURCE_EXHAUSTED'
}

interface ToolError {
  code: ErrorCode
  message: string // 用户可读信息
  details?: object // 开发诊断信息
  traceId: string // 追踪 ID
  retryable: boolean // 是否可重试
  retryAfter?: number // 重试等待时间(毫秒)
}

function handleError(error: unknown): ToolError {
  if (error instanceof ValidationError) {
    return {
      code: ErrorCode.INVALID_INPUT,
      message: '输入参数格式不正确,请检查后重试',
      details: { errors: error.errors },
      traceId: generateTraceId(),
      retryable: false
    }
  }

  if (error instanceof TimeoutError) {
    return {
      code: ErrorCode.TIMEOUT,
      message: '请求超时,请稍后重试',
      traceId: generateTraceId(),
      retryable: true,
      retryAfter: 1000
    }
  }

  // 未知错误
  return {
    code: ErrorCode.SERVICE_UNAVAILABLE,
    message: '服务暂时不可用',
    traceId: generateTraceId(),
    retryable: true,
    retryAfter: 3000
  }
}

性能建议

  • 热路径缓存。
  • 慢调用超时和熔断。
  • 并发上限控制。

性能配置示例

yaml
# mcp-server-config.yaml
server:
  name: my-mcp-server
  version: 1.0.0

performance:
  # 超时配置
  timeout:
    default: 30000 # 默认 30 秒
    max: 60000 # 最大 60 秒

  # 熔断配置
  circuitBreaker:
    enabled: true
    failureThreshold: 5 # 连续失败 5 次触发熔断
    resetTimeout: 30000 # 30 秒后尝试恢复

  # 并发控制
  concurrency:
    maxConcurrent: 100 # 最大并发数
    queueSize: 500 # 排队等待数

  # 缓存配置
  cache:
    enabled: true
    defaultTTL: 300 # 默认 5 分钟
    maxSize: 10000 # 最大缓存条目

  # 重试配置
  retry:
    maxRetries: 3
    backoff:
      initial: 1000 # 初始等待 1 秒
      max: 10000 # 最大等待 10 秒
      multiplier: 2 # 指数退避倍数