Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 8 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -710,12 +710,13 @@ Token is persisted locally after `ms-hub login` and auto-loaded in subsequent se

| Variable | Default | Description |
|----------|---------|-------------|
| `MODELSCOPE_UPLOAD_MAX_WORKERS` | `min(8, cpu+4)` | Default parallel worker threads |
| `MODELSCOPE_UPLOAD_CACHE` | `true` | Enable resumable upload cache |
| `MODELSCOPE_UPLOAD_MAX_CONCURRENT_WORKERS` | `min(8, cpu+4)` | Default parallel worker threads |
| `MODELSCOPE_UPLOAD_CACHE_ENABLED` | `true` | Enable resumable upload cache |
| `MODELSCOPE_UPLOAD_IGNORE_FILE_PATTERN` | — | File pattern excluded by legacy `push_to_hub` uploads |
| `MODELSCOPE_UPLOAD_MAX_FILE_SIZE_MB` | `102400` | Max single file size (MB, default 100 GB) |
| `MODELSCOPE_UPLOAD_MAX_FILE_COUNT` | `100000` | Max total files per upload |
| `MODELSCOPE_UPLOAD_CONNECT_TIMEOUT` | `30` | Upload connect timeout (seconds) |
| `MODELSCOPE_UPLOAD_READ_TIMEOUT` | `3600` | Upload read timeout (seconds) |
| `MODELSCOPE_UPLOAD_BLOB_CONNECT_TIMEOUT_SECONDS` | `30` | Blob upload connect timeout (seconds) |
| `MODELSCOPE_UPLOAD_BLOB_READ_TIMEOUT_SECONDS` | `3600` | Blob upload read timeout (seconds) |

**Logging:**

Expand All @@ -725,8 +726,9 @@ Token is persisted locally after `ms-hub login` and auto-loaded in subsequent se
| `MODELSCOPE_NO_DEPRECATION_WARNINGS` | — | Suppress deprecation warnings |

> Old variable names (e.g. `API_TIMEOUT`, `DOWNLOAD_RETRY_TIMES`, `UPLOAD_USE_CACHE`) are
> still accepted but emit a `FutureWarning`. Run `ms-hub list --envs` to see which deprecated
> names are active in your environment.
> deprecated and remain temporarily supported. They emit a `FutureWarning` and will be removed
> in a future version. Run `ms-hub list --envs` to see which deprecated names are active in your
> environment.

</details>

Expand Down
12 changes: 6 additions & 6 deletions src/modelscope_hub/_legacy_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
REPO_FILES_TRUNCATION_LIMIT,
REPO_TREE_MAX_REQUESTS,
REPO_TREE_WALK_WORKERS,
UPLOAD_BLOB_CONNECT_TIMEOUT,
UPLOAD_BLOB_READ_TIMEOUT,
UPLOAD_RETRY_ALLOWED_METHODS,
UPLOAD_BLOB_CONNECT_TIMEOUT_SECONDS,
UPLOAD_BLOB_READ_TIMEOUT_SECONDS,
UPLOAD_HTTP_RETRY_ALLOWED_METHODS,
RepoType,
)
from .errors import InvalidParameter, NetworkError, RequestTimeoutError, ServerError, raise_for_status
Expand Down Expand Up @@ -108,7 +108,7 @@ def __init__(
total=max_retries,
backoff_factor=0.5,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=UPLOAD_RETRY_ALLOWED_METHODS,
allowed_methods=UPLOAD_HTTP_RETRY_ALLOWED_METHODS,
)
adapter = HTTPAdapter(max_retries=retry)
self._session.mount("https://", adapter)
Expand Down Expand Up @@ -778,7 +778,7 @@ def upload_blob(
size: int,
*,
headers: dict[str, str] | None = None,
timeout: int | None = None,
timeout: int | tuple[int, int] | None = None,
) -> dict:
"""Upload a blob to the presigned URL returned by :meth:`validate_blobs`.

Expand All @@ -805,7 +805,7 @@ def upload_blob(
upload_url,
data=data,
headers=upload_headers,
timeout=timeout or (UPLOAD_BLOB_CONNECT_TIMEOUT, UPLOAD_BLOB_READ_TIMEOUT),
timeout=timeout or (UPLOAD_BLOB_CONNECT_TIMEOUT_SECONDS, UPLOAD_BLOB_READ_TIMEOUT_SECONDS),
)
except requests.ConnectionError as exc:
raise NetworkError(f"Blob upload connection failed: {exc}") from exc
Expand Down
53 changes: 50 additions & 3 deletions src/modelscope_hub/_openapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@
from .config import HubConfig, get_default_config
from .constants import API_CONNECT_TIMEOUT, API_MAX_RETRIES, API_TIMEOUT, OPENAPI_PREFIX
from .errors import (
APIError,
AuthenticationError,
InvalidParameter,
NetworkError,
PermissionDeniedError,
RateLimitError,
RequestTimeoutError,
ServerError,
Expand Down Expand Up @@ -262,6 +264,7 @@ def _request(
files: Any | None = None,
headers: Mapping[str, str] | None = None,
require_token: bool = True,
anonymous: bool = False,
unwrap: bool = True,
timeout: float | None = None,
) -> Any:
Expand All @@ -277,7 +280,7 @@ def _request(
# Only attach our credentials when the target is our own host. Absolute
# URLs to a foreign host (e.g. signed OSS upload URLs) must not receive
# the Authorization header or session cookies, which carry the token.
if self._same_host_as_endpoint(final_url):
if self._same_host_as_endpoint(final_url) and not anonymous:
merged_headers = dict(self._auth_headers(require_token=require_token))
request_cookies = self._auth_cookies()
else:
Expand Down Expand Up @@ -678,6 +681,26 @@ def update_studio_settings(
# ==================================================================
# MCP (Model Context Protocol) servers
# ==================================================================
@staticmethod
def _flatten_mcp_list_params(body: Mapping[str, Any]) -> QueryParams:
params: QueryParams = []
for key, value in body.items():
if key == "filter" and isinstance(value, Mapping):
for filter_key, filter_value in value.items():
params.append(
(
f"filter.{filter_key}",
str(filter_value).lower() if isinstance(filter_value, bool) else str(filter_value),
)
)
else:
params.append((key, str(value).lower() if isinstance(value, bool) else str(value)))
return params

@staticmethod
def _is_method_or_route_unsupported(exc: APIError) -> bool:
return exc.status_code in (404, 405, 501)

def list_mcp_servers(
self,
*,
Expand All @@ -687,7 +710,12 @@ def list_mcp_servers(
filter: Mapping[str, Any] | None = None,
extra: Mapping[str, Any] | None = None,
) -> JSON:
"""``PUT /mcp/servers`` — discover MCP servers (JSON body, not query).
"""``GET /mcp/servers`` — discover MCP servers.

Falls back to the historical ``PUT /mcp/servers`` endpoint while the
service rolls out GET support. If an optional token is rejected by the
legacy PUT list endpoint, retry anonymously so readonly or stale tokens
do not block public MCP discovery.

Parameters
----------
Expand All @@ -708,7 +736,26 @@ def list_mcp_servers(
if extra:
body.update(extra)
body = {k: v for k, v in body.items() if v is not None}
return self._request("PUT", "/mcp/servers", json_body=body, require_token=False)
params = self._flatten_mcp_list_params(body)
has_token = self._resolve_token() is not None
try:
return self._request("GET", "/mcp/servers", params=params, require_token=False)
except APIError as exc:
if not self._is_method_or_route_unsupported(exc):
raise

try:
return self._request("PUT", "/mcp/servers", json_body=body, require_token=False)
except (AuthenticationError, PermissionDeniedError):
if not has_token:
raise
return self._request(
"PUT",
"/mcp/servers",
json_body=body,
require_token=False,
anonymous=True,
)

def list_operational_mcp_servers(self) -> JSON:
"""``GET /mcp/servers/operational`` — list servers deployed by the caller."""
Expand Down
Loading
Loading