ADR-010: MCP Server for AI Integration

Status

Superseded by ADR-013 (LangChain4j @Tool Approach)

Date: 2025-12-01 (Superseded: 2025-12-06)

Decision Outcome

This ADR originally proposed using the Quarkus MCP Server extension for AI integration. During implementation (December 2025), we adopted LangChain4j's @Tool annotation approach instead (see ADR-013), which provides:

MCP functionality still exists but uses LangChain4j @Tool wrappers in mcp/tools/ package rather than Quarkus MCP Server extension. The tools expose the same capabilities via HTTP/SSE on port 8765.

See ADR-013 for the implemented architecture.


Original Proposal (Historical Context)

Context

The CLI needs to be accessible from AI assistants (Claude Code, Claude Desktop) and automation tools (n8n). The Model Context Protocol (MCP) provides a standardized way to expose tools to AI systems.

Why MCP?

Aspect MCP REST API
AI Integration Native (Claude Code, Claude Desktop) Requires custom integration
Natural Language Built-in tool descriptions Needs OpenAPI + LLM wrapper
Streaming Progress notifications, logging Polling or SSE
Context Awareness Resources, prompts, sampling Manual implementation
Transport stdio (local), SSE (remote) HTTP only

Architecture Overview

┌─────────────────────────────────────────────────────────────────┐
│                    Claude Code / Claude Desktop                  │
│                         (MCP Client)                             │
└──────────────────────────┬──────────────────────────────────────┘
                           │ JSON-RPC over HTTP/SSE (port 8765)
┌──────────────────────────▼──────────────────────────────────────┐
│              idempiere-cli (Quarkus MCP Server)                  │
│  ┌────────────────────────────────────────────────────────────┐ │
│  │ MCP Tools (using @Tool annotations):                       │ │
│  │  - McpRegistryTools: listTables, describeTable, etc.       │ │
│  │  - McpQueryTools: executeQuery, explainQuery               │ │
│  │  - McpTableTools: createTable, syncTable, deleteTable      │ │
│  │  - McpGeneratorTools: generatePlugin, generateModel, etc.  │ │
│  │  - McpDoctorTools: checkEnvironment, checkApi, etc.        │ │
│  └────────────────────────────────────────────────────────────┘ │
│                               │                                  │
│                               ▼                                  │
│              ┌────────────────────────────────┐                  │
│              │    Shared Tool Logic Layer     │                  │
│              │  (org.idempiere.cli.ai.shared) │                  │
│              └────────────────────────────────┘                  │
└──────────────────────────┬──────────────────────────────────────┘
                           │
              ┌────────────┼────────────┐
              ▼            ▼            ▼
       ┌───────────┐ ┌───────────┐ ┌───────────┐
       │ iDempiere │ │ PostgreSQL│ │   Local   │
       │  REST API │ │  Database │ │   Files   │
       └───────────┘ └───────────┘ └───────────┘

Decision

1. Use Quarkus MCP Server Extension

Instead of implementing MCP manually with the raw MCP Java SDK, we use the Quarkus MCP Server extension which provides:

Maven Dependency:

<!-- Quarkus MCP Server (ADR-010) -->
<!-- NOTE: Using HTTP transport instead of stdio to avoid stdout capture conflict with Picocli -->
<dependency>
    <groupId>io.quarkiverse.mcp</groupId>
    <artifactId>quarkus-mcp-server-http</artifactId>
    <version>${quarkus-mcp.version}</version>
</dependency>

Why HTTP instead of STDIO?

The CLI uses Picocli which captures stdout for command output. STDIO transport conflicts with this because MCP also uses stdout for JSON-RPC messages. HTTP/SSE transport runs on a separate port, avoiding this conflict.

2. Shared Tool Logic Layer

All business logic is in the org.idempiere.cli.ai.shared package, shared between:

org.idempiere.cli.ai/
├── shared/                    # Core business logic
│   ├── ToolResult.java        # Standardized result format
│   ├── RegistryToolLogic.java # AD registry operations
│   ├── QueryToolLogic.java    # SQL query execution
│   ├── TableToolLogic.java    # Table operations
│   ├── GeneratorToolLogic.java# Code generation
│   └── DoctorToolLogic.java   # Diagnostics
│
├── langchain/tools/           # LangChain4j wrappers (ADR-013)
│   ├── RegistryTools.java
│   └── QueryTools.java
│
└── ../mcp/tools/              # MCP wrappers (this ADR)
    ├── McpRegistryTools.java
    ├── McpQueryTools.java
    ├── McpTableTools.java
    ├── McpGeneratorTools.java
    └── McpDoctorTools.java

3. Tool Implementation Example

@ApplicationScoped
public class McpRegistryTools {

    @Inject
    RegistryToolLogic registryLogic;

    @Tool(description = "List tables in the iDempiere Application Dictionary.")
    ToolResponse listTables(
            @ToolArg(description = "SQL LIKE pattern to filter tables") String pattern,
            @ToolArg(description = "Only show custom tables (XX_ prefix)") Boolean customOnly,
            @ToolArg(description = "Maximum number of results") Integer limit) {

        ToolResult result = registryLogic.listTables(pattern,
                customOnly != null ? customOnly : false, limit);
        return result.isSuccess()
                ? ToolResponse.success(result.toJson())
                : ToolResponse.error(result.toJson());
    }
}

4. Registered Tools

Category Tools
Registry listTables, describeTable, listColumns, listWindows, listProcesses, listReferences, searchRegistry, getStatistics
Query executeQuery, explainQuery, getQueryTemplates
Table createTable, syncTable, listTablesByEntity, deleteTable, getColumnPrefixHelp
Generator listGenerators, getGeneratorInfo, generatePlugin, generateModel, generateProcess, generateCallout, runGenerator
Doctor checkEnvironment, checkApi, checkDatabase, getConfigStatus

5. Running the MCP Server

The CLI runs in two modes:

Mode HTTP Port Usage
CLI (default) Disabled (0) java -jar idempiere-hub-runner.jar doctor
MCP Server 8765 java -Dquarkus.profile=mcp -jar idempiere-hub-runner.jar mcp-server

Start MCP Server:

# With dual database connection (iDempiere + RAG Vector DB)
IDEMPIERE_DB_HOST="localhost" \
IDEMPIERE_DB_PORT="5433" \
IDEMPIERE_DB_NAME="idempiere" \
IDEMPIERE_DB_USER="adempiere" \
IDEMPIERE_DB_PASSWORD="adempiere" \
RAG_VECTORDB_PG_HOST="localhost" \
RAG_VECTORDB_PG_PORT="5432" \
RAG_VECTORDB_PG_NAME="vector" \
RAG_VECTORDB_PG_USER="postgres" \
RAG_VECTORDB_PG_PASSWORD="postgres" \
java -Dquarkus.profile=mcp -jar target/idempiere-hub-runner.jar server mcp

# MCP endpoints will be available at:
#   - Streamable HTTP: http://localhost:8765/mcp
#   - SSE:             http://localhost:8765/mcp/sse

6. Claude Desktop Configuration

For HTTP/SSE transport (recommended), configure Claude Desktop to connect to the running MCP server with Bearer token authentication:

Step 1: Obtain JWT Token from iDempiere

# Login to get JWT access token
POST http://localhost:8080/api/v1/auth/tokens
{
  "userName": "SuperUser",
  "password": "System",
  "parameters": {
    "clientId": 0,      # System tenant for AD operations
    "roleId": 0,        # System Administrator
    "organizationId": 0
  }
}

# Response
{
  "token": "eyJraWQiOiJpZ...",  # ← Use this as Bearer token
  "refresh_token": "...",
  "userId": 100
}

Step 2: Configure Claude Desktop with Bearer Token

~/.claude/mcp.json:

{
  "mcpServers": {
    "iDempiere": {
      "httpUrl": "http://localhost:8080/mcp/streaming",
      "timeout": 30000,
      "trust": true,
      "headers": {
        "Authorization": "Bearer eyJraWQiOiJpZ..."
      }
    }
  }
}

Note on Token Expiration:

Alternative: STDIO transport (requires separate build with quarkus-mcp-server-stdio):

{
  "mcpServers": {
    "idempiere": {
      "command": "java",
      "args": ["-jar", "/path/to/idempiere-hub-runner.jar"],
      "env": {
        "IDEMPIERE_DB_HOST": "localhost",
        "IDEMPIERE_DB_PORT": "5432",
        "IDEMPIERE_DB_NAME": "idempiere",
        "IDEMPIERE_DB_USER": "adempiere",
        "IDEMPIERE_DB_PASSWORD": "adempiere"
      }
    }
  }
}

Consequences

Positive

Negative

Neutral

Usage Guide

See USER_GUIDE.md for detailed usage instructions.

References

Path: /docs/developers/architecture/idempiere-hub/010-mcp-server-architecture