DEVCON 2026    |    2-5 November 2026 – QEII Centre – London, UK    |    Register now! 

Blogs

Liferay DXP Is an MCP Server. Now What?

Connecting Claude Code to Liferay DXP 2026.Q3 and seeing what an AI agent can actually do with the platform.

David H Nebinger
David H Nebinger
11 minuten lezen

Liferay DXP 2026.Q3 includes a capability I have been wanting to experiment with: Liferay can now act as a Model Context Protocol server.

I knew what MCP was conceptually, but I had no idea what I would actually find once I connected an AI client to Liferay and let it explore.

So I did what seemed reasonable.

I started a disposable local Liferay instance, enabled MCP, connected Claude Code, gave it an Omniadmin account, and let it investigate.

The result was much more interesting than "AI can retrieve some content."

Claude created Liferay Objects, added fields and relationships, published them, immediately discovered the new APIs generated from those Objects, created and queried data, built out a Commerce catalog and storefront configuration, and even created MCP prompts and profiles.

That changed how I thought about the feature.

MCP isn't really about adding an AI API to Liferay.

It is about making the Liferay platform itself discoverable and operable by an AI agent.

What MCP Actually Means

The Model Context Protocol, or MCP, is an open standard for connecting AI applications to external tools and data.

Starting with Liferay DXP 2026.Q3, Liferay can act as an MCP server. An MCP-capable client such as Claude, GitHub Copilot, Cursor, or Gemini CLI can connect to Liferay and interact with capabilities exposed by the platform.

See the Liferay documentation for the complete setup and configuration details: Using Liferay as an MCP Server.

At a high level:

MCP is not another AI model.

It is the protocol that lets an AI application discover and invoke capabilities provided by another system.

Another way to think about it is:

REST gives applications a way to work with Liferay programmatically. MCP gives AI applications a standard way to discover how to work with Liferay programmatically.

That second part, discover, turns out to be important.

Liferay Does Not Expose Thousands of MCP Tools

When I first connected Claude to Liferay, I expected MCP tools/list to be enormous.

Liferay has a lot of APIs.

Instead, it returned exactly four tools.

Tool Purpose
getToolSetsPage Discover available groups of Liferay operations
getToolSetToolSetNameToolSummariesPage Discover operations in one tool set
getToolSetToolSetNameTool Retrieve the input schema for one operation
postToolSetToolSetNameToolInvoke Invoke the selected operation

So Liferay uses progressive discovery:

I like this architecture.

My initial system exposed 76 tool sets spanning CMS, Objects, sites, users, workflow, search, Commerce, batch processing, OAuth, SAML, audit, notifications, and other platform capabilities. Behind those tool sets were roughly 4,000 individual operations.

Loading thousands of tool definitions into the model before the user has asked a question would consume a lot of context.

Instead, the initial four-tool MCP definition was only about 2.9 KB in my testing. The client pays the larger discovery cost only when it needs to explore a particular area of Liferay.

That means an agent trying to work with Objects can progressively discover Object capabilities without first loading every Commerce, Workflow, User Management, and CMS operation.

Enabling MCP in Liferay

The MCP server is disabled by default.

For Liferay DXP 2026.Q3, first enable the release feature flag:

LPD-63311

Then navigate to:

Control Panel
  -> Instance Settings
    -> Platform
      -> MCP Server

Enable the MCP server for the virtual instance.

See Using Liferay as an MCP Server for the current configuration steps.

The endpoint is:

/o/mcp

A useful first test is:

curl -i http://localhost:8080/o/mcp

If MCP is enabled but no credentials are supplied, you should receive an HTTP 401.

If MCP is disabled for the virtual instance, the endpoint returns 404.

Liferay supports both Basic authentication and OAuth 2.0 bearer tokens. In either case, the important part is that the request is associated with a Liferay user and operations execute according to that user's permissions.

For my disposable development environment, I used Basic authentication.

Connecting Claude Code

I chose Claude Code for most of my experimentation because it is already part of my normal development workflow.

The setup was pleasantly uneventful.

I put the authorization value in an environment variable:

export LIFERAY_MCP_AUTH="Basic <your-base64-credentials>"

Then I created a .mcp.json file in my working directory:

{
  "mcpServers": {
    "liferay": {
      "type": "http",
      "url": "http://127.0.0.1:8080/o/mcp",
      "headers": {
        "Authorization": "${LIFERAY_MCP_AUTH}"
      }
    }
  }
}

That was essentially the entire integration.

When I started Claude Code from that directory, it picked up the project-level .mcp.json automatically.

Running:

/mcp

showed the Liferay connection and its four MCP tools.

There was no separate registration process and no custom Claude integration to write.

One Important Compatibility Detail

At the time I performed these tests, my dxp-2026.q3.5 installation reported:

MCP protocol: 2025-11-25
Server: Java SDK MCP Server 0.15.0

Claude Code also supports a newer generation of MCP protocol negotiation, so I launched it explicitly in its legacy-compatible mode:

MCP_SDK_GENERATION=v1 \
  MCP_PROTOCOL_NEGOTIATION=legacy \
  claude

With that configuration, Claude connected cleanly.

This is worth knowing when connecting current MCP clients to Liferay 2026.Q3. If your client supports multiple MCP protocol generations, select its legacy or 2025-compatible negotiation mode.

Once Claude connected, /mcp showed:

Project MCPs
✓ liferay    4 tools

And that was enough to start exploring.

MCP Still Uses Liferay Security

Before getting to the fun experiments, there is an architectural point that matters.

An AI agent should not get some special "AI administrator" path around Liferay security.

Fortunately, that is not how the MCP server works.

Authentication resolves to a Liferay user, and Liferay permissions are applied when tools are invoked. My permission experiments confirmed that operations the user was not allowed to perform were rejected.

That suggests a very familiar security model:

ye

The fact that the caller happens to be Claude instead of a browser or custom application doesn't eliminate the need for normal permission design.

Write Access in Development, Not Production

For my experiments, I intentionally used Omniadmin.

I could do that because the instance was disposable.

I would not connect an Omniadmin AI agent directly to production.

There are simply too many powerful operations available once the identity has sufficient permissions.

My preferred architecture is:

Use MCP to help build things in a lower environment.

Then use the same mechanisms you would normally use to promote approved work into production.

Depending on what you're building, that might include Publications, export/import, batch operations, Site Initializers, or another controlled deployment mechanism.

Read-Only MCP in Production Is More Interesting

I do see a useful production pattern.

Instead of giving the agent write access, create a dedicated Liferay identity with narrowly scoped view permissions.

Then expose only the MCP capabilities needed by that agent.

Now questions like these become interesting:

Which content has not been updated in the last year?

Which products are currently out of stock?

Which sites use this structure?

Which Object entries are in this state?

What changed recently in this environment?

That is a substantially different risk profile from letting an agent administer production.

Liferay MCP profiles give us another useful tool for building that architecture.

I'll come back to profiles shortly.

Enough Architecture. What Can It Actually Do?

Once Claude was connected, I gave it permission to explore the disposable environment.

I didn't tell it exactly which REST APIs to call.

Instead, I let it use MCP discovery to figure out how Liferay worked.

Three experiments stood out.

Experiment 1: Build an Application With Liferay Objects

This ended up being my favorite experiment.

Claude created two Object definitions:

MCPResearchCategory
MCPResearchItem

The item definition contained fields such as:

itemName
quantity
unitPrice
inStock
contactEmail
contactPhone
notes

Claude also created a one-to-many relationship:

Then it published both Object definitions.

And something interesting happened.

On the next MCP discovery call, Liferay exposed two new tool sets:

c-mcpresearchitems
c-mcpresearchcategories

Claude had created a new application data model, and Liferay immediately exposed the APIs generated from that model back through MCP.

The loop became:

There was no restart.

There was no client regeneration.

There was no MCP configuration change.

The platform changed, and MCP discovery changed with it.

That is a powerful combination.

Liferay Objects already let us create application data models without writing a traditional backend.

MCP means an AI agent can participate in creating that model and then immediately start using the application it just created.

Creating and Using the Data

Claude continued by:

  1. Creating a category.
  2. Batch-creating three items.
  3. Linking them to the category using an external reference code.
  4. Querying entries using filters.
  5. Sorting results.
  6. Updating an entry.
  7. Traversing the Object relationship.
  8. Creating and deleting a temporary entry.
  9. Adding another field to the published Object definition.

All of those functional operations went through MCP.

An update ultimately looked like this:

{
  "toolSetName": "c-mcpresearchitems",
  "toolName": "patchByExternalReferenceCode",
  "body": {
    "externalReferenceCode": "mcp-research-item-3",
    "fields": [
      "itemName",
      "quantity"
    ],
    "body": {
      "quantity": 40,
      "inStock": true
    }
  }
}

That brings up an important operating pattern.

Prefer Sparse PATCH Operations

For agent-driven modifications, I strongly prefer PATCH operations that contain only the fields the agent actually intends to change.

For example:

{
  "quantity": 40,
  "inStock": true
}

rather than retrieving the complete entity, modifying two values, and sending the whole thing back.

The pattern should be:

There are several benefits:

  • Smaller requests.
  • Clearer intent.
  • Fewer accidental changes.
  • Unchanged values remain untouched.
  • Transformed or masked fields from a response do not need to be submitted again.

This is good REST practice in general, but it becomes especially useful when an agent is orchestrating the API calls.

Experiment 2: Build Out a Commerce Storefront

The Commerce experiment demonstrated how far an agent can go once it understands a set of related APIs.

I started with an essentially empty Commerce setup.

Claude created this sequence:

Specifically, the experiment created:

  1. A USD Commerce catalog.
  2. A product and default SKU.
  3. A product specification.
  4. An option with values.
  5. A warehouse.
  6. 250 units of inventory.
  7. A promotional price.
  8. A Commerce channel associated with the test site.
  9. A buyer-facing storefront view of the product.

The delivery API then showed the product with its regular price, promotional price, and calculated final price.

The important part wasn't that these REST APIs exist.

We already know that.

The interesting part was watching the AI determine which parts of Commerce it needed, discover the appropriate operations, inspect the required schemas, execute the calls, and continue to the next step.

That leads naturally to more practical requests.

For example:

Find every product without a description
and draft one using its specifications.

Or:

Show me products with fewer than 20 units
available in any warehouse.

Or:

Create a new Commerce catalog with these
products, SKUs, specifications and prices.

Those are workflows rather than individual API calls.

And workflows are where giving an agent a discoverable platform becomes much more interesting.

Experiment 3: Liferay Can Configure Its Own MCP Experience

Another thing I wanted to understand was how much control Liferay gives us over the MCP surface itself.

Quite a lot, as it turns out.

Liferay represents several MCP concepts using Liferay Objects, including:

  • MCP prompts.
  • MCP server profiles.
  • Data masks.
  • Profile-to-mask associations.

That means MCP configuration itself participates in familiar Liferay concepts such as Object data, permissions, APIs, and environment promotion.

MCP Prompts

I had Claude create an MCP prompt named:

mcp-research-summarize-site

The prompt contained instructions for summarizing a site's content.

As soon as the Object entry was created, it appeared through MCP prompts/list.

No restart.

No client reconnect.

Updating the prompt was reflected on the next request.

That means MCP prompts can themselves be managed as Liferay data.

MCP Profiles

Profiles may be even more interesting.

The normal MCP endpoint is:

/o/mcp

Custom profiles can be exposed as:

/o/mcp/<profile-name>

A profile can define which tools are exposed from that endpoint.

So we could conceptually create:

/o/mcp/developer

/o/mcp/content

/o/mcp/commerce

/o/mcp/production-reader

Each one can present a different MCP surface for a different use case.

That fits very naturally with the production architecture discussed earlier.

For example:

Liferay permissions still decide what the identity is allowed to do.

The MCP profile can reduce which operations the client sees in the first place.

Those are complementary controls.

A Few Patterns I Would Use From the Beginning

After working with MCP for a while, several implementation habits became useful quickly.

Use External Reference Codes

Give anything you create an explicit ERC when possible.

For example:

mcp-research-site
mcp-research-item-1
mcp-research-catalog
mcp-research-product-mug

Numeric IDs are normally environment-specific.

ERCs give the agent stable identifiers that make sense across DEV, UAT, and production.

That makes both retries and eventual promotion easier.

Instead of:

Update Object entry 43827

you can work with:

Update the item with ERC mcp-research-item-1

That is a much better contract for long-running or repeatable automation.

Use fields Aggressively

Liferay's Headless APIs support response field projection, and the same capability is valuable through MCP.

If the agent only needs:

id
name
status

ask for exactly those fields.

During the Object experiment, using fields on one write reduced the response from roughly 10 KB to around 150 bytes.

For an AI workflow, that reduction matters for more than bandwidth.

The response becomes part of the model's context.

So this:

{
  "fields": [
    "id",
    "name",
    "status"
  ]
}

can directly reduce how much context an operation consumes.

Remember That Batch Operations Are Asynchronous

Not every MCP invocation ends with the final business result.

Claude batch-created Object entries during the experiment. That operation returned a Liferay import task, which then needed to be checked through the Batch Engine API until processing completed.

The architecture looks more like:

An agent working effectively with an enterprise platform needs to understand both synchronous and asynchronous workflows.

MCP does not remove those architectural differences.

It gives the agent a way to participate in them.

What About Sensitive Data?

Liferay also supports data masks for MCP responses.

There are built-in masks for common data patterns, including email addresses, telephone numbers, credit card numbers, IP addresses, IBANs, and several national identification formats. Custom masks can also be created and associated with MCP profiles.

See Masking Sensitive Data in MCP Server Responses for the configuration details.

I would treat masking as an additional data-handling mechanism rather than a substitute for access control.

The first line of defense should still be:

Which user is this?

What may that user see?

What may that user modify?

Then MCP profiles and response handling can further shape what is exposed to the client.

For write operations, the sparse PATCH pattern is also useful here. If the agent only sends the properties it intends to change, it does not need to round-trip unrelated values from the response.

Where Could This Go?

Once you stop thinking about MCP as a collection of individual API calls, the possibilities get more interesting.

Content Review

Find content that has not been modified in
the last year.

Summarize it and identify items that should
probably be reviewed.

Application Prototyping

Create an Object for conference sessions.

A session has a title, abstract, speaker,
room, start time, end time and capacity.

Create a Speaker Object, relate the two,
publish them and seed some sample data.

Commerce Administration

Find products that are missing descriptions.

Draft descriptions from their specifications.

Show them to me before updating anything.

Production Investigation

With an appropriately permissioned read-only identity:

Which sites are using this structure?

Which products are currently out of stock?

Which content was modified this week?

How many Object entries are in each status?

Environment Setup

In a development environment:

Create the Object definitions, catalogs,
sample data and initial content needed for
this application.

Then review the resulting configuration and promote it through your normal delivery process.

Another experiment I want to tackle separately is using MCP to assist with migration from Liferay's legacy CMS into the new CMS. That becomes much more than copying records because structures, content formats, referenced assets, and dependencies all need to be transformed. That deserves its own investigation rather than a paragraph here.

MCP Changes the Interface, Not the Platform

This may be the most important thing I took away from the experiment.

MCP does not replace Liferay's architecture.

Claude was still working with:

  • Liferay users.
  • Liferay permissions.
  • Headless APIs.
  • Objects.
  • CMS.
  • Commerce.
  • Batch processing.
  • External reference codes.
  • Normal platform services.

The architecture is still:

We're not building a separate "AI version" of Liferay.

Instead, capabilities that already exist in the platform become discoverable and operable by an AI client.

That is why I think this is more interesting than simply adding another chatbot feature.

Final Thoughts

I started this experiment without really knowing what I would find.

What convinced me wasn't the fact that Claude could make an API call.

It was watching Claude create a Liferay Object definition, publish it, discover the newly generated API through MCP, and then immediately start using that API.

It was watching the same agent move across several Commerce APIs to build a catalog-to-storefront workflow.

And it was seeing that the security model still comes back to familiar Liferay concepts such as identities, roles, permissions, profiles, and environment separation.

For development and UAT, I can see real value in write-capable agents helping create application models, seed environments, configure Commerce, generate content, and automate repetitive platform tasks.

For production, I am more interested in narrowly permissioned, read-only agents that can answer questions about the actual environment without being able to change it.

The question is no longer whether an AI can talk to Liferay.

With MCP, it can.

The more interesting question is:

Which parts of Liferay do we want an agent to operate, under which identity, and in which environment?

That is the experiment I think is worth continuing.

Paginareacties

Related Assets...

Geen resultaten gevonden

More Blog Entries...

David H Nebinger
september 28, 2026
David H Nebinger
september 25, 2026
David H Nebinger
september 23, 2026