Adobe Journey Optimizer Content API MCP server

Adobe Journey Optimizer Content API MCP server

Enables interaction with Adobe Journey Optimizer content through the Content API, supporting sandbox configuration and secure credential management.

Category
访问服务器

README

Adobe Journey Optimizer Content API MCP server

This project exposes Adobe Journey Optimizer Content API operations as MCP tools.

Quickstart

Follow these steps if you want to get the server running quickly.

  1. Create a config folder.
  2. Add config/credentials.json with your Adobe credentials export.
  3. Add config/settings.json with your sandbox name.
  4. Build the Docker image.
  5. Start the server in either HTTP mode or stdio mode.
  6. Point your MCP client at the running server.

If you are not sure which transport to use:

  • Use HTTP when your client connects to a URL like http://localhost:3000/mcp.
  • Use stdio when your client launches this server as a subprocess.

Prerequisites

  • Docker, if you want to run the containerized server
  • Node.js 20+, if you want to run the server directly
  • Adobe Journey Optimizer credentials exported as JSON
  • The Adobe sandbox name you want the server to use

Recommended workspace layout

my-workspace/
├── config/
│   └── credentials.json
├── docker-compose.yml
└── ajo-content-mcp-server/
    ├── Dockerfile
    └── ...

Place the exported Adobe environment JSON at config/credentials.json and create a small config/settings.json for the sandbox name. Mount ./config into the container.

Dedicated settings file

Create config/settings.json before starting the server.

Create config/settings.json like this:

{
  "sandboxName": "dev"
}

The container reads this file by default from /app/config/settings.json and uses it to populate AJO_SANDBOX_NAME.

You can override the path with:

AJO_SETTINGS_FILE=/custom/path/settings.json

Behavior

At startup, the container:

  1. Looks for /app/config/settings.json and loads the sandbox name.
  2. Looks for /app/config/credentials.json and loads the Adobe credentials.
  3. Converts those JSON files into generated env files.
  4. Sources the generated env files.
  5. Starts the MCP server.

You can override the JSON path with:

AJO_CREDENTIALS_FILE=/custom/path/credentials.json

The credentials loader expects the Adobe credentials export to provide values such as CLIENT_SECRET, API_KEY, ACCESS_TOKEN, SCOPES, TECHNICAL_ACCOUNT_ID, IMS, and IMS_ORG. It maps those into the internal AJO_* environment variables used by the app.

Build

docker build -t ajo-content-api-mcp-server .

Run

Choose one of the following runtime modes.

The default container mode is HTTP:

docker run --rm -it \
  -p 3000:3000 \
  -v "$(pwd)/config:/app/config:ro" \
  ajo-content-api-mcp-server

Run in HTTP mode

docker run --rm -it \
  -p 3000:3000 \
  -e MCP_TRANSPORT=http \
  -e MCP_PORT=3000 \
  -v "$(pwd)/config:/app/config:ro" \
  ajo-content-api-mcp-server

Run in stdio mode

docker run --rm -i \
  -e MCP_TRANSPORT=stdio \
  -v "$(pwd)/config:/app/config:ro" \
  ajo-content-api-mcp-server

Use stdio mode when your MCP client launches the containerized server as a subprocess and communicates over stdin/stdout.

Run Directly with Node.js

Build the project first:

npm install
npm run build

Run in HTTP mode:

AJO_SETTINGS_FILE="$(pwd)/config/settings.json" \
AJO_CREDENTIALS_FILE="$(pwd)/config/credentials.json" \
MCP_TRANSPORT=http \
MCP_PORT=3000 \
node dist/index.js

Run in stdio mode:

AJO_SETTINGS_FILE="$(pwd)/config/settings.json" \
AJO_CREDENTIALS_FILE="$(pwd)/config/credentials.json" \
MCP_TRANSPORT=stdio \
node dist/index.js

Docker Compose

services:
  ajo-content-mcp:
    build: .
    image: ajo-content-api-mcp-server
    environment:
      MCP_TRANSPORT: http
      MCP_PORT: 3000
    ports:
      - "3000:3000"
    volumes:
      - ./config:/app/config:ro

  ajo-content-mcp-stdio:
    build: .
    image: ajo-content-api-mcp-server
    command: ["node", "dist/index.js"]
    environment:
      MCP_TRANSPORT: stdio
    stdin_open: true
    tty: true
    volumes:
      - ./config:/app/config:ro

With this layout, credentials.json and settings.json both live under the same mounted folder. Use ajo-content-mcp for HTTP clients and ajo-content-mcp-stdio for subprocess-based stdio clients.

Connecting to the MCP Server

This MCP server supports both stdio and HTTP-streamable transports.

Best settings for local LLMs like Gemma

If you are connecting a smaller local model, prefer these settings:

  • Use stdio transport when possible.
  • Start with the simplified wrapper tools:
    • list_fragments
    • get_fragment
    • create_fragment
    • publish_fragment
    • list_templates
    • get_template
  • Use the discovery resources first if your client supports MCP resources:
    • overview://capabilities
    • overview://operations
    • overview://examples
  • Fall back to the generated OpenAPI tools only when you need a less common API operation.

Why this helps:

  • local LLMs often handle flat tool arguments better than nested path/query/headers/body objects
  • some MCP clients discover servers more reliably when resources are exposed
  • stdio is usually simpler for local MCP clients than session-based HTTP transports

Example stdio startup for local clients:

AJO_SETTINGS_FILE="$(pwd)/config/settings.json" \
AJO_CREDENTIALS_FILE="$(pwd)/config/credentials.json" \
MCP_TRANSPORT=stdio \
node dist/index.js

Transport selection

  • MCP_TRANSPORT=stdio — runs as a stdio MCP server
  • MCP_TRANSPORT=http — runs the HTTP-streamable server at /mcp (default)

Example stdio startup:

MCP_TRANSPORT=stdio node dist/index.js

This mode is intended for MCP clients that launch the server as a subprocess.

HTTP mode

When MCP_TRANSPORT is unset or set to http, the server exposes an HTTP-streamable MCP endpoint at /mcp.

Default URL

  • http://localhost:3000/mcp

Environment variables

  • MCP_PORT — port the server listens on (default: 3000)
  • AJO_SETTINGS_FILE — optional custom path to settings.json
  • AJO_CREDENTIALS_FILE — optional custom path to credentials.json

HTTP endpoints

  • POST /mcp

    • Used for initialization and normal MCP JSON-RPC requests.
    • The client should send the MCP initialize request first when no mcp-session-id header is present.
    • Subsequent requests must include the mcp-session-id header returned by the server.
  • GET /mcp

    • Used to open the streamable event channel for the existing session.
    • Must include the same mcp-session-id header from the initialization response.
  • DELETE /mcp

    • Used to terminate an active MCP session.
    • Must include the same mcp-session-id header.

Example connection flow

  1. Start the server:
MCP_PORT=3000 docker run --rm -it \
  -v "$(pwd)/config:/app/config:ro" \
  ajo-content-api-mcp-server
  1. Initialize the session with a POST to /mcp.
  2. Open a GET stream to /mcp using the returned mcp-session-id.
  3. Send follow-up POST requests with the same mcp-session-id.
  4. Close the session with DELETE /mcp.

The repository test files are lightweight smoke checks. The HTTP example test is skipped unless you manually run the MCP server locally, and the stdio test is skipped unless the required Adobe environment variables are present.

Example curl usage

# 1) Initialize the session and capture the returned MCP session ID
response=$(curl -s -X POST \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"initialize","params":{"clientName":"ajo-mcp"},"id":1}' \
  http://localhost:3000/mcp)

session_id=$(echo "$response" | jq -r '.result.sessionId')

# 2) Open the stream using the same session ID
curl -N -H "mcp-session-id: $session_id" http://localhost:3000/mcp

# 3) Send another MCP request over the same session
curl -X POST \
  -H "Content-Type: application/json" \
  -H "mcp-session-id: $session_id" \
  -d '{"jsonrpc":"2.0","method":"someToolCall","params":{"input":{}},"id":2}' \
  http://localhost:3000/mcp

Notes

  • The server uses the HTTP-streamable transport, so the LLM or MCP client can receive streamed tool results and notifications.
  • The server is scoped to the sandbox defined in config/settings.json and authenticated via config/credentials.json.

MCP Client Configuration Examples

Use the following examples based on the client you are configuring. For subprocess-based MCP clients, use MCP_TRANSPORT=stdio. For URL-based MCP clients, point them at http://localhost:3000/mcp.

Claude Desktop example

Example claude_desktop_config.json snippet for a local stdio launch:

{
  "mcpServers": {
    "ajo-content": {
      "command": "node",
      "args": ["/absolute/path/to/ajo-content-mcp-server/dist/index.js"],
      "env": {
        "MCP_TRANSPORT": "stdio",
        "AJO_SETTINGS_FILE": "/absolute/path/to/config/settings.json",
        "AJO_CREDENTIALS_FILE": "/absolute/path/to/config/credentials.json"
      }
    }
  }
}

For an HTTP-connected client shape, use:

{
  "mcpServers": {
    "ajo-content": {
      "url": "http://localhost:3000/mcp"
    }
  }
}

Codex example

Example MCP server entry for Codex using the local stdio process:

{
  "mcpServers": {
    "ajo-content": {
      "command": "node",
      "args": ["/absolute/path/to/ajo-content-mcp-server/dist/index.js"],
      "env": {
        "MCP_TRANSPORT": "stdio",
        "AJO_SETTINGS_FILE": "/absolute/path/to/config/settings.json",
        "AJO_CREDENTIALS_FILE": "/absolute/path/to/config/credentials.json"
      }
    }
  }
}

During development, you can swap the args value to ["--import", "tsx", "/absolute/path/to/ajo-content-mcp-server/src/index.ts"].

Or with Docker:

{
  "mcpServers": {
    "ajo-content": {
      "command": "docker",
      "args": [
        "run",
        "--rm",
        "-i",
        "-e",
        "MCP_TRANSPORT=stdio",
        "-v",
        "/absolute/path/to/config:/app/config:ro",
        "ajo-content-api-mcp-server"
      ]
    }
  }
}

Cursor example

Example Cursor MCP configuration using the local stdio process:

{
  "mcpServers": {
    "ajo-content": {
      "command": "node",
      "args": ["/absolute/path/to/ajo-content-mcp-server/dist/index.js"],
      "env": {
        "MCP_TRANSPORT": "stdio",
        "AJO_SETTINGS_FILE": "/absolute/path/to/config/settings.json",
        "AJO_CREDENTIALS_FILE": "/absolute/path/to/config/credentials.json"
      }
    }
  }
}

Available Tools for LLM Integration

This MCP server exposes the following tools to LLMs for managing Adobe Journey Optimizer content templates and fragments:

Content Template Tools

createTemplate

Create a new content template for use in campaigns and journeys.

  • Input: body object matching the OpenAPI schema, for example name, description, templateType, channels, and template
  • Output: Created template with auto-generated ID and metadata
  • Hint: Destructive operation

Example email template request body:

{
  "body": {
    "name": "Test Template",
    "description": "Test Description",
    "templateType": "html",
    "channels": ["email"],
    "template": {
      "html": "<h1>Hello</h1>"
    }
  }
}

getTemplates

List all available content templates with optional filtering and pagination.

  • Input: Optional filters (by name, channel, template type, creation date, etc.), pagination params
  • Output: JSON text payload including status, response headers, and returned data
  • Hint: Read-only operation

getTemplate

Fetch a specific content template by ID with full details.

  • Input: Template ID, Accept header
  • Output: Complete template details including audit information and ETag
  • Hint: Read-only operation

putTemplate

Update an existing content template by ID.

  • Input: Template ID, updated template payload, If-Match header (ETag for concurrency)
  • Output: HTTP 204 No Content (success indicator)
  • Hint: Idempotent operation

deleteTemplate

Delete a content template by ID.

  • Input: Template ID
  • Output: HTTP 204 No Content (success indicator)
  • Hint: Destructive operation

patchTemplate

Patch specific fields of a content template using JSON Patch format (RFC 6902).

  • Input: Template ID, JSON Patch operations, If-Match header
  • Output: Updated template with new ETag
  • Supported paths: /name, /description, /parentFolderId
  • Hint: Idempotent operation

Content Fragment Tools

createFragment

Create a new reusable content fragment.

  • Input: Fragment name, description, channel type, and content
  • Output: Created fragment with auto-generated ID and metadata
  • Hint: Destructive operation

getFragments

List all available content fragments with optional filtering and pagination.

  • Input: Optional filters (by name, channel, fragment type, creation date, etc.), pagination params
  • Output: Paginated list of fragment summaries
  • Hint: Read-only operation

getFragment

Fetch a specific content fragment by ID with full details.

  • Input: Fragment ID, Accept header
  • Output: Complete fragment details including audit information and ETag
  • Hint: Read-only operation

putFragment

Update an existing content fragment by ID.

  • Input: Fragment ID, updated fragment payload, If-Match header (ETag for concurrency)
  • Output: HTTP 204 No Content (success indicator)
  • Hint: Idempotent operation

patchFragment

Patch specific fields of a content fragment using JSON Patch format (RFC 6902).

  • Input: Fragment ID, JSON Patch operations, If-Match header
  • Output: HTTP 204 No Content (success indicator)
  • Supported paths: /name, /description, /parentFolderId
  • Hint: Idempotent operation

publishFragment

Publish a content fragment to freeze its content and make it available for use in campaigns/journeys.

  • Input: Fragment ID, publication request
  • Output: HTTP 202 Accepted (async operation)
  • Note: Publishing is asynchronous and may take a few seconds to complete
  • Hint: Destructive operation

getLiveFragment

Fetch the content of a fragment's last successful publication.

  • Input: Fragment ID
  • Output: Published fragment content ready for use
  • Note: Returns the frozen content from the most recent successful publication
  • Hint: Read-only operation

getLastPublicationStatus

Fetch the status of the last publication request for a fragment.

  • Input: Fragment ID
  • Output: Publication status (successful, in progress, or error)
  • Note: Use this to check async publication progress
  • Hint: Read-only operation

Tool Usage Notes

  • Authentication: All tools are automatically authenticated using the credentials loaded from config/credentials.json
  • Sandbox Context: All operations are scoped to the sandbox specified in config/settings.json
  • Request Tracking: Each request includes a unique x-request-id header for tracing
  • Concurrency Control: Update operations (put, patch) use ETags for optimistic concurrency control
  • Async Operations: Publication operations are asynchronous; use getLastPublicationStatus to monitor progress
  • Filtering: List operations support powerful filtering by various attributes (name regex, date ranges, creation info, etc.)
  • Pagination: List operations support limit and offset-based pagination via limit and start parameters

推荐服务器

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 模型以安全和受控的方式获取实时的网络信息。

官方
精选