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
| Name | Required | Description | Default |
|---|---|---|---|
| skill_id | Yes | ||
| rating | Yes | ||
| comment | No | ||
| api_key | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- mcp_server/skill_store_mcp.py:1030-1102 (handler)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}" - mcp_server/skill_store_mcp.py:1030-1030 (registration)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() - mcp_server/skill_store_mcp.py:33-45 (helper)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