Access Doors
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. resolveIntoresolves a row explicitly into the target wiki, andisAuthorizedapplies 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.