DMVCFramework的MCP服务器
](https://github.com/danieleteti/mcp-server-delphi)  
应用程序通过标准化的MCP协议向AI助手公开工具、资源和提示。
🚀 带DMVCFramework的MCP服务器?当然!即使对于本地AI引擎也是如此。 这意味着,例如,您可以将ERP功能直接集成到任何AI客户端中。 所以,你可以问你的克劳德/双子座/其他: *“3月份哪种产品的收入最高?”* 答案将来自 您的ERP! 💡 毕竟,如果不是DMVCFramework服务器,那么托管MCP服务器最容易的地方是什么? 😉
特性
- MCP协议2025-03-26 顺从的
- 服务器、客户端和代理:构建MCP服务器,并使用它们
TMCPClient(HTTP)或TMCPStdioClient(子进程+管道),并通过以下方式从任何兼容OpenAI的LLM驱动它们TMCPOpenAIAgent(与OpenAI、OpenRouter、Anthropic compat、Together、Groq、Ollama、vLLM、llama.cpp合作--api) - 属性驱动 使用RTTI进行工具/资源/提示注册
- 双重运输,服务器端和客户端:可流式传输的HTTP和stdio
- 会话管理 具有自动清理功能
- 类型安全 具有自动JSON模式生成的参数绑定
- 多种内容类型:文本、图像(base64)、音频(base64的)、嵌入式资源
- 流利的API 用于构建多内容响应
- 丰富的提示信息:提示中的文本、图像和嵌入式资源内容
- DMVC框架集成 通过
PublishObject模式
快速开始
最快的开始方式是 复制快速入门示例 并对其进行自定义。有三个项目可供选择——选择一个适合您的部署:
| 项目 | 角色 | 传输 | 需要TaurusTLS | 在以下情况下使用 |
|---|---|---|---|---|
quickstart/quickstart/ | 服务器 | HTTP+stdio | 是 | 您想要一个AI客户端通过HTTP连接的网络服务器 |
quickstart/quickstart_stdio/ | 仅限服务器 | stdio | 不 | 您希望AI客户端(例如Claude Desktop)在本地启动服务器 |
quickstart/quickstart_stdio_agent/ | 代理(主机+客户端) | 站立 | 不 | 你想要一个Delphi端的AI代理,它生成并使用一个由OpenAI兼容的LLM驱动的stdio MCP服务器 |
两个项目共享 同一供应商单位 在 quickstart/shared/ --您只需编写一次工具、资源和提示,两种传输方式都会使用它们。
1.复制和构建
quickstart/
├── shared/ 💡 如果改用HTTP+stdio项目,请添加 `"args": ["--transport", "stdio"]`.
#### ♊ 谷歌Gemini CLI
编辑 `~/.gemini/settings.json`:
{ "mcpServers": { "my-server": { "url": "http://localhost:8080/mcp" } } }
#### 🧑💻 克劳德代码(CLI)
claude mcp add --transport http my-server http://localhost:8080/mcp
#### 🦊 继续(VS代码/JetBrains)
编辑 `~/.continue/config.yaml`:
mcpServers: - name: my-server url: http://localhost:8080/mcp
#### 🔌 任何兼容MCP的客户端
POST http://:8080/mcp
> 💡 **提示:** 对于生产,请在您的 `.env` 归档并替换 `localhost` 使用服务器的主机名。
## 建筑
┌─────────────────────────────────────────────────────────────┐ │ Client (AI Assistant) │ └──────────┬─────────────────────────────────┬────────────────┘ │ Streamable HTTP │ stdio ▼ ▼ ┌──────────────────────────────┐ ┌──────────────────────────┐ │ TMCPEndpoint (PublishObject)│ │ TMCPStdioTransport │ │ TMCPSessionController │ │ (stdin/stdout JSON-RPC) │ │ (POST/DELETE /mcp) │ │ │ └──────────────┬──────────────┘ └─────────────┬────────────┘ │ │ └──────────┬─────────────────────┘ ▼ ┌─────────────────────────────────────────────────────────────┐ │ TMCPRequestHandler (transport-agnostic dispatch) │ └─────────────────────────┬───────────────────────────────────┘ ▼ ┌─────────────────────────────────────────────────────────────┐ │ TMCPServer (Singleton) │ │ ├─ Tool Registry: TDictionary │ │ ├─ Resource Registry: TDictionary│ │ ├─ Prompt Registry: TDictionary │ │ └─ Session Manager: IMCPSessionManager │ └─────────────────────────────────────────────────────────────┘ │ ┌───────────┼───────────┐ ▼ ▼ ▼ TMCPTool TMCPResource TMCPPrompt Provider Provider Provider
## API 参考
### 工具结果工厂方法
|方法|说明|
|--------|-------------|
| `TMCPToolResult.Text(const AText: string)` |返回文本内容|
| `TMCPToolResult.Error(const AMessage: string)` |返回错误文本 `isError=true` |
| `TMCPToolResult.Image(const ABase64Data, AMimeType: string)` |返回图像内容|
| `TMCPToolResult.Audio(const ABase64Data, AMimeType: string)` |返回音频内容|
| `TMCPToolResult.Resource(AURI, AText, AMimeType)` |返回嵌入资源(文本)|
| `TMCPToolResult.ResourceBlob(AURI, ABase64Data, AMimeType)` |返回嵌入式资源(blob)|
| `TMCPToolResult.JSON(AJSON: TJDOJsonObject)` |将JSON对象序列化为文本|
| `TMCPToolResult.FromObject(AObject: TObject)` |将TObject序列化为JSON文本|
| `TMCPToolResult.FromCollection(AList: TObject)` |将TObjectList序列化为JSON数组|
| `TMCPToolResult.FromRecord(ARecord, ARecordTypeInfo)` |将记录序列化为JSON文本|
| `TMCPToolResult.FromDataSet(ADataSet: TDataSet)` |将数据集序列化为JSON数组|
| `TMCPToolResult.FromValue(...)` |将整数、Int64、双精度或布尔值转换为文本|
| `TMCPToolResult.FromStream(AStream, AMimeType)` |将流编码为base64图像内容|
### 生成器方法(Fluent API)
Result := TMCPToolResult.Text('Analysis complete') .AddImage(LChartBase64, 'image/png') .AddResource('file:///report.csv', LCsvData, 'text/csv');
### 属性
|属性|目标|签名|
|-----------|--------|-----------|
| `[MCPTool(Name, Description)]` |方法|将该方法注册为MCP工具|
| `[MCPParam(Description)]` |参数|必填参数(默认)|
| `[MCPParam(Description, TMCPParamPresence.Optional)]` |参数|可选参数--省略时接收零/空默认值|
| `[MCPResource(URI, Name, Description, MimeType)]` |方法|将该方法注册为MCP资源|
| `[MCPPrompt(Name, Description)]` |方法|将该方法注册为MCP提示符|
| `[MCPPromptArg(Name, Description)]` |方法|可选提示参数(默认)|
| `[MCPPromptArg(Name, Description, TMCPParamPresence.Required)]` |方法|必需的提示参数|
`TMCPParamPresence` 是一个作用域枚举(`{$SCOPEDENUMS ON}`)有两个值: `Required` 和 `Optional`。每个调用站点都必须使用完全限定的形式。参数名称和类型是通过RTTI从Delphi签名中自动发现的——只需要在属性中拼写描述(以及可选的存在性)。
[MCPTool('concat_strings', 'Concatenates two strings with a separator')] function ConcatStrings( [MCPParam('First string')] const A: string; [MCPParam('Second string')] const B: string; [MCPParam('Separator (default: space)', TMCPParamPresence.Optional)] const Sep: string ): TMCPToolResult;
支持的参数类型: `string`, `Integer`, `Int64`, `Double`, `Boolean`。库生成相应的JSON模式 `type` 自动。
### 资源URI模板(RFC 6570级别1)
URI包含的资源 `{placeholder}` 分段是a **模板**:
一个宣言代表了一个无限的具体资源家族。这
框架列出了以下模板 `resources/templates/list` 和比赛
传入的 `resources/read` URI会自动针对它们。
type TMyResources = class(TMCPResourceProvider) public // Single-variable template [MCPResource('user://{id}', 'User Profile', 'Returns a user profile by ID', 'application/json')] function GetUser(const URI, id: string): TMCPResourceResult;
// Multi-variable template (canonical MCP spec example) [MCPResource('weather://forecast/{city}/{date}', 'Weather Forecast', 'Returns the forecast for a city on a date', 'application/json')] function GetForecast(const URI, city, date: string): TMCPResourceResult; end;
**方法签订合同**:
- 第一个参数始终是完整的具体URI(符合静态资源约定)。
- 另一个 `string` 参数per `{var}` 在模板中,按从左到右的顺序。
- 参数名称必须与占位符名称匹配(不区分大小写)。框架在启动时拒绝不匹配的签名。
**调度单**一 `resources/read` 请求首先在
静态注册表(O(1))。未命中时,依次匹配已注册的模板
通过缓存的正则表达式(每个捕获组一个 `{var}`).静态资源保持
他们的预模板性能。
**局限性** (有意):仅RFC 6570级别1(`{var}`)支持。
运营商喜欢 `{+var}`, `{#var}`, `{?var}` 注册时被拒绝
时间有明显的错误。每个变量都匹配 `[^/]+` (一个路径段),
它涵盖了绝大多数资源模板用例。
### MCP协议方法
|方法|说明|
|--------|-------------|
| `initialize` |创建会话,返回服务器功能|
| `notifications/initialized` |客户端通知(无响应)|
| `ping` |健康检查|
| `tools/list` |列出可用工具|
| `tools/call` |执行工具|
| `resources/list` |列出可用的具体资源|
| `resources/templates/list` |列出URI模板化资源(RFC 6570级别1)|
| `resources/read` |按URI读取资源(具体或模板匹配)|
| `prompts/list` |列出可用提示|
| `prompts/get` |获取带有参数的提示|
## 配置
创建一个 `.env` 应用程序目录中的文件:
Server
dmvc.server.port=8080
Logger (optional — overrides defaults picked by BootConfigU)
logger.config.file=loggerpro.json logger.config.file.stdio=loggerpro.stdio.json
Profiler (optional, Sydney+)
dmvc.profiler.enabled=false dmvc.profiler.warning_threshold=1000 dmvc.profiler.logs_only_over_threshold=true
HTTPS (optional — run generate_certificates.bat first)
https.enabled=true https.cert.cacert=certificates\localhost.crt https.cert.privkey=certificates\localhost.key https.cert.password=
这 `sample/` 和 `tests/testproject/` 项目同时提供
`loggerpro.json` (控制台+文件附加器,用于HTTP模式)和
`loggerpro.stdio.json` (仅限文件,因此MCP的stdout保持干净
JSON-RPC)在他们的 `bin/` 文件夹。 `BootConfigU` 选对了
自动基于 `--transport`.
### 🔒 HTTPS设置
A. `generate_certificates.bat` 脚本包含在 `sample/bin/` 为本地开发生成自签名证书:
cd sample/bin generate_certificates.bat
这创造了 `certificates\localhost.crt` 和 `certificates\localhost.key`,准备与 `.env` 上面的配置。该脚本需要OpenSSL(与Windows版Git捆绑或可单独安装)。
## 测试✅
三个独立的合规套件覆盖了整个库:
- **Python HTTP合规套件** (`tests/test_mcp_server.py`)--185个测试用例通过Streamable HTTP对服务器进行端到端的测试。验证JSON-RPC 2.0、MCP协议、会话生命周期、所有 `TMCPToolResult` 内容类型、URI模板和错误处理。
- **Python stdio合规套件** (`tests/test_mcp_server_stdio.py`)--142个测试用例执行端到端的stdio传输。涵盖初始化、所有协议方法、批拒绝、stdout纯度、通知语义和错误代码。
- **TMCP客户端套件** (`tests/clientproject/`)--21个Delphi测试用例,驱动客户端与正在运行的测试服务器进行交互。跑 **两次**:一旦通过流式HTTP(`TMCPClient`)一旦通过stdio(`TMCPStdioClient` 在stdio模式下生成相同的testprojectexe)。相同的测试代码,通过传输切换 `--stdio-cmd`。涵盖:握手、工具、静态+模板化资源、提示、网桥代理工具、JSON-RPC错误信封处理。
- **TMCPOpenAIAgent套件** (`tests/agentproject/`)--8个执行代理循环的Delphi测试用例(`MVCFramework.MCP.OpenAIAgent`)端到端。嵌入确定性假LLM(DMVCFramework控制器响应 `/v1/chat/completions`)因此可以在没有外部网络依赖性的情况下验证循环。涵盖了单工具调度、令牌计费、系统提示前缀、OpenRouter分析标头以及 `MaxTurns` 安全网。
测试项目(`tests/testproject/`)注册行使权利的提供者 **每个特征** 图书馆:
- **18工具** 涵盖所有 `TMCPToolResult` 工厂方法: `Text`, `Error`, `Image`, `Audio`, `JSON`, `FromValue`, `FromObject`, `FromCollection`, `FromStream`, `Resource`,流利 `AddText`/`AddImage`/`AddResource` 建筑商API
- **3静态资源** (文本JSON、文本纯文本、图像blob)+ **2个模板化资源** (`user://{id}` 和 `weather://forecast/{city}/{date}`)练习单变量和多变量URI模板
- **3个提示** --具有必需/可选参数和多消息对话
- **合规性提供商** --MCP协议一致性测试的专用工具、资源和提示(文本、图像、音频、嵌入式资源、多内容、错误处理)
- 所有参数类型: `string`, `Integer`, `Double`, `Boolean`,加上可选参数
### 同时运行所有套房(推荐)
cd tests build_all.bat :: builds testproject + clientproject + agentproject (Win32 Debug) run_all.bat :: starts the server, runs Python + TMCPClient + TMCPOpenAIAgent suites, exits non-zero on any failure
### 经营个人套房
1. Build the test server
cd tests/testproject
(build with Delphi IDE or command line)
2a. HTTP transport: start the server manually, then run the HTTP suite
bin/MCPServerUnitTest.exe --transport http python ../test_mcp_server.py -v
2b. Stdio transport: the suite launches the server as a subprocess
python ../test_mcp_server_stdio.py -v
2c. Delphi TMCPClient compliance (server must be running)
../clientproject/bin/MCPClientTest.exe --url http://localhost:8080/mcp
2d. Delphi TMCPOpenAIAgent compliance (server must be running;
the agent test starts its own fake LLM on port 9091)
../agentproject/bin/MCPAgentTest.exe --mcp-url http://localhost:8080/mcp
stdio套件可以通过以下方式指向任何支持stdio的MCP服务器
`--cmd "path/to/exe [args...]"` 并检查,除其他事项外
stdout仅包含有效的JSON-RPC(无日志污染)。
合规范围包括:
- MCP 2025-03-26协议合规性
- JSON-RPC 2.0规范
- 会话生命周期(创建、验证、删除、超时)
- 工具/资源/快速执行和错误处理
- 所有内容类型:文本、图像、音频、嵌入式资源
- URI模板: `resources/templates/list` 形状、多变量匹配、拒绝未膨胀 `{var}` URI和不完整段URI
- 并发会话
- HTTP方法限制
- 内容类型验证
## 项目结构
. ├── sources/ # Core library │ ├── MVCFramework.MCP.Server.pas # Server registry and endpoint │ ├── MVCFramework.MCP.RequestHandler.pas # Transport-agnostic MCP dispatch │ ├── MVCFramework.MCP.Client.pas # MCP client over Streamable HTTP (TMCPClient + abstract TMCPClientBase) │ ├── MVCFramework.MCP.Client.Stdio.pas # MCP client over stdio (subprocess + pipes) │ ├── MVCFramework.MCP.OpenAIAgent.pas # Agent loop: OpenAI-compat LLM + MCP tools (any transport) │ ├── MVCFramework.MCP.Stdio.pas # stdio transport (stdin/stdout) │ ├── MVCFramework.MCP.TransportConf.pas # Early transport detection │ ├── MVCFramework.MCP.Attributes.pas # Custom attributes │ ├── MVCFramework.MCP.ToolProvider.pas # Tool base class and results │ ├── MVCFramework.MCP.ResourceProvider.pas # Resource base class │ ├── MVCFramework.MCP.PromptProvider.pas # Prompt base class │ ├── MVCFramework.MCP.Session.pas # Session management │ └── MVCFramework.MCP.Types.pas # Protocol types and constants ├── quickstart/ # Quick-start samples (minimal, pedagogical) │ ├── shared/ # ★ Shared providers — customize these │ │ ├── ToolProviderU.pas # Example tools │ │ ├── ResourceProviderU.pas # Example resources │ │ └── PromptProviderU.pas # Example prompts │ ├── quickstart/ # HTTP + stdio server (Indy Direct) │ │ ├── QuickStart.dpr/.dproj # Console app │ │ └── bin/.env # Server port configuration │ ├── quickstart_stdio/ # stdio-only server (no TaurusTLS) │ │ └── QuickStartStdio.dpr/.dproj # Lightweight console app │ └── quickstart_stdio_agent/ # ★ Agent that spawns & consumes a stdio server │ ├── QuickStartStdioAgent.dpr/.dproj # Delphi-side AI agent (REPL) │ └── bin/.env.example # LLM key + model + server command ├── sample/ # Full-featured example (wizard-style layout) │ ├── MCPServerSample.dpr # Slim entry point (HTTP + stdio + HTTPS) │ ├── BootConfigU.pas # dotEnv + LoggerPro + profiler │ ├── EngineConfigU.pas # Controllers + PublishObject wiring │ ├── MyToolsU.pas # Example MCP tools │ └── bin/ │ ├── loggerpro.json # Console + file appender config │ ├── loggerpro.stdio.json # File-only appender config (stdio mode) │ └── generate_certificates.bat # Self-signed SSL cert generator └── tests/ ├── test_mcp_server.py # Python compliance suite (HTTP) ├── test_mcp_server_stdio.py # Python compliance suite (stdio) ├── build_all.bat # Builds all three test projects ├── run_all.bat # Orchestrates the full pipeline ├── testproject/ # Delphi test server (wizard-style layout) │ ├── MCPServerUnitTest.dpr # Slim entry point (HTTP + stdio) │ ├── BootConfigU.pas # dotEnv + LoggerPro + profiler │ ├── EngineConfigU.pas # Controllers + PublishObject wiring │ ├── MCPTestToolsU.pas # 18 tools covering all result types │ ├── MCPTestResourcesU.pas # 3 static + 2 templated resources │ ├── MCPTestPromptsU.pas # 3 prompts with arguments │ └── MCPConformanceProvidersU.pas # Conformance test providers ├── clientproject/ # TMCPClient compliance (Delphi console) │ └── MCPClientTest.dpr # 17 test cases └── agentproject/ # TMCPOpenAIAgent compliance (Delphi console) └── MCPAgentTest.dpr # 8 test cases + embedded fake LLM controller
## 服务器体系结构
所有HTTP/HTTPS传输都在DMVCFramework上运行 **Indy Direct** 后端。
发动机是用 `TMVCEngine.Create(AConfigAction)` 并被包裹
`TMVCServerFactory.CreateIndyDirect`不 `TWebModule`,没有网上经纪服务
桥:引擎直接从以下位置发送请求 `TIdHTTPServer`.
HTTPS是通过以下方式选择加入的 `TaurusTLSIndyConfigurator` 随着 `CertFile` /
`KeyFile` / `CertPassword` 属性在 `IMVCServer`.
### 项目布局(向导风格)
这 `sample/` 和 `tests/testproject/` 项目遵循DMVC框架
向导布局: `.dpr` 保持纤薄,配置分为
两个单位:
- **`BootConfigU.Boot`** --启动时运行一次:配置dotEnv,
安装a `LoggerPro` JSON配置中的记录器(选择
`loggerpro.stdio.json` 在stdio模式下, `loggerpro.json` 否则),以及
启用分析器。称之为第一个声明 `begin..end`,
之前任何 `LogI`.
- **`EngineConfigU.ConfigureEngine`** --添加控制器
(`TMCPSessionController`)并在以下位置发布MCP端点 `/mcp` 通过
`PublishObject`扩展此单元以添加您自己的控制器,
例如硬件、中间件或额外发布的对象。
阅读 `MCPServerSample.dpr` 从上到下显示整个启动过程
序列:解析命令行→ `Boot` → 创建引擎→ `ConfigureEngine`
→ 运行HTTP(可选HTTPS)或stdio传输。
## 需求
- 德尔福11+(亚历山大)或更高版本
- DMVC框架3.5.x
## 许可证
Apache许可证2.0-请参阅 [许可证](LICENSE) 了解详情。
## 链接
- [模型上下文协议规范](https://modelcontextprotocol.io/specification/2025-03-26)
- [DMVC框架](https://github.com/danieleteti/delphimvcframework)
- [问题追踪器](https://github.com/danieleteti/delphimvcframework/issues)
______________________________________________________________________
建于❤️ 作者:丹妮·特蒂