Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
df58eb6
feat: add HTTP MCP search server with partition ACLs
EnjoyBacon7 Feb 24, 2026
6ba0fc8
Added mcp search and metadata fetching + tests
EnjoyBacon7 Feb 26, 2026
dd6d45b
Added more tools & tests
EnjoyBacon7 Feb 26, 2026
9577638
Added mcp tests
EnjoyBacon7 Mar 9, 2026
7cfcc20
feat: add OpenRAGApplicationService as shared app-layer facade
EnjoyBacon7 Mar 9, 2026
9d23edf
refactor(mcp): consolidate services into OpenRAGApplicationService
EnjoyBacon7 Mar 9, 2026
adc89ec
refactor(routers): route all operations through OpenRAGApplicationSer…
EnjoyBacon7 Mar 9, 2026
20d734f
test(mcp): update patched_services fixture for composite app_service
EnjoyBacon7 Mar 9, 2026
58b90bf
fix(rag): prevent ContextWindowExceededError by correcting context bu…
EnjoyBacon7 Mar 9, 2026
289e52f
fix(chunker): prevent ContextWindowExceededError during chunk context…
EnjoyBacon7 Mar 9, 2026
ad5d117
fix(mcp): paginate get_file_chunks to prevent LLM context overflow
EnjoyBacon7 Mar 9, 2026
13f1098
fix(mcp): use limit=-1 instead of limit=100_000 for unbounded chunk f…
EnjoyBacon7 Mar 9, 2026
a32601d
fix(mcp): lower get_file_chunks default limit from 10 to 3
EnjoyBacon7 Mar 9, 2026
d254ab7
fix(mcp): auto-create partition on index_url when partition does not …
EnjoyBacon7 Mar 11, 2026
1468737
fix(mcp): forward user to add_file in index_url to fix task ownership…
EnjoyBacon7 Mar 11, 2026
2a31f12
fix(mcp): catch non-PermissionError in dispatch middleware to avoid 5…
EnjoyBacon7 Mar 12, 2026
61a262b
fix(mcp): prevent ContextVar mutation, enforce editor ACL on write op…
EnjoyBacon7 Mar 12, 2026
866a071
fix(api): replace deprecated @app.on_event with lifespan context mana…
EnjoyBacon7 Mar 12, 2026
82a2909
fix(routers): remove redundant Ray remote call in get_task_status (#3)
EnjoyBacon7 Mar 12, 2026
c0032ce
fix(app): pass None instead of invalid Ray task_id in execute_tool (#6)
EnjoyBacon7 Mar 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
BASE_URL=
API_KEY=
MODEL=
# LLM_CONTEXT_WINDOW=8192 # Token context window of the LLM (used to cap RAG context size)

# VLM (Visual Language Model) you can set it to the same as LLM if your LLM supports images
VLM_BASE_URL=
VLM_API_KEY=
VLM_MODEL=
# VLM_CONTEXT_WINDOW=8192 # Token context window of the VLM (used to cap chunk contextualizer input size)

## FastAPI App (no need to change it)
# APP_PORT=8080 # this is the forwarded port
Expand Down Expand Up @@ -60,3 +62,12 @@ LOG_LEVEL=DEBUG # See possible values https://loguru.readthedocs.io/en/stable/ap
# SERVER
# Set the preferred URL scheme for generated URLs (e.g., task_status_url).
PREFERRED_URL_SCHEME=https

# MCP SERVER
# OPENRAG_MCP_SERVER_NAME="OpenRAG MCP"
# OPENRAG_MCP_HOST=0.0.0.0
# OPENRAG_MCP_PORT=8081
# OPENRAG_MCP_PATH=/mcp
# OPENRAG_MCP_DEFAULT_TOP_K=5
# OPENRAG_MCP_MAX_TOP_K=50
# OPENRAG_MCP_SIMILARITY_THRESHOLD=0.8
11 changes: 11 additions & 0 deletions .hydra_config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@ llm:
base_url: ${oc.env:BASE_URL}
model: ${oc.env:MODEL}
api_key: ${oc.env:API_KEY}
context_window: ${oc.decode:${oc.env:LLM_CONTEXT_WINDOW, 8192}}

vlm:
<<: *llm_params
base_url: ${oc.env:VLM_BASE_URL}
model: ${oc.env:VLM_MODEL}
api_key: ${oc.env:VLM_API_KEY}
context_window: ${oc.decode:${oc.env:VLM_CONTEXT_WINDOW, 8192}}

semaphore:
llm_semaphore: ${oc.decode:${oc.env:LLM_SEMAPHORE, 10}}
Expand Down Expand Up @@ -72,6 +74,15 @@ verbose:
server:
preferred_url_scheme: ${oc.env:PREFERRED_URL_SCHEME, null}

mcp:
server_name: ${oc.env:OPENRAG_MCP_SERVER_NAME, OpenRAG MCP}
host: ${oc.env:OPENRAG_MCP_HOST, 0.0.0.0}
port: ${oc.decode:${oc.env:OPENRAG_MCP_PORT, 8081}}
path: ${oc.env:OPENRAG_MCP_PATH, /mcp}
default_top_k: ${oc.decode:${oc.env:OPENRAG_MCP_DEFAULT_TOP_K, 5}}
max_top_k: ${oc.decode:${oc.env:OPENRAG_MCP_MAX_TOP_K, 50}}
similarity_threshold: ${oc.decode:${oc.env:OPENRAG_MCP_SIMILARITY_THRESHOLD, 0.8}}

paths:
prompts_dir: ${oc.env:PROMPTS_DIR, ../prompts/example1}
data_dir: ${oc.env:DATA_DIR, ../data}
Expand Down
18 changes: 17 additions & 1 deletion openrag/api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import os
import warnings
from contextlib import AsyncExitStack, asynccontextmanager
from enum import Enum
from importlib.metadata import version as get_package_version
from pathlib import Path
Expand Down Expand Up @@ -29,6 +30,9 @@
from routers.search import router as search_router
from routers.tools import router as tools_router
from routers.users import router as users_router
from mcp_server import create_mcp_http_app
from mcp_server import path as mcp_path
from mcp_server import server as mcp_server
from starlette.middleware.base import BaseHTTPMiddleware
from utils.dependencies import get_vectordb
from utils.exceptions import OpenRAGError
Expand Down Expand Up @@ -82,7 +86,17 @@ def __init__(self, config):
except Exception:
app_version = "unknown"

app = FastAPI(version=app_version)
_mcp_lifespan_stack = AsyncExitStack()


@asynccontextmanager
async def lifespan(app):
await _mcp_lifespan_stack.enter_async_context(mcp_server.session_manager.run())
yield
await _mcp_lifespan_stack.aclose()


app = FastAPI(version=app_version, lifespan=lifespan)


def custom_openapi():
Expand Down Expand Up @@ -180,10 +194,12 @@ async def openrag_exception_handler(request: Request, exc: OpenRAGError):
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
expose_headers=["Mcp-Session-Id"],
)

app.state.app_state = AppState(config)
app.mount("/static", StaticFiles(directory=DATA_DIR.resolve(), check_dir=True), name="static")
app.mount(mcp_path, create_mcp_http_app(), name="mcp")


@app.get("/health_check", summary="Health check endpoint for API", dependencies=[])
Expand Down
11 changes: 11 additions & 0 deletions openrag/components/app/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from .interfaces import OpenRAGApiInterface

__all__ = ["OpenRAGApiInterface", "OpenRAGApplicationService"]


def __getattr__(name: str):
if name == "OpenRAGApplicationService":
from .service import OpenRAGApplicationService # noqa: PLC0415

return OpenRAGApplicationService
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
Loading