Jahia MCP Community Server

Jahia MCP Community Server

Enables AI assistants to query and mutate Jahia content via GraphQL through MCP tools, with skill management and access control.

Category
访问服务器

README

Jahia MCP Community Server

GitHub: https://github.com/Jahia/jahia-mcp-community-server

An OSGi bundle that exposes Jahia's GraphQL API as a Model Context Protocol (MCP) server, enabling AI assistants such as Claude to query and mutate Jahia content directly over a secure HTTP endpoint.

How it works

The servlet registers at /modules/community-mcp and implements the stateless MCP JSON-RPC 2.0 protocol over HTTP. When an MCP client calls a tool, the servlet dispatches the GraphQL request in-process via an OSGi service reference to OsgiGraphQLHttpServlet — no extra HTTP hop is involved.

MCP Client (Claude Code)
    │  POST /modules/community-mcp
    │  Authorization: APIToken <token>
    ▼
McpServlet  ──[whitelist check]──►  OsgiGraphQLHttpServlet
                                     (graphql-dxm-provider)

The caller's Authorization header and the current Jahia user are forwarded so that all JCR permission checks apply normally.

Requirements

  • Jahia 8.2+ with graphql-dxm-provider deployed
  • personal-api-tokens module deployed (for API token authentication)
  • Java 17

Installation

Deploy the bundle JAR via the Jahia Module Manager or drop it into $JAHIA_HOME/modules/.

On first activation the module automatically seeds a set of default skills into JCR under /sites/systemsite/contents/mcp-skills/.

Authentication

Access to /modules/community-mcp requires a personal API token with both the graphql and community-mcp scopes.

Generate one in Jahia under Administration → Profile → Personal API Tokens, or via GraphQL:

mutation {
    admin {
        personalApiTokens {
            createToken(name: "my-mcp-token", scopes: ["graphql", "community-mcp"])
        }
    }
}

Pass the token in every request:

Authorization: APIToken <your-token>

The mcp permission is automatically granted to users with the admin role (configured in META-INF/configurations/org.jahia.bundles.api.authorization-community-mcp.yml).

MCP client setup (Claude Code)

Add the following to ~/.claude/settings.json:

{
  "mcpServers": {
    "jahia-mcp": {
      "type": "http",
      "url": "http://localhost:8080/modules/community-mcp",
      "headers": {
        "authorization": "APIToken <your-token>"
      }
    }
  }
}

Available tools

introspectSchema

Returns all available top-level GraphQL query and mutation operations with full type details. Call this first to discover what operations and arguments are available before calling executeGraphQL.

No input arguments required.

executeGraphQL

Executes any GraphQL query or mutation against Jahia's graphql-dxm-provider, subject to the configured whitelist.

Field Type Required Description
query string yes GraphQL query or mutation
variables object no Variables map for the operation

Example — list root child nodes:

query {
    jcr {
        nodeByPath(path: "/") {
            children {
                nodes {
                    name
                    path
                    primaryNodeType { name }
                }
            }
        }
    }
}

Introspection fields (__schema, __type) always pass regardless of whitelist configuration.

listSkills

Returns the name, display name (mcpName), and description of every skill stored in JCR under /sites/systemsite/contents/mcp-skills/. Skills can be organized in sub-folders at any depth.

No input arguments required.

Example response:

[
  {"name":"hello-jahia","mcpName":"Hello Jahia","description":"How to respond to Hello Jahia"}
]

getSkill

Returns the full Markdown content of a skill by name. Call listSkills first to discover available names.

Field Type Required Description
name string yes Skill name as returned by listSkills (may include sub-folder path, e.g. default/hello-jahia)

Skills

Skills are Markdown documents stored as mcp:skill JCR nodes. They allow Jahia-specific knowledge and instructions to be delivered dynamically to any MCP client session.

Default skills

A set of default skills is seeded into JCR on module activation. They are defined as .md files under src/main/resources/skills/ and are only created if the node does not already exist.

Managing skills via GraphQL

# List all skills
query {
    mcpSkills {
        name
        mcpName
        description
        content
    }
}

# Create or update a skill
mutation {
    mcpSaveSkill(
        name: "my-skill",
        mcpName: "My Skill Display Name",
        description: "What this skill does",
        content: "# My Skill\n\nInstructions for Claude..."
    )
}

# Delete a skill
mutation {
    mcpDeleteSkill(name: "my-skill")
}

Adding a bundled default skill

Drop a .md file with frontmatter into src/main/resources/skills/<subfolder>/:

---
mcpName: My Skill Display Name
description: Short description of what this skill does
---
Full Markdown instructions here...

The file name (without .md) becomes the JCR node name. The folder hierarchy mirrors the JCR sub-folder structure under mcp-skills/.

Security notes

Allow-all mode (empty whitelist)

When the whitelist is empty (the default), all GraphQL operations are permitted to any caller who holds a valid API token with the community-mcp scope. The server logs a WARN on every request in this state to make it visible in logs:

WARN McpServlet - MCP GraphQL gate is running in ALLOW-ALL mode (whitelist is empty). ...

Configure an explicit whitelist in Administration → MCP Server (or in META-INF/configurations/org.jahia.community.mcp.cfg) to restrict which operations MCP clients may call.

Named fragment spreads blocked when whitelist is active

When a whitelist is configured, GraphQL queries that use named fragment spreads (...FragmentName) are rejected. The whitelist gate cannot resolve spread contents without the full fragment definition, so it fails closed rather than allowing a bypass.

Inline fragments (... on TypeName { ... }) are fully supported.

X-Forwarded-For not trusted

Client IP logged in audit/block messages is taken from HttpServletRequest.getRemoteAddr() (the TCP peer address). X-Forwarded-For is intentionally ignored to prevent IP spoofing. If Jahia is behind a trusted reverse proxy, configure RemoteIpValve at the Tomcat layer to rewrite remoteAddr to the real client IP before the request reaches the servlet.

Request body size cap

POST bodies larger than 2 MB are rejected with a JSON-RPC -32700 error before any parsing.

Access control — Allow List

The admin UI at Administration → MCP Server lets you restrict which GraphQL operations the MCP server may execute.

Behaviour

Whitelist state Effect
Empty All operations are allowed
Non-empty Only listed operations (and their sub-paths) are allowed

Dot-path entries

Entries are dot-separated field paths that mirror the GraphQL selection hierarchy:

Entry Covers
admin All operations under admin
admin.jahia All operations under admin.jahia
admin.jahia.isAlive Only that specific nested field

Whitelist entries are persisted in the OSGi configuration org.jahia.community.mcp and can also be set manually in META-INF/configurations/org.jahia.community.mcp.cfg:

whitelist=jcr,currentUser,admin.jahia.isAlive

Blocked operation log

Every blocked operation is logged at WARN level with the operation path, the authenticated user, and the client IP:

WARN McpServlet - MCP operation blocked: path='admin.jahia.shutdown', reason=not in the whitelist, user='john', ip='10.0.0.5'

Health check

A GET /modules/community-mcp request returns a JSON status response for authenticated users with the mcp permission:

{"status":"Jahia MCP server running","version":"1.0.0","tools":["executeGraphQL","introspectSchema","listSkills","getSkill"]}

Testing

Docker-based Cypress integration tests live in tests/. They require a running Docker environment.

cd tests
cp .env.example .env          # fill JAHIA_IMAGE and JAHIA_LICENSE
yarn install
./ci.build.sh                  # build the Cypress Docker image
./ci.startup.sh                # start Jahia + run tests + collect results

Test results are written to tests/results/.

Test coverage

Spec What is tested
01-mcpSettings.cy.ts GraphQL settings API: read, write, round-trip, dot-path persistence
02-mcpEndpoint.cy.ts MCP endpoint: whitelist enforcement, dot-path coverage, introspection pass-through, 401 for unauthenticated requests
03-mcpSkills.cy.ts Skills GraphQL API (save/read/update/delete), MCP listSkills and getSkill tools, default skill seeding

推荐服务器

Baidu Map

Baidu Map

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

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

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

官方
精选
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

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

官方
精选
本地
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

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

官方
精选
本地
TypeScript
VeyraX

VeyraX

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

官方
精选
本地
Kagi MCP Server

Kagi MCP Server

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

官方
精选
Python
graphlit-mcp-server

graphlit-mcp-server

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

官方
精选
TypeScript
Neon MCP Server

Neon MCP Server

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

官方
精选
Exa MCP Server

Exa MCP Server

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

官方
精选
mcp-server-qdrant

mcp-server-qdrant

这个仓库展示了如何为向量搜索引擎 Qdrant 创建一个 MCP (Managed Control Plane) 服务器的示例。

官方
精选