Skip to content

Commit e2422f7

Browse files
authored
Merge pull request #26 from umbraco/main
refresh dev
2 parents f90da88 + 808402b commit e2422f7

File tree

7 files changed

+105
-27
lines changed

7 files changed

+105
-27
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2025 Matthew-Wise
3+
Copyright (c) 2025-present Umbraco
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Umbraco MCP ![GitHub License](https://img.shields.io/github/license/matthew-wise/umbraco-mcp?style=plastic&link=https%3A%2F%2Fgithub.com%2FMatthew-Wise%2Fumbraco-mcp%3Ftab%3DMIT-1-ov-file%23readme)
1+
# Umbraco MCP ![GitHub License](https://img.shields.io/github/license/umbraco/Umbraco-CMS-MCP-Dev?style=plastic&link=https%3A%2F%2Fgithub.com%2Fumbraco%2FUmbraco-CMS-MCP-Dev%2Fblob%2Fmain%2FLICENSE)
22

33
An MCP (Model Context Protocol) server for [Umbraco CMS](https://umbraco.com/)
44
it provides access to key parts of the Management API enabling you to do back office tasks with your agent.
@@ -34,7 +34,7 @@ Once you have this information head back into Claude desktop app and head to Set
3434
"mcpServers": {
3535
"umbraco-mcp": {
3636
"command": "npx",
37-
"args": ["@umbraco-mcp/umbraco-mcp-cms@alpha"],
37+
"args": ["@umbraco-cms/mcp-dev@beta"],
3838
"env": {
3939
"NODE_TLS_REJECT_UNAUTHORIZED": "0",
4040
"UMBRACO_CLIENT_ID": "umbraco-back-office-mcp",
@@ -62,7 +62,7 @@ Restart Claude and try it out with a simple prompt such as `Tell me the GUID of
6262
Use the Claude Code CLI to add the Umbraco MCP server:
6363

6464
```bash
65-
claude mcp add umbraco-mcp npx @umbraco-mcp/umbraco-mcp-cms@alpha
65+
claude mcp add umbraco-mcp npx @umbraco-cms/mcp-dev@beta
6666
```
6767

6868
Or configure environment variables and scope:
@@ -71,7 +71,7 @@ Or configure environment variables and scope:
7171
npm install -g @anthropic-ai/claude-code
7272

7373
# Add with environment variables
74-
claude mcp add umbraco-mcp --env UMBRACO_CLIENT_ID="your-id" --env UMBRACO_CLIENT_SECRET="your-secret" --env UMBRACO_BASE_URL="https://your-domain.com" --env NODE_TLS_REJECT_UNAUTHORIZED="0" --env UMBRACO_INCLUDE_TOOL_COLLECTIONS="culture,document,media" -- npx @umbraco-mcp/umbraco-mcp-cms@alpha
74+
claude mcp add umbraco-mcp --env UMBRACO_CLIENT_ID="your-id" --env UMBRACO_CLIENT_SECRET="your-secret" --env UMBRACO_BASE_URL="https://your-domain.com" --env NODE_TLS_REJECT_UNAUTHORIZED="0" --env UMBRACO_INCLUDE_TOOL_COLLECTIONS="culture,document,media" -- npx @umbraco-cms/mcp-dev@beta
7575

7676
# Verify installation
7777
claude mcp list
@@ -99,7 +99,7 @@ Follow the MCP [install guide](https://code.visualstudio.com/docs/copilot/custom
9999
"umbraco-mcp": {
100100
"type": "stdio",
101101
"command": "npx",
102-
"args": ["@umbraco-mcp/umbraco-mcp-cms@alpha"],
102+
"args": ["@umbraco-cms/mcp-dev@beta"],
103103
"env": {
104104
"UMBRACO_CLIENT_ID": "<API user name>",
105105
"UMBRACO_CLIENT_SECRET": "<API client secret>",
@@ -127,7 +127,7 @@ Add the following to the config file and update the env variables.
127127
"mcpServers": {
128128
"umbraco-mcp": {
129129
"command": "npx",
130-
"args": ["@umbraco-mcp/umbraco-mcp-cms@alpha"],
130+
"args": ["@umbraco-cms/mcp-dev@beta"],
131131
"env": {
132132
"UMBRACO_CLIENT_ID": "<API user name>",
133133
"UMBRACO_CLIENT_SECRET": "<API client secret>",

build/azure-pipelines.yml

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,25 @@ stages:
7171
# Setup temp npm project to load in defaults from the local .npmrc
7272
npm init -y
7373
74-
# Find the first .tgz file in the current directory and publish it
74+
# Find the first .tgz file in the current directory
7575
files=( ./*.tgz )
76-
npm publish "${files[0]}"
77-
displayName: Push to npm
76+
77+
# Extract version from package.json in the tarball
78+
tar -tf "${files[0]}" | grep package/package.json | head -1 | xargs tar -xf "${files[0]}" --strip-components=1
79+
version=$(node -p "require('./package.json').version")
80+
81+
# Determine tag based on version
82+
if [[ "${version}" == *"alpha"* ]]; then
83+
tag="alpha"
84+
elif [[ "${version}" == *"beta"* ]]; then
85+
tag="beta"
86+
elif [[ "${version}" == *"rc"* ]]; then
87+
tag="rc"
88+
else
89+
tag="latest"
90+
fi
91+
92+
echo "Publishing version ${version} with tag ${tag}"
93+
npm publish "${files[0]}" --tag $tag --access public
94+
displayName: Push to npm with dynamic tagging
7895
workingDirectory: $(Pipeline.Workspace)/npm-package

package-lock.json

Lines changed: 4 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
2-
"name": "@umbraco-mcp/umbraco-mcp-cms",
3-
"version": "0.1.0-alpha.7",
2+
"name": "@umbraco-cms/mcp-dev",
3+
"version": "16.0.0-beta.1",
44
"type": "module",
55
"description": "A model context protocol (MCP) server for Umbraco CMS",
66
"main": "index.js",
@@ -30,7 +30,7 @@
3030
],
3131
"repository": {
3232
"type": "git",
33-
"url": "git+https://github.com/Matthew-Wise/umbraco-mcp.git"
33+
"url": "git+https://github.com/umbraco/Umbraco-CMS-MCP-Dev"
3434
},
3535
"keywords": [
3636
"Umbraco",
@@ -43,9 +43,9 @@
4343
"author": "",
4444
"license": "MIT",
4545
"bugs": {
46-
"url": "https://github.com/Matthew-Wise/umbraco-mcp/issues"
46+
"url": "https://github.com/umbraco/Umbraco-CMS-MCP-Dev/issues"
4747
},
48-
"homepage": "https://github.com/Matthew-Wise/umbraco-mcp#readme",
48+
"homepage": "https://github.com/umbraco/Umbraco-CMS-MCP-Dev#readme",
4949
"dependencies": {
5050
"@modelcontextprotocol/sdk": "^1.9.0",
5151
"@types/uuid": "^10.0.0",

src/umb-management-api/tools/document/__tests__/create-document.test.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,4 +74,49 @@ describe("create-document", () => {
7474
};
7575
expect(norm).toMatchSnapshot();
7676
});
77+
78+
it("should create a document with specific cultures", async () => {
79+
// Create document with specific cultures
80+
const docModel = {
81+
documentTypeId: ROOT_DOCUMENT_TYPE_ID,
82+
name: TEST_DOCUMENT_NAME,
83+
cultures: ["en-US", "da-DK"],
84+
values: [],
85+
};
86+
87+
const result = await CreateDocumentTool().handler(docModel, {
88+
signal: new AbortController().signal,
89+
});
90+
91+
expect(result).toMatchSnapshot();
92+
93+
const item = await DocumentTestHelper.findDocument(TEST_DOCUMENT_NAME);
94+
expect(item).toBeDefined();
95+
// Should have variants for both cultures
96+
expect(item!.variants).toHaveLength(2);
97+
const cultures = item!.variants.map(v => v.culture).sort();
98+
expect(cultures).toEqual(["da-DK", "en-US"]);
99+
});
100+
101+
it("should create a document with empty cultures array (null culture)", async () => {
102+
// Create document with empty cultures array - should behave like original (null culture)
103+
const docModel = {
104+
documentTypeId: ROOT_DOCUMENT_TYPE_ID,
105+
name: TEST_DOCUMENT_NAME,
106+
cultures: [],
107+
values: [],
108+
};
109+
110+
const result = await CreateDocumentTool().handler(docModel, {
111+
signal: new AbortController().signal,
112+
});
113+
114+
expect(result).toMatchSnapshot();
115+
116+
const item = await DocumentTestHelper.findDocument(TEST_DOCUMENT_NAME);
117+
expect(item).toBeDefined();
118+
// Should have single variant with null culture (original behavior)
119+
expect(item!.variants).toHaveLength(1);
120+
expect(item!.variants[0].culture).toBeNull();
121+
});
77122
});

src/umb-management-api/tools/document/post/create-document.ts

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ const createDocumentSchema = z.object({
1010
documentTypeId: z.string().uuid("Must be a valid document type type UUID"),
1111
parentId: z.string().uuid("Must be a valid document UUID").optional(),
1212
name: z.string(),
13+
cultures: z.array(z.string()).optional().describe("Array of culture codes. If not provided or empty array, will create single variant with null culture."),
1314
values: z
1415
.array(
1516
z.object({
@@ -25,7 +26,10 @@ const createDocumentSchema = z.object({
2526

2627
const CreateDocumentTool = CreateUmbracoTool(
2728
"create-document",
28-
`Creates a document,
29+
`Creates a document with support for multiple cultures.
30+
31+
If cultures parameter is provided, a variant will be created for each culture code.
32+
If cultures parameter is not provided or is an empty array, will create a single variant with null culture (original behavior).
2933
3034
Always follow these requirements when creating documents exactly, do not deviate in any way.
3135
@@ -633,6 +637,24 @@ const CreateDocumentTool = CreateUmbracoTool(
633637

634638
const documentId = uuidv4();
635639

640+
// Determine cultures to use
641+
let culturesToUse: (string | null)[] = [];
642+
643+
if (model.cultures === undefined || model.cultures.length === 0) {
644+
// If cultures not provided or empty array, use original behavior (null culture)
645+
culturesToUse = [null];
646+
} else {
647+
// Use provided cultures
648+
culturesToUse = model.cultures;
649+
}
650+
651+
// Create variants for each culture
652+
const variants = culturesToUse.map(culture => ({
653+
culture,
654+
name: model.name,
655+
segment: null,
656+
}));
657+
636658
const payload: CreateDocumentRequestModel = {
637659
id: documentId,
638660
documentType: {
@@ -645,13 +667,7 @@ const CreateDocumentTool = CreateUmbracoTool(
645667
: undefined,
646668
template: null,
647669
values: model.values,
648-
variants: [
649-
{
650-
culture: null,
651-
name: model.name,
652-
segment: null,
653-
},
654-
],
670+
variants,
655671
};
656672

657673
const response = await client.postDocument(payload);

0 commit comments

Comments
 (0)