feat: add mcp server

This commit is contained in:
Abhishek Kumar 2026-04-15 22:19:41 +05:30
parent e31b38122e
commit d895ac0fba
18 changed files with 440 additions and 74 deletions

View file

@ -12,14 +12,11 @@ from .base import BaseFileSystem
class MinioFileSystem(BaseFileSystem):
"""MinIO implementation of the filesystem interface for OSS users.
Handles both internal (container-to-container) and external (browser) access:
- endpoint: Used for API operations (uploads, downloads from code)
- public_endpoint: Used for generating browser-accessible presigned URLs
Auto-detection logic:
1. If MINIO_PUBLIC_ENDPOINT env var is set, use it (for production/custom domains)
2. If endpoint is "minio:9000" (Docker internal), auto-use "localhost:9000" for browser
3. Otherwise, endpoint works for both (e.g., "localhost:9000" in local non-Docker setup)
Two endpoints, two different purposes:
- endpoint (host:port) + secure (bool): used by the MinIO SDK for
container-to-container calls. The SDK requires these split.
- public_endpoint (full URL, e.g. "https://example.com"): used verbatim
when building URLs that browsers will fetch. Required.
"""
def __init__(
@ -31,9 +28,22 @@ class MinioFileSystem(BaseFileSystem):
secure: bool = False,
public_endpoint: Optional[str] = None,
):
if not public_endpoint:
raise ValueError(
"MinioFileSystem requires public_endpoint (set MINIO_PUBLIC_ENDPOINT). "
"Expected a full URL with scheme, e.g. 'http://localhost:9000' or 'https://example.com'."
)
if not (
public_endpoint.startswith("http://")
or public_endpoint.startswith("https://")
):
raise ValueError(
f"MINIO_PUBLIC_ENDPOINT must include a scheme (http:// or https://), got: {public_endpoint!r}"
)
self.bucket_name = bucket_name
self.endpoint = endpoint
self.public_endpoint = public_endpoint or endpoint
self.public_endpoint = public_endpoint.rstrip("/")
self.secure = secure
self.access_key = access_key
self.secret_key = secret_key
@ -115,13 +125,12 @@ class MinioFileSystem(BaseFileSystem):
use_internal_endpoint: bool = False,
) -> Optional[str]:
try:
# For MinIO in local development, return unsigned URLs
# This avoids signature mismatch issues when endpoint differs
# MinIO must be configured to allow anonymous read access
protocol = "https" if self.secure else "http"
endpoint = self.endpoint if use_internal_endpoint else self.public_endpoint
url = f"{protocol}://{endpoint}/{self.bucket_name}/{file_path}"
return url
if use_internal_endpoint:
protocol = "https" if self.secure else "http"
base = f"{protocol}://{self.endpoint}"
else:
base = self.public_endpoint
return f"{base}/{self.bucket_name}/{file_path}"
except Exception as e:
logger.error(f"Error generating MinIO URL: {e}")
return None
@ -162,9 +171,7 @@ class MinioFileSystem(BaseFileSystem):
The bucket policy allows anonymous s3:PutObject, so no signature is needed.
"""
try:
# Return unsigned URL for anonymous upload
protocol = "https" if self.secure else "http"
url = f"{protocol}://{self.public_endpoint}/{self.bucket_name}/{file_path}"
url = f"{self.public_endpoint}/{self.bucket_name}/{file_path}"
logger.debug(f"Generated unsigned upload URL: {url}")
return url
except Exception as e:

View file

@ -25,46 +25,24 @@ def get_storage_for_backend(backend: str) -> BaseFileSystem:
"""
# Code 2: MinIO implementation (local/OSS deployments)
if backend == StorageBackend.MINIO.value:
endpoint = MINIO_ENDPOINT
# Auto-detect public endpoint:
# - If MINIO_PUBLIC_ENDPOINT is set, use it (for custom domains/IPs)
# - If running in Docker and endpoint is "minio:9000", use "localhost:9000" for local dev
# - Otherwise, use the endpoint as-is (both containers and browser can reach it)
public_endpoint = MINIO_PUBLIC_ENDPOINT
if not public_endpoint:
# Auto-detect based on endpoint
if endpoint.startswith("minio:"):
# Docker internal endpoint detected, assume local development
public_endpoint = endpoint.replace("minio:", "localhost:")
logger.info(
f"Auto-detected local development: using {public_endpoint} for public access"
)
elif endpoint.startswith("host.docker.internal:"):
# Docker Desktop special DNS detected, use localhost for browser access
public_endpoint = endpoint.replace(
"host.docker.internal:", "localhost:"
)
logger.info(
f"Auto-detected Docker Desktop: using {public_endpoint} for public access"
)
else:
# Already using a public endpoint (localhost:9000 or domain:9000)
public_endpoint = endpoint
access_key = MINIO_ACCESS_KEY
secret_key = MINIO_SECRET_KEY
bucket = MINIO_BUCKET
secure = MINIO_SECURE
if not MINIO_PUBLIC_ENDPOINT:
raise ValueError(
"MINIO_PUBLIC_ENDPOINT is required for MinIO storage. "
"Set it to the full URL browsers use to reach MinIO, "
"e.g. 'http://localhost:9000' for local dev or "
"'https://your-server.example.com' for a remote deployment."
)
logger.info(
f"Initializing {backend} storage at {endpoint} (public: {public_endpoint}) with bucket '{bucket}'"
f"Initializing {backend} storage at {MINIO_ENDPOINT} "
f"(public: {MINIO_PUBLIC_ENDPOINT}) with bucket '{MINIO_BUCKET}'"
)
return MinioFileSystem(
endpoint=endpoint,
access_key=access_key,
secret_key=secret_key,
bucket_name=bucket,
secure=secure,
public_endpoint=public_endpoint,
endpoint=MINIO_ENDPOINT,
access_key=MINIO_ACCESS_KEY,
secret_key=MINIO_SECRET_KEY,
bucket_name=MINIO_BUCKET,
secure=MINIO_SECURE,
public_endpoint=MINIO_PUBLIC_ENDPOINT,
)
# Code 1: AWS S3 implementation (cloud deployments)