Skip to content

Commit 10576e5

Browse files
hifi-philPhil Whittakerclaude
authored
Release/16.0.0 beta.2 (#32)
* Add .env file support for MCP server configuration - Centralize configuration management in new config.ts module - Load environment variables from .env file (default) or custom path via --env flag - Support CLI argument overrides for all configuration options (--umbraco-*) - Track configuration sources (CLI vs ENV) for transparency - Add comprehensive validation and error reporting for missing credentials - Update documentation with .env usage examples and .mcp.json configuration - Refactor tests to use centralized config system - Remove deprecated env.ts helper - Improve multi-culture document test with proper setup and cleanup 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Improve copy-document tool with flattened schema and clearer workflow (#30) - Flatten tool parameter schema for better LLM usability - Replace nested `id` + `data` structure with top-level parameters - Use `idToCopy` instead of `id` for clarity - Move `relateToOriginal` and `includeDescendants` to top level - Make `parentId` optional (omit for root, provide for specific parent) - Add comprehensive tool description with workflow examples - Document the empty string return value behavior - Provide clear copy-only vs copy-and-update workflow patterns - Explain search-document requirement for post-copy operations - Update e2e test to use update-document instead of search - Simplify workflow: copy → update → publish → delete - Remove unnecessary search-document and document-type lookups - Update allowed tools list to match actual workflow - Pin mcp-server-tester to version 1.4.0 for consistency - Update copy-document unit tests to match new schema 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Phil Whittaker <[email protected]> Co-authored-by: Claude <[email protected]> * Add universal media upload tools with URL and base64 support (#31) * Update create-temporary-file to accept base64 encoded data - Changed schema from ReadStream to base64 string input for MCP compatibility - Converts base64 → Buffer → temp file → ReadStream for Umbraco API - Uses os.tmpdir() for temporary file storage - Automatic cleanup of temp files in finally block - Updated tests to use base64 encoding - All tests passing (11/11) This makes the tool compatible with LLM/MCP usage where files are provided as base64 strings rather than file system streams. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Add editorAlias and entityType to media value objects - Updated media-builder to include editorAlias and entityType in image values - Fixed focalPoint to use correct properties (left, top) - Changed temporaryFileId property name (was temporaryFilId) - Added documentation to create-media tool with complete example - Documented API quirk in docs/comments.md - Added experimental test-file-format tool for testing file upload formats These fields are required by the Umbraco API but not documented in the OpenAPI spec. Without them, media items are created but files are not properly uploaded/attached. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Add universal media upload tools with URL and base64 support - Add create-media tool supporting filePath, URL, and base64 sources - Add create-media-multiple tool for batch uploads (max 20 files) - Implement automatic MIME type detection using mime-types library - Add comprehensive media upload helpers with proper error handling - Fix extension handling: only add to temp files, not media item names - Add test infrastructure including builders and helpers - Add integration tests with snapshot testing - Support all media types: Image, File, Video, Audio, SVG, etc. Technical improvements: - Use mime-types library for robust MIME type to extension mapping - Proper temp file cleanup after uploads - SVG media type auto-correction (Image → Vector Graphic) - Continue-on-error strategy for batch uploads - Comprehensive test coverage with proper cleanup 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Remove obsolete TEST_FILE_FORMAT_README.md 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Remove obsolete test-file-format.ts 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> --------- Co-authored-by: Phil Whittaker <[email protected]> Co-authored-by: Claude <[email protected]> --------- Co-authored-by: Phil Whittaker <[email protected]> Co-authored-by: Claude <[email protected]>
1 parent 9fedfd8 commit 10576e5

File tree

51 files changed

+2263
-347
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+2263
-347
lines changed

README.md

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,34 @@ claude mcp list
8080

8181
This will add umbraco-mcp to the existing project in the claude.json config file.
8282

83+
#### Configuration via .mcp.json (Project-specific)
84+
85+
For project-specific Claude Code configuration, create a `.mcp.json` file in your project root that references environment variables for sensitive data:
86+
87+
```json
88+
{
89+
"mcpServers": {
90+
"umbraco-mcp": {
91+
"command": "npx",
92+
"args": ["@umbraco-cms/mcp-dev@beta"],
93+
"env": {
94+
"NODE_TLS_REJECT_UNAUTHORIZED": "0",
95+
"UMBRACO_CLIENT_ID": "umbraco-back-office-mcp",
96+
"UMBRACO_CLIENT_SECRET": "your-client-secret-here",
97+
"UMBRACO_BASE_URL": "https://localhost:44391",
98+
"UMBRACO_INCLUDE_TOOL_COLLECTIONS": "culture,document,media",
99+
"UMBRACO_EXCLUDE_TOOLS": "delete-document,empty-recycle-bin"
100+
}
101+
}
102+
}
103+
}
104+
```
105+
106+
Using the `.mcp.json` file allows you to:
107+
- Configure MCP servers per project
108+
- Share configuration with team members (commit to version control)
109+
- Override global Claude Code MCP settings for specific projects
110+
- Move the environment varaibles to a .env file to prevent leaking of secrets to your code repo
83111

84112
</details>
85113

@@ -142,6 +170,7 @@ Add the following to the config file and update the env variables.
142170
```
143171
</details>
144172

173+
145174
#### Authentication Configuration Keys
146175

147176
- `UMBRACO_CLIENT_ID`
@@ -156,6 +185,40 @@ Umbraco API User client secert
156185

157186
Url of the Umbraco site, it only needs to be the scheme and domain e.g https://<nolink/>example.com
158187

188+
### Environment Configuration Options
189+
190+
The Umbraco MCP server supports environment configuration via:
191+
1. **Environment variables in MCP client config as above** (Claude Desktop, VS Code, etc.)
192+
2. **Local `.env` file** for development (see `.env.example`)
193+
3. **CLI arguments** when running directly
194+
195+
**Configuration precedence:** CLI arguments > Environment variables > `.env` file
196+
197+
#### Using a `.env` file (Development)
198+
199+
For local development, you can create a `.env` file in the project root:
200+
201+
```bash
202+
# Edit with your values
203+
UMBRACO_CLIENT_ID=your-api-user-id
204+
UMBRACO_CLIENT_SECRET=your-api-secret
205+
UMBRACO_BASE_URL=http://localhost:56472
206+
```
207+
208+
The `.env` file is gitignored to keep your secrets secure.
209+
210+
#### CLI Arguments
211+
212+
You can also pass configuration via CLI arguments:
213+
214+
```bash
215+
npx @umbraco-cms/mcp-dev@beta \
216+
--umbraco-client-id="your-id" \
217+
--umbraco-client-secret="your-secret" \
218+
--umbraco-base-url="http://localhost:56472" \
219+
--env="/path/to/custom/.env"
220+
```
221+
159222
## API Coverage
160223

161224
This MCP server provides **comprehensive coverage** of the Umbraco Management API. We have achieved **full parity** with all applicable endpoints, implementing tools for every operational endpoint suitable for AI-assisted content management.
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
# Universal Media Upload Implementation
2+
3+
## Overview
4+
5+
The media upload system has been redesigned to provide a unified, simplified interface for uploading any type of media file to Umbraco. This simplifies the standard two-step process (create temporary file → create media) with a single tool call that handles all media types.
6+
7+
## Architecture Decision: Single Universal Tool
8+
9+
Instead of creating separate tools for each media type (create-image, create-pdf, create-video, etc.), we implemented a **single universal tool** that:
10+
- Accepts any media type via an explicit `mediaTypeName` parameter
11+
- Trusts the LLM to specify the correct media type based on context
12+
- Only validates SVG files (the one exception where file type matters for technical reasons)
13+
- Supports custom media types created in Umbraco via dynamic API lookup
14+
15+
### Why Trust the LLM?
16+
17+
**Advantages:**
18+
- ✅ LLMs understand semantic context better than file extensions
19+
- ✅ Simpler implementation - no complex extension mapping tables
20+
- ✅ Works seamlessly with custom media types
21+
- ✅ Explicit is better than implicit
22+
- ✅ Dynamic lookup ensures compatibility with any Umbraco installation
23+
24+
**The Only Exception - SVG:**
25+
- SVGs can be mistaken for images by LLMs
26+
- File extension check is simple and reliable for this one case
27+
- Auto-correct prevents technical errors (SVG uploaded as "Image" type fails in Umbraco)
28+
29+
## Tools Implemented
30+
31+
### 1. create-media
32+
33+
**Purpose:** Upload any single media file to Umbraco
34+
35+
**Schema:**
36+
```typescript
37+
{
38+
sourceType: "filePath" | "url" | "base64",
39+
name: string,
40+
mediaTypeName: string, // Required: explicit media type
41+
filePath?: string, // Required if sourceType = "filePath"
42+
fileUrl?: string, // Required if sourceType = "url"
43+
fileAsBase64?: string, // Required if sourceType = "base64"
44+
parentId?: string // Optional: parent folder UUID
45+
}
46+
```
47+
48+
**Supported Media Types:**
49+
- **Image** - jpg, png, gif, webp (supports cropping features)
50+
- **Article** - pdf, docx, doc
51+
- **Audio** - mp3, wav, etc.
52+
- **Video** - mp4, webm, etc.
53+
- **Vector Graphic (SVG)** - svg files only
54+
- **File** - any other file type
55+
- **Custom** - any custom media type name created in Umbraco
56+
57+
**Source Types:**
58+
1. **filePath** - Most efficient, zero token overhead, works with any size file
59+
2. **url** - Fetch from web URL
60+
3. **base64** - Only for small files (<10KB) due to token usage
61+
62+
**Example Usage:**
63+
```typescript
64+
// Upload an image from local filesystem
65+
{
66+
sourceType: "filePath",
67+
name: "Product Photo",
68+
mediaTypeName: "Image",
69+
filePath: "/path/to/image.jpg"
70+
}
71+
72+
// Upload a PDF from URL
73+
{
74+
sourceType: "url",
75+
name: "Annual Report",
76+
mediaTypeName: "Article",
77+
fileUrl: "https://example.com/report.pdf"
78+
}
79+
80+
// Upload small image as base64
81+
{
82+
sourceType: "base64",
83+
name: "Icon",
84+
mediaTypeName: "Image",
85+
fileAsBase64: "iVBORw0KGgoAAAANS..."
86+
}
87+
```
88+
89+
### 2. create-media-multiple
90+
91+
**Purpose:** Batch upload multiple media files (maximum 20 per batch)
92+
93+
**Schema:**
94+
```typescript
95+
{
96+
sourceType: "filePath" | "url", // No base64 for batch uploads
97+
files: Array<{
98+
name: string,
99+
filePath?: string,
100+
fileUrl?: string,
101+
mediaTypeName?: string // Optional per-file override, defaults to "File"
102+
}>,
103+
parentId?: string // Optional: parent folder for all files
104+
}
105+
```
106+
107+
**Features:**
108+
- Sequential processing to avoid API overload
109+
- Continue-on-error strategy - individual failures don't stop the batch
110+
- Returns detailed results per file with success/error status
111+
- Validates 20-file batch limit
112+
113+
**Example Usage:**
114+
```typescript
115+
{
116+
sourceType: "filePath",
117+
files: [
118+
{ name: "Photo 1", filePath: "/path/to/photo1.jpg", mediaTypeName: "Image" },
119+
{ name: "Photo 2", filePath: "/path/to/photo2.jpg", mediaTypeName: "Image" },
120+
{ name: "Document", filePath: "/path/to/doc.pdf", mediaTypeName: "Article" }
121+
],
122+
parentId: "parent-folder-id"
123+
}
124+
```
125+

docs/tool-collection-filtering.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -89,16 +89,16 @@ Some collections have dependencies that are automatically resolved:
8989

9090
### Configuration Loading
9191

92-
Configuration is loaded from environment variables with automatic parsing:
92+
Configuration is loaded from the server config object:
9393

9494
```typescript
9595
export class CollectionConfigLoader {
96-
static loadFromEnv(): CollectionConfiguration {
96+
static loadFromConfig(config: UmbracoServerConfig): CollectionConfiguration {
9797
return {
98-
enabledCollections: env.UMBRACO_INCLUDE_TOOL_COLLECTIONS ?? DEFAULT_COLLECTION_CONFIG.enabledCollections,
99-
disabledCollections: env.UMBRACO_EXCLUDE_TOOL_COLLECTIONS ?? DEFAULT_COLLECTION_CONFIG.disabledCollections,
100-
enabledTools: env.UMBRACO_INCLUDE_TOOLS ?? DEFAULT_COLLECTION_CONFIG.enabledTools,
101-
disabledTools: env.UMBRACO_EXCLUDE_TOOLS ?? DEFAULT_COLLECTION_CONFIG.disabledTools,
98+
enabledCollections: config.includeToolCollections ?? DEFAULT_COLLECTION_CONFIG.enabledCollections,
99+
disabledCollections: config.excludeToolCollections ?? DEFAULT_COLLECTION_CONFIG.disabledCollections,
100+
enabledTools: config.includeTools ?? DEFAULT_COLLECTION_CONFIG.enabledTools,
101+
disabledTools: config.excludeTools ?? DEFAULT_COLLECTION_CONFIG.disabledTools,
102102
};
103103
}
104104
}
@@ -108,7 +108,7 @@ export class CollectionConfigLoader {
108108

109109
The `UmbracoToolFactory` processes configuration and loads tools:
110110

111-
1. Load configuration from environment variables
111+
1. Load configuration from server config
112112
2. Validate collection names and dependencies
113113
3. Resolve collection dependencies automatically
114114
4. Filter collections based on configuration

jest.setup.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
11
import dotenv from 'dotenv';
2+
import { initializeUmbracoAxios } from './src/orval/client/umbraco-axios.js';
23

3-
// Load environment variables from .env.test
4-
dotenv.config({ path: '.env' });
4+
// Load environment variables from .env
5+
dotenv.config({ path: '.env' });
6+
7+
// Initialize Umbraco Axios client with environment variables
8+
initializeUmbracoAxios({
9+
clientId: process.env.UMBRACO_CLIENT_ID || '',
10+
clientSecret: process.env.UMBRACO_CLIENT_SECRET || '',
11+
baseUrl: process.env.UMBRACO_BASE_URL || ''
12+
});

0 commit comments

Comments
 (0)