uWebMCP
创建您的Umbraco网站 代理本地.uWebMCP实现了 模型上下文协议(MCP) 对于Umbraco 17,使AI代理能够发现您的网站提供的内容,与表单交互,并采用您的品牌声音——所有这些都是通过标准化协议实现的。
问题
Umbraco网站对AI代理是不可见的。代理(Chrome EPP、Claude、Gemini)没有标准化的方法来发现网站提供的操作或以编程方式与表单和内容进行交互。
解决方案
uWebMCP将您的Umbraco网站转换为 代理内容平台 通过:
- 提供发现清单 在
/.well-known/mcp-manifest.json这样代理就知道你的网站提供了什么工具和资源 - 将内容类型分为工具和资源 --可操作类型(联系表单)成为可调用的工具;信息类型(博客、产品)成为结构化资源
- 支持具有真实执行逻辑的自定义工具 通过
IWebMcpTool--定义“购买产品”工具、“预约”工具或任何其他具有实际行为的工具 - 将Umbraco Forms转换为代理可调用工具 内置验证(幻觉防护)和蜜罐垃圾邮件防护
- 定义品牌声音(“灵魂”) 代理在代表您的网站进行交互时采用的方法
- 提供分析 哪些AI代理正在发现和调用您网站的工具
建筑
uWebMcp.Core Razor Class Library — persistence, services, caching, middleware, API
uWebMcp.Forms Optional — maps Umbraco.Forms into MCP tool definitions
uWebMcp.Backoffice Management API + Lit/TypeScript "Agent Intelligence" dashboard运作原理
AI Agent Umbraco Site
│ │
├── GET /.well-known/mcp-manifest.json ──► McpManifestMiddleware
│ ◄── { tools, resources, prompts } reads from ToolCacheService
│ │
├── GET /umbraco/api/webmcp/tools ──────► WebMcpToolsController
│ ◄── [{ name, inputSchema, ... }] actionable tools only
│ │
├── GET /umbraco/api/webmcp/resources ──► WebMcpToolsController
│ ◄── [{ uri, name, description }] informational resources
│ │
├── POST /umbraco/api/webmcp/tools/ │
│ {alias}/execute ───────────────► Validates CSRF + honeypot
│ ◄── { success, message, data } delegates to IWebMcpTool
│ │
└── GET /umbraco/api/webmcp/prompts/get ► SoulService
◄── { persona, tone, rules } brand voice configuration快速开始
先决条件
- .NET 10 SDK
- Node.js 20+(用于后台仪表板开发)
运行演示网站
git clone
cd uWebMCP
# Build and run
dotnet build
dotnet run --project demo/uWebMcp.DemoSite演示站点使用无人值守安装,不需要向导。导航到 https://localhost:44391 并使用默认管理员凭据登录(admin@example.com / 1234567890).初学者工具包提供博客、产品、联系人和其他内容类型。使用演示配置, contact 成为一种工具,同时 blogPost 和 product 成为资源。习俗 buy-product 该工具演示 IWebMcpTool 可扩展性。
验证它是否有效
# Discovery manifest (includes tools, resources, and prompts)
curl https://localhost:44391/.well-known/mcp-manifest.json
# List actionable tools only
curl https://localhost:44391/umbraco/api/webmcp/tools
# List informational resources
curl https://localhost:44391/umbraco/api/webmcp/resources
# Check Link header on any page
curl -I https://localhost:44391/
# → Link: ; rel="mcp-tool"一 api-tests.http 该文件包含在演示站点中,用于使用VS Code REST客户端或Rider HTTP客户端测试所有端点。
清单示例
这是什么 /.well-known/mcp-manifest.json return——AI代理消耗的完整发现负载:
Click to expand full manifest
{
"SchemaVersion": "1.0",
"SiteName": "localhost",
"SiteUrl": "https://localhost:44391",
"Tools": [
{
"Name": "submit-contact",
"Description": "Submit data for Contact",
"Method": "POST",
"InputSchema": {
"type": "object",
"properties": {
"pageTitle": {
"type": "string",
"description": "The title of the page, this is also the first text in a google search result. The ideal length is between 40 and 60 characters"
},
"contactFormHeader": {
"type": "string",
"description": "Contact Form Header"
},
"contactIntro": {
"type": "string",
"description": "Contact Intro"
},
"mapHeader": {
"type": "string",
"description": "Map Header"
},
"mapCoordinates": {
"type": "string",
"description": "Map Coordinates"
}
},
"required": ["pageTitle", "contactFormHeader", "contactIntro"]
},
"AutoSubmit": true,
"ExecutionUrl": "/umbraco/api/webmcp/tools/contact/execute"
},
{
"Name": "buy-product",
"Description": "Add a product to the shopping cart",
"Method": "POST",
"InputSchema": {
"type": "object",
"properties": {
"productName": {
"type": "string",
"description": "Product name"
},
"quantity": {
"type": "integer",
"description": "Quantity",
"minimum": 1
}
},
"required": ["productName", "quantity"]
},
"AutoSubmit": false,
"ExecutionUrl": "/umbraco/api/webmcp/tools/buy-product/execute"
}
],
"Resources": [
{
"Uri": "content://blogpost",
"Name": "Blogpost",
"Description": "Excerpt",
"MimeType": "application/json"
},
{
"Uri": "content://product",
"Name": "Product Name",
"Description": "Description",
"MimeType": "application/json"
}
],
"Prompts": [
{
"Name": "brand-voice",
"Persona": null,
"Tone": null,
"Rules": [],
"RawContent": "# Brand Voice\n\nYou are the website assistant for a creative agency store built with Umbraco.\n\n## Persona\n- Helpful, knowledgeable about our products and blog content\n- Professional yet approachable\n\n## Tone\n- Warm and concise\n- Use clear, direct language\n\n## Guidelines\n- Always provide accurate product information including pricing\n- For detailed inquiries, guide users to the contact page\n- When discussing blog posts, summarize key points and link to the full article\n- For product purchases, confirm the item and quantity before proceeding\n"
}
]
}工具定义可操作的端点(表单、自定义操作),资源公开结构化内容(博客、产品),提示传达您的品牌声音,以便代理以您的语气说话。
配置
添加到您的 appsettings.json:
{
"Umbraco": {
"WebMcp": {
"Enabled": true,
"EnrichDeliveryApi": true,
"TargetContentTypes": ["blogPost", "product", "contact"],
"ActionableContentTypes": ["contact"],
"ResourceDefaults": {
"NameAlias": "title",
"DescriptionAlias": "description"
},
"ResourceMappings": {
"product": { "NameAlias": "productName", "DescriptionAlias": "description" },
"blogPost": { "NameAlias": "title", "DescriptionAlias": "excerpt" }
},
"Analytics": {
"RetentionDays": 90
},
"Security": {
"RateLimitPerMinute": 60,
"RequireCsrfForTools": true
},
"Soul": {
"Persona": "You are a helpful university advisor",
"Tone": "Professional, warm, concise",
"Rules": [
"Never discuss competitors",
"Always suggest booking a campus tour"
]
}
}
}
}工具与资源
TargetContentTypes--要公开哪些内容类型(空=全部)ActionableContentTypes--哪些成为工具(空=都是工具,向后兼容)- 一切都在
TargetContentTypes但不在ActionableContentTypes成为资源
资源 是代理可以引用的只读结构化数据(博客、产品、文章)。 工具 是代理可以调用的可操作端点(联系表单、提交)。
资源字段映射
资源解决其 Name 和 Description 从内容类型属性:
ResourceDefaults--所有资源类型的回退映射(NameAlias: "title",DescriptionAlias: "description")ResourceMappings--按内容类型覆盖(例如,产品使用productName而不是title)
自定义工具(IWebMcpTool)
通过实现定义具有真实执行逻辑的工具 IWebMcpTool:
public class BuyProductTool : IWebMcpTool
{
public string ToolName => "buy-product";
public McpToolDefinition GetDefinition() => new()
{
Name = "buy-product",
Description = "Add a product to the shopping cart",
Method = "POST",
AutoSubmit = false,
ExecutionUrl = "/umbraco/api/webmcp/tools/buy-product/execute",
InputSchema = new JsonObject
{
["type"] = "object",
["properties"] = new JsonObject
{
["productName"] = new JsonObject { ["type"] = "string" },
["quantity"] = new JsonObject { ["type"] = "integer", ["minimum"] = 1 }
},
["required"] = new JsonArray { "productName", "quantity" }
}
};
public Task ExecuteAsync(JsonObject payload, HttpContext context)
{
var productName = payload["productName"]?.GetValue() ?? "Unknown";
var quantity = payload["quantity"]?.GetValue() ?? 1;
return Task.FromResult(new WebMcpToolResult
{
Success = true,
Message = $"Added {quantity}x '{productName}' to cart",
Data = new { productName, quantity, cartUpdated = true }
});
}
}注册于 Program.cs (或任何DI设置):
builder.Services.AddScoped();自定义工具会自动包含在清单、工具列表和缓存中。通过执行时 /umbraco/api/webmcp/tools/{toolName}/execute,控制器委托匹配 IWebMcpTool.ExecuteAsync().
整合
剃刀视图(单片)
两者都渲染 `` 阻碍。清单标记帮助程序包括工具、资源和提示。
重要提示: 在您的 _ViewImports.cshtml:
@addTagHelper *, uWebMcp.Core交付API(无头)
当 EnrichDeliveryApi 启用(默认),uWebMCP通过 _mcp 针对目标内容类型的块:
{
"name": "My Blog Post",
"contentType": "blogPost",
"properties": { ... },
"_mcp": {
"isEnabled": true,
"discoveryUrl": "/umbraco/api/webmcp/tools/blogPost",
"tools": [
{ "name": "blog-post", "method": "POST" }
]
}
}这使得无头前端和AI代理可以直接从内容响应中发现MCP功能。
品牌声音
以三种方式配置您网站的“灵魂”(按优先级顺序选中):
- 后台控制面板 --设置>代理智能>品牌语音编辑器
- soul.md文件 --将标记文件放在
wwwroot/soul.md - 应用程序参数 --The
Umbraco:WebMcp:Soul部分
翁布拉科。表单集成
安装 uWebMcp.Forms 包装旁边 Umbraco.Forms 将表单自动映射到MCP工具中。每个表单都成为一个可调用的工具,具有:
- 从表单字段和验证规则派生的JSON模式
- 蜜罐字段注入用于垃圾邮件防护
- 通过以下方式进行所需的现场执行
"required"在模式中
后台控制面板
这 特工情报 仪表板出现在Umbraco设置部分,显示:
- KPI卡 --代理发现、工具调用、表单提交(30天)
- 模型份额 --哪些AI代理正在与您的网站交互的分布
- 工具健康状况 --启用/禁用带有视觉状态指示器的工具
- 资源 --作为MCP资源公开的信息内容类型列表
- 灵魂编辑 --直接从后台配置品牌语音
构建仪表板客户端
cd src/uWebMcp.Backoffice/Client
npm install
npm run build # Outputs to wwwroot/App_Plugins/uWebMcp/
npm run watch # Rebuild on file changes安全
- 速率限制 --通过应用每IP固定窗口速率限制器
[EnableRateLimiting]在所有/umbraco/api/webmcp/路由(默认值:60请求/分钟) - CSRF保护 --双重提交cookie模式(
webmcp-csrf饼干+X-WebMCP-CSRFheader)在POST工具执行时 - 蜜罐田 --隐藏
_website字段默默地拒绝机器人提交(返回200以避免检测) - 缓存失效 --工具和资源模式在内容发布事件时自动刷新
API 参考
公共端点(无身份验证)
| 方法 | 路线 | 描述 |
|---|---|---|
| 得到 | /.well-known/mcp-manifest.json | 完整的MCP清单(工具+资源+提示) |
| 得到 | /umbraco/api/webmcp/tools | 列出所有工具定义 |
| 得到 | /umbraco/api/webmcp/tools/{alias} | 单一工具JSON模式 |
| 职位 | /umbraco/api/webmcp/tools/{alias}/execute | 执行工具 |
| 得到 | /umbraco/api/webmcp/resources | 列出所有资源定义 |
| 得到 | /umbraco/api/webmcp/prompts/get | 品牌语音提示 |
管理API(需要后台授权)
| 方法 | 路线 | 描述 |
|---|---|---|
| 得到 | /umbraco/management/api/v1/webmcp/stats/overview | 30天KPI总结 |
| 得到 | /umbraco/management/api/v1/webmcp/stats/agents | 代理商分布 |
| 得到 | /umbraco/management/api/v1/webmcp/stats/timeline | 每日时间序列 |
| 得到 | /umbraco/management/api/v1/webmcp/tools | 工具注册表 |
| PUT | /umbraco/management/api/v1/webmcp/tools/{id}/toggle | 启用/禁用工具 |
| 得到 | /umbraco/management/api/v1/webmcp/resources | 资源列表 |
| 得到 | /umbraco/management/api/v1/webmcp/soul | 获得品牌声音 |
| PUT | /umbraco/management/api/v1/webmcp/soul | 更新品牌声音 |
发展
# Build
dotnet build
# Test (58 tests across 10 test classes)
dotnet test
# Run specific test class
dotnet test --filter "ToolSchemaBuilder"
# Run demo site
dotnet run --project demo/uWebMcp.DemoSite技术栈
- 运行时间: .NET 10,Umbraco 17 LTS
- 数据库: SQL Server/SQLite(通过Umbraco的NPoco ORM)
IScopeProvider) - 缓存:
IDistributedCache(内存、Redis或SQL Server中) - 前端: @umbraco cms/后台(Lit)+TypeScript+Vite
- 测试: 单元 + Moq
许可证
麻省理工学院
