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
63 changes: 63 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,34 @@ claude mcp list

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

#### Configuration via .mcp.json (Project-specific)

For project-specific Claude Code configuration, create a `.mcp.json` file in your project root that references environment variables for sensitive data:

```json
{
"mcpServers": {
"umbraco-mcp": {
"command": "npx",
"args": ["@umbraco-cms/mcp-dev@beta"],
"env": {
"NODE_TLS_REJECT_UNAUTHORIZED": "0",
"UMBRACO_CLIENT_ID": "umbraco-back-office-mcp",
"UMBRACO_CLIENT_SECRET": "your-client-secret-here",
"UMBRACO_BASE_URL": "https://localhost:44391",
"UMBRACO_INCLUDE_TOOL_COLLECTIONS": "culture,document,media",
"UMBRACO_EXCLUDE_TOOLS": "delete-document,empty-recycle-bin"
}
}
}
}
```

Using the `.mcp.json` file allows you to:
- Configure MCP servers per project
- Share configuration with team members (commit to version control)
- Override global Claude Code MCP settings for specific projects
- Move the environment varaibles to a .env file to prevent leaking of secrets to your code repo

</details>

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


#### Authentication Configuration Keys

- `UMBRACO_CLIENT_ID`
Expand All @@ -156,6 +185,40 @@ Umbraco API User client secert

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

### Environment Configuration Options

The Umbraco MCP server supports environment configuration via:
1. **Environment variables in MCP client config as above** (Claude Desktop, VS Code, etc.)
2. **Local `.env` file** for development (see `.env.example`)
3. **CLI arguments** when running directly

**Configuration precedence:** CLI arguments > Environment variables > `.env` file

#### Using a `.env` file (Development)

For local development, you can create a `.env` file in the project root:

```bash
# Edit with your values
UMBRACO_CLIENT_ID=your-api-user-id
UMBRACO_CLIENT_SECRET=your-api-secret
UMBRACO_BASE_URL=http://localhost:56472
```

The `.env` file is gitignored to keep your secrets secure.

#### CLI Arguments

You can also pass configuration via CLI arguments:

```bash
npx @umbraco-cms/mcp-dev@beta \
--umbraco-client-id="your-id" \
--umbraco-client-secret="your-secret" \
--umbraco-base-url="http://localhost:56472" \
--env="/path/to/custom/.env"
```

## API Coverage

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.
Expand Down
125 changes: 125 additions & 0 deletions docs/proto-docs/universal-media-upload.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Universal Media Upload Implementation

## Overview

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.

## Architecture Decision: Single Universal Tool

Instead of creating separate tools for each media type (create-image, create-pdf, create-video, etc.), we implemented a **single universal tool** that:
- Accepts any media type via an explicit `mediaTypeName` parameter
- Trusts the LLM to specify the correct media type based on context
- Only validates SVG files (the one exception where file type matters for technical reasons)
- Supports custom media types created in Umbraco via dynamic API lookup

### Why Trust the LLM?

**Advantages:**
- ✅ LLMs understand semantic context better than file extensions
- ✅ Simpler implementation - no complex extension mapping tables
- ✅ Works seamlessly with custom media types
- ✅ Explicit is better than implicit
- ✅ Dynamic lookup ensures compatibility with any Umbraco installation

**The Only Exception - SVG:**
- SVGs can be mistaken for images by LLMs
- File extension check is simple and reliable for this one case
- Auto-correct prevents technical errors (SVG uploaded as "Image" type fails in Umbraco)

## Tools Implemented

### 1. create-media

**Purpose:** Upload any single media file to Umbraco

**Schema:**
```typescript
{
sourceType: "filePath" | "url" | "base64",
name: string,
mediaTypeName: string, // Required: explicit media type
filePath?: string, // Required if sourceType = "filePath"
fileUrl?: string, // Required if sourceType = "url"
fileAsBase64?: string, // Required if sourceType = "base64"
parentId?: string // Optional: parent folder UUID
}
```

**Supported Media Types:**
- **Image** - jpg, png, gif, webp (supports cropping features)
- **Article** - pdf, docx, doc
- **Audio** - mp3, wav, etc.
- **Video** - mp4, webm, etc.
- **Vector Graphic (SVG)** - svg files only
- **File** - any other file type
- **Custom** - any custom media type name created in Umbraco

**Source Types:**
1. **filePath** - Most efficient, zero token overhead, works with any size file
2. **url** - Fetch from web URL
3. **base64** - Only for small files (<10KB) due to token usage

**Example Usage:**
```typescript
// Upload an image from local filesystem
{
sourceType: "filePath",
name: "Product Photo",
mediaTypeName: "Image",
filePath: "/path/to/image.jpg"
}

// Upload a PDF from URL
{
sourceType: "url",
name: "Annual Report",
mediaTypeName: "Article",
fileUrl: "https://example.com/report.pdf"
}

// Upload small image as base64
{
sourceType: "base64",
name: "Icon",
mediaTypeName: "Image",
fileAsBase64: "iVBORw0KGgoAAAANS..."
}
```

### 2. create-media-multiple

**Purpose:** Batch upload multiple media files (maximum 20 per batch)

**Schema:**
```typescript
{
sourceType: "filePath" | "url", // No base64 for batch uploads
files: Array<{
name: string,
filePath?: string,
fileUrl?: string,
mediaTypeName?: string // Optional per-file override, defaults to "File"
}>,
parentId?: string // Optional: parent folder for all files
}
```

**Features:**
- Sequential processing to avoid API overload
- Continue-on-error strategy - individual failures don't stop the batch
- Returns detailed results per file with success/error status
- Validates 20-file batch limit

**Example Usage:**
```typescript
{
sourceType: "filePath",
files: [
{ name: "Photo 1", filePath: "/path/to/photo1.jpg", mediaTypeName: "Image" },
{ name: "Photo 2", filePath: "/path/to/photo2.jpg", mediaTypeName: "Image" },
{ name: "Document", filePath: "/path/to/doc.pdf", mediaTypeName: "Article" }
],
parentId: "parent-folder-id"
}
```

14 changes: 7 additions & 7 deletions docs/tool-collection-filtering.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,16 @@ Some collections have dependencies that are automatically resolved:

### Configuration Loading

Configuration is loaded from environment variables with automatic parsing:
Configuration is loaded from the server config object:

```typescript
export class CollectionConfigLoader {
static loadFromEnv(): CollectionConfiguration {
static loadFromConfig(config: UmbracoServerConfig): CollectionConfiguration {
return {
enabledCollections: env.UMBRACO_INCLUDE_TOOL_COLLECTIONS ?? DEFAULT_COLLECTION_CONFIG.enabledCollections,
disabledCollections: env.UMBRACO_EXCLUDE_TOOL_COLLECTIONS ?? DEFAULT_COLLECTION_CONFIG.disabledCollections,
enabledTools: env.UMBRACO_INCLUDE_TOOLS ?? DEFAULT_COLLECTION_CONFIG.enabledTools,
disabledTools: env.UMBRACO_EXCLUDE_TOOLS ?? DEFAULT_COLLECTION_CONFIG.disabledTools,
enabledCollections: config.includeToolCollections ?? DEFAULT_COLLECTION_CONFIG.enabledCollections,
disabledCollections: config.excludeToolCollections ?? DEFAULT_COLLECTION_CONFIG.disabledCollections,
enabledTools: config.includeTools ?? DEFAULT_COLLECTION_CONFIG.enabledTools,
disabledTools: config.excludeTools ?? DEFAULT_COLLECTION_CONFIG.disabledTools,
};
}
}
Expand All @@ -108,7 +108,7 @@ export class CollectionConfigLoader {

The `UmbracoToolFactory` processes configuration and loads tools:

1. Load configuration from environment variables
1. Load configuration from server config
2. Validate collection names and dependencies
3. Resolve collection dependencies automatically
4. Filter collections based on configuration
Expand Down
12 changes: 10 additions & 2 deletions jest.setup.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
import dotenv from 'dotenv';
import { initializeUmbracoAxios } from './src/orval/client/umbraco-axios.js';

// Load environment variables from .env.test
dotenv.config({ path: '.env' });
// Load environment variables from .env
dotenv.config({ path: '.env' });

// Initialize Umbraco Axios client with environment variables
initializeUmbracoAxios({
clientId: process.env.UMBRACO_CLIENT_ID || '',
clientSecret: process.env.UMBRACO_CLIENT_SECRET || '',
baseUrl: process.env.UMBRACO_BASE_URL || ''
});
Loading
Loading