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

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:

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:
- Creating a category.
- Batch-creating three items.
- Linking them to the category using an external reference code.
- Querying entries using filters.
- Sorting results.
- Updating an entry.
- Traversing the Object relationship.
- Creating and deleting a temporary entry.
- 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:
- A USD Commerce catalog.
- A product and default SKU.
- A product specification.
- An option with values.
- A warehouse.
- 250 units of inventory.
- A promotional price.
- A Commerce channel associated with the test site.
- 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.

