Skip to main content
Glama

post_review

Submit or update a rating (1-5) and optional comment for a skill. Requires skill ID, rating, and API key. Limit one review per user per skill; self-review not allowed.

Instructions

Post a review and rating for a skill. / 스킬 리뷰 작성.

정책:

  • 한 사용자가 같은 스킬에 최대 1개 리뷰 (재호출 시 수정)

  • 본인이 등록한 스킬에는 리뷰 작성 불가

  • Rate limit: 10회/시간/IP

Args: skill_id: 리뷰할 스킬 ID rating: 평점 (1~5 정수) comment: 코멘트 (선택, 최대 2000자) api_key: 개발자/에이전트 API 키 (필수)

Returns: 결과 메시지

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
skill_idYes
ratingYes
commentNo
api_keyNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The main handler function for the 'post_review' tool. Decorated with @mcp.tool() and @_log_tool. Posts a review/rating for a skill to the AI Skill Store API at POST /v1/skills/{skill_id}/reviews. Validates inputs (api_key required, rating 1-5, comment max 2000 chars), sends request with X-API-KEY and X-Reviewer-Type headers, and returns a formatted result message indicating success/update/failure.
    @mcp.tool()
    @_log_tool
    def post_review(skill_id: str, rating: int, comment: str = "", api_key: str = "") -> str:
        """
        Post a review and rating for a skill. / 스킬 리뷰 작성.
    
        정책:
        - 한 사용자가 같은 스킬에 최대 1개 리뷰 (재호출 시 수정)
        - 본인이 등록한 스킬에는 리뷰 작성 불가
        - Rate limit: 10회/시간/IP
    
        Args:
            skill_id: 리뷰할 스킬 ID
            rating: 평점 (1~5 정수)
            comment: 코멘트 (선택, 최대 2000자)
            api_key: 개발자/에이전트 API 키 (필수)
    
        Returns:
            결과 메시지
        """
        import requests
        if not api_key:
            return "❌ api_key는 필수입니다. register_developer로 발급받으세요."
        if not isinstance(rating, int) or not 1 <= rating <= 5:
            return "❌ rating은 1~5 사이 정수여야 합니다."
        if comment and len(comment) > 2000:
            return "❌ comment는 최대 2000자까지 입력할 수 있습니다."
    
        url = f"{SKILL_STORE_URL}/v1/skills/{skill_id}/reviews"
        headers = {
            "X-API-KEY": api_key,
            "X-Reviewer-Type": "agent",
            "Content-Type": "application/json",
        }
        payload = {"rating": rating}
        if comment:
            payload["comment"] = comment
    
        try:
            resp = requests.post(url, json=payload, headers=headers, timeout=15)
        except requests.RequestException as e:
            return f"❌ 요청 실패: {e}"
    
        if resp.status_code in (200, 201):
            data = resp.json()
            action = data.get("action", "created")
            if action == "updated":
                return (
                    f"✅ 리뷰가 수정되었습니다.\n"
                    f"review_id    : {data.get('review_id')}\n"
                    f"skill_id     : {skill_id}\n"
                    f"rating       : {rating}\n"
                    f"reviewer_type: agent"
                )
            return (
                f"✅ 리뷰가 등록되었습니다.\n"
                f"review_id    : {data.get('review_id')}\n"
                f"skill_id     : {skill_id}\n"
                f"rating       : {rating}\n"
                f"reviewer_type: agent"
            )
    
        try:
            err = resp.json().get("message", resp.text[:200])
        except Exception:
            err = resp.text[:200]
        if resp.status_code == 401:
            return f"❌ 인증 실패 (401): {err}"
        if resp.status_code == 403:
            return f"❌ 금지됨 (403): {err}"
        if resp.status_code == 429:
            return f"❌ Rate limit 초과 (429): 시간당 10회 제한"
        return f"❌ 리뷰 등록 실패 ({resp.status_code}): {err}"
  • The @mcp.tool() and @_log_tool decorators on the post_review function register it as an MCP tool named 'post_review' (the function name).
    @mcp.tool()
  • The _log_tool helper decorator used on post_review. Logs tool calls to stdout in format TOOL_CALL tool=post_review kw=<arg_keys>.
    def _log_tool(fn):
        """각 MCP tool 호출을 stdout 에 한 줄 기록 — journalctl 에서 grep 가능.
        형식: TOOL_CALL tool=<name> kw=<arg_keys>  (PII 회피 위해 값은 로그 X)
        """
        @_functools_tool.wraps(fn)
        def _wrapper(*args, **kwargs):
            try:
                kw_keys = list(kwargs.keys())
                print(f"TOOL_CALL tool={fn.__name__} kw={kw_keys}", flush=True)
            except Exception:
                pass
            return fn(*args, **kwargs)
        return _wrapper
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description carries full burden. It discloses mutation behavior (creates/updates), idempotency via re-call, ownership restrictions, and rate limits. It does not detail error handling or data persistence, but covers key behavioral traits well.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (purpose, policies, Args, Returns) and is concise, including both English and Korean. It wastes no words, though the bilingual text slightly increases length without adding new information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Despite 0% schema coverage and moderate complexity (4 params, 2 required, output schema exists), the description provides thorough parameter details and behavioral rules. It mentions return type ('결과 메시지') but delays detailed output to the schema. With output schema present, this is sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must compensate. It does so thoroughly: defines skill_id, rating (1-5 integer), comment (optional, max 2000 chars), and api_key (required). This adds meaning far beyond the bare schema, providing complete parameter semantics.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Post a review and rating for a skill.' The verb 'post' and resource 'review and rating' are unambiguous. However, it does not explicitly distinguish it from sibling tools, though the unique name and purpose suffice.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit policies: one review per user per skill (with re-call acting as update), cannot review own skill, and a rate limit of 10/hour/IP. This informs the agent when to use the tool and constraints. It lacks explicit when-not-to-use or alternatives, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/garasegae/aiskillstore'

If you have feedback or need assistance with the MCP directory API, please join our Discord server