Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@

1. List tools: `curl -vs http://localhost:9001 -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'`
1. Get item: `curl -vs http://localhost:9001 -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name": "get_item", "arguments": {"pathOrId": "/sitecore/content/home"}}}'`
1. Or use the MCP inspector by running: `npx @modelcontextprotocol/inspector`
2 changes: 1 addition & 1 deletion src/SitecoreBasicMcp.Http/SitecoreBasicMcp.Http.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="ModelContextProtocol.AspNetCore" Version="0.5.0-preview.1" />
<PackageReference Include="ModelContextProtocol.AspNetCore" Version="0.6.0-preview.1" />
</ItemGroup>

<ItemGroup>
Expand Down
26 changes: 13 additions & 13 deletions src/SitecoreBasicMcp.Http/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
"net10.0": {
"ModelContextProtocol.AspNetCore": {
"type": "Direct",
"requested": "[0.5.0-preview.1, )",
"resolved": "0.5.0-preview.1",
"contentHash": "4KYK/rc6E8uuSJorludY/0Gpcm0wCXT5BGyZPcLRHisMT+cqW/P6lOv5luQZvy6iOxhwMmTMmY7DzU+VKVvjaw==",
"requested": "[0.6.0-preview.1, )",
"resolved": "0.6.0-preview.1",
"contentHash": "UltrLduMY0CRzh4XZAx3hp9fQeprxeVqd8hXhKWlBRib2WUo8yAavTy5yQZrel4JnbjfGGN77dXPyphshpwvbQ==",
"dependencies": {
"ModelContextProtocol": "0.5.0-preview.1"
"ModelContextProtocol": "0.6.0-preview.1"
}
},
"GraphQL.Client": {
Expand Down Expand Up @@ -52,23 +52,23 @@
},
"Microsoft.Extensions.AI.Abstractions": {
"type": "Transitive",
"resolved": "10.0.0",
"contentHash": "PHeuDm2tC6wJPEQvleUr2kNQaIMNqSf3aEbzkIPlZyQ0+0SYI9SwXVLdGD1NPBI+xB+Vb2lxZKhrFlIf9kP9WA=="
"resolved": "10.1.1",
"contentHash": "cgj8iHv4JwUpcPANZ0oLILz146Y1Oa+l280b1c1a3DjwZflH9nmYcrX952YUuqftz2sheAC2TPCGcEa6unKQgQ=="
},
"ModelContextProtocol": {
"type": "Transitive",
"resolved": "0.5.0-preview.1",
"contentHash": "QJpuNEnMZLJmvASbZ2nvMqENTZk3HYF83IihoHs3EJ5vTlz4sYjji9bXh2HP5UxpXIdHGn0iuHu0X2Tpq2zilw==",
"resolved": "0.6.0-preview.1",
"contentHash": "onUtGV9yny1rFZQ1qGUp6XPJBB2VxvWXvEioq8+/8hYOX6zEoc/Mc4tX8u7KRhU1mLss48jMh5DHFBMKifMiVw==",
"dependencies": {
"ModelContextProtocol.Core": "0.5.0-preview.1"
"ModelContextProtocol.Core": "0.6.0-preview.1"
}
},
"ModelContextProtocol.Core": {
"type": "Transitive",
"resolved": "0.5.0-preview.1",
"contentHash": "33V1Druluweou6x2LN6MSMbhiwHOYZxTUEJ1okFKjYDRIthctTVe0EJi//nifl4MRld2b5D5LnuV9sezz54p6g==",
"resolved": "0.6.0-preview.1",
"contentHash": "vjpbeJL7O4kNAgwv6wZtqlAAUX/tWaYLtbBzENDablIQfI1bH2tYTD/eK/6JvxP+Qp1H/lXaMvuRM6wohAzauA==",
"dependencies": {
"Microsoft.Extensions.AI.Abstractions": "10.0.0"
"Microsoft.Extensions.AI.Abstractions": "10.1.1"
}
},
"System.Reactive": {
Expand All @@ -81,7 +81,7 @@
"dependencies": {
"GraphQL.Client": "[6.1.0, )",
"GraphQL.Client.Serializer.SystemTextJson": "[6.1.0, )",
"ModelContextProtocol": "[0.5.0-preview.1, )"
"ModelContextProtocol": "[0.6.0-preview.1, )"
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/SitecoreBasicMcp.Stdio/SitecoreBasicMcp.Stdio.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="ModelContextProtocol" Version="0.5.0-preview.1" />
<PackageReference Include="ModelContextProtocol" Version="0.6.0-preview.1" />
</ItemGroup>

<ItemGroup>
Expand Down
20 changes: 10 additions & 10 deletions src/SitecoreBasicMcp.Stdio/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
"net10.0": {
"ModelContextProtocol": {
"type": "Direct",
"requested": "[0.5.0-preview.1, )",
"resolved": "0.5.0-preview.1",
"contentHash": "QJpuNEnMZLJmvASbZ2nvMqENTZk3HYF83IihoHs3EJ5vTlz4sYjji9bXh2HP5UxpXIdHGn0iuHu0X2Tpq2zilw==",
"requested": "[0.6.0-preview.1, )",
"resolved": "0.6.0-preview.1",
"contentHash": "onUtGV9yny1rFZQ1qGUp6XPJBB2VxvWXvEioq8+/8hYOX6zEoc/Mc4tX8u7KRhU1mLss48jMh5DHFBMKifMiVw==",
"dependencies": {
"ModelContextProtocol.Core": "0.5.0-preview.1"
"ModelContextProtocol.Core": "0.6.0-preview.1"
}
},
"GraphQL.Client": {
Expand Down Expand Up @@ -52,15 +52,15 @@
},
"Microsoft.Extensions.AI.Abstractions": {
"type": "Transitive",
"resolved": "10.0.0",
"contentHash": "PHeuDm2tC6wJPEQvleUr2kNQaIMNqSf3aEbzkIPlZyQ0+0SYI9SwXVLdGD1NPBI+xB+Vb2lxZKhrFlIf9kP9WA=="
"resolved": "10.1.1",
"contentHash": "cgj8iHv4JwUpcPANZ0oLILz146Y1Oa+l280b1c1a3DjwZflH9nmYcrX952YUuqftz2sheAC2TPCGcEa6unKQgQ=="
},
"ModelContextProtocol.Core": {
"type": "Transitive",
"resolved": "0.5.0-preview.1",
"contentHash": "33V1Druluweou6x2LN6MSMbhiwHOYZxTUEJ1okFKjYDRIthctTVe0EJi//nifl4MRld2b5D5LnuV9sezz54p6g==",
"resolved": "0.6.0-preview.1",
"contentHash": "vjpbeJL7O4kNAgwv6wZtqlAAUX/tWaYLtbBzENDablIQfI1bH2tYTD/eK/6JvxP+Qp1H/lXaMvuRM6wohAzauA==",
"dependencies": {
"Microsoft.Extensions.AI.Abstractions": "10.0.0"
"Microsoft.Extensions.AI.Abstractions": "10.1.1"
}
},
"System.Reactive": {
Expand All @@ -73,7 +73,7 @@
"dependencies": {
"GraphQL.Client": "[6.1.0, )",
"GraphQL.Client.Serializer.SystemTextJson": "[6.1.0, )",
"ModelContextProtocol": "[0.5.0-preview.1, )"
"ModelContextProtocol": "[0.6.0-preview.1, )"
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/SitecoreBasicMcp/SitecoreBasicMcp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.1" />
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.1" />
<PackageReference Include="ModelContextProtocol" Version="0.5.0-preview.1" />
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.2" />
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.2" />
<PackageReference Include="ModelContextProtocol" Version="0.6.0-preview.1" />
<PackageReference Include="GraphQL.Client" Version="6.1.0" />
<PackageReference Include="GraphQL.Client.Serializer.SystemTextJson" Version="6.1.0" />
</ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions src/SitecoreBasicMcp/Tools/CreateItemTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ mutation CreateItem(
record CreateItemData(BasicItem Item);
record CreateItemMutationResponse(CreateItemData CreateItem);

[McpServerTool(Idempotent = false, ReadOnly = false, UseStructuredContent = true), Description("Create a new Sitecore item under parent id or path.")]
[McpServerTool(Idempotent = false, ReadOnly = false), Description("Create a new Sitecore item under parent id or path.")]
public async Task<object> CreateItem(string parentPathOrId, string name, string templateId, string language, Field[] fields, CancellationToken cancellationToken)
{
var client = await GetAuthoringClient(cancellationToken);
Expand Down Expand Up @@ -70,7 +70,7 @@ public async Task<object> CreateItem(string parentPathOrId, string name, string
return ErrorResultFromGraphQL(response.Errors);
}

return response.Data.CreateItem.Item;
return ItemResult(response.Data.CreateItem.Item);
}
}

7 changes: 4 additions & 3 deletions src/SitecoreBasicMcp/Tools/CreateItemVersionTool.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using GraphQL;
using Microsoft.Extensions.Options;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
using SitecoreBasicMcp.Authentication;
using System.ComponentModel;
Expand All @@ -25,8 +26,8 @@ mutation AddItemVersion($itemId: ID!, $language: String!) {
record AddItemVersionData(BasicItem Item);
record AddItemVersionMutationResponse(AddItemVersionData AddItemVersion);

[McpServerTool(Idempotent = false, ReadOnly = false, UseStructuredContent = true), Description("Create a new language version to a Sitecore item by its path or id.")]
public async Task<object> CreateItemVersion(string pathOrId, string language, CancellationToken cancellationToken)
[McpServerTool(Idempotent = false, ReadOnly = false), Description("Create a new language version to a Sitecore item by its path or id.")]
public async Task<CallToolResult> CreateItemVersion(string pathOrId, string language, CancellationToken cancellationToken)
{
var client = await GetAuthoringClient(cancellationToken);
var resolveItemIdResult = await ResolveItemId(pathOrId, language, client, cancellationToken);
Expand All @@ -53,7 +54,7 @@ public async Task<object> CreateItemVersion(string pathOrId, string language, Ca
return ErrorResultFromGraphQL(response.Errors);
}

return response.Data.AddItemVersion.Item;
return ItemResult(response.Data.AddItemVersion.Item);
}
}

15 changes: 12 additions & 3 deletions src/SitecoreBasicMcp/Tools/DeleteItemTool.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using GraphQL;
using Microsoft.Extensions.Options;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
using SitecoreBasicMcp.Authentication;
using System.ComponentModel;
Expand All @@ -24,8 +25,8 @@ mutation DeleteItem($path: String!) {
record DeleteItemData(bool Successful);
record DeleteItemMutationResponse(DeleteItemData DeleteItem);

[McpServerTool(Idempotent = false, ReadOnly = false, UseStructuredContent = true), Description("Delete a Sitecore item by its path or id.")]
public async Task<object> DeleteItem(string pathOrId, CancellationToken cancellationToken)
[McpServerTool(Idempotent = false, ReadOnly = false), Description("Delete a Sitecore item by its path or id.")]
public async Task<CallToolResult> DeleteItem(string pathOrId, CancellationToken cancellationToken)
{
var client = await GetAuthoringClient(cancellationToken);
var request = new GraphQLRequest(_deleteItemMutation)
Expand All @@ -43,6 +44,14 @@ public async Task<object> DeleteItem(string pathOrId, CancellationToken cancella
return ErrorResultFromGraphQL(response.Errors);
}

return response.Data.DeleteItem.Successful;
if (!response.Data.DeleteItem.Successful)
{
return ErrorResult("Item was not deleted.");
}

return new()
{
Content = [new TextContentBlock { Text = "Item was deleted." }],
};
}
}
7 changes: 4 additions & 3 deletions src/SitecoreBasicMcp/Tools/DeleteItemVersionTool.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using GraphQL;
using Microsoft.Extensions.Options;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
using SitecoreBasicMcp.Authentication;
using System.ComponentModel;
Expand Down Expand Up @@ -27,8 +28,8 @@ mutation DeleteVersionItem($itemId: ID!, $language: String!, $version: Int!) {
record DeleteItemVersionData(BasicItem Item);
record DeleteItemMutationResponse(DeleteItemVersionData DeleteItemVersion);

[McpServerTool(Idempotent = false, ReadOnly = false, UseStructuredContent = true), Description("Delete a language version on a Sitecore item by its path or id.")]
public async Task<object> DeleteItemVersion(string pathOrId, string language, int version, CancellationToken cancellationToken)
[McpServerTool(Idempotent = false, ReadOnly = false), Description("Delete a language version on a Sitecore item by its path or id.")]
public async Task<CallToolResult> DeleteItemVersion(string pathOrId, string language, int version, CancellationToken cancellationToken)
{
var client = await GetAuthoringClient(cancellationToken);
var resolveItemIdResult = await ResolveItemId(pathOrId, language, client, cancellationToken);
Expand Down Expand Up @@ -56,6 +57,6 @@ public async Task<object> DeleteItemVersion(string pathOrId, string language, in
return ErrorResultFromGraphQL(response.Errors);
}

return response.Data.DeleteItemVersion.Item;
return ItemResult(response.Data.DeleteItemVersion.Item);
}
}
34 changes: 17 additions & 17 deletions src/SitecoreBasicMcp/Tools/GetItemTool.cs
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
using GraphQL;
using Microsoft.Extensions.Options;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
using SitecoreBasicMcp.Authentication;
using System.ComponentModel;
using System.Text.Json;

namespace SitecoreBasicMcp.Tools;

[McpServerToolType]
public class GetItemTool(IOptions<SitecoreSettings> options, SitecoreAuthenticationService authenticationService) : SitecoreAuthoringToolBase(options, authenticationService)
{
private static readonly string _getItemQuery = """
query GetItem($path: String, $language: String, $ownFields: Boolean) {
fragment BasicItem on Item {
id: itemId
name
path
version
}

query GetItem($path: String, $language: String!) {
item(where: { path: $path, language: $language }) {
id: itemId
path
name
version
...BasicItem
template {
id: templateId
fullName
name
}
parent {
id: itemId
path
name
version
...BasicItem
}
children {
nodes {
id: itemId
path
name
version
...BasicItem
}
}
fields(ownFields:$ownFields) {
fields(ownFields: true) {
nodes {
name
value
Expand All @@ -47,8 +47,8 @@ query GetItem($path: String, $language: String, $ownFields: Boolean) {

record GetItemQueryResponse(Item? Item);

[McpServerTool(Idempotent = true, ReadOnly = true, UseStructuredContent = true), Description("Get a Sitecore item by its path or id.")]
public async Task<object> GetItem(string pathOrId, CancellationToken cancellationToken, string language = "en", bool includeStandardFields = false)
[McpServerTool(Idempotent = true, ReadOnly = true), Description("Get a Sitecore item by its path or id.")]
public async Task<CallToolResult> GetItem(string pathOrId, CancellationToken cancellationToken, string language = "en", bool includeStandardFields = false)
{
var client = await GetAuthoringClient(cancellationToken);
var request = new GraphQLRequest(_getItemQuery)
Expand All @@ -75,6 +75,6 @@ public async Task<object> GetItem(string pathOrId, CancellationToken cancellatio
return ErrorResult("Item was not found.");
}

return item;
return ItemResult(item);
}
}
19 changes: 17 additions & 2 deletions src/SitecoreBasicMcp/Tools/ItemModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,20 @@ public record ChildItem(string Id, string Name, string Path, int Version);
public record Children(ChildItem[] Nodes);
public record Template(string Id, string Name, string FullName);
public record Parent(string Id, string Name, string Path, int Version);
public record Item(string Id, string Name, string Path, int Version, Fields Fields, Children Children, Template Template, Parent? Parent);
public record BasicItem(string Id, string Name, string Path, int Version);

public class BasicItem
{
public required string Id { get; set; }
public required string Name { get; set; }
public required string Path { get; set; }
public int Version { get; set; }
}

public class Item : BasicItem
{
public required Fields Fields { get; set; }
public required Children Children { get; set; }
public required Template Template { get; set; }
public Parent? Parent { get; set; }

}
16 changes: 16 additions & 0 deletions src/SitecoreBasicMcp/Tools/SitecoreAuthoringToolBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,22 @@ protected CallToolResult ErrorResultFromGraphQL(GraphQLError[] errors)
Content = [new TextContentBlock { Text = text }],
IsError = true
};

protected CallToolResult ItemResult<T>(T item) where T : BasicItem
{
var node = JsonSerializer.SerializeToNode(item);

if (node == null)
{
return ErrorResult("Node was null, item could not be serialized.");
}

return new()
{

Content = [new TextContentBlock { Text = node.ToJsonString() }],
};
}
}

public record ResolveItemIdResults(string? ItemId = null, CallToolResult? ErrorResult = null);
7 changes: 4 additions & 3 deletions src/SitecoreBasicMcp/Tools/UpdateItemTool.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using GraphQL;
using Microsoft.Extensions.Options;
using ModelContextProtocol.Protocol;
using ModelContextProtocol.Server;
using SitecoreBasicMcp.Authentication;
using System.ComponentModel;
Expand Down Expand Up @@ -29,8 +30,8 @@ mutation UpdateItem(
record UpdateItemData(BasicItem Item);
record UpdateItemMutationResponse(UpdateItemData UpdateItem);

[McpServerTool(Idempotent = false, ReadOnly = false, UseStructuredContent = true), Description("Update a Sitecore item by its path or id.")]
public async Task<object> UpdateItem(string pathOrId, string language, Field[] fields, CancellationToken cancellationToken)
[McpServerTool(Idempotent = false, ReadOnly = false), Description("Update a Sitecore item by its path or id.")]
public async Task<CallToolResult> UpdateItem(string pathOrId, string language, Field[] fields, CancellationToken cancellationToken)
{
var client = await GetAuthoringClient(cancellationToken);
var request = new GraphQLRequest(_updateItemMutation)
Expand All @@ -50,6 +51,6 @@ public async Task<object> UpdateItem(string pathOrId, string language, Field[] f
return ErrorResultFromGraphQL(response.Errors);
}

return response.Data.UpdateItem.Item;
return ItemResult(response.Data.UpdateItem.Item);
}
}
Loading