Access Doors

Last modified by Vincent Massol on 2026/09/04 20:04

Reference

The access doors centralize the MCP server's authorization and scoping decisions so that no tool re-implements them.

Three are public component roles of the application-ai-llm-mcp-api module (package org.xwiki.contrib.llm.mcp), so a tool contributed by any module can inject them: MCPDocumentAccess, MCPWikiReach and MCPDocumentSearch. Two are internal to the server module (package org.xwiki.contrib.llm.mcp.internal.access): MCPSpaceFilter, which the public doors apply on the caller's behalf, and MCPRowQuery.

A tool must never resolve a DocumentReference itself: doing so escapes the space policy and can reach another wiki unchecked.

MCPDocumentAccess

Single sanctioned way to resolve a reference and enforce authorization.

@Role
public interface MCPDocumentAccess {
    DocumentReference resolveAndAuthorize(String reference, Right right)
        throws MCPAccessDeniedException;
}

Applies in order: reach gate → ContextualAuthorizationManager.hasAccess → space filter. Throws MCPAccessDeniedException with an agent-facing refusal message.

MCPSpaceFilter

Applies the MCP space whitelist or blacklist. Internal to the server module: the public doors above already apply it, so a tool in another module does not call it directly.

@Role
public interface MCPSpaceFilter {
    boolean isAllowed(DocumentReference reference);
    List<String> filterQueries();
}
Method Returns
isAllowed(reference) Whether that one document passes the configured filter mode and entries
filterQueries() The Solr filter query clauses that scope search results to the same set

A space entry covers the space and its whole subtree; a document entry matches exactly one document. Both fail closed on read errors: isAllowed denies, and filterQueries returns a match-nothing -*:* clause.

MCPWikiReach

Decides how far an endpoint reaches beyond its own wiki.

@Role
public interface MCPWikiReach {
    boolean isReachEnabled();
    boolean canReachWiki(String wikiId);
    List<String> resolveSearchWikis(String wikiParam);
}
Method Returns
isReachEnabled() Whether this endpoint may cross wikis at all
canReachWiki(wikiId) Whether that one target wiki is reachable
resolveSearchWikis(wikiParam) The wikis a search covers, from the tool's wiki parameter: blank → the current wiki, "all" → the whole farm, an id → that single wiki, validated

Backed by the main-wiki-only reachEnabledWikis list. A reach-enabled endpoint reaches every wiki in the farm regardless of the target's own enable gate, tool toggles, or space filter.

MCPDocumentSearch

Builds a Solr search query scoped to wikis, space filter, and rights.

@Role
public interface MCPDocumentSearch {
    Query createQuery(String statement, List<String> additionalFilterQueries,
                      List<String> targetWikiIds);
}

Uses SecureQuery with checkCurrentUser(true), wiki-scope clauses, and the space filter — the single query path for query_documents.

MCPAccessDeniedException

public class MCPAccessDeniedException extends Exception {
    public MCPAccessDeniedException(String message) { ... }
}

Carries the agent-facing refusal message. Thrown by MCPDocumentAccess.resolveAndAuthorize() and caught by the tool to produce an isError result.

MCPRowQuery

Internal door to the authorized HQL row pipeline of the navigation tools: bounded row fetching against one target wiki, plus per-row resolution and authorization of the fetched rows.

  • Every fetch limit is clamped to at most MAX_FETCH_PER_QUERY (2000 rows), so a broad statement cannot materialize an unbounded row set.
  • resolveInto resolves a row explicitly into the target wiki, and isAuthorized applies the space filter and then the view right, in that order.
  • Hidden-page exclusion is explicit HQL rather than a query filter, so it holds regardless of the calling user's own profile preference.

Related

Get Connected