Skip to main content

Write Your First AI SKILL

Scenario

You want to package a business feature into an AI-callable SKILL, but there's no ready-made template to use. This tutorial walks through the full process from scaffold to working SKILL, using a "weather query" example.

Prerequisites

Steps

Step 1: Create the SKILL scaffold

npx mp-skills create weather-skill

Expected output:

* 创建 Skill: weather-skill
ok 目录已创建: miniprogram/skills/weather-skill/
ok SKILL.md 已创建
ok mcp.json 已创建
ok index.js 已创建
ok apis/ 目录已创建
ok app.json 已更新
ok project.config.json 已更新

[OK] Skill 创建完成

Generated structure:

miniprogram/skills/weather-skill/
├── SKILL.md # Business description — AI reads this to decide when to trigger
├── mcp.json # API declaration — defines parameters and return values
├── index.js # Entry point — registers the atomic API
└── apis/
└── getWeather.js # API implementation

Step 2: Write SKILL.md

# Weather Query

## Trigger Scenarios

User wants to check weather. Examples:
- "What's the weather like in Beijing today?"
- "Will it rain tomorrow?"
- "Shanghai temperature this weekend"
- "Check the weather in Shenzhen for the next 3 days"

## Out of Scope

- Date or time queries
- Image/video content requests

Step 3: Configure mcp.json

Write miniprogram/skills/weather-skill/mcp.json:

{
"apis": [
{
"name": "getWeather",
"description": "Get weather for a specified location. Call when user provides a city name or location. Requires location and optional days parameters.",
"inputSchema": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "Location to query, e.g. city name (Beijing, Shanghai). Source: user's original message."
},
"days": {
"type": "number",
"description": "Forecast days, 1-7, defaults to 1."
}
},
"required": ["location"]
},
"outputSchema": {
"type": "object",
"properties": {
"location": { "type": "string" },
"forecasts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"date": { "type": "string" },
"weather": { "type": "string" },
"tempHigh": { "type": "number" },
"tempLow": { "type": "number" }
}
}
}
}
},
"_meta": {
"ui": { "componentPath": "components/weather-card/index" }
}
}
],
"components": [
{
"path": "components/weather-card/index",
"relatedPage": "/pages/index/index"
}
]
}

Step 4: Implement the atomic API

Write miniprogram/skills/weather-skill/apis/getWeather.js:

async function getWeather({ location, days = 1 }) {
if (!location) {
return {
isError: true,
content: [{ type: 'text', text: 'Missing location parameter. Please provide a city name.' }]
}
}

try {
const res = await wx.request({
url: 'https://api.example.com/weather',
data: { city: location, days: Math.min(days, 7) }
})

return {
isError: false,
content: [{ type: 'text', text: `Weather forecast for ${location} (${days} days)` }],
structuredContent: {
location,
forecasts: res.data.forecasts.map(f => ({
date: f.date,
weather: f.weather,
tempHigh: f.tempMax,
tempLow: f.tempMin
}))
}
}
} catch (err) {
return {
isError: true,
content: [{ type: 'text', text: `Weather query failed: ${err.message}. Please try again.` }]
}
}
}

module.exports = getWeather

Step 5: Create the atomic component

Create miniprogram/skills/weather-skill/components/weather-card/ with 4 files:

index.wxml:

<view class="card">
<text class="title">{{location}} Weather</text>
<view wx:for="{{forecasts}}" wx:key="date" class="day-row">
<text class="date">{{item.date}}</text>
<text class="weather">{{item.weather}}</text>
<text class="temp">{{item.tempLow}}°~{{item.tempHigh}}°</text>
</view>
</view>

index.js:

Component({
lifetimes: {
created() {
const modelCtx = wx.modelContext.getContext(this)
modelCtx.on(wx.modelContext.NotificationType.Result, (data) => {
const sc = data?.result?.structuredContent || {}
this.setData({
location: sc.location || '',
forecasts: sc.forecasts || []
})
})
}
}
})

index.json: { "component": true, "usingComponents": {} }

index.wxss:

.card { padding: 16px; background: #fff; border-radius: 12px; }
.title { font-size: 16px; font-weight: 600; margin-bottom: 12px; }
.day-row { display: flex; justify-content: space-between; padding: 8px 0; }
.date { font-size: 14px; color: #333; }
.weather { font-size: 14px; color: #666; }
.temp { font-size: 14px; color: #1677ff; }

Step 6: Register the API

Write miniprogram/skills/weather-skill/index.js:

const getWeather = require('./apis/getWeather')

function registerAPIs() {
const skill = wx.modelContext.createSkill('skills/weather-skill')
skill.registerAPI('getWeather', getWeather)
}

registerAPIs()

Step 7: Validate

npx mp-skills validate

Step 8: Test in DevTools

Switch to "Mini Program AI Compile" mode:

  1. SKILL list should show weather-skill
  2. Select it to see the getWeather API
  3. Enter {"location": "Beijing", "days": 3} and execute
  4. Verify the weather card renders correctly

Verification Checklist

  • npx mp-skills validate passes
  • getWeather API works in DevTools
  • Weather data renders via weather-card component
  • Missing location returns error message

Common Issues

skill.registerAPI name mismatch

  • Check that mcp.json's apis[].name matches the name in your code

API called but no result returned

  • Check module.exports is present
  • Check require path in index.js

Component shows no data

  • Check componentPath in mcp.json
  • Check structuredContent field names match the atomic API output

Reference