Skip to content

fix: get url auth #21

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 27, 2025
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
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
# v1.2.1
- 处理多媒体签名问题

# v1.2.0
- 支持文件上传至七牛 Bucket

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[project]
name = "qiniu-mcp-server"
version = "1.2.0"
version = "1.2.1"
description = "A MCP server project of Qiniu."
requires-python = ">=3.12"
authors = [
Expand Down
2 changes: 1 addition & 1 deletion src/mcp_server/core/media_processing/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

def load(cfg: config.Config):
cli = processing.MediaProcessingService(cfg)
register_tools(cli)
register_tools(cfg, cli)


__all__ = [
Expand Down
26 changes: 15 additions & 11 deletions src/mcp_server/core/media_processing/tools.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import logging
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing module docstring (missing-module-docstring)

Details

lint 解释

这个lint结果表明在文件 src/mcp_server/core/media_processing/tools.py 中缺少模块文档字符串(module docstring)。模块文档字符串是用于描述整个模块的注释,通常放在模块的最开始部分。

错误用法

# src/mcp_server/core/media_processing/tools.py
def process_media(file_path):
    # 处理媒体文件的逻辑
    pass

在这个例子中,tools.py 文件没有包含任何文档字符串。

正确用法

"""
src/mcp_server/core/media_processing/tools.py

This module contains various tools for media processing.
"""

def process_media(file_path):
    """
    Process the given media file.

    :param file_path: Path to the media file to be processed.
    """
    # 处理媒体文件的逻辑
    pass

在这个例子中,tools.py 文件包含了一个模块文档字符串,并且每个函数也包含了相应的文档字符串。


💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流


import qiniu
from mcp import types
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unable to import 'mcp' (import-error)

Details

lint 解释

这个lint结果表明在代码中尝试导入一个名为 mcp 的模块,但该模块无法被找到。这通常是因为模块路径配置不正确或者模块本身不存在。

错误用法

# 错误的导入方式
import mcp

正确用法

  1. 确保模块存在:

    • 确认 mcp 模块是否存在于你的项目目录中,或者是否安装在你的Python环境中。
  2. 检查模块路径:

    • 如果 mcp 是一个自定义模块,确保它位于你的Python路径中。可以通过以下方式添加路径:
      import sys
      sys.path.append('/path/to/your/module')
      import mcp
  3. 安装第三方模块:

    • 如果 mcp 是一个第三方模块,确保你已经通过包管理工具(如 pip)正确安装了它:
      pip install mcp
  4. 检查拼写错误:

    • 确认导入的模块名称拼写正确。

通过以上步骤,你应该能够解决 Unable to import 'mcp' (import-error) 的问题。


💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流


from . import utils
from .processing import MediaProcessingService
from ...config import config
from ...consts import consts
from ...tools import tools

Expand All @@ -12,7 +15,8 @@


class _ToolImpl:
def __init__(self, cli: MediaProcessingService):
def __init__(self, cfg: config.Config, cli: MediaProcessingService):
self.auth = qiniu.Auth(cfg.access_key, cfg.secret_key)
self.client = cli

@tools.tool_meta(
Expand Down Expand Up @@ -55,8 +59,8 @@ def image_scale_by_percent(
types.TextContent(type="text", text="percent must be between 1 and 999")
]

fop = f"imageMogr2/thumbnail/!{percent}p"
object_url = utils.url_add_processing_func(object_url, fop)
func = f"imageMogr2/thumbnail/!{percent}p"
object_url = utils.url_add_processing_func(auth=self.auth, url=object_url, func=func)
return [
types.TextContent(
type="text",
Expand Down Expand Up @@ -111,16 +115,16 @@ def image_scale_by_size(
if object_url is None or len(object_url) == 0:
return [types.TextContent(type="text", text="object_url is required")]

fop = f"{width}x{height}"
if len(fop) == 1:
func = f"{width}x{height}"
if len(func) == 1:
return [
types.TextContent(
type="text", text="At least one width or height must be set"
)
]

fop = f"imageMogr2/thumbnail/{fop}"
object_url = utils.url_add_processing_func(object_url, fop)
func = f"imageMogr2/thumbnail/{func}"
object_url = utils.url_add_processing_func(auth=self.auth, url=object_url, func=func)
return [
types.TextContent(
type="text",
Expand Down Expand Up @@ -191,7 +195,7 @@ def image_round_corner(self, **kwargs) -> list[types.TextContent]:
radius_y = radius_x

func = f"roundPic/radiusx/{radius_x}/radiusy/{radius_y}"
object_url = utils.url_add_processing_func(object_url, func)
object_url = utils.url_add_processing_func(auth=self.auth, url=object_url, func=func)
return [
types.TextContent(
type="text",
Expand Down Expand Up @@ -228,7 +232,7 @@ def image_info(self, **kwargs) -> list[types.TextContent]:
]

func = "imageInfo"
object_url = utils.url_add_processing_func(object_url, func)
object_url = utils.url_add_processing_func(auth=self.auth, url=object_url, func=func)
return [
types.TextContent(
type="text",
Expand Down Expand Up @@ -259,8 +263,8 @@ def get_fop_status(self, **kwargs) -> list[types.TextContent]:
return [types.TextContent(type="text", text=str(status))]


def register_tools(cli: MediaProcessingService):
tool_impl = _ToolImpl(cli)
def register_tools(cfg: config.Config, cli: MediaProcessingService):
tool_impl = _ToolImpl(cfg, cli)
tools.auto_register_tools(
[
tool_impl.image_scale_by_percent,
Expand Down
40 changes: 38 additions & 2 deletions src/mcp_server/core/media_processing/utils.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import time
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing module docstring (missing-module-docstring)

Details

lint 解释

missing-module-docstring 是一个常见的代码质量检查,用于确保每个模块(即 .py 文件)都有一个文档字符串。文档字符串是位于文件顶部的注释块,通常用三引号括起来,用于描述模块的功能和用途。

错误用法

以下是一个缺少模块文档字符串的示例:

# src/mcp_server/core/media_processing/utils.py

def add(a, b):
    return a + b

在这个例子中,utils.py 文件没有包含任何文档字符串。

正确用法

以下是添加了模块文档字符串的正确示例:

# src/mcp_server/core/media_processing/utils.py

"""
This module contains utility functions for media processing.
"""

def add(a, b):
    """
    Adds two numbers and returns the result.

    Args:
        a (int): The first number.
        b (int): The second number.

    Returns:
        int: The sum of `a` and `b`.
    """
    return a + b

在这个例子中,模块顶部添加了一个文档字符串,描述了该模块的功能。每个函数也都有自己的文档字符串,详细说明了函数的参数和返回值。


💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流

from urllib import parse

import qiniu
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unable to import 'qiniu' (import-error)

Details

lint 解释

这个lint结果表明在代码中尝试导入qiniu模块时失败了。具体来说,Python解释器无法找到并加载名为qiniu的模块。

错误用法

from qiniu import Auth, put_file

在这个示例中,代码试图从qiniu模块导入Authput_file。由于qiniu模块未安装或未正确配置,导致导入失败。

正确用法

要解决这个问题,你需要确保qiniu模块已经安装在你的Python环境中。你可以通过以下命令来安装它:

pip install qiniu

安装完成后,代码应该可以正常运行:

from qiniu import Auth, put_file

这样,Python解释器就能找到并加载qiniu模块了。


💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流


from mcp_server.core.storage.tools import logger

FUNC_POSITION_NONE = "none"
FUNC_POSITION_PREFIX = "prefix"
FUNC_POSITION_SUFFIX = "suffix"


def url_add_processing_func(url: str, func: str) -> str:
def url_add_processing_func(auth: qiniu.auth, url: str, func: str) -> str:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing function or method docstring (missing-function-docstring)

Details

lint 解释

missing-function-docstring 是一个常见的代码质量检查,用于确保函数或方法有文档字符串(docstring)。文档字符串是用于描述函数、类或模块用途的字符串,通常放在函数定义的第一行。它有助于其他开发者理解代码的功能和使用方式。

错误用法

以下是一个缺少函数文档字符串的示例:

def calculate_area(length, width):
    return length * width

在这个例子中,calculate_area 函数没有文档字符串,这可能会导致其他开发者难以理解该函数的作用。

正确用法

以下是添加了文档字符串的正确示例:

def calculate_area(length, width):
    """
    计算矩形面积
    
    参数:
    length (float): 矩形的长度
    width (float): 矩形的宽度
    
    返回:
    float: 矩形的面积
    """
    return length * width

在这个正确的示例中,calculate_area 函数有一个文档字符串,详细描述了函数的功能、参数和返回值。这有助于提高代码的可读性和可维护性。


💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流

func_items = func.split("/")
func_prefix = func_items[0]

Expand All @@ -14,7 +19,8 @@ def url_add_processing_func(url: str, func: str) -> str:
new_query = parse.quote(new_query, safe='&=')
url_info = url_info._replace(query=new_query)
new_url = parse.urlunparse(url_info)
return str(new_url)
new_url = _sign_url(str(new_url), auth)
return new_url


def _query_add_processing_func(query: str, func: str, func_prefix: str) -> str:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Too many return statements (7/6) (too-many-return-statements)

Details

lint 解释

too-many-return-statements 是一个常见的代码质量检查,用于检测函数中返回语句的数量。根据 PEP 8 的建议,函数应该尽量保持简洁和单一职责,因此通常不建议在一个函数中使用过多的返回语句。

错误用法

以下是一个示例代码,展示了错误的用法:

def check_number(num):
    if num > 0:
        return "Positive"
    elif num < 0:
        return "Negative"
    else:
        return "Zero"

在这个例子中,函数 check_number 使用了三个返回语句来处理不同的情况。

正确用法

以下是一个示例代码,展示了正确的用法:

def check_number(num):
    if num > 0:
        return "Positive"
    elif num < 0:
        return "Negative"
    return "Zero"

在这个例子中,函数 check_number 将所有可能的情况都处理完毕后,最后返回一个默认值。这样可以减少返回语句的数量,并使代码更加简洁和易读。


💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流

Expand Down Expand Up @@ -70,3 +76,33 @@ def _query_add_processing_func(query: str, func: str, func_prefix: str) -> str:
func = first_query + func.removeprefix(func_prefix)
queries.insert(0, func)
return "&".join(queries)


def _sign_url(url: str, auth: qiniu.auth) -> str:
url_info = parse.urlparse(url)
query = url_info.query
if ('e=' not in query) or ('token=' not in query):
return url

queries = query.split("&")
if '' in queries:
queries.remove('')

# 移除之前的签名信息,但顺序不可变
expires = 3600
new_queries = []
for query_item in queries:
if query_item.startswith('e='):
try:
deadline = int(query_item.removeprefix('e='))
expires = deadline - int(time.time())
except Exception as e:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Catching too general exception Exception (broad-exception-caught)

Details

lint 解释

这个lint结果表明代码捕获了一个过于通用的异常 Exception。这样做可能会隐藏潜在的问题,因为任何类型的异常都会被捕获,而不仅仅是预期的异常类型。

错误用法

try:
    # 一些可能抛出异常的代码
    pass
except Exception as e:
    print(f"An error occurred: {e}")

在这个例子中,Exception 是一个过于通用的异常类型。如果代码中抛出了 KeyboardInterrupt 或其他非预期的异常,这些异常也会被捕获并处理。

正确用法

try:
    # 一些可能抛出异常的代码
    pass
except SpecificException as e:
    print(f"A specific error occurred: {e}")

在这个例子中,SpecificException 是一个更具体的异常类型。这样可以确保只有特定类型的异常会被捕获和处理,从而避免隐藏潜在的问题。


💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流

logger.warning(f"expires parse fail for url:{url} err:{str(e)}")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use lazy % formatting in logging functions (logging-fstring-interpolation)

Details

lint 解释

在日志记录函数中使用惰性格式化(lazy % formatting)可以提高性能,因为它避免了在每次调用时进行字符串格式化。然而,lint 工具提示你使用 f-string 进行格式化,因为 f-string 在某些情况下可能更高效且更易读。

错误用法

import logging

logger = logging.getLogger(__name__)

def log_message():
    user_name = "Alice"
    logger.info("User %s logged in" % user_name)

在这个例子中,使用了 % 进行字符串格式化。

正确用法

import logging

logger = logging.getLogger(__name__)

def log_message():
    user_name = "Alice"
    logger.info(f"User {user_name} logged in")

在这个例子中,使用了 f-string 进行字符串格式化。


💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流

expires = 3600
elif not query_item.startswith('token='):
new_queries.append(query_item)

new_query = "&".join(new_queries)
url_info = url_info._replace(query=new_query)
new_url = parse.urlunparse(url_info)
return auth.private_download_url(new_url, expires=expires)
2 changes: 1 addition & 1 deletion src/mcp_server/core/version/version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing module docstring (missing-module-docstring)

Details

lint 解释

missing-module-docstring 是一个常见的代码质量检查,用于确保每个模块(即 .py 文件)都有一个文档字符串。文档字符串是位于文件顶部的字符串,通常用三引号括起来,用于描述模块的功能和用途。

错误用法

以下是一个缺少模块文档字符串的示例:

# version.py

def get_version():
    return "1.0.0"

在这个例子中,version.py 文件没有包含任何文档字符串。

正确用法

以下是添加了模块文档字符串的正确示例:

"""
This module provides functions to manage and retrieve the version information of the application.
"""

def get_version():
    return "1.0.0"

在这个例子中,version.py 文件顶部包含了一个文档字符串,描述了该模块的功能。


💡 以上内容由 AI 辅助生成,如有疑问欢迎反馈交流

VERSION = '1.2.0'
VERSION = '1.2.1'
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading