mcp-clean-architecture
FastMCP 整洁架构 — MCP 应用 UI 模板
一个面向生产的模板,用于使用 Python 和 FastMCP 构建 MCP 服务器和 MCP 应用,遵循整洁架构、依赖倒置、关注点分离以及现代 Python 实践。
该项目也旨在为来自 C# / .NET 的开发者提供学习参考。
目标不仅是构建一个可运行的 MCP 服务器,而是构建一个保持可维护性、可测试性、可扩展性,并且独立于外部框架和服务的服务器。
目标
此模板演示了如何使用以下技术构建 MCP 应用:
Python
FastMCP
Streamable HTTP 传输
无状态 HTTP
MCP 工具
MCP 资源
MCP 提示词
MCP 应用 / 应用 UI
整洁架构
依赖倒置
仓储模式
用例
Pydantic 模型
外部 REST API 集成
基于环境的配置
异步 HTTP 通信
依赖注入 / 组合
集中式错误处理
结构化应用错误
日志记录
单元测试
集成测试
示例领域是一个电子商务应用。
产品从公共外部 API 获取,并通过 MCP 暴露。
该应用将逐步演进以支持以下操作:
搜索产品
查看产品详情
将产品添加到购物车
查看购物车
从购物车中移除产品
MCP 应用 UI 将在兼容的 MCP 主机内提供交互式体验。
架构
该项目遵循整洁架构原则。
MCP HOST
Claude / Copilot / etc.
|
| MCP over HTTP
v
+---------------------------------------------------------+
| PRESENTATION |
| |
| FastMCP Server |
| MCP Tools |
| MCP Resources |
| MCP Prompts |
| MCP App UI |
| Error Boundary |
+---------------------------+-----------------------------+
|
v
+---------------------------------------------------------+
| APPLICATION |
| |
| Use Cases |
| |
| GetProductUseCase |
| SearchProductsUseCase |
| AddProductToCartUseCase |
| GetCartUseCase |
+---------------------------+-----------------------------+
|
v
+---------------------------------------------------------+
| DOMAIN |
| |
| Entities / Models |
| |
| Product |
| Cart |
| |
| Repository Contracts |
| |
| ProductRepository |
| CartRepository |
| |
| Domain Errors |
+---------------------------+-----------------------------+
^
|
+---------------------------+-----------------------------+
| INFRASTRUCTURE |
| |
| External API implementations |
| HTTP clients |
| Configuration |
| Persistence adapters |
| |
| DummyJsonProductRepository |
| DummyJsonCartRepository |
+---------------------------+-----------------------------+
|
v
External REST API依赖规则
最重要的规则是:
Presentation ---> Application ---> Domain
^
|
Infrastructure ----------+依赖指向核心应用。
领域层绝不能依赖:
FastMCP
HTTP libraries
Uvicorn
DummyJSON
Claude
Copilot
databases
environment variables
MCP App UI例如:
MCP Tool
|
v
GetProductUseCase
|
v
ProductRepository
^
|
DummyJsonProductRepository
|
v
DummyJSON REST APIGetProductUseCase 知道 ProductRepository 抽象。
它不知道产品是通过 HTTP 或 DummyJSON 获取的。
这允许:
DummyJSON之后被替换为:
SQL Server
PostgreSQL
MongoDB
another REST API
mock repository而无需更改应用用例。
项目结构
项目将逐步演进为以下结构:
mcp-clean-architecture/
|
|-- src/
| |
| |-- domain/
| | |
| | |-- entities/
| | | |-- __init__.py
| | | |-- product.py
| | | `-- cart.py
| | |
| | |-- repositories/
| | | |-- __init__.py
| | | |-- product_repository.py
| | | `-- cart_repository.py
| | |
| | `-- errors/
| | |-- __init__.py
| | `-- domain_errors.py
| |
| |-- application/
| | |
| | |-- use_cases/
| | | |-- __init__.py
| | | |-- get_product.py
| | | |-- search_products.py
| | | |-- add_product_to_cart.py
| | | `-- get_cart.py
| | |
| | `-- errors/
| | |-- __init__.py
| | `-- application_errors.py
| |
| |-- infrastructure/
| | |
| | |-- config/
| | | |-- __init__.py
| | | `-- environment.py
| | |
| | |-- http/
| | |
| | |-- repositories/
| | | |-- __init__.py
| | | |-- dummy_json_product_repository.py
| | | `-- dummy_json_cart_repository.py
| | |
| | `-- errors/
| | |-- __init__.py
| | `-- infrastructure_errors.py
| |
| `-- presentation/
| |
| `-- mcp/
| |-- __init__.py
| |-- server.py
| |
| |-- tools/
| |
| |-- resources/
| |
| |-- prompts/
| |
| `-- apps/
|
|-- tests/
| |
| |-- unit/
| `-- integration/
|
|-- .env.example
|-- .gitignore
|-- .python-version
|-- pyproject.toml
|-- uv.lock
`-- README.md文件夹应在具有实际职责时引入。
模板不应仅仅为了拥有更多层而创建抽象。
层职责
Related MCP server: NitroStack
领域层
包含核心业务概念和契约。
示例:
Product
Cart
ProductRepository
CartRepository
ProductNotFoundError
CartError领域层应包含业务概念,而不需要知道外部世界如何与应用通信。
应用层
包含应用特定的工作流和用例。
示例:
GetProductUseCase
SearchProductsUseCase
AddProductToCartUseCase
GetCartUseCase用例协调领域抽象。
它不应直接调用外部 API。
不好的做法
class GetProductUseCase:
def execute(self, product_id: int):
requests.get(
f"https://external-api/products/{product_id}"
)用例现在知道了:
HTTP 存在
使用了哪个 HTTP 库
使用了哪个外部提供商
提供商 URL 如何工作
推荐做法
class GetProductUseCase:
def __init__(self, repository: ProductRepository):
self.repository = repository
def execute(self, product_id: int) -> Product:
return self.repository.get_by_id(product_id)现在用例只知道契约:
ProductRepository基础设施层
包含外部技术关注点的实现。
示例:
HTTP clients
REST APIs
repositories
databases
cache
environment configuration
external service adapters例如:
ProductRepository
^
|
DummyJsonProductRepository基础设施实现领域抽象。
领域层不依赖基础设施层。
表示层
包含 MCP 特定的入口点。
示例:
FastMCP Server
MCP Tools
MCP Resources
MCP Prompts
MCP AppsMCP 工具应保持精简。
其职责主要是:
MCP Request
|
v
Validate / map input
|
v
Use Case
|
v
Map result
|
v
MCP Response业务逻辑不应存在于 MCP 装饰器内部。
MCP 架构
MCP 和 FastMCP 是不同的概念。
MCP
|
`-- Protocol
FastMCP
|
`-- Python framework implementing MCP应用通过 Streamable HTTP 使用 MCP。
MCP Host
|
| Streamable HTTP
v
http://localhost:8000/mcp
|
v
FastMCP Server服务器默认配置为运行无状态 HTTP。
MCP 组件
工具
模型可以执行的操作。
示例:
get_product
search_products
add_product_to_cart
get_cart
remove_product_from_cart概念上:
LLM
|
| tool call
v
MCP Tool
|
v
Use Case资源
资源暴露 MCP 主机可以读取的数据或上下文。
它们不应成为应用业务逻辑的替代品。
提示词
提示词通过 MCP 提供可复用的提示词模板。
它们属于 MCP / 表示层边界。
MCP 应用 UI
MCP 应用允许兼容的 MCP 主机显示与 MCP 功能关联的交互式 UI。
我们的电子商务示例最终将渲染概念上类似于以下内容的东西:
+--------------------------------+
| Product |
| |
| Smartphone |
| |
| $799.99 |
| |
| [ Add to cart ] |
+---------------+----------------+
|
v
MCP Tool Call
|
v
AddProductToCartUseCase
|
v
CartRepository重要的架构规则是:
MCP 应用 UI 是表示层关注点。
UI 不应实现业务规则。
例如,点击:
[ Add to cart ]应导致:
MCP App UI
|
v
MCP Tool
|
v
AddProductToCartUseCase
|
v
CartRepositoryUI 不直接操作基础设施。
环境配置
运行时配置必须来自环境变量,而不是硬编码。
当前变量:
MCP_SERVER_TRANSPORT
MCP_SERVER_HOST
MCP_SERVER_PORT
MCP_STATELESS_HTTP示例:
$env:MCP_SERVER_PORT="9000"配置流程为:
Operating System / Container
|
| Environment Variables
v
EnvironmentSettings
|
v
server.py
|
v
FastMCP这允许相同的应用代码在以下环境中运行:
Local
Development
Test
Staging
Production
Docker
Kubernetes
Cloud environments并使用不同的配置。
机密信息绝不能提交到 Git。
Python 包约定
__init__.py 可用于定义 Python 包的公共 API。
例如:
from infrastructure.config.environment import EnvironmentSettings
__all__ = [
"EnvironmentSettings",
]使用者随后可以使用:
from infrastructure.config import EnvironmentSettings而不是:
from infrastructure.config.environment import EnvironmentSettings这减少了对内部文件结构的耦合。
概念上,这类似于 TypeScript 中的:
index.ts用作桶导出(barrel export)。
__all__ 定义了预期的公共 API。
它不是像 C# 中 public 或 private 那样的访问修饰符。
Python / C# 参考
该项目也旨在帮助 .NET 开发者学习 Python。
Python | C# 概念 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 大致相当于 |
|
|
|
|
|
|
仓储 | 通常类似于 |
| 近似于 |
|
|
|
|
|
|
| 构造函数 |
| 包初始化 / 与桶导出目的类似 |
Pydantic | 类型化模型 + 验证/序列化 |
| 概念上类似于特性/中间件行为,具体取决于用法 |
当引入新的 Python 概念时,应在有用时记录其 C# 对应概念。
领域模型
在验证和序列化有用的情况下,结构化模型使用 Pydantic。
示例:
from typing import Annotated
from pydantic import BaseModel
class Product(BaseModel):
id: Annotated[int, "Product identifier"]
title: Annotated[str, "Product title"]
description: Annotated[str, "Product description"]
price: Annotated[float, "Product price"]
thumbnail: Annotated[str, "Product thumbnail URL"]Pydantic 提供:
validation
type coercion
serialization
JSON-compatible output
JSON Schema generation仓储模式
仓储代表对数据或外部系统的抽象。
示例:
from abc import ABC, abstractmethod
from domain.entities import Product
class ProductRepository(ABC):
@abstractmethod
def get_by_id(self, product_id: int) -> Product:
pass对于 C# 开发者来说,这在概念上类似于:
public interface IProductRepository
{
Product GetById(int productId);
}具体的基础设施实现随后可以提供实际行为:
ProductRepository
^
|
DummyJsonProductRepository外部 API
外部 API 必须从基础设施层访问。
初始实现使用公共 DummyJSON API 作为电子商务示例。
架构防止应用用例直接依赖 DummyJSON。
Application
|
v
ProductRepository
^
|
Infrastructure implementation
|
v
DummyJSON这允许以后替换外部提供商,而无需重写应用层或领域层。
错误处理策略
项目使用受整洁架构和常见 .NET 异常处理模式启发的集中式异常层次结构。
目标是区分:
expected business failures
vs
technical/infrastructure failures同时提供统一的结构化错误契约。
错误层次结构
AppError
|
|-- DomainError
| |
| |-- ProductNotFoundError
| `-- CartError
|
|-- ValidationError
|
`-- InfrastructureError
|
|-- ExternalAPIError
`-- ExternalAPITimeoutError所有已知的应用错误最终都派生自:
AppError基础应用错误
from typing import Any
class AppError(Exception):
error_code: str = "UNKNOWN_ERROR"
def __init__(
self,
message: str,
details: dict[str, Any] | None = None,
):
self.message = message
self.details = details or {}
super().__init__(message)
def to_dict(self) -> dict:
return {
"error_code": self.error_code,
"error_type": self.__class__.__name__,
"message": self.message,
"details": self.details,
}概念上,这类似于 C#:
public abstract class AppException : Exception
{
public string ErrorCode { get; }
protected AppException(
string message,
string errorCode)
: base(message)
{
ErrorCode = errorCode;
}
}领域错误
领域错误表示预期的业务失败。
示例:
Product does not exist
Cart is empty
Product cannot be added to the cart
Requested quantity violates a business rule示例:
class DomainError(AppError):
error_code = "DOMAIN_ERROR"
class ProductNotFoundError(DomainError):
error_code = "PRODUCT_NOT_FOUND"
def __init__(self, product_id: int):
super().__init__(
message=f"Product '{product_id}' was not found.",
details={
"product_id": product_id,
},
)概念上类似于:
public class ProductNotFoundException : DomainException
{
public int ProductId { get; }
public ProductNotFoundException(int productId)
: base($"Product '{productId}' was not found.")
{
ProductId = productId;
}
}验证错误
验证错误表示无效的应用输入或违反的约束。
示例:
Invalid product ID
Quantity must be greater than zero
Missing required input
Invalid cart operation这些是预期的失败。
它们应提供足够的结构化信息,使 MCP 主机或 LLM 能够理解需要纠正什么。
基础设施错误
基础设施错误表示涉及技术依赖的失败。
示例:
External API unavailable
HTTP timeout
Connection failure
Unexpected downstream response
Database unavailable例如:
class InfrastructureError(AppError):
error_code = "INFRASTRUCTURE_ERROR"
class ExternalAPIError(InfrastructureError):
error_code = "EXTERNAL_API_ERROR"领域层绝不能依赖基础设施异常。
原始库异常不应泄漏到整个应用。
例如:
httpx.TimeoutException
|
v
ExternalAPITimeoutError
|
v
Application / Presentation而不是:
httpx.TimeoutException
|
+---------------------> MCP Host错误转换
基础设施负责在适当时转换低层技术失败。
例如:
HTTP 404 from product provider
|
v
ProductNotFoundError
HTTP timeout
|
v
ExternalAPITimeoutError
HTTP 500
|
v
ExternalAPIError这防止应用的其余部分与特定 HTTP 库耦合。
表示层错误边界
MCP 工具不应包含重复的错误处理。
避免:
@mcp.tool
def tool_one():
try:
...
except AppError:
...
@mcp.tool
def tool_two():
try:
...
except AppError:
...
@mcp.tool
def tool_three():
try:
...
except AppError:
...期望的架构是:
MCP Host
|
v
Presentation Error Boundary
|
v
MCP Tool
|
v
Use Case
|
v
Domain / Repository已知的应用错误可以转换为结构化的 MCP 友好错误。
意外异常应:
logged
|
v
converted to generic internal error
|
v
returned without sensitive details这在概念上类似于 ASP.NET Core:
Python / MCP ASP.NET Core
AppError AppException
DomainError DomainException
InfrastructureError InfrastructureException
central error boundary IExceptionHandler / Middleware
raise throw
except catch结构化错误
错误在有用时应包含结构化信息。
示例:
{
"error_code": "PRODUCT_NOT_FOUND",
"error_type": "ProductNotFoundError",
"message": "Product '123' was not found.",
"details": {
"product_id": 123
}
}结构化错误改善了:
MCP 客户端行为
LLM 推理
日志记录
可观测性
自动化测试
调试
错误处理规则
不要直接将原始基础设施异常暴露给 MCP 客户端。
不要在每一个 MCP 工具中重复
try/except块。对预期的业务失败使用特定的领域错误。
对无效输入和违反的约束使用验证错误。
将外部技术失败转换为应用特定错误。
通过
details保留有用的结构化上下文。在应用边界记录意外异常。
绝不向 MCP 客户端暴露机密、令牌、堆栈跟踪或敏感的基础设施细节。
保持错误代码稳定,以便客户端和自动化测试可以依赖它们。
表示层负责将应用错误转换为 MCP 友好的响应。
依赖注入与组合
依赖关系应显式化。
例如:
DummyJsonProductRepository
|
v
GetProductUseCase
|
v
MCP Tool组合/根接线属于应用入口点附近,而不是领域层内部。
项目应在实际可行时避免隐藏的全局依赖。
这将随着应用的增长逐步引入。
测试策略
架构应允许在不依赖以下条件的情况下测试业务行为:
starting FastMCP
calling DummyJSON
opening an HTTP port
running MCP App UI例如:
Unit Test
|
v
GetProductUseCase
|
v
FakeProductRepository这使得用例可以独立测试。
单元测试
单元测试应专注于:
Domain behavior
Use Cases
Validation
Error handling使用假(fake)或模拟(mock)依赖。
集成测试
集成测试可以分别验证边界:
Infrastructure
|
v
DummyJSON API以及:
MCP Client
|
v
FastMCP Server这种分离防止外部 API 行为使每个业务测试变得不可靠。
开发环境设置
要求:
Python 3.12+
uv安装/同步依赖:
uv sync运行 MCP 服务器:
uv run python -m presentation.mcp.server默认端点:
http://localhost:8000/mcp虚拟环境
项目使用:
.venv/用于隔离的 Python 依赖。
uv 自动管理项目环境。
命令通常应使用以下方式执行:
uv run ...例如:
uv run python --version这可以避免依赖全局安装的项目依赖。
开发原则
在扩展此模板时:
将 MCP 特定代码保留在 Presentation 中。
将业务工作流保留在 Application 中。
在可行的情况下,保持业务模型和契约独立于框架。
将外部集成保留在 Infrastructure 中。
依赖抽象而不是具体的 Infrastructure 实现。
保持 MCP Tools 轻量。
不要硬编码特定于环境的配置。
不要提交机密信息。
优先使用类型化 Python。
在系统边界验证外部数据。
当外部 API DTO 与领域模型结构不同时,将其分开。
使用例可独立测试。
优先使用显式依赖,而不是隐藏的全局状态。
在解决实际架构问题时添加抽象。
保持 Domain 独立于 FastMCP。
在将 Infrastructure 故障暴露到其边界之外之前进行转换。
使用稳定的结构化错误代码。
保持 MCP App UI 专注于表示和交互。
不要将业务逻辑放在 MCP 装饰器中。
保持外部 API 可替换。
计划的学习流程
该模板正在增量构建中。
FastMCP Server
|
v
HTTP Transport
|
v
Environment Configuration
|
v
Python Package Structure
|
v
Pydantic Models
|
v
Domain Entities
|
v
Repository Contracts
|
v
Error Hierarchy
|
v
Infrastructure / External API
|
v
Application Use Cases
|
v
MCP Tools
|
v
Dependency Composition
|
v
Centralized Error Handling
|
v
MCP Resources
|
v
MCP Prompts
|
v
MCP App UI
|
v
Interactive MCP Actions
|
v
Unit Tests
|
v
Integration Tests
|
v
Claude / Copilot integration最终目标
最终项目应演示完整流程:
Claude / Copilot
|
| MCP over HTTP
v
FastMCP Server
|
v
MCP App UI
|
| user action
v
MCP Tool
|
v
Application Use Case
|
v
Domain Contract
|
v
Infrastructure Adapter
|
| HTTP
v
External Service错误则安全地沿相反方向流动:
External failure
|
v
Infrastructure Error
|
v
Application / Domain Error
|
v
Presentation Error Boundary
|
v
Structured MCP Error
|
v
Claude / Copilot目的
本仓库旨在成为一个可复用的模板和学习参考,用于使用 Clean Architecture 创建生产级 FastMCP 服务器和 MCP 应用。
该项目演示了如何将 MCP 视为应用程序边界,而不是让 MCP 特定的关注点扩散到整个代码库。
核心业务逻辑应保持独立于:
FastMCP
MCP transport
MCP App UI
Claude
Copilot
HTTP providers
databases
external APIs这使应用程序更易于:
maintain
test
extend
replace integrations
run in different environments
connect to different MCP hosts同时保持清晰的架构边界。
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- FlicenseNot gradedqualityDmaintenanceA Model Context Protocol server that enables AI assistants to interact with a complete e-commerce application, providing authentication, product browsing, and shopping cart management through standardized MCP tools.

NitroStackofficial
FlicenseNot gradedqualityBmaintenanceA Python framework for building MCP servers with modular architecture, dependency injection, and built-in authentication. Enables creating scalable, testable MCP services with features like pipeline interceptors and background tasks.3- AlicenseNot gradedqualityCmaintenanceA production-ready template for developing Model Context Protocol (MCP) servers using Python and FastMCP.Apache 2.0
- FlicenseNot gradedqualityCmaintenanceThis enterprise MCP server template provides a production-ready, architecture-first foundation for building MCP servers in Python, with capability registry, dependency injection, and Docker support.
Related MCP Connectors
FastMCP commerce server starter: product catalog, search, and checkout. Deploy to Vercel in 5 min.
Hosted Amazon Seller and Vendor MCP server for Claude, ChatGPT, Cursor, Codex, Gemini, Copilot.
MCP Server for Slima - AI Writing IDE for Novel Authors with AI Beta Reader.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/renaisanci/mcp-clean-architecture'
If you have feedback or need assistance with the MCP directory API, please join our Discord server