npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@402md/skillmd

v0.1.1

Published

Parser, validator, and generator for SKILL.md — the spec-as-code for paid AI agent skills

Readme

@402md/skillmd

The package.json for paid AI agent APIs.

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.

This package parses, validates, generates, and converts SKILL.md files. One dependency (yaml). Works in Node, browsers, and edge runtimes.

npm install @402md/skillmd

Why SKILL.md?

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.

  • For API sellers — Describe your endpoints, set prices, get paid via x402
  • For agent builders — Parse any SKILL.md, auto-generate MCP tools, let agents pay and call APIs
  • For framework authors — Validate and convert between SKILL.md, OpenAPI, and MCP tool definitions

Quick Start

Parse

import { parseSkillMd } from '@402md/skillmd'

const manifest = parseSkillMd(`---
name: weather-api
description: Real-time weather data
base_url: https://api.weatherco.com
type: API
payment:
  networks: [stellar, base]
  asset: USDC
  payTo: GABC...XYZ
endpoints:
  - path: /v1/current
    method: POST
    description: Get current weather
    priceUsdc: "0.001"
---

# Weather API
`)

manifest.name                // 'weather-api'
manifest.payment.networks    // ['stellar', 'base']
manifest.endpoints[0].path   // '/v1/current'

From a file:

import { readFileSync } from 'node:fs'
import { parseSkillMd } from '@402md/skillmd'

const manifest = parseSkillMd(readFileSync('./SKILL.md', 'utf-8'))

Validate

Catch problems before publishing:

import { validateSkillMd } from '@402md/skillmd'

const result = validateSkillMd(content)

if (!result.valid) {
  result.errors.forEach(e => console.error(`${e.field}: ${e.message}`))
}
// Warnings for missing optional fields (version, tags, etc.)
result.warnings.forEach(w => console.warn(`${w.field}: ${w.message}`))

Generate

Create a SKILL.md from code:

import { generateSkillMd } from '@402md/skillmd'

const skillMd = generateSkillMd({
  name: 'my-api',
  description: 'Does cool things',
  base_url: 'https://api.example.com',
  payment: {
    networks: ['stellar'],
    asset: 'USDC',
    payTo: 'GABC...XYZ'
  },
  endpoints: [
    {
      path: '/v1/run',
      method: 'POST',
      description: 'Run the thing',
      priceUsdc: '0.001'
    }
  ]
})
// Returns a complete SKILL.md string with frontmatter + body

SKILL.md to MCP Tools

Turn any SKILL.md into MCP tool definitions. No @modelcontextprotocol/sdk dependency — just the shape your MCP server needs:

import { parseSkillMd, toMcpToolDefinitions } from '@402md/skillmd'

const tools = toMcpToolDefinitions(parseSkillMd(content))
// [
//   {
//     name: 'weather-api_v1_current',
//     description: 'Get current weather (0.001 USDC via stellar)',
//     inputSchema: { type: 'object', properties: { location: { type: 'string' } } }
//   }
// ]

Each endpoint becomes one tool. inputSchema is passed through directly, so MCP clients get full type information.

OpenAPI Interop

Already have a Swagger spec? Convert it to SKILL.md:

import { generateFromOpenAPI } from '@402md/skillmd'

const manifest = generateFromOpenAPI(openApiSpec, {
  networks: ['base'],
  asset: 'USDC',
  payTo: '0xabc...def'
}, {
  pricing: {
    'GET /pets': '0.001',
    'POST /pets': '0.05',
    '*': '0.005'  // fallback
  }
})

Going the other way — export any SKILL.md as OpenAPI 3.0 for Swagger UI, Postman, or any OpenAPI tool:

import { toOpenAPI } from '@402md/skillmd'

const spec = toOpenAPI(manifest)
// spec.paths['/v1/current'].post.responses['402'].description = 'Payment Required — 0.001 USDC'

SKILL.md Format (v2)

---
name: weather-api
displayName: Weather API
description: Real-time weather data for any location worldwide
version: 1.0.0
author: weatherco
base_url: https://api.weatherco.com
type: API

payment:
  networks:
    - stellar
    - base
  asset: USDC
  payTo: GABC...XYZ
  facilitator: https://x402.org/facilitator

endpoints:
  - path: /v1/current
    method: POST
    description: Get current weather for a location
    priceUsdc: "0.001"
    inputSchema:
      type: object
      properties:
        location:
          type: string
      required: [location]
    outputSchema:
      type: object
      properties:
        temperature:
          type: number
        conditions:
          type: string

tags: [weather, geolocation]
category: data
sla: "99.9%"
rateLimit: 1000/hour
sandbox: https://sandbox.weatherco.com
---

# Weather API

Real-time weather data for any location worldwide.

Required fields

| Field | Description | |-------|-------------| | name | Unique identifier (kebab-case) | | description | What the skill does | | base_url | Base URL of the API | | payment.networks | Supported chains (stellar, base, base-sepolia, stellar-testnet) | | payment.payTo | Recipient wallet address | | endpoints[].path | Endpoint path (starts with /) | | endpoints[].method | HTTP method | | endpoints[].description | What the endpoint does | | endpoints[].priceUsdc | Price per call in USDC (e.g. "0.001") |

Optional fields

| Field | Description | |-------|-------------| | displayName | Human-readable name | | version | Semver version | | author | Author name | | type | API | SAAS | PRODUCT | SERVICE | SUBSCRIPTION | CONTENT | | payment.asset | Payment asset (default: USDC) | | payment.payToEvm | EVM address fallback | | payment.facilitator | Facilitator URL | | endpoints[].inputSchema | JSON Schema for request body | | endpoints[].outputSchema | JSON Schema for response | | tags | Discovery tags | | category | Skill category | | sla | Uptime guarantee | | rateLimit | Rate limit | | sandbox | Free test endpoint URL |

API Reference

Parse

| Function | Description | |----------|-------------| | parseSkillMd(content) | Parse a SKILL.md string into a SkillManifest | | parseFrontmatter(md) | Extract raw frontmatter (lower-level, v1-compat) |

Validate

| Function | Description | |----------|-------------| | validateSkill(manifest) | Validate a SkillManifest object | | validateSkillMd(content) | Parse + validate a raw SKILL.md string |

Generate & Convert

| Function | Description | |----------|-------------| | generateSkillMd(config) | Generate a SKILL.md string from a SkillConfig | | generateFromOpenAPI(spec, payment, options?) | OpenAPI spec to SkillManifest | | toOpenAPI(manifest) | SkillManifest to OpenAPI 3.0 spec | | toMcpToolDefinitions(manifest) | SkillManifest to MCP McpToolDefinition[] |

Schema & Constants

| Export | Description | |--------|-------------| | SKILLMD_JSON_SCHEMA | JSON Schema for v2 frontmatter — for external validators (ajv, zod, etc.) | | SKILL_TYPES | Valid skill types (['API', 'SAAS', ...]) | | HTTP_METHODS | Valid HTTP methods (['GET', 'POST', ...]) | | PAYMENT_NETWORKS | Valid payment networks (['stellar', 'base', ...]) |

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.

Legacy v1 Support

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: '' }.

License

MIT