Zero-Trust Context Retrieval

Secure Model Context Protocol (MCP) Server

Give AI models and agents direct access to enterprise knowledge databases while enforcing strict, server-side Access Control Lists (ACLs). Prevent prompt injection leaks and unauthorized document retrieval.

Server-Side Security Filtering

Dynamic pre-filtering inside database queries (PostgreSQL/pgvector) guarantees LLMs never receive raw data matching unauthorized ACLs, eliminating context boundary bypasses.

Identity & Role Propagation

Accepts user principal identities (email, username) and LDAP/Active Directory group roles at query time. Seamlessly maps caller tokens to repository Security SIDs.

Spring AI 2.0 Native

Built directly into the oc-runtime module using Spring AI standard `@McpTool` annotations and WebMVC/SSE transport protocols for seamless Java ecosystem integration.

Zero-Trust Retrieval Pipeline

How OpenCrawling intercepts AI client requests to enforce document permissions before vector store search execution.

graph TD subgraph AI Client Layer LLM[LLM Agent / MCP Client] end subgraph OpenCrawling Runtime MCP[McpVectorServer] Auth[Authority Service] VecStore[PgVectorStore / Milvus] end subgraph Storage Boundary DB[(Vector Store Database)] end LLM -->|1. secureVectorSearch query, principal, roles| MCP MCP -->|2. Resolve identity & active tokens| Auth MCP -->|3. Build dynamic security FilterExpression| VecStore VecStore -->|4. SQL query with WHERE acl IN user_rights| DB DB -->|5. Permitted vector chunk candidates| VecStore VecStore -->|6. Filtered results with metadata| MCP MCP -->|7. Sanitized JSON context response| LLM

Exposed MCP Tools Specification

The standard tools made dynamically available to connected LLMs and AI agent frameworks.

secureVectorSearch Core Search Tool

Performs semantic vector similarity search on indexed enterprise documents, pre-filtering results on the server using the caller's identity and group permissions.

Parameter Type Required Description
query String Yes Natural language search phrase or keywords.
userPrincipal String Yes User email or principal identity performing the query.
userRoles String Optional Comma-separated roles/groups (e.g. finance,engineering).
maxResults Integer Optional Maximum top-K results to return (default: 5).
minScore Double Optional Minimum vector similarity threshold (0.0 - 1.0).
dimensions Integer Optional Target vector dimension store (384, 768, or 1024).
getDocumentContent Document Retrieval

Retrieves complete document content and metadata for a specific URI, verifying caller authorization prior to payload retrieval.

Parameter Type Required Description
documentUri String Yes Target document URI (e.g. file:///data/reports/q3.pdf).
userPrincipal String Yes User principal identity verifying access rights.
userRoles String Optional Comma-separated group memberships of caller.
listAccessibleSources Discovery

Returns a list of all indexed documents and knowledge sources accessible to the specified user identity.

Parameter Type Required Description
userPrincipal String Yes User principal identity for ACL enumeration.
userRoles String Optional Comma-separated group memberships.

Client Integration Setup

Configure your preferred AI environment to talk directly to the OpenCrawling Secure MCP Server.

Add the server entry to your local claude_desktop_config.json:

{
  "mcpServers": {
    "opencrawling-secure-vector-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/client-cli",
        "sse",
        "http://localhost:8080/mcp/sse"
      ]
    }
  }
}

Add entry in workspace or global ~/.cursor/mcp.json:

{
  "mcpServers": {
    "opencrawling-secure-vector-mcp": {
      "url": "http://localhost:8080/mcp/sse"
    }
  }
}

Add entry to ~/.codeium/windsurf/mcp_config.json:

{
  "mcpServers": {
    "opencrawling-mcp": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/client-cli",
        "sse",
        "http://localhost:8080/mcp/sse"
      ]
    }
  }
}

Add SSE server provider in ~/.continue/config.json:

{
  "experimental": {
    "modelContextProtocolServers": [
      {
        "transport": {
          "type": "sse",
          "url": "http://localhost:8080/mcp/sse"
        }
      }
    ]
  }
}

Register via agy CLI or ~/.gemini/antigravity-cli/mcp.json:

# Command line setup:
agy mcp add opencrawling-mcp http://localhost:8080/mcp/sse --transport sse

# Configuration JSON:
{
  "mcpServers": {
    "opencrawling-mcp": {
      "transport": "sse",
      "url": "http://localhost:8080/mcp/sse"
    }
  }
}

Query the MCP server asynchronously using the Python mcp library:

import asyncio
from mcp import ClientSession
from mcp.client.sse import sse_client

async def main():
    async with sse_client("http://localhost:8080/mcp/sse") as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            
            result = await session.call_tool(
                "secureVectorSearch",
                arguments={
                    "query": "Q3 Financial Growth Strategy",
                    "userPrincipal": "alice@company.com",
                    "userRoles": "finance,executives",
                    "maxResults": 5
                }
            )
            print(result.content)

asyncio.run(main())

Consumer settings & Service injection in Spring Boot Java microservices:

# application.yml:
spring:
  ai:
    mcp:
      client:
        enabled: true
        name: opencrawling-client
        sse:
          opencrawling-server:
            base-url: http://localhost:8080
            sse-endpoint: /mcp/sse

// Java Service Code:
@Autowired
private McpClient mcpClient;

public String searchKnowledge(String userEmail, String query) {
    var response = mcpClient.callTool("secureVectorSearch", Map.of(
        "query", query,
        "userPrincipal", userEmail,
        "userRoles", "engineering"
    ));
    return response.content().toString();
}

Direct manual SSE listening and JSON-RPC execution via cURL:

# 1. Listen to SSE Stream:
curl -N -H "Accept: text/event-stream" http://localhost:8080/mcp/sse

# 2. Call Tool via JSON-RPC POST (use sessionId from SSE output):
curl -X POST "http://localhost:8080/mcp/message?sessionId=YOUR_SESSION_ID" \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "secureVectorSearch",
      "arguments": {
        "query": "Kubernetes cluster security",
        "userPrincipal": "devops@company.com",
        "userRoles": "engineering"
      }
    }
  }'

Run the dedicated MCP microservice using docker container build:

docker build -f docker/Dockerfile.mcp-server -t opencrawling-mcp-server .
docker run -p 8080:8080 \
  -e OPENCRAWLING_MCP_SERVER_ENABLED=true \
  -e SPRING_AI_MCP_SERVER_ANNOTATION_SCANNER_ENABLED=true \
  opencrawling-mcp-server