Publish Your First Skill
Ship a skill from your laptop to your AI Coach catalog in five steps. Free or paid (one-time fee, 60/40 split). Anyone with the AI Coach MCP server can then discover, install, and run your skill.
What gets published
A skill is a gzipped tarball with a fixed layout. v1 enforces markdown only — no executable scripts, no compiled binaries. Anything outside the allowlist is rejected at finalize.
bundle.tar.gz
├── SKILL.md # required, YAML frontmatter + body
├── LICENSE* # optional
├── NOTICE* # optional
├── references/ # optional, .md only
│ └── playbook.md
└── assets/ # optional, .json .txt .md .png .svg only
└── config.json Bundle is capped at 5 MB compressed, 20 MB decompressed. The SHA-256 of the tarball is your content hash — it's shown to buyers and printed in the install command.
SKILL.md frontmatter contract
name must match the skill's slug (kebab-case, 1–64 chars). description is the one-liner shown in search results — max 200 chars.
---
name: code-review-coach
description: Senior-eng code review with focus on readability + bugs
---
# Code Review Coach
Walk through the diff like a senior reviewer would... Prerequisites
- Sign in to AI Coach and enable publisher mode (one POST to
/api/publisher/becomeor the toggle on your account page). - Mint an API key with the
publisher:writescope. Key management → - Your publisher slug is derived from your GitHub username. Reserved handles (
aicoach,anthropic, trademarks, etc.) are blocked — contact support if affected.
Step 1 — Create the skill record
Starts in status: 'draft', visibility: 'private'. Goes 'published' automatically when your first version finalizes.
curl -X POST https://aicoach.pw/api/publisher/skills \
-H "Authorization: Bearer mcp_xxx" \
-H "Content-Type: application/json" \
-d '{
"slug": "code-review-coach",
"displayName": "Code Review Coach",
"descriptionShort": "Senior-eng code review with focus on readability + bugs",
"visibility": "private",
"pricingModel": "free"
}' Response includes skill.id — capture it as $SKILL_ID for the next steps.
Step 2 — Build + hash the bundle
tar -czf bundle.tar.gz SKILL.md references/ assets/
shasum -a 256 bundle.tar.gz Step 3 — Reserve a version
Semver is enforced: every new version must be strictly greater than the last. You're committing to the SHA-256 here — the actual upload in step 4 has to match exactly.
curl -X POST https://aicoach.pw/api/publisher/skills/$SKILL_ID/versions \
-H "Authorization: Bearer mcp_xxx" \
-H "Content-Type: application/json" \
-d '{
"semver": "0.1.0",
"sha256": "abc123…",
"sizeBytes": 4096,
"changelog": "Initial release"
}' Step 4 — Upload the bundle
PUT the raw tar.gz body to the uploadUrl returned by step 3. We re-hash on receipt and reject any mismatch.
tar -czf bundle.tar.gz SKILL.md references/ assets/
SHA=$(shasum -a 256 bundle.tar.gz | cut -d' ' -f1)
SIZE=$(stat -f%z bundle.tar.gz) # macOS; use stat -c%s on Linux
curl -X PUT https://aicoach.pw/api/publisher/skills/$SKILL_ID/versions/0.1.0/bundle \
-H "Authorization: Bearer mcp_xxx" \
-H "Content-Type: application/gzip" \
--data-binary @bundle.tar.gz Step 5 — Finalize + publish
Finalize runs the server-side validator: gzip integrity, file allowlist, SKILL.md frontmatter shape, slug match. On success the version flips to 'finalized' and the skill's latestVersionId pointer moves. On failure you get a structured report — fix the bundle, re-upload to the same version, finalize again. Failed finalizes don't burn the version slot.
curl -X POST https://aicoach.pw/api/publisher/skills/$SKILL_ID/versions/0.1.0/finalize \
-H "Authorization: Bearer mcp_xxx" Make it discoverable
Drafts and private skills are visible only to you. Flip to 'unlisted' for share-by-link, 'public' for the marketplace + MCP search.
curl -X PATCH https://aicoach.pw/api/publisher/skills/$SKILL_ID \
-H "Authorization: Bearer mcp_xxx" \
-d '{ "visibility": "public" }' Charge for it
Switch pricingModel to 'one_time' with a priceCents between 100 ($1.00) and 100,000 ($1000.00). Buyers pay once via Stripe Checkout; you keep 60%, the platform keeps 40%. USD only in v1; Stripe handles FX for non-USD cards.
curl -X PATCH https://aicoach.pw/api/publisher/skills/$SKILL_ID \
-H "Authorization: Bearer mcp_xxx" \
-H "Content-Type: application/json" \
-d '{
"pricingModel": "one_time",
"priceCents": 999,
"visibility": "public"
}' Earnings accumulate in your publisher wallet. Payouts in v1 are manual (Stripe Connect is on the v2 roadmap) — contact support to request a payout once the balance crosses your threshold.
Publishing updates
Repeat steps 2–5 with a bumped semver. Old versions stay downloadable for buyers who pinned to them — never republish under the same number. Soft-deprecate an old version with DELETE /api/publisher/skills/$SKILL_ID/versions/$SEMVER; existing buyers keep access, new buyers get the next live version.
Common errors
must_bump_version— your semver isn't strictly greater than the last finalized one.hash_mismatch— the SHA-256 you committed in step 3 doesn't match the bytes you PUT in step 4. Re-hash and try again.disallowed_path— bundle contains a file outside the markdown-only allowlist (e.g.scripts/,.sh,.js).frontmatter_name_mismatch— your SKILL.md'sname:doesn't equal your skill slug.too_large— bundle exceeds 5 MB. Trim assets or split into multiple skills.reserved_publisher_slug— your GitHub handle clashes with a reserved name. Contact support.
Next
- Publishing an MCP server with paid access? Paid MCP server guide →
- License token format for paid MCP servers: License tokens reference →