@402md/skillmd 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +279 -0
- package/dist/index.cjs +771 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +331 -0
- package/dist/index.d.ts +331 -0
- package/dist/index.js +723 -0
- package/dist/index.js.map +1 -0
- package/package.json +82 -0
package/README.md
ADDED
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
# @402md/skillmd
|
|
2
|
+
|
|
3
|
+
**The `package.json` for paid AI agent APIs.**
|
|
4
|
+
|
|
5
|
+
SKILL.md is an open format that describes what an API does, how much it costs, and how to pay — in a single markdown file that both humans and AI agents can read. Think of it as a machine-readable menu for your API.
|
|
6
|
+
|
|
7
|
+
This package parses, validates, generates, and converts SKILL.md files. One dependency (`yaml`). Works in Node, browsers, and edge runtimes.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @402md/skillmd
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Why SKILL.md?
|
|
14
|
+
|
|
15
|
+
AI agents need to discover and pay for APIs autonomously. Today, there's no standard way for an API to say "I cost $0.001 per call, pay me in USDC on Stellar." SKILL.md solves that — one file, readable by any agent framework.
|
|
16
|
+
|
|
17
|
+
- **For API sellers** — Describe your endpoints, set prices, get paid via [x402](https://www.x402.org/)
|
|
18
|
+
- **For agent builders** — Parse any SKILL.md, auto-generate MCP tools, let agents pay and call APIs
|
|
19
|
+
- **For framework authors** — Validate and convert between SKILL.md, OpenAPI, and MCP tool definitions
|
|
20
|
+
|
|
21
|
+
## Quick Start
|
|
22
|
+
|
|
23
|
+
### Parse
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
import { parseSkillMd } from '@402md/skillmd'
|
|
27
|
+
|
|
28
|
+
const manifest = parseSkillMd(`---
|
|
29
|
+
name: weather-api
|
|
30
|
+
description: Real-time weather data
|
|
31
|
+
base_url: https://api.weatherco.com
|
|
32
|
+
type: API
|
|
33
|
+
payment:
|
|
34
|
+
networks: [stellar, base]
|
|
35
|
+
asset: USDC
|
|
36
|
+
payTo: GABC...XYZ
|
|
37
|
+
endpoints:
|
|
38
|
+
- path: /v1/current
|
|
39
|
+
method: POST
|
|
40
|
+
description: Get current weather
|
|
41
|
+
priceUsdc: "0.001"
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
# Weather API
|
|
45
|
+
`)
|
|
46
|
+
|
|
47
|
+
manifest.name // 'weather-api'
|
|
48
|
+
manifest.payment.networks // ['stellar', 'base']
|
|
49
|
+
manifest.endpoints[0].path // '/v1/current'
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
From a file:
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { readFileSync } from 'node:fs'
|
|
56
|
+
import { parseSkillMd } from '@402md/skillmd'
|
|
57
|
+
|
|
58
|
+
const manifest = parseSkillMd(readFileSync('./SKILL.md', 'utf-8'))
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Validate
|
|
62
|
+
|
|
63
|
+
Catch problems before publishing:
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
import { validateSkillMd } from '@402md/skillmd'
|
|
67
|
+
|
|
68
|
+
const result = validateSkillMd(content)
|
|
69
|
+
|
|
70
|
+
if (!result.valid) {
|
|
71
|
+
result.errors.forEach(e => console.error(`${e.field}: ${e.message}`))
|
|
72
|
+
}
|
|
73
|
+
// Warnings for missing optional fields (version, tags, etc.)
|
|
74
|
+
result.warnings.forEach(w => console.warn(`${w.field}: ${w.message}`))
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Generate
|
|
78
|
+
|
|
79
|
+
Create a SKILL.md from code:
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { generateSkillMd } from '@402md/skillmd'
|
|
83
|
+
|
|
84
|
+
const skillMd = generateSkillMd({
|
|
85
|
+
name: 'my-api',
|
|
86
|
+
description: 'Does cool things',
|
|
87
|
+
base_url: 'https://api.example.com',
|
|
88
|
+
payment: {
|
|
89
|
+
networks: ['stellar'],
|
|
90
|
+
asset: 'USDC',
|
|
91
|
+
payTo: 'GABC...XYZ'
|
|
92
|
+
},
|
|
93
|
+
endpoints: [
|
|
94
|
+
{
|
|
95
|
+
path: '/v1/run',
|
|
96
|
+
method: 'POST',
|
|
97
|
+
description: 'Run the thing',
|
|
98
|
+
priceUsdc: '0.001'
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
})
|
|
102
|
+
// Returns a complete SKILL.md string with frontmatter + body
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### SKILL.md to MCP Tools
|
|
106
|
+
|
|
107
|
+
Turn any SKILL.md into MCP tool definitions. No `@modelcontextprotocol/sdk` dependency — just the shape your MCP server needs:
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { parseSkillMd, toMcpToolDefinitions } from '@402md/skillmd'
|
|
111
|
+
|
|
112
|
+
const tools = toMcpToolDefinitions(parseSkillMd(content))
|
|
113
|
+
// [
|
|
114
|
+
// {
|
|
115
|
+
// name: 'weather-api_v1_current',
|
|
116
|
+
// description: 'Get current weather (0.001 USDC via stellar)',
|
|
117
|
+
// inputSchema: { type: 'object', properties: { location: { type: 'string' } } }
|
|
118
|
+
// }
|
|
119
|
+
// ]
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Each endpoint becomes one tool. `inputSchema` is passed through directly, so MCP clients get full type information.
|
|
123
|
+
|
|
124
|
+
### OpenAPI Interop
|
|
125
|
+
|
|
126
|
+
Already have a Swagger spec? Convert it to SKILL.md:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
import { generateFromOpenAPI } from '@402md/skillmd'
|
|
130
|
+
|
|
131
|
+
const manifest = generateFromOpenAPI(openApiSpec, {
|
|
132
|
+
networks: ['base'],
|
|
133
|
+
asset: 'USDC',
|
|
134
|
+
payTo: '0xabc...def'
|
|
135
|
+
}, {
|
|
136
|
+
pricing: {
|
|
137
|
+
'GET /pets': '0.001',
|
|
138
|
+
'POST /pets': '0.05',
|
|
139
|
+
'*': '0.005' // fallback
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Going the other way — export any SKILL.md as OpenAPI 3.0 for Swagger UI, Postman, or any OpenAPI tool:
|
|
145
|
+
|
|
146
|
+
```typescript
|
|
147
|
+
import { toOpenAPI } from '@402md/skillmd'
|
|
148
|
+
|
|
149
|
+
const spec = toOpenAPI(manifest)
|
|
150
|
+
// spec.paths['/v1/current'].post.responses['402'].description = 'Payment Required — 0.001 USDC'
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## SKILL.md Format (v2)
|
|
154
|
+
|
|
155
|
+
```yaml
|
|
156
|
+
---
|
|
157
|
+
name: weather-api
|
|
158
|
+
displayName: Weather API
|
|
159
|
+
description: Real-time weather data for any location worldwide
|
|
160
|
+
version: 1.0.0
|
|
161
|
+
author: weatherco
|
|
162
|
+
base_url: https://api.weatherco.com
|
|
163
|
+
type: API
|
|
164
|
+
|
|
165
|
+
payment:
|
|
166
|
+
networks:
|
|
167
|
+
- stellar
|
|
168
|
+
- base
|
|
169
|
+
asset: USDC
|
|
170
|
+
payTo: GABC...XYZ
|
|
171
|
+
facilitator: https://x402.org/facilitator
|
|
172
|
+
|
|
173
|
+
endpoints:
|
|
174
|
+
- path: /v1/current
|
|
175
|
+
method: POST
|
|
176
|
+
description: Get current weather for a location
|
|
177
|
+
priceUsdc: "0.001"
|
|
178
|
+
inputSchema:
|
|
179
|
+
type: object
|
|
180
|
+
properties:
|
|
181
|
+
location:
|
|
182
|
+
type: string
|
|
183
|
+
required: [location]
|
|
184
|
+
outputSchema:
|
|
185
|
+
type: object
|
|
186
|
+
properties:
|
|
187
|
+
temperature:
|
|
188
|
+
type: number
|
|
189
|
+
conditions:
|
|
190
|
+
type: string
|
|
191
|
+
|
|
192
|
+
tags: [weather, geolocation]
|
|
193
|
+
category: data
|
|
194
|
+
sla: "99.9%"
|
|
195
|
+
rateLimit: 1000/hour
|
|
196
|
+
sandbox: https://sandbox.weatherco.com
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
# Weather API
|
|
200
|
+
|
|
201
|
+
Real-time weather data for any location worldwide.
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Required fields
|
|
205
|
+
|
|
206
|
+
| Field | Description |
|
|
207
|
+
|-------|-------------|
|
|
208
|
+
| `name` | Unique identifier (kebab-case) |
|
|
209
|
+
| `description` | What the skill does |
|
|
210
|
+
| `base_url` | Base URL of the API |
|
|
211
|
+
| `payment.networks` | Supported chains (`stellar`, `base`, `base-sepolia`, `stellar-testnet`) |
|
|
212
|
+
| `payment.payTo` | Recipient wallet address |
|
|
213
|
+
| `endpoints[].path` | Endpoint path (starts with `/`) |
|
|
214
|
+
| `endpoints[].method` | HTTP method |
|
|
215
|
+
| `endpoints[].description` | What the endpoint does |
|
|
216
|
+
| `endpoints[].priceUsdc` | Price per call in USDC (e.g. `"0.001"`) |
|
|
217
|
+
|
|
218
|
+
### Optional fields
|
|
219
|
+
|
|
220
|
+
| Field | Description |
|
|
221
|
+
|-------|-------------|
|
|
222
|
+
| `displayName` | Human-readable name |
|
|
223
|
+
| `version` | Semver version |
|
|
224
|
+
| `author` | Author name |
|
|
225
|
+
| `type` | `API` \| `SAAS` \| `PRODUCT` \| `SERVICE` \| `SUBSCRIPTION` \| `CONTENT` |
|
|
226
|
+
| `payment.asset` | Payment asset (default: `USDC`) |
|
|
227
|
+
| `payment.payToEvm` | EVM address fallback |
|
|
228
|
+
| `payment.facilitator` | Facilitator URL |
|
|
229
|
+
| `endpoints[].inputSchema` | JSON Schema for request body |
|
|
230
|
+
| `endpoints[].outputSchema` | JSON Schema for response |
|
|
231
|
+
| `tags` | Discovery tags |
|
|
232
|
+
| `category` | Skill category |
|
|
233
|
+
| `sla` | Uptime guarantee |
|
|
234
|
+
| `rateLimit` | Rate limit |
|
|
235
|
+
| `sandbox` | Free test endpoint URL |
|
|
236
|
+
|
|
237
|
+
## API Reference
|
|
238
|
+
|
|
239
|
+
### Parse
|
|
240
|
+
|
|
241
|
+
| Function | Description |
|
|
242
|
+
|----------|-------------|
|
|
243
|
+
| `parseSkillMd(content)` | Parse a SKILL.md string into a `SkillManifest` |
|
|
244
|
+
| `parseFrontmatter(md)` | Extract raw frontmatter (lower-level, v1-compat) |
|
|
245
|
+
|
|
246
|
+
### Validate
|
|
247
|
+
|
|
248
|
+
| Function | Description |
|
|
249
|
+
|----------|-------------|
|
|
250
|
+
| `validateSkill(manifest)` | Validate a `SkillManifest` object |
|
|
251
|
+
| `validateSkillMd(content)` | Parse + validate a raw SKILL.md string |
|
|
252
|
+
|
|
253
|
+
### Generate & Convert
|
|
254
|
+
|
|
255
|
+
| Function | Description |
|
|
256
|
+
|----------|-------------|
|
|
257
|
+
| `generateSkillMd(config)` | Generate a SKILL.md string from a `SkillConfig` |
|
|
258
|
+
| `generateFromOpenAPI(spec, payment, options?)` | OpenAPI spec to `SkillManifest` |
|
|
259
|
+
| `toOpenAPI(manifest)` | `SkillManifest` to OpenAPI 3.0 spec |
|
|
260
|
+
| `toMcpToolDefinitions(manifest)` | `SkillManifest` to MCP `McpToolDefinition[]` |
|
|
261
|
+
|
|
262
|
+
### Schema & Constants
|
|
263
|
+
|
|
264
|
+
| Export | Description |
|
|
265
|
+
|--------|-------------|
|
|
266
|
+
| `SKILLMD_JSON_SCHEMA` | JSON Schema for v2 frontmatter — for external validators (ajv, zod, etc.) |
|
|
267
|
+
| `SKILL_TYPES` | Valid skill types (`['API', 'SAAS', ...]`) |
|
|
268
|
+
| `HTTP_METHODS` | Valid HTTP methods (`['GET', 'POST', ...]`) |
|
|
269
|
+
| `PAYMENT_NETWORKS` | Valid payment networks (`['stellar', 'base', ...]`) |
|
|
270
|
+
|
|
271
|
+
> `SKILLMD_JSON_SCHEMA` is for external consumers who want to validate with ajv or similar. The built-in `validateSkill()` / `validateSkillMd()` use manual validation for better error messages.
|
|
272
|
+
|
|
273
|
+
## Legacy v1 Support
|
|
274
|
+
|
|
275
|
+
The parser handles v1 SKILL.md files (without the `payment` block). The `price` field on endpoints is mapped to `priceUsdc`, and payment defaults to `{ networks: ['base'], asset: 'USDC', payTo: '' }`.
|
|
276
|
+
|
|
277
|
+
## License
|
|
278
|
+
|
|
279
|
+
MIT
|