# License Obligation

> "What licence does this npm or PyPI package declare, and what does that licence roughly require (keep notices, share source, and so on)?" It can also take a list of package names and flag the ones with copyleft licences.

- Status: MCP package (hosted access coming soon)

## The question it answers

"What licence does this npm or PyPI package declare, and what does that licence roughly require (keep notices, share source, and so on)?" It can also take a list of package names and flag the ones with copyleft licences.

## Use it when

- An agent needs a quick first-pass licence check on a handful of dependencies.
- You have an SPDX id (like `MIT` or `LGPL-3.0`) and want a plain summary of must / may / cannot.

## Do not use it when

- You need legal advice. The summaries are short, curated and heuristic.
- You need a full dependency tree. It checks only the names you give it (max 40 per scan, no transitive resolution).
- Your expressions mix `AND` and `OR`. **Known bug in this version:** `GPL-3.0 AND (MIT OR Apache-2.0)` is reported as MIT with no copyleft, which is wrong. Check any mixed expression by hand.

## Example call

There is no public HTTP route yet, so no curl example. Locally:
```bash
npx tsx src/cli.ts pkg npm express
```
MCP tools: `license_spdx_obligations {spdx}`, `license_lookup_package {ecosystem, name}`, `license_scan_manifest {ecosystem, names[]}`.

## Example response (`license_lookup_package`; trimmed; shape follows the code)

```json
{
  "tool": "license-obligation",
  "version": "0.1.0",
  "ecosystem": "npm",
  "name": "express",
  "latest": "5.3.0",
  "declaredLicense": "MIT",
  "obligations": {
    "spdx": "MIT",
    "expression": "MIT",
    "licenses": ["MIT"],
    "family": "permissive",
    "copyleft": "none",
    "must": ["Keep copyright + license notice"],
    "may": ["Commercial use", "Modify", "Distribute", "Sublicense", "Private use"],
    "cannot": ["Hold author liable"],
    "needsReview": false,
    "notes": "MIT: Very permissive. Notice preservation is the main obligation.",
    "disclaimer": "Not legal advice. Verify SPDX expression + counsel for shipping products."
  },
  "billing": { "sku": "license_obligation", "plannedPriceUsd": 0.02, "x402Enabled": false }
}
```
For an `OR` expression you also get `options[]` and a `choiceHint`, and `needsReview` is true. In a scan, `copyleftHits` lists `name:SPDX` for every package whose `copyleft` is not `none`.

## Data sources and licence

- npm registry metadata (`registry.npmjs.org`) and the PyPI JSON API (`pypi.org`). Public package metadata; check each service's terms for high-volume use.
- The obligation summaries are our own short text, not the licence texts.

## Freshness and caching

Package lookups are cached for 24 hours.

## Honest limits

- Only 15 real licences plus `proprietary` / `UNKNOWN` are in the table. Others (Zlib, CC-BY, BSL, SSPL ...) come back `UNKNOWN` with `needsReview: true`.
- It reads only the declared licence field. A wrong or missing field in the registry gives a wrong or `UNKNOWN` answer. It does not read licence files in the package.
- PyPI: only the first mapped `License ::` classifier is used.
- `bsd` alone is guessed as BSD-3-Clause.
- Scan: first 40 unique names, looked up one after another, so large scans are slow.
- Not legal advice.
