Hello everyone,
this is a very WIP MR to discuss implementation details and how to proceed further.
What?
The MR is about making ERP5 an MCP Server so that MCP clients can connect to ERP5. An MCP client can be used by AI hosts to let an LLM perform actual work with ERP5 (e.g., search, create, or modify something).
There is a TypeScript tool named modelcontextprotocol/inspector that functions as an MCP client. It can be run with:
npx -y @modelcontextprotocol/inspector
The inspector is helpful to illustrate the concept in the context of ERP5:
When connecting, an MCP endpoint must be specified.
I use /erp5/portal_web_services/mcp.
Most client requests are POST, but some are also GET and DELETE.
The client specifies authentication in the request header:
For authentication, I used for now Access Tokens from the erp5_access_token business template.
Yet MCP also supports OAuth.
To create the access token, I used:
access_token = portal.access_token_module.newContent(
portal_type="Restricted Access Token",
url_string="https://softinstXXXXXX.host.vifib.net/erp5/portal_web_services/mcp",
url_method="POST",
)
person = portal.person_module[my_person_id]
access_token.edit(agent_value=person)
Then the client can connect to the server with the initialize method:
MCP is built on top of JSON-RPC 2.0, so they communicate with JSON:
MCP has multiple features, but the most important ones are Tools.
Tools are essentially well-documented functions with side-effects or complex calculations to gather information.
(The latter includes queries to differentiate them from Resources, which fetch data with a GET request.)
Tools function as an API for the LLM to work with ERP5.
My WIP implementation currently only supports the Tools feature.
The client can ask the server to list all available tools. This list of tools does not have to be universal for all clients but can, for instance, depend on the user through which the client authenticated itself.
The client can call tools. Input and output of a tool are provided by JSON schemas.
(Note that this example tool, which I quickly created, is merely for demonstration purposes, the type specification in the description is redundant.)
How?
MCP Service
On the ERP5 side, I currently implemented the feature with the new portal type MCP Service.
An MCP Service can be created in portal_web_services.
Then tools can be added.
MCP Tool (manual)
I implemented a MCP Tools as a special type of a Python Script in portal_callables.
(Again, this particular tool is just for demonstration.)
The reason we need a dedicated portal type and cannot just use Python Script is because MCP tools require input and output schemas.
In the current implementation, I quickly coded a function to convert typed Python function signatures to JSON schema.
However, that's actually not ideal. Not only because it's redundant with parameter_signature to keep Python 2 compatibility, but also because input/output schemas do more than just type parameters, they can also provide descriptions for them.
@klaus suggested that instead of parsing a string, we could add MCP Tool Line objects, where each Line represents one input or output parameter (possibly with name, type, default, description fields).
I like this suggestion and think it's very apt for the context of ERP5. What do others think?
MCP Tool (automatic)
Klaus (and I believe others as well) proposes that ERP5 should not only support manually created MCP Tools, but also automatically translate ERP5 forms into MCP Tools. However, it's not yet clear what the best way to tackle this is:
- On a technical level, should these dynamic tools be created at request time, and should they then be represented by temporary
MCP Toolobjects? - Is it better to have a large number of tools (e.g., a dedicated search tool for each Module), or to have fewer, more generic tools where the module can be provided as an input parameter?
Execution plan
To prevent an AI agent from applying unwanted or harmful changes to an ERP5 instance, @yusei proposed the concept of an execution plan. The idea is that the AI first collects all necessary changes for a user's request, but doesn't apply them yet. Only when the user, after receiving and reviewing the plan, explicitly accepts it, the changes are committed. However, it's not clear what the best way to implement such an execution plan would be.
JSON RPC
@romain suggested that I not base the initial draft of the MCPService on JsonRpcService.
I asked him because JsonRpcService assumes the service has multiple endpoints, whereas the latest MCP specification only works with one endpoint.
Yet I also noticed something else: it seems that erp5_json_rpc_api is not actually related to JSON-RPC.
For instance, an error response in JSON-RPC 2.0 should look like:
{
"jsonrpc": "2.0",
"error": {
"code": <number>,
"message": <string>,
"data": <optional>
},
"id": ...
}
Am I missing something here?
Otherwise, I wonder if we should rename erp5_json_rpc_api to avoid confusion with JSON-RPC?
Concurrency
I'm not yet sure how to handle concurrency in a multi-node Zope deployment, or if it requires specific action at all. There's a detailed comment in the code explaining the issue and potential mitigation strategies.
Best, Levin







