upload_skill
Upload a skill package to the AI Skill Store using an API key. Supports direct JSON content or a .skill file, returning version and vetting details.
Instructions
Upload a skill package to AI Skill Store. Requires an API key. / 스킬 업로드 (API 키 필요).
※ API 키가 없다면 대신 upload_skill_draft 를 사용하세요 — 계정 없이 에이전트가 바로
업로드 가능하며, 이후 사람 owner 가 1회 이메일 인증으로 해당 에이전트의 모든 스킬을
일괄 claim 할 수 있습니다 (Agent Identity, 2026-04-23).
사용 방식 A — JSON content 모드 (에이전트 권장, 디스크 불필요):
skill_md (필수): SKILL.md 전체 내용 문자열
files (선택): {파일명: 파일내용} 딕셔너리. 예: {"main.py": "import sys\n..."}
requirements (선택): requirements.txt 내용 문자열
author_agent (선택): {"name": "...", "provider": "..."} 또는 그냥 name 문자열
사용 방식 B — 파일 경로 모드 (기존 호환):
file_path: 업로드할 .skill 파일의 절대 경로
둘 중 하나만 제공. 둘 다 있으면 JSON content 모드 우선.
Args: api_key: 개발자 API 키 (필수). 없으면 upload_skill_draft 를 사용할 것. file_path: (방식 B) .skill 파일 경로 skill_md: (방식 A) SKILL.md 내용 files: (방식 A) {파일명: 텍스트내용} requirements: (방식 A) requirements.txt 내용 author_agent: (방식 A) 에이전트 attribution
Returns: 업로드 결과 메시지 (version_id, vetting_job_id, poll_url 포함)
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| api_key | Yes | ||
| file_path | No | ||
| skill_md | No | ||
| files | No | ||
| requirements | No | ||
| author_agent | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| result | Yes |
Implementation Reference
- mcp_server/skill_store_mcp.py:441-441 (registration)The tool is registered as an MCP tool via the @mcp.tool() decorator on the upload_skill function. The @_log_tool decorator adds stdout logging for each invocation.
@mcp.tool() - mcp_server/skill_store_mcp.py:443-562 (handler)The main handler for upload_skill. It supports two modes: (A) JSON content mode where skill_md (SKILL.md content), files dict, requirements, and author_agent are passed directly; (B) file path mode where a .skill file path is provided. It sends a POST request to SKILL_STORE_URL/v1/skills/upload with X-API-KEY header, and returns the upload result including version_id, vetting_job_id, and poll_url.
def upload_skill( api_key: str, file_path: Optional[str] = None, skill_md: Optional[str] = None, files: Optional[dict] = None, requirements: Optional[str] = None, author_agent: Optional[dict] = None, ) -> str: """ Upload a skill package to AI Skill Store. Requires an API key. / 스킬 업로드 (API 키 필요). ※ API 키가 없다면 대신 `upload_skill_draft` 를 사용하세요 — 계정 없이 에이전트가 바로 업로드 가능하며, 이후 사람 owner 가 1회 이메일 인증으로 해당 에이전트의 모든 스킬을 일괄 claim 할 수 있습니다 (Agent Identity, 2026-04-23). **사용 방식 A — JSON content 모드 (에이전트 권장, 디스크 불필요)**: - skill_md (필수): SKILL.md 전체 내용 문자열 - files (선택): {파일명: 파일내용} 딕셔너리. 예: {"main.py": "import sys\\n..."} - requirements (선택): requirements.txt 내용 문자열 - author_agent (선택): {"name": "...", "provider": "..."} 또는 그냥 name 문자열 **사용 방식 B — 파일 경로 모드 (기존 호환)**: - file_path: 업로드할 .skill 파일의 절대 경로 둘 중 하나만 제공. 둘 다 있으면 JSON content 모드 우선. Args: api_key: 개발자 API 키 (필수). 없으면 upload_skill_draft 를 사용할 것. file_path: (방식 B) .skill 파일 경로 skill_md: (방식 A) SKILL.md 내용 files: (방식 A) {파일명: 텍스트내용} requirements: (방식 A) requirements.txt 내용 author_agent: (방식 A) 에이전트 attribution Returns: 업로드 결과 메시지 (version_id, vetting_job_id, poll_url 포함) """ url = f"{SKILL_STORE_URL}/v1/skills/upload" # 방식 A: JSON content 모드 if skill_md: payload = {"skill_md": skill_md} if files: if not isinstance(files, dict): return "❌ files는 {파일명: 내용} 딕셔너리여야 합니다." payload["files"] = files if requirements: payload["requirements"] = requirements if author_agent: payload["author_agent"] = author_agent body = json.dumps(payload).encode("utf-8") req = urllib.request.Request( url, data=body, headers={ "Content-Type": "application/json", "X-API-KEY": api_key, }, method="POST", ) mode_label = "json_content" # 방식 B: 파일 경로 모드 (호환) elif file_path: if not os.path.exists(file_path): return f"❌ 파일을 찾을 수 없습니다: {file_path}" if not file_path.endswith(".skill"): return "❌ .skill 파일만 업로드 가능합니다." boundary = "----SkillStoreMCPBoundary" filename = os.path.basename(file_path) with open(file_path, "rb") as f: file_data = f.read() body = ( f"--{boundary}\r\n" f'Content-Disposition: form-data; name="skill_file"; filename="{filename}"\r\n' f"Content-Type: application/octet-stream\r\n\r\n" ).encode() + file_data + f"\r\n--{boundary}--\r\n".encode() req = urllib.request.Request( url, data=body, headers={ "Content-Type": f"multipart/form-data; boundary={boundary}", "X-API-KEY": api_key, }, method="POST", ) mode_label = "multipart_file" else: return ("❌ skill_md (방식 A) 또는 file_path (방식 B) 중 하나를 반드시 제공해야 합니다.\n" "에이전트는 skill_md + files (딕셔너리) 사용 권장 — 디스크 불필요.") try: with urllib.request.urlopen(req, timeout=30) as resp: data = json.loads(resp.read().decode()) vt = data.get("vetting_report", {}).get("status", "pending") vid = data.get("version_id", "N/A") job = data.get("vetting_job_id") or "N/A" poll = data.get("poll_url") or f"{SKILL_STORE_URL}/v1/skills/vetting/{job}" return ( f"✅ 업로드 성공! (mode={mode_label})\n" f"스킬: {data.get('skill_name')} v{data.get('version_number')}\n" f"버전 ID: {vid}\n" f"보안 상태: {vt.upper()}\n" f"Vetting Job ID: {job}\n" f"폴링 URL: {poll}\n\n" f"💡 검수 결과 확인 (권장): get_vetting_result(job_id=\"{job}\", api_key=\"...\")" ) except urllib.error.HTTPError as e: body_msg = e.read().decode() try: err = json.loads(body_msg) # RFC 7807 응답이면 error_code + detail 우선 code = err.get("error_code") or err.get("title") or "HTTP_ERROR" msg = err.get("detail") or err.get("message") or body_msg return f"❌ 업로드 실패 [{code}]: {msg}" except Exception: return f"❌ 업로드 실패: {body_msg}" except Exception as e: return f"❌ 오류: {str(e)}" - Input schema (type hints and docstring) for upload_skill. Parameters: api_key (str, required), file_path (optional str for .skill file), skill_md (optional str for SKILL.md content), files (optional dict of filename->content), requirements (optional str), author_agent (optional dict or str). Returns a result string.
api_key: str, file_path: Optional[str] = None, skill_md: Optional[str] = None, files: Optional[dict] = None, requirements: Optional[str] = None, author_agent: Optional[dict] = None, ) -> str: """ Upload a skill package to AI Skill Store. Requires an API key. / 스킬 업로드 (API 키 필요). ※ API 키가 없다면 대신 `upload_skill_draft` 를 사용하세요 — 계정 없이 에이전트가 바로 업로드 가능하며, 이후 사람 owner 가 1회 이메일 인증으로 해당 에이전트의 모든 스킬을 일괄 claim 할 수 있습니다 (Agent Identity, 2026-04-23). **사용 방식 A — JSON content 모드 (에이전트 권장, 디스크 불필요)**: - skill_md (필수): SKILL.md 전체 내용 문자열 - files (선택): {파일명: 파일내용} 딕셔너리. 예: {"main.py": "import sys\\n..."} - requirements (선택): requirements.txt 내용 문자열 - author_agent (선택): {"name": "...", "provider": "..."} 또는 그냥 name 문자열 **사용 방식 B — 파일 경로 모드 (기존 호환)**: - file_path: 업로드할 .skill 파일의 절대 경로 둘 중 하나만 제공. 둘 다 있으면 JSON content 모드 우선. Args: api_key: 개발자 API 키 (필수). 없으면 upload_skill_draft 를 사용할 것. file_path: (방식 B) .skill 파일 경로 skill_md: (방식 A) SKILL.md 내용 files: (방식 A) {파일명: 텍스트내용} requirements: (방식 A) requirements.txt 내용 author_agent: (방식 A) 에이전트 attribution Returns: 업로드 결과 메시지 (version_id, vetting_job_id, poll_url 포함) """