Skip to content

Commit 3219664

Browse files
committed
refactor: improve pyproject.toml and adjust related project files
1 parent 1602b4c commit 3219664

22 files changed

+162
-699
lines changed

.vscode/tasks.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,11 @@
7070
"problemMatcher": []
7171
},
7272
{
73-
"label": "uv run pytest -s",
74-
"detail": "Run pytest tests with output",
73+
"label": "uv run pytest",
74+
"detail": "Run pytest tests",
7575
"type": "shell",
7676
"command": "uv",
77-
"args": ["run", "pytest", "-s"],
77+
"args": ["run", "pytest"],
7878
"group": {
7979
"kind": "test",
8080
"isDefault": false

demo.py

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,7 @@ async def demo_get_current_user(client: Client) -> None:
2626
username = user_info.get("username", "N/A")
2727
email = user_info.get("email", "N/A")
2828
authenticated = user_info.get("authenticated", "N/A")
29-
print(
30-
f" • Result: Username={username}, Email={email}, Authenticated={authenticated}"
31-
)
29+
print(f" • Result: Username={username}, Email={email}, Authenticated={authenticated}")
3230
else:
3331
print(" • Result: No user information retrieved")
3432
print()
@@ -37,9 +35,7 @@ async def demo_get_current_user(client: Client) -> None:
3735
async def demo_search_models(client: Client) -> None:
3836
"""Demo: Search models using various parameters."""
3937
print("2. 🛠️ Tool: search_models")
40-
print(
41-
" • Task: 🔍 Search text-generation models (keyword='DeepSeek', support inference, limit 3 results)"
42-
)
38+
print(" • Task: 🔍 Search text-generation models (keyword='DeepSeek', support inference, limit 3 results)")
4339

4440
result = await client.call_tool(
4541
"search_models",
@@ -68,9 +64,7 @@ async def demo_search_models(client: Client) -> None:
6864
async def demo_search_papers(client: Client) -> None:
6965
"""Demo: Search papers using query."""
7066
print("3. 🛠️ Tool: search_papers")
71-
print(
72-
" • Task: 📚 Search academic papers (keyword='Qwen3', sort='hot', limit 1 result)"
73-
)
67+
print(" • Task: 📚 Search academic papers (keyword='Qwen3', sort='hot', limit 1 result)")
7468

7569
result = await client.call_tool(
7670
"search_papers",
@@ -85,9 +79,7 @@ async def demo_search_papers(client: Client) -> None:
8579
authors = paper.get("authors", "N/A")
8680
arxiv_id = paper.get("arxiv_id", "N/A")
8781
views = paper.get("view_count", 0)
88-
print(
89-
f" • Result: '{title}' Authors={authors}, ArXiv ID={arxiv_id}, Views={views:,}"
90-
)
82+
print(f" • Result: '{title}' Authors={authors}, ArXiv ID={arxiv_id}, Views={views:,}")
9183
else:
9284
print(" • Result: No papers found")
9385
else:
@@ -98,9 +90,7 @@ async def demo_search_papers(client: Client) -> None:
9890
async def demo_search_mcp_servers(client: Client) -> None:
9991
"""Demo: Search MCP servers using various parameters."""
10092
print("4. 🛠️ Tool: search_mcp_servers")
101-
print(
102-
" • Task: 🔍 Search MCP servers (keyword='Chrome', category='browser-automation', limit 3 results)"
103-
)
93+
print(" • Task: 🔍 Search MCP servers (keyword='Chrome', category='browser-automation', limit 3 results)")
10494

10595
result = await client.call_tool(
10696
"search_mcp_servers",
@@ -119,9 +109,7 @@ async def demo_search_mcp_servers(client: Client) -> None:
119109
publisher = server.get("publisher", "N/A")
120110
views = server.get("view_count", 0)
121111
server_summary.append(f"{name} by {publisher} (Views {views:,})")
122-
print(
123-
f" • Result: Found {len(servers)} servers - {' | '.join(server_summary)}"
124-
)
112+
print(f" • Result: Found {len(servers)} servers - {' | '.join(server_summary)}")
125113
else:
126114
print(" • Result: No MCP servers found")
127115
print()
@@ -130,14 +118,12 @@ async def demo_search_mcp_servers(client: Client) -> None:
130118
async def demo_generate_image(client: Client) -> None:
131119
"""Demo: Generate image URL from text prompt."""
132120
print("5. 🛠️ Tool: generate_image")
133-
print(
134-
" • Task: 🎨 Generate image (prompt='A curious cat wearing a tiny wizard hat in candy cloud kingdom')"
135-
)
121+
print(" • Task: 🎨 Generate image (prompt='A curious cat wearing a tiny wizard hat in candy cloud kingdom')")
136122

137123
result = await client.call_tool(
138124
"generate_image",
139125
{
140-
"prompt": "A curious cat wearing a tiny wizard hat, casting magical rainbow sparkles while riding a flying donut through a candy cloud kingdom",
126+
"prompt": "A curious cat wearing a tiny wizard hat in candy cloud kingdom",
141127
},
142128
)
143129

@@ -150,7 +136,7 @@ async def demo_generate_image(client: Client) -> None:
150136

151137

152138
def setup_signal_handler():
153-
"""Setup signal handler for graceful shutdown."""
139+
"""Set up signal handler for graceful shutdown."""
154140

155141
def signal_handler(signum, frame):
156142
print("\n🛑 Demo interrupted by user")
@@ -160,6 +146,7 @@ def signal_handler(signum, frame):
160146

161147

162148
async def main():
149+
"""Run the demo."""
163150
parser = argparse.ArgumentParser(description="ModelScope MCP server demo")
164151
parser.add_argument(
165152
"--full",
@@ -170,9 +157,7 @@ async def main():
170157

171158
print(f"🤖 ModelScope MCP Server Demo (v{__version__})")
172159
if not args.full:
173-
print(
174-
"💡 Running basic demos only. Use --full to include slow demos (like image generation)"
175-
)
160+
print("💡 Running basic demos only. Use --full to include slow demos (like image generation)")
176161

177162
# Set log level to WARNING to avoid too many logs
178163
settings.log_level = "WARNING"

pyproject.toml

Lines changed: 45 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
[project]
22
name = "modelscope-mcp-server"
33
dynamic = ["version"]
4-
description = "ModelScope MCP Server"
4+
description = "A Model Context Protocol (MCP) server that integrates with ModelScope's ecosystem."
55
readme = "README.md"
6-
authors = [{ name = "ModelScope Team" }]
6+
authors = [
7+
{ name = "ModelScope Team", email = "contact@modelscope.cn" }
8+
]
79
license = { file = "LICENSE" }
810
requires-python = ">=3.10"
911
dependencies = [
@@ -14,21 +16,16 @@ dependencies = [
1416
keywords = [
1517
"modelscope",
1618
"mcp",
17-
"mcp server",
1819
"model-context-protocol",
19-
"fastmcp",
2020
"llm",
21-
"agent",
21+
"ai",
2222
]
2323
classifiers = [
2424
"Development Status :: 3 - Alpha",
2525
"Intended Audience :: Developers",
26-
"License :: OSI Approved :: MIT License",
26+
"License :: OSI Approved :: Apache Software License",
2727
"Topic :: Scientific/Engineering :: Artificial Intelligence",
2828
"Programming Language :: Python :: 3",
29-
"Programming Language :: Python :: 3.10",
30-
"Programming Language :: Python :: 3.11",
31-
"Programming Language :: Python :: 3.12",
3229
]
3330

3431
[project.urls]
@@ -50,35 +47,61 @@ packages = ["src/modelscope_mcp_server"]
5047

5148
[dependency-groups]
5249
dev = [
53-
"build>=1.2.2.post1",
54-
"twine>=6.1.0",
5550
"pytest>=8.4.1",
56-
"pyright>=1.1.403",
57-
"pre-commit>=4.2.0",
58-
"ruff>=0.12.3",
5951
"pytest-asyncio>=1.0.0",
6052
"pytest-cov>=6.2.1",
61-
"pytest-env>=1.1.5",
62-
"pytest-report>=0.2.1",
63-
"pytest-timeout>=2.4.0",
53+
"pyright>=1.1.403",
54+
"ruff>=0.12.3",
6455
]
6556

6657
[tool.pytest.ini_options]
6758
asyncio_mode = "auto"
68-
env = ["MODELSCOPE_LOG_LEVEL=INFO"]
59+
testpaths = ["tests"]
60+
addopts = [
61+
"--cov=src/modelscope_mcp_server",
62+
"--cov-report=term-missing",
63+
]
64+
env = [
65+
"MODELSCOPE_LOG_LEVEL=INFO"
66+
]
6967

7068

7169
[tool.pyright]
72-
include = ["src"]
73-
exclude = ["**/__pycache__", ".venv", ".git", "dist"]
70+
include = ["src", "tests"]
71+
exclude = ["**/__pycache__"]
7472
pythonVersion = "3.10"
75-
pythonPlatform = "Darwin"
7673
typeCheckingMode = "basic"
7774
reportMissingImports = true
7875
reportMissingTypeStubs = false
7976
useLibraryCodeForTypes = true
8077
venvPath = "."
8178
venv = ".venv"
8279

80+
[tool.ruff]
81+
target-version = "py310"
82+
line-length = 120
83+
8384
[tool.ruff.lint]
84-
extend-select = ["I", "UP"]
85+
extend-select = [
86+
"E", # pycodestyle errors (PEP 8 style violations)
87+
"W", # pycodestyle warnings (PEP 8 style warnings)
88+
"F", # pyflakes (unused imports, variables, etc.)
89+
"I", # isort (import sorting and organization)
90+
"B", # flake8-bugbear (common bug patterns)
91+
"UP", # pyupgrade (Python version upgrade suggestions)
92+
"D", # pydocstyle (docstring style checking)
93+
]
94+
ignore = [
95+
"D203", # 1 blank line required before class docstring (conflicts with D211)
96+
"D213", # Multi-line docstring summary should start at the second line (conflicts with D212)
97+
]
98+
99+
[tool.ruff.lint.per-file-ignores]
100+
"tests/**/*" = ["D"]
101+
102+
[tool.ruff.lint.isort]
103+
known-first-party = ["modelscope_mcp_server"]
104+
105+
[tool.ruff.format]
106+
quote-style = "double"
107+
indent-style = "space"

scripts/bump_version.py

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
#!/usr/bin/env python3
2-
"""
3-
Version bumping script for ModelScope MCP Server releases.
2+
"""Version bumping script for ModelScope MCP Server releases.
43
54
Usage:
65
python scripts/bump_version.py patch # 1.2.3 -> 1.2.4
@@ -36,7 +35,7 @@ def get_current_version():
3635

3736
return __version__
3837
except ImportError as e:
39-
raise ValueError(f"Could not import version module: {e}")
38+
raise ValueError(f"Could not import version module: {e}") from e
4039
finally:
4140
if str(SRC_DIR) in sys.path:
4241
sys.path.remove(str(SRC_DIR))
@@ -53,16 +52,14 @@ def parse_version(version_string):
5352
try:
5453
major, minor, patch = map(int, match.groups())
5554
return major, minor, patch
56-
except ValueError:
57-
raise ValueError(f"Invalid version format: {version_string}")
55+
except ValueError as e:
56+
raise ValueError(f"Invalid version format: {version_string}") from e
5857

5958

6059
def validate_version_format(version_string):
6160
"""Validate that the version string follows PEP 440 format."""
6261
if not re.match(PEP440_PATTERN, version_string):
63-
raise ValueError(
64-
f"Invalid version format (should follow PEP 440): {version_string}"
65-
)
62+
raise ValueError(f"Invalid version format (should follow PEP 440): {version_string}")
6663

6764

6865
def bump_version(current_version, bump_type):
@@ -82,9 +79,7 @@ def bump_version(current_version, bump_type):
8279
def update_version(new_version):
8380
"""Update version in _version.py and sync dependencies."""
8481
content = VERSION_FILE.read_text()
85-
new_content = re.sub(
86-
r'__version__ = "[^"]+"', f'__version__ = "{new_version}"', content
87-
)
82+
new_content = re.sub(r'__version__ = "[^"]+"', f'__version__ = "{new_version}"', content)
8883
VERSION_FILE.write_text(new_content)
8984

9085
# Run uv sync to update lock file
@@ -95,7 +90,7 @@ def update_version(new_version):
9590

9691

9792
def handle_version_change(action_description, new_version):
98-
"""Common logic for handling version changes."""
93+
"""Handle version changes with common logic."""
9994
current = get_current_version()
10095
print(f"{action_description} from {current} to {new_version}")
10196
update_version(new_version)
@@ -106,17 +101,13 @@ def handle_version_change(action_description, new_version):
106101
def print_next_steps(version):
107102
"""Print the next steps after version update."""
108103
print("\nNext steps:")
109-
print(
110-
f"1. Commit the change: git add {FILES_TO_COMMIT} && git commit -m 'chore: bump version to {version}'"
111-
)
104+
print(f"1. Commit the change: git add {FILES_TO_COMMIT} && git commit -m 'chore: bump version to {version}'")
112105
print(f"2. Create and push tag: git tag v{version} && git push origin v{version}")
113-
print(
114-
"3. The GitHub Action will automatically create a release and publish to PyPI and Container Registry"
115-
)
106+
print("3. The GitHub Action will automatically create a release and publish to PyPI and Container Registry")
116107

117108

118109
def main():
119-
"""Main function to handle version bumping."""
110+
"""Handle version bumping operations."""
120111
if len(sys.argv) not in [2, 3]:
121112
print(__doc__)
122113
sys.exit(1)

src/modelscope_mcp_server/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
"""ModelScope MCP Server"""
1+
"""ModelScope MCP Server."""
22

33
from ._version import __version__
44
from .settings import settings
55

66

77
def main():
8-
"""Main entry point for ModelScope MCP Server"""
8+
"""Serve as the main entry point for ModelScope MCP Server."""
99
from .cli import main as cli_main
1010

1111
cli_main()

src/modelscope_mcp_server/__main__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Entry point for python -m modelscope_mcp_server"""
1+
"""Entry point for python -m modelscope_mcp_server."""
22

33
from . import main
44

src/modelscope_mcp_server/cli.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
"""Command line interface for ModelScope MCP Server"""
1+
"""Command line interface for ModelScope MCP Server."""
22

33
import argparse
44
import sys
@@ -52,7 +52,7 @@ def validate_args(args: argparse.Namespace) -> None:
5252

5353

5454
def main() -> None:
55-
"""Main CLI entry point."""
55+
"""Handle CLI entry point operations."""
5656
parser = create_parser()
5757
args = parser.parse_args()
5858

src/modelscope_mcp_server/server.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
"""ModelScope MCP Server implementation."""
2+
13
from typing import cast
24

35
from fastmcp import FastMCP
@@ -22,7 +24,6 @@
2224

2325
def create_mcp_server() -> FastMCP:
2426
"""Create and configure the MCP server with all ModelScope tools."""
25-
2627
fastmcp_settings.log_level = cast(LOG_LEVEL, settings.log_level)
2728

2829
mcp = FastMCP(

src/modelscope_mcp_server/settings.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ class Settings(BaseSettings):
2424
)
2525

2626
# ModelScope API settings
27-
api_token: str | None = Field(
28-
default=None, description="ModelScope API token for authentication"
29-
)
27+
api_token: str | None = Field(default=None, description="ModelScope API token for authentication")
3028
api_base_url: str = Field(
3129
default=MODELSCOPE_API_ENDPOINT,
3230
description="Base URL for ModelScope API",
@@ -86,9 +84,7 @@ def show_settings(self) -> None:
8684
# API Configuration
8785
print("🔑 API Configuration:")
8886
masked_token = (
89-
self.api_token[:-8] + "********"
90-
if self.api_token and len(self.api_token) > 4
91-
else "Not configured"
87+
self.api_token[:-8] + "********" if self.api_token and len(self.api_token) > 4 else "Not configured"
9288
)
9389
print(f" • Token: {masked_token}")
9490
print(f" • Base URL: {self.api_base_url}")
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1 @@
1-
"""
2-
ModelScope MCP Server tools package.
3-
"""
1+
"""ModelScope MCP Server tools package."""

0 commit comments

Comments
 (0)