AffinityMCP

AffinityMCP

Enables natural language control of Affinity Photo/Designer/Publisher and Canva workflows through MCP tools, supporting file operations, filters, and batch processing up to 16 files simultaneously.

Category
访问服务器

README

AffinityMCP

The Universal MCP Server (Rust) exposes tools for Canva workflows—and Affinity Photo/Designer/Publisher automation—designed for natural language usage in MCP-compatible clients.

Features

  • 🎨 Natural Language Control: Control Affinity applications using natural language commands
  • 🖼️ File Operations: Open files, create new documents, export in various formats
  • 16-Parallel Processing: Process up to 16 files simultaneously for maximum efficiency
  • 🔧 Advanced Tools: Apply filters, get document info, and more
  • 🚀 Easy Setup: Simple setup for beginners with comprehensive documentation
  • 🌐 Cross-Platform Ready: Currently macOS (AppleScript), Windows support planned

Quick Start

For beginners, see SETUP_GUIDE.md for detailed step-by-step instructions.

Quick installation:

# Build
cargo build --release
cp target/release/affinity-mcp dist/

# Use with Cursor
# Add to Cursor MCP settings:
{
  "mcpServers": {
    "affinity-mcp": {
      "command": "npx",
      "args": ["affinity-mcp"],
      "autoStart": true
    }
  }
}

Installation

Prerequisites

  • Node.js 18+ (for the thin npx wrapper)

  • Rust 1.76+ / Cargo (for local builds)

  • Set AFFINITY_MCP_API_KEY if using Canva Connect/MCP endpoints.

Get an API key

  • If your tools require Canva APIs, obtain credentials from the Canva developer console or MCP server guidance. Otherwise, you can skip this step.

Build locally

cd /path/to/affinity-mcp
cargo build --release
# copy target/release/affinity-mcp -> ./dist/
cp target/release/affinity-mcp dist/

Setup: Claude Code (CLI)

Use this one-liner (replace with your real values):

claude mcp add AffinityMCP -s user -e AFFINITY_MCP_API_KEY="sk-your-real-key" -- npx affinity-mcp

To remove:

claude mcp remove AffinityMCP

Setup: Cursor (Do not commit .cursor/mcp.json here)

Create the config in your client:

{
  "mcpServers": {
    "affinity-mcp": {
      "command": "npx",
      "args": ["affinity-mcp"],
      "env": { "AFFINITY_MCP_API_KEY": "sk-your-real-key" },
      "autoStart": true
    }
  }
}

Other Clients and Agents

<details><summary>VS Code</summary>

code --add-mcp '{"name":"affinity-mcp","command":"npx","args":["affinity-mcp"],"env":{"AFFINITY_MCP_API_KEY":"sk-your-real-key"}}'

</details>

<details><summary>Claude Desktop</summary>

Follow the MCP install guide and reuse the standard config above.

</details>

<details><summary>LM Studio</summary>

  • Command: npx
  • Args: ["affinity-mcp"]
  • Env: AFFINITY_MCP_API_KEY=sk-your-real-key

</details>

<details><summary>Goose</summary>

  • Type: STDIO
  • Command: npx
  • Args: ["affinity-mcp"]
  • Enabled: true

</details>

<details><summary>opencode</summary>

~/.config/opencode/opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "affinity-mcp": {
      "type": "local",
      "command": ["npx", "affinity-mcp"],
      "enabled": true
    }
  }
}

</details>

<details><summary>Qodo Gen</summary>

Add a new MCP and paste the standard JSON config.

</details>

<details><summary>Windsurf</summary>

See docs and reuse the standard config above.

</details>

Setup: Codex (TOML)

Example (Serena):

[mcp_servers.serena]
command = "uvx"
args = ["--from", "git+https://github.com/oraios/serena", "serena", "start-mcp-server", "--context", "codex"]

This server (minimal):

[mcp_servers.affinity-mcp]
command = "npx"
args = ["affinity-mcp"]

# Optional environment variables:
# AFFINITY_MCP_API_KEY = "sk-your-real-key"
# MCP_NAME = "affinity-mcp"

Configuration (Env)

  • AFFINITY_MCP_API_KEY: Canva API key or token (if applicable)
  • MCP_NAME: Server name override (default: affinity-mcp)

If your tools are purely local, no API keys are required.

Available Tools

Affinity Tools (Natural Language Support)

All Affinity tools support natural language commands. Examples:

  • "Open the file /path/to/image.jpg in Affinity Photo"
  • "Create a new document with width 1920 and height 1080"
  • "Export the current document as PDF to /path/to/output.pdf"

affinity.open_file

Open a file in Affinity application (auto-detects app from file extension).

  • inputs: { "path": string, "app"?: "Photo"|"Designer"|"Publisher" }
  • outputs: { "opened": boolean, "app": string, "path": string }

affinity.create_new

Create a new Affinity document.

  • inputs: { "app": "Photo"|"Designer"|"Publisher", "width"?: number, "height"?: number }
  • outputs: { "created": boolean, "app": string }

affinity.export

Export the currently open document.

  • inputs: { "path": string, "format": "pdf"|"png"|"jpg"|"tiff"|"svg", "quality"?: number }
  • outputs: { "exported": boolean, "path": string }

affinity.apply_filter

Apply a filter to the current document.

  • inputs: { "filter_name": string, "intensity"?: number }
  • outputs: { "applied": boolean, "filter_name": string }

affinity.get_active_document

Get information about the currently active document.

  • inputs: {}
  • outputs: { "is_open": boolean, "name"?: string, "path"?: string }

affinity.close_document

Close the currently open document.

  • inputs: {}
  • outputs: { "closed": boolean }

affinity.batch_open_files ⚡ 16-Parallel

Open multiple files simultaneously (up to 16 files in parallel).

  • inputs: { "paths": string[], "app"?: "Photo"|"Designer"|"Publisher" }
  • outputs: { "success_count": number, "failure_count": number, "results": OpenFileResult[] }

Natural language example: "Open multiple files: /path/to/image1.jpg, /path/to/image2.jpg, /path/to/image3.jpg"

affinity.batch_export ⚡ 16-Parallel

Export multiple documents simultaneously (up to 16 exports in parallel).

  • inputs: { "exports": ExportParams[] }
  • outputs: { "success_count": number, "failure_count": number, "results": ExportResult[] }

Natural language example: "Export all open documents as PDF files"

Canva Tools

canva.create_design

  • inputs: { "title": string, "template_id"?: string, "width"?: number, "height"?: number }
  • outputs: { "design_id": string, "url"?: string }

Example Usage

Natural Language Commands

In Cursor or other MCP-compatible clients, you can use natural language:

Example 1: Open a file

User: "Open /Users/john/Desktop/image.jpg in Affinity Photo"
AI: [Calls affinity.open_file with path="/Users/john/Desktop/image.jpg", app="Photo"]

Example 2: Create and export

User: "Create a new Affinity Photo document with size 1920x1080, then export it as PDF to my Desktop"
AI: [Calls affinity.create_new, then affinity.export]

Example 3: Get document info

User: "What document is currently open?"
AI: [Calls affinity.get_active_document]

Example 4: Batch operations (16-parallel)

User: "Open these 5 images simultaneously: /path/to/img1.jpg, /path/to/img2.jpg, /path/to/img3.jpg, /path/to/img4.jpg, /path/to/img5.jpg"
AI: [Calls affinity.batch_open_files with paths array]

Example 5: Batch export (16-parallel)

User: "Export all open documents as PDF files to the Desktop"
AI: [Calls affinity.batch_export with multiple export configurations]

Direct Tool Invocation (MCP tool call)

{
  "type": "tool",
  "name": "affinity.open_file",
  "arguments": {
    "path": "/path/to/image.jpg",
    "app": "Photo"
  }
}

Documentation

  • SETUP_GUIDE.md: Beginner-friendly setup guide with step-by-step instructions
  • SPEC.md: Technical specification (Japanese)
  • README.md: This file (English documentation)

For complex schemas, see src/tools/*.rs.

Name Consistency & Troubleshooting

Always use CANONICAL_ID (affinity-mcp) for identifiers and keys.

Use CANONICAL_DISPLAY (AffinityMCP) only for UI labels.

Do not mix legacy keys after registration.

Consistency Matrix

  • npm package name → affinity-mcp
  • Binary name → affinity-mcp
  • MCP server name → affinity-mcp
  • Env default MCP_NAME → affinity-mcp
  • Client registry key → affinity-mcp
  • UI label → AffinityMCP

Conflict Cleanup

Remove stale keys and re-add with affinity-mcp only.

Cursor is UI-configured only; this repo intentionally omits .cursor/mcp.json.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选