Sitefinity社区。模型上下文协议(Model Context Protocol)
A. 模型上下文协议 (MCP)服务器 Sitefinity CMS。允许Claude Code(和任何MCP客户端)直接访问Sitefinity日志、诊断和CMS状态。
受...启发 Laravel Boost --设计为一个可扩展的框架,添加新工具只需要创建一个新的类文件。
为什么存在
MCP服务器在web开发生态系统中如雨后春笋般涌现——Laravel有Boost,Rails和Next.js有自己的——Sitefinity也值得拥有。
我为自己建造了这个。我每天都在Sitefinity工作,并希望拥有其他框架已经拥有的相同的人工智能辅助工作流程。Sitefinity的官方存储库存在于GitHub上,但社区PR往往会被搁置——当你需要日常工作时,你不能无限期地等待。这首先触及了我自己的痒:如果一个功能可以节省我在真实项目上的时间,它就会被构建出来。这意味着它保持实用性并积极维护,而不是理论性的。
它是开源和社区驱动的——欢迎贡献、想法和反馈。对时间表没有保证(这是一个附带项目),但由于我每天都在使用它,有用的改进往往很快就会实现。
特性
- 日志工具 --读取错误/跟踪日志,使用正则表达式搜索所有日志文件,获取最后一个错误
- 网站信息 --Sitefinity版本。NET版本、项目名称、配置的语言、多站点信息
- 模块检查器 --列出所有已安装的模块,包括类型、状态和启动类型
- 内容模型 --浏览模块生成器动态类型及其字段定义
- 页面检查器 -列出所有CMS页面路由(通过Sitemap API获取性能),获取完整的页面详细信息,包括模板名称、所有小部件及其配置的属性
- 路由发现 -浏览带有URL评估警告、ServiceStack API路由和OData实体集的CMS页面路由
- 状态检查 --验证Sitefinity是否已引导并准备就绪
- 多环境 --在dev/ststage/prod环境之间动态切换
- 双模式日志 --开发人员可以访问本地文件系统,远程服务器可以通过配套插件访问HTTP
- 自动发现 --新工具通过以下方式自动拾取
[McpServerToolType]属性 - API密钥验证 --MCP服务器和Sitefinity插件之间的主动密钥匹配
安装
有两个组件需要设置: MCP服务器 (在您的开发机器上运行)和 Sitefinity插件 (插入您的Sitefinity web应用程序)。按顺序执行这些步骤。
步骤1--获取MCP服务器
将此仓库克隆到本地计算机:
git clone https://github.com/SitefinityCommunity/SitefinityCommunity.Mcp.git
cd SitefinityCommunity.Mcp
dotnet build步骤2--将插件安装到Sitefinity项目中
配套插件在以下位置公开REST端点 /RestApi/mcp/* MCP服务器调用的。它作为源文件(而不是NuGet包)分发,因此它可以根据现有的Sitefinity程序集进行编译——不同版本之间没有DLL绑定冲突。
运行安装脚本,将其指向您的Sitefinity web应用程序根目录:
.\install-plugin.ps1 -Target "C:\Path\To\SitefinityWebApp"这会将插件源文件复制到 Code\Mcp\SitefinityCommunity\ 在你的项目中。
然后把它连接起来 Global.asax.cs 在你的 Bootstrapper_Initialized 处理程序:
protected void Bootstrapper_Initialized(object sender, ExecutedEventArgs e)
{
if (e.CommandName == "Bootstrapped")
{
SitefinityCommunity.Mcp.SitefinityPlugin.McpInit.Register();
}
}构建您的Sitefinity项目并回收应用程序池。
步骤3-生成API密钥
MCP服务器和Sitefinity插件使用共享的API密钥进行身份验证。生成一个加密安全的:
dotnet run --project src/SitefinityCommunity.Mcp -- generate-key这将打印一个新的256位Base64密钥。复制它——你将在接下来的两个步骤中使用它。
重要提示: 键流只有一个方向——在此处生成,然后将其粘贴到两个位置。做 不 将密钥从Sitefinity的高级配置中复制回来——存储在那里的是加密值,而不是原始密钥。
步骤4--配置Sitefinity插件
在 Sitefinity管理>设置>高级>McpSettings:
- 将生成的密钥粘贴到 API密钥
- 检查 启用 (这是
false默认情况下,您必须选择加入) - 保存,然后 回收应用程序池 -启动时读取启用标志和API密钥
密钥通过Sitefinity的静态加密存储 [SecretData] 机制。保存后,您在Advanced配置中看到的是加密表单——始终在中使用原始生成的密钥 sitefinity-mcp.json.
步骤5——创建配置文件
创建 sitefinity-mcp.json 在你的机器上的某个地方(保持它被忽略——它包含密钥):
{
"defaultEnvironment": "dev",
"environments": {
"dev": {
"url": "https://dev.example.com",
"logsPath": "C:\\Path\\To\\Sitefinity\\App_Data\\Sitefinity\\Logs",
"sitefinityApiKey": "your-key-from-step-3"
},
"staging": {
"url": "https://staging.example.com",
"sitefinityApiKey": "your-staging-api-key"
}
}
}sitefinityApiKey--粘贴您在Sitefinity管理中放置的相同密钥logsPath--当Sitefinity在同一台计算机上运行时(本地模式)设置此选项。对于远程服务器省略它——日志是通过插件通过HTTP获取的url--每种环境都需要
步骤6——配置您的AI客户端
克劳德代码
添加到您的项目 .mcp.json:
{
"mcpServers": {
"sitefinity-mcp": {
"type": "stdio",
"command": "dotnet",
"args": ["run", "--project", "C:\\GitHub\\SitefinityCommunity.Mcp\\src\\SitefinityCommunity.Mcp"],
"env": {
"SITEFINITY_MCP_CONFIG": "C:\\Path\\To\\sitefinity-mcp.json"
}
}
}
}VS Code
创建 .vscode/mcp.json 在您的工作区中(或运行 MCP:添加服务器 从命令选项板):
{
"servers": {
"sitefinity-mcp": {
"command": "dotnet",
"args": ["run", "--project", "C:\\GitHub\\SitefinityCommunity.Mcp\\src\\SitefinityCommunity.Mcp"],
"env": {
"SITEFINITY_MCP_CONFIG": "C:\\Path\\To\\sitefinity-mcp.json"
}
}
}
}然后在VS Code中打开聊天,并在询问时批准MCP信任提示。
步骤7——验证连接
问克劳德: *“检查Sitefinity是否正在运行”* --它将呼叫 sitefinity_check_status.如果API密钥不匹配,您将得到一个明确的错误消息,而不是一个神秘的401。
关键验证行为:
- 密钥匹配 --工具工作正常
- 钥匙不匹配 -工具返回:“API密钥不匹配…”错误
- 无法访问Sitefinity --工具会发出警告(这样在调试停机的服务器时,您仍然可以读取本地日志)
- 空白按键 --双方均被拒绝(MCP服务器无法启动;Sitefinity不会注册端点)
步骤8(可选)--安装Sitefinity技能
该仓库提供了精心策划的技能,教人工智能代理如何思考Sitefinity小部件和页面组合。技能可以安装到Claude Code、Cursor、Codex和GitHub Copilot中。
运行安装程序,它会引导您完成两个选择:范围(项目或全局)和要安装到哪些代理中(检测到的代理是预先选择的)。
# Interactive — prompts for scope and agents
.\install-skills.ps1
# Non-interactive / CI
.\install-skills.ps1 -Scope project -Target "C:\Proj" -Agents claude,cursor -Force
.\install-skills.ps1 -Scope global -Agents claude -Force如何安装: 标准副本将转到 /.agents/skills//,然后每个选定代理的技能目录都会获得一个指向规范副本的符号链接。更新规范副本一次,每个代理都会看到它。
每个代理路径:
| Agent | 技能目录 |
|---|---|
| 克劳德代码 | .claude/skills/ |
| 光标 | .cursor/skills/ |
| 食品法典委员会 | .codex/skills/ |
| GitHub副本 | .github/copilot/skills/ |
Windows注意事项: 创建目录符号链接需要开发人员模式(设置→ 系统→ 对于开发人员)或管理shell。如果符号链接不可用,安装程序会自动回退到普通副本——更新不会自动传播。
目前捆绑:
- sitefinity小部件专家 --MVC小部件开发、设计器属性、视图约定、JSON持久性
- sitefinity页面检查器 --了解检查页面小部件及其配置属性所需的MCP工具
______________________________________________________________________
可用工具
| 工具 | 说明 |
|---|---|
sitefinity_read_error_log | Error.log中的最后N个条目 |
sitefinity_read_trace_log | Trace.log中的最后N个条目 |
sitefinity_list_log_files | 所有包含大小和修改日期的.log文件 |
sitefinity_read_log_file | 按名称读取任何日志文件 |
sitefinity_search_logs | 使用上下文在所有日志中搜索正则表达式 |
sitefinity_get_last_error | 最新错误及完整详细信息 |
sitefinity_check_status | 检查Sitefinity是否已引导 |
sitefinity_get_site_info | Sitefinity版本。NET版本、项目名称、语言、多站点信息 |
sitefinity_list_modules | 所有已安装的模块,包括类型、状态、启动类型 |
sitefinity_list_dynamic_types | 按模块和字段计数分组的模块生成器类型 |
sitefinity_get_type_fields | 特定动态类型的字段定义 |
sitefinity_list_page_routes | 所有CMS页面路由通过Sitemap API(快速,缓存)。包括动态路由页面的URL评估警告 |
sitefinity_list_api_routes | ServiceStack REST API路由和OData实体集 |
sitefinity_get_page_details | 按ID、URL路径、slug或标题列出的完整页面详细信息。返回页面元数据、模板名称以及页面上的每个小部件及其配置的属性(包括级别2设置子项) |
sitefinity_get_widget_properties | 按GUID+页面标识符显示单个小部件的完整属性详细信息。返回具有更高截断限制的级别1属性和级别2设置子级(设计器字段值、内容等) |
sitefinity_get_page_widget_tree | 以同级渲染顺序将页面组合作为占位符树。布局控件自身嵌套 _Col00/_Col01 儿童占位符;小部件属性是一个合并的级别1+级别2视图(级别2获胜)。空列是根据布局标题预先创建的,因此结构可见 |
sitefinity_list_content | 任何Sitefinity类型(新闻、博客、模块生成器类型等)的分页实时内容项。返回Id、Title、UrlName、Status、DateCreated、LastModified,以便小部件可以引用真实的内容Id |
sitefinity_list_templates | 所有CMS页面模板——Id、名称、框架(MVC/WebForms)、ParentTemplateId、区域性 |
sitefinity_list_taxonomies | 所有分类(类别、标签、自定义)加上按分类Id键入的顶级分类群样本 |
sitefinity_list_forms | 所有包含字段计数和提交计数的Sitefinity表单 |
sitefinity_get_form_fields | 给定表单的字段定义--返回 开发者名称 (the FieldName Sitefinity API用于输入值,例如。 FormTextBox_C001)、标题、字段类型、必填项和选项。通过 debug=true 还可以转储原始的Properties/ChildProperties树(当名称/标题在不熟悉的Sitefinity版本上变为空时非常有用) |
sitefinity_list_form_responses | 表单提交,最新优先,可选不区分大小写 searchTerm 按任何字段值(或IP/UserAgent)过滤条目。敏感的命名字段值(密码/秘密/apiKey/令牌/…)被编辑 之前 搜索匹配,因此敏感值不会通过搜索泄漏 |
sitefinity_list_environments | 显示已配置的环境 |
sitefinity_set_default_environment | 切换活动环境 |
页面检查器
页面工具使您的AI助手能够查看Sitefinity的CMS页面结构,否则这些页面结构将锁定在数据库中,只能通过Sitefinity后端UI可见。
sitefinity_list_page_routes --使用Sitefinity的 网站地图API (FrontendSiteMap 供应商)以提高性能。站点地图是页面树在内存中缓存的表示形式,因此列出数百个页面很快,不会碰到任何问题 PageManager 查询。返回每个页面的URL、标题、树中的深度,并标记使用动态URL评估的页面(这可能会导致路由意外)。
sitefinity_get_page_details --返回单个页面的所有内容:元数据(ID、标题、URL、模板名称、发布状态)和 页面上放置的每个小部件 以及它们配置的属性。每个小部件都包括其GUID、CLR类型、占位符位置、标题、是否是布局控件、级别1属性和级别2设置子项(实际的设计器字段值)。通过以下方式接受灵活查找:
- 页面ID (Guid)--
fefefa59-f39a-4ac9-bf2f-a54d005f135d - URL路径 —
/about/team - URL 别名 —
team - 页面标题 —
Our Team(首选完全匹配,部分匹配有警告)
sitefinity_get_widget_properties --通过单个小部件的GUID及其所在的页面(均来自 sitefinity_get_page_details 结果)。返回具有比页面级视图更高截断限制的级别1属性(ControllerName、ID、Settings)和级别2设置子级(SharedContentID、ProviderName、Model JSON等)。当您需要检查特定小部件的实际配置值时,请使用此选项。
sitefinity_get_page_widget_tree --完整页面 *构成*:页面上的每个小部件都以同级呈现顺序作为占位符树返回。布局控件自己的子占位符名为 {ControlId}_Col00, _Col01,…--它们的内部列作为子列嵌套 Placeholders 关于布局 WidgetNode.每个小部件的 Properties 是一个 *合并* 级别1(ORM)+级别2(设置子项)的视图,级别2在冲突中获胜(小部件设计者实际保存的内容)。空列是从布局中预先创建的 grid-8+4 标题,以便LLM可以看到预期的结构。通过 includeLayoutControls=false 使布局节点变平。
实时内容查询
这三个工具使LLM可以直接查看真实内容、模板和分类,从而生成小部件配置和代码 *实际的* ID——不是占位符字符串。
sitefinity_list_content --任何类型的全名(例如。, Telerik.Sitefinity.News.Model.NewsItem 或模块生成器动态类型)。返回Id、标题、UrlName、状态、创建日期、上次修改时间。使用 sitefinity_list_dynamic_types 首先发现可用的类型名称。
sitefinity_list_templates --每个页面模板(MVC和WebForms),包括模板Id、父模板和区域性。生成需要固定到真实模板的新页面定义时很方便。
sitefinity_list_taxonomies --每个分类(类别、标签和任何自定义分类)加上由分类Id键控的顶级分类群样本。因此,配置了类别/标签过滤器的小部件可以引用真实的分类群Id。
表格和提交
sitefinity_list_forms --所有Sitefinity表单及其字段数和提交数。
sitefinity_get_form_fields --一个表单的字段定义(按Id或名称)。返回每个字段的 开发者名称 (the FieldName Sitefinity API在读取条目值时使用-例如。 FormTextBox_C001),其显示标题、字段类型、IsRequired标志和选项(用于下拉菜单/收音机)。通过 debug=true 另外返回一个原始的Properties/ChildProperties树转储,这对于诊断空属性很有用 Name/Title 在不熟悉的Sitefinity版本上,元数据位于控件设置树下的不同路径。
sitefinity_list_form_responses --表格提交,先订购最新的。通过 searchTerm 仅返回任何字段值(或 IpAddress / UserAgent)包含术语(不区分大小写的子字符串)。回应包括 TotalCount (表格上的所有条目), MatchedCount (搜索过滤器后的条目),并返回 SearchTerm 你发送。使用 take/skip 浏览匹配的集合。任何名称看起来敏感的字段(Password, ApiKey, Secret, Token,…)被擦洗 之前 离开Sitefinity *以及之前* 搜索匹配运行,因此敏感值永远不会通过精心设计的搜索词泄漏。
秘密行动
日志工具、小部件工具、表单响应工具和list_content返回的每个字符串都经过一个拒绝列表+模式扫描程序。按以下方式键入的值 Password, ApiKey, Secret等成为 [REDACTED];嵌入式JWT、AWS密钥、GitHub PAT、Slack令牌、OpenAI密钥、Azure连接字符串,以及 Password=... 连接字符串片段被替换为 [REDACTED:] 标签。对于开发调试,您可以设置 "allowRawSecrets": true 在非prod环境中 sitefinity-mcp.json --名称以开头的环境 prod 不管怎样,都要编辑。
______________________________________________________________________
安全模型
启用标志 --The Enabled Sitefinity管理>高级>McpSettings中的复选框充当具有两个强制层的终止开关:
- 启动门 —
McpInit.Register()检查Enabled和ApiKey在注册ServiceStack插件之前。如果其中之一为禁用/空白/RestApi/mcp/*路线根本不存在(404,没有攻击面)。需要应用程序池回收才能切换。 - 运行时间门 --The
[McpApiKey]请求筛选器属性检查Enabled在每一个请求。如果有人在启动后在管理员中禁用MCP,则请求会立即被阻止,而不会进行应用程序池回收。
静态加密 -Sitefinity配置中的API密钥标记为 [SecretData],所以它被加密存储在 McpConfig.config.Sitefinity在代码中读取属性时透明地解密它。
空白密钥保护 --在每个检查点都会拒绝空白、空和仅空白的键:
- MCP服务器配置验证(
IsNullOrWhiteSpace)--服务器无法启动 - Sitefinity启动(
McpInit.Register)--插件不会注册端点 - Sitefinity请求筛选器(
McpApiKeyAttribute)--运行时阻止的请求
______________________________________________________________________
建筑
双组件设计:
- MCP服务器 (此回购)--。NET控制台应用程序使用官方 模型上下文协议SDK.通过stdio与Claude Code通信。
- Sitefinity插件 (源文件)--
.cs您放入任何Sitefinity web应用程序的文件。在以下位置注册ServiceStack端点/RestApi/mcp/*用于远程日志访问。根据现有程序集编译--没有DLL冲突。
┌─────────────┐ stdio ┌──────────────────┐
│ Claude Code │◄───────────►│ MCP Server │
│ (MCP Client) │ │ (.NET console) │
└─────────────┘ └────────┬─────────┘
│
┌─────────────┼─────────────┐
│ │ │
Local logs HTTP + API Key │
(if logsPath (X-MCP-API-Key) │
is set) │ │
│ ▼ ▼
│ ┌─────────────┐ ┌─────────────┐
│ │ Sitefinity │ │ Sitefinity │
│ │ (Dev) │ │ (Staging) │
│ │ /RestApi/ │ │ /RestApi/ │
│ │ mcp/* │ │ mcp/* │
│ └─────────────┘ └─────────────┘
│ Plugin ▲ Plugin ▲
│ source │ source │
▼ files │ files │
┌──────────┐ │ │
│ Log files│ Sitefinity APIs: │
│ on disk │ SystemManager, │
└──────────┘ ModuleBuilder, │
MultisiteManager │
AppSettings │本地模式 (dev):MCP服务器通过以下方式直接从磁盘读取日志文件 logsPath. 远程模式 (stage/prod):MCP服务器在以下位置调用插件REST端点 /RestApi/mcp/*,已通过身份验证 X-MCP-API-Key 头球该插件查询Sitefinity的内部API,并以JSON格式返回结果。
______________________________________________________________________
添加新工具
创建一个类,对其进行注释,注入服务——完成。对Program.cs没有任何更改:
[McpServerToolType]
public sealed class ContentTools(ISitefinityStatusService status)
{
[McpServerTool(Name = "sitefinity_list_pages", ReadOnly = true)]
[Description("List Sitefinity CMS pages.")]
public async Task ListPages(CancellationToken ct = default)
{
var s = await status.CheckStatusAsync(ct);
if (!s.IsReady) return $"Sitefinity not ready: {s.Summary}";
// ... call Sitefinity OData API ...
}
}______________________________________________________________________
测试
设置
- 复制
tests/test-config.example.json到tests/test-config.json - 填写Sitefinity dev URL和API密钥(此文件为gitignored)
运行测试
# All tests (unit + integration)
dotnet test
# Unit tests only (no Sitefinity needed)
dotnet test --filter "Category=Unit"
# Integration tests only (requires running Sitefinity)
dotnet test --filter "Category=Integration"如果出现以下情况,集成测试将自动跳过 test-config.json 丢失或 Sitefinity无法访问,它们不会让您的构建失败。
______________________________________________________________________
作者
建造于 史蒂夫·麦克尼文·斯科特 (@Sitefinity网站 | )--Sitefinity MVP和长期社区贡献者。为Sitefinity社区构建开发人员工具。
许可证
麻省理工学院
