Architecture

Last modified by gabrielc on 2026/07/13 16:51

Explanation

The MCP server is four thin layers riding existing XWiki infrastructure, plus an extension point for custom tools.

Module layout

application-ai-llm-mcp/
├── application-ai-llm-mcp-api/        MCPTool @Role (the extension point)
├── application-ai-llm-mcp-server/     endpoint, manager, config reader,
│                                      access doors, 6 bundled tools,
│                                      tool support (internal)
└── application-ai-llm-mcp-ui/         admin UI + config pages (XAR)

The server module has no dependency on the index/RAG stack. It is installable standalone. Bundled tools query XWiki's built-in Solr index.

Four-layer architecture

                        HTTP (JSON-RPC over POST)
                                 │
   ┌─────────────────────────────▼───────────────────────────────┐
   │ DefaultMCPResource               identity & routing layer   │
   │   /rest/wikis/{wiki}/aiLLM/mcp                              │
   │   - per-wiki enable gate (disabled wiki → 404)              │
   │   - OAuth/OIDC discovery (RFC 9728)                         │
   │   - rejects unauthenticated callers (when OIDC present)     │
   │   - sets the target wiki on the XWikiContext                │
   └─────────────────────────────┬───────────────────────────────┘
                                 │
   ┌─────────────────────────────▼───────────────────────────────┐
   │ XWikiMCPServerManager        lifecycle & middleware layer   │
   │   - one SDK server per wiki, built lazily, cached           │
   │   - registers only the wiki's enabled MCPTool components    │
   │   - executeWrapped(): per-call middleware (audit,           │
   │     exception normalization)                                │
   └─────────────────────────────┬───────────────────────────────┘
                                 │
   ┌─────────────────────────────▼───────────────────────────────┐
   │ MCPTool components                       capability layer   │
   │   man · query_documents · get_document · edit_document      │
   │   · write_document · list_wikis (reach-gated)               │
   │   (index module contributes list_collections /              │
   │    search_collections when installed)                       │
   └─────────────────────────────┬───────────────────────────────┘
                                 │
   ┌─────────────────────────────▼───────────────────────────────┐
   │ Access doors                   shared authorization layer   │
   │   MCPDocumentAccess · MCPWikiReach · MCPSpaceFilter         │
   │   · MCPDocumentSearch                                       │
   │   - reach gate → rights check → space filter, in that order │
   │   - always as the authenticated user, via XWiki's normal    │
   │     rights model                                            │
   └─────────────────────────────────────────────────────────────┘

Design principles

Every hard problem is delegated to something XWiki already has:

  • Authentication rides the existing filter chain (OIDC bridge).
  • Authorization rides SecureQuery and ContextualAuthorizationManager.
  • Save attribution rides com.xpn.xwiki.api.Document.
  • Extensibility rides the component manager.
  • Configuration rides a per-wiki wiki document plus an event listener.

Request lifecycle

  1. HTTP request arrives at DefaultMCPResource (/rest/wikis/{wiki}/aiLLM/mcp).
  2. Enable gate: disabled wiki returns 404 before anything else.
  3. Authentication has already happened (filter chain). Guest + OIDC → 401.
  4. Resource sets the target wiki on the XWikiContext and calls XWikiMCPServerManager.handleRequest().
  5. Manager resolves the wiki's cached SDK server (built lazily, one per wiki).
  6. SDK parses the JSON-RPC message and dispatches tools/call to the registered handler.
  7. Handler is the middleware (executeWrapped), which invokes the tool's execute() synchronously on the request thread.
  8. Result serialized back as HTTP response.

Threading

Tool handlers run inline on the HTTP request thread, where XWiki's thread-locals (current user, wiki) natively live. The SDK builder sets immediateExecution(true) to prevent offloading to Reactor worker threads.

Server lifecycle

  • XWikiMCPServerManager owns a ConcurrentHashMap of SDK servers, one per wiki.
  • buildServer(wikiId): reads config, enumerates MCPTool components, filters by enabled tool ids, registers each on a fresh transport.
  • Registration is fault-isolated per tool: a throwing tool is skipped with a WARN.
  • Invalidation is event-driven: MCPConfigChangeEventListener watches saves of AI.MCP.Code.MCPServerConfig. Main wiki saves invalidate all servers (cross-wiki reach may have changed); other wiki saves invalidate only that wiki.

MCP SDK

Version 2.0.0 of io.modelcontextprotocol.sdk:mcp-core. The version is owned by the mcp-bom import in the root POM. Two SDK defaults are overridden:

  • immediateExecution(true) — tools run on the request thread, not Reactor workers.
  • validateToolInputs(false) — the MCPToolSupport declarative parameter layer is the designed validation gate.

Get Connected