Publishing tools

MSR JSON for AI agents

Hand this page to your coding agent — Claude Code, Codex, Cursor, Gemini CLI, Antigravity, Copilot or your own — and it can write your manifest. It is written for a machine: the rules, every field, the enums, a complete example and the checks to run before publishing.

Fetchable as plain Markdown at The skill file · /msr-skill.md · Or fill the form yourself

Writing an msr.json manifest

Instructions for an AI agent asked to describe a software product as an MSR JSON 2.0 manifest. MSR JSON is the machine-readable file a product publishes about itself, the way robots.txt is the file a site publishes about crawling.


1. The one rule that matters

Never invent a fact. Every value in this file is a claim the publisher makes in public, and a registry, a crawler or a buying agent may act on it. If you do not have a value, leave the field out. An absent optional field is correct; a guessed one is a false claim.

This applies hardest to: version numbers, release dates, prices, licenses, SPDX identifiers, country codes and any URL. Do not derive a download URL from a pattern. Do not assume the license from the word "free". Do not write today's date as the release date because you do not know the real one.

If a required field is unknown, stop and ask the publisher for it. A manifest that cannot be written truthfully is not written.


2. Required structure

Five top-level keys are required: $schema, protocol, entity, capabilities, releases.

protocol — fixed, never edited

Copy this block verbatim. It states facts about the specification, not about the product, and a manifest that alters it is not an MSR manifest.

{
  "name": "MSR JSON",
  "version": "2.0.0",
  "author": "Antonio Santos",
  "specification_license": "CC-BY-4.0",
  "reference_implementation_license": "MIT"
}

protocol.canonical_url is optional: the public URL this very file is served from.

entity — what the product is

Field Required Notes
name yes The product name as the publisher writes it, version excluded
slug yes Lowercase ASCII, words joined by -, derived from name
domain yes Bare DNS name, no scheme and no path: acme.example
type yes One of the enum below
descriptions yes At least one locale, each with a summary
license no { "type": ..., "spdx_id": ... }
vendor no { "name", "website", "country_code", "support_url" }

entity.type is one of: software, saas, ai-agent, mcp-server, api, open-source, framework, library, plugin, extension, mobile.

entity.license.type is one of: open-source, freeware, freemium, commercial, trial, subscription. Use spdx_id only for a real SPDX identifier such as MIT or Apache-2.0.

descriptions is keyed by BCP 47 tag. summary is required and capped at 500 characters; tagline is capped at 120; text is unbounded prose. Write the locales the publisher actually has. Do not machine-translate marketing copy into locales the publisher never approved.

capabilities — how it is delivered

deployment is required and is an array of: cloud, self-hosted, on-premise, hybrid, desktop, mobile, edge, docker.

pricing is optional: { "model": "free" }, or a starting price as integer minor units plus an ISO 4217 code — { "starting_price_cents": 2900, "currency": "USD" }. Never write a price as a float or as a formatted string.

releases.latest — the current version

version and published_at are both required. published_at is an RFC 3339 timestamp in UTC. release_type is one of initial, major, minor, patch, security. changelog_url and artifacts are optional; an artifact is { "platform", "uri", "sha256" } and the sha256 is a digest you have actually been given, never one you compute a placeholder for.


3. A complete, valid example

{
  "$schema": "https://msrjson.org/schemas/msr-2.0.json",
  "protocol": {
    "name": "MSR JSON",
    "version": "2.0.0",
    "author": "Antonio Santos",
    "specification_license": "CC-BY-4.0",
    "reference_implementation_license": "MIT",
    "canonical_url": "https://acme.example/.well-known/msr.json"
  },
  "entity": {
    "name": "Acme Notes",
    "slug": "acme-notes",
    "domain": "acme.example",
    "type": "saas",
    "license": { "type": "freemium" },
    "vendor": {
      "name": "Acme Labs",
      "website": "https://acme.example",
      "country_code": "BR",
      "support_url": "https://acme.example/support"
    },
    "descriptions": {
      "en": {
        "tagline": "Shared notes that stay in sync",
        "summary": "Acme Notes keeps a team's notes in sync across devices, with offline editing and per-workspace permissions.",
        "text": "Longer prose about the product, its audience and what it does not do."
      },
      "pt-BR": {
        "tagline": "Notas compartilhadas sempre em sincronia",
        "summary": "O Acme Notes mantém as notas de um time sincronizadas entre dispositivos, com edição offline e permissões por workspace."
      }
    }
  },
  "capabilities": {
    "deployment": ["cloud", "desktop"],
    "pricing": { "model": "freemium", "starting_price_cents": 2900, "currency": "USD" }
  },
  "releases": {
    "latest": {
      "version": "4.2.0",
      "published_at": "2026-09-14T00:00:00Z",
      "release_type": "minor",
      "changelog_url": "https://acme.example/changelog"
    }
  }
}

4. Checklist before you hand the file over

  1. Every required field is present: $schema, protocol, entity, capabilities, releases.latest.
  2. Every enum value is spelled exactly as the schema lists it — lowercase, with hyphens, not underscores.
  3. Every URL is absolute and https.
  4. domain has no scheme, no path and no www. prefix.
  5. Money is integer minor units plus a currency code. Dates are UTC.
  6. No field was filled with a guess. Anything unknown was left out or asked about.
  7. The file parses as JSON — no trailing commas, no comments.

5. Publishing and submitting

Serve the file at https://<domain>/.well-known/msr.json with Content-Type: application/json. That path is where registries and agents look for it without being told.

To list the product on MySoftRank, submit the public URL of the manifest at https://mysoftrank.com/publish. No account is required; the listing is queued for moderation. A product whose vendor is already claimed by an account must be updated from that account, not anonymously.

Legacy PAD XML is also accepted. POST /api/v1/convert/pad converts a PAD document into an MSR draft, and POST /api/v1/validate/pad returns a field-by-field verdict on one. A converted draft is a draft: the publisher reviews it before it is published, because PAD carries no equivalent for several MSR fields.


6. Using this file with your coding agent

This file is plain Markdown with no tool-specific syntax, so it works in any harness — Claude Code, OpenAI Codex, Cursor, Gemini CLI, Antigravity, GitHub Copilot, Qwen Code, a DeepSeek-backed agent, or your own loop. Put it where yours reads from:

Harness Where it looks
Codex, and any agent following the open convention AGENTS.md at the repository root
Claude Code CLAUDE.md, or a skill under .claude/skills/
Cursor .cursor/rules/ (it also reads AGENTS.md)
GitHub Copilot .github/copilot-instructions.md
Gemini CLI GEMINI.md
Antigravity its own rules directory in the repository
Anything else — DeepSeek, Qwen, a local Ollama model, a custom harness paste it into the system prompt

Two ways to use it. Either commit it, so the agent has the rules whenever it touches your repository, or paste it once into a chat and ask for the manifest in that turn. Both work; committing it is what keeps the manifest correct on the next release, when the version and the date change and nobody remembers the rules.

Conventions move faster than this document. If your harness reads a path that is not listed here, the file still works there — nothing in it depends on the tool.