LicenseGuard について
LicenseGuardは、ソフトウェアの配布方法に応じて依存パッケージのライセンス義務を確認する開発者向けMCPサーバーです。SaaS、社内利用、ソフトウェア配布などの条件に照らして条項を評価します。
主な機能
- 01配布形態別のライセンス評価
- 02依存パッケージやマニフェストの確認
- 03配布形態ごとの要件説明
- 046つのパッケージエコシステムに対応
- 05ロックファイルとJSON SBOMの読み込み
活用シーン
- 01依存パッケージ追加前の確認
- 02プロジェクトのロックファイル監査
- 03SaaSと配布での条件比較
MCP 対応
依存パッケージの確認、マニフェストのスキャン、ライセンス要件の説明を行うツールをMCPクライアントに提供します。ホスト型のStreamable HTTPまたはローカルstdioで利用できます。
設定
リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。
https://license-guard.rcc-aoki.workers.dev/mcpclaude mcp add --transport http rccaoki-wq-license-guard https://license-guard.rcc-aoki.workers.dev/mcp{"mcpServers":{"rccaoki-wq-license-guard":{"type":"http","url":"https://license-guard.rcc-aoki.workers.dev/mcp"}}}Cursor で開く{"servers":{"rccaoki-wq-license-guard":{"type":"http","url":"https://license-guard.rcc-aoki.workers.dev/mcp"}}}VS Code で開く{"mcpServers":{"rccaoki-wq-license-guard":{"type":"http","url":"https://license-guard.rcc-aoki.workers.dev/mcp"}}}{"mcpServers":{"rccaoki-wq-license-guard":{"serverUrl":"https://license-guard.rcc-aoki.workers.dev/mcp"}}}コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。
ghcr.io/rccaoki-wq/license-guard:1.1.0stdioツール
3| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| name | string | はい | マニフェストに記載されているパッケージ名。例:"express"、"requests"、"github.com/gin-gonic/gin"、"serde"。 |
| scope | enum | いいえ | 依存関係の用途。配布する成果物に含まれないものには "dev"、"build"、"test" を使用してください。これらには配布義務はありません。デフォルトは "runtime" です。runtime | dev | build | test | optional |
| version | string | いいえ | 判明している場合は正確なバージョンを指定してください。省略すると、インストール済みのバージョンとは異なる可能性がある最新公開バージョンが使用されます。 |
| ecosystem | enum | はい | 依存関係の取得元となるパッケージレジストリ。npm | pypi | go | cargo | rubygems | nuget |
| distribution_model | enum | はい | この依存関係を含むソフトウェアをユーザーに届ける方法。判定結果は次のとおりです:"saas" = ユーザーがネットワーク経由で利用する;"distributed-binary" = アプリまたはバイナリとして配布する;"on-prem-delivery" = 顧客の環境にインストールする;"internal-only" = 組織外に出さない;"library-published" = 他者が依存できるライブラリとして公開する。saas | distributed-binary | on-prem-delivery | internal-only | library-published |
詳細
LicenseGuard
English | 日本語
mcpservers.org、Smithery、TensorBlock MCP Index、Docker MCP catalogにも掲載されています。
この依存関係のライセンスは、あなたがソフトウェアを配布する方法にどのような義務を課しますか?
汎用的なライセンススキャナーが答えるのは別の質問、「これはどのライセンスか?」です。そして、あらゆるものに警告を出します。LicenseGuard は、配布モデルに照らしてライセンスを評価するため、同じライセンスでも、ソフトウェアがユーザーに届く方法によって判定が異なります。
稼働中:https://licenseguard.tenchorooms.com
以下の workers.dev オリジンは同じデプロイ先です。MCP カタログが参照する安定したエンドポイントとして維持されています。
なぜ配布モデルによって判定が変わるのですか?
| 配布方法 | AGPL-3.0 の依存関係 |
|---|---|
| SaaS(ネットワーク経由でアクセス可能) | ブロック — §13 のネットワーク条項 |
| 社内利用のみ | 許可 |
| バイナリ配布/オンプレミス | ブロック — 継承される GPL の配布条件 |
| devDependency(成果物に含まれない) | 許可 |
最後の行こそが重要な点です。AGPL のビルド時リンターは配布されないため、何の問題も引き起こしません。それでも警告するツールを使うと、あらゆる警告を無視するようになってしまいます。
同様の区分はライセンス全体にわたって見られますが、それぞれの違いは互いに置き換えられません。
- GPL の義務は配布に適用されます。GPL コードをネットワークサービスとして実行することは、配布には該当しません。
- AGPL は §13 を追加し、ネットワーク上のやり取りにも適用します。これは GPL の配布条件とは別の発動条件です。配布に関する事例で §13 を引き合いに出すのは単純に誤りであり、LicenseGuard はそのようなことはしません。
- MPL/EPL/CDDL はファイル単位で適用され、リンク方式に依存しません。MPL-2.0 §3.3 は、より大きな著作物を独自の条件で配布することを明示的に認めています。これらに LGPL の再リンクに関する考え方を適用すると、誤検出が生じます。
- LGPL は実際にリンク方式によって扱いが変わります。静的リンクでは再リンクの義務が生じますが、動的リンクでは生じません。
判定は、該当条項を引用した事実として提示します。LicenseGuard が対応方法を指示することはありません。
よくある質問
ソフトウェアをホスティングするだけで、配布しない場合にも GPL は適用されますか? いいえ。GPL-3.0 の義務が発生するのは配布時です。ホスト型 SaaS は配布ではないため、現時点では義務は生じません。ただし、同じソフトウェアを後でオンプレミス導入向け、バイナリ、または公開ライブラリとして提供すると、作品全体のソース開示義務が発生します。
ソフトウェアを SaaS としてホスティングするだけでも AGPL は適用されますか? はい。AGPL-3.0 §13 は、ネットワーク経由で改変版を利用するユーザーに、作品全体の対応するソースを提供するよう求めています。この条項が、ホスト型サービスにおいて AGPL と GPL の挙動を異なるものにしており、実務上の両者の違いはこれだけです。
ビルド時の依存関係や開発用の依存関係によって、ライセンス上の義務は生じますか? いいえ。開発用の依存関係は配布する成果物に含まれないため、配布によって発生する義務は生じません。コードジェネレーターなど、出力にコードを生成するツールは別のケースなので、個別に確認する価値があります。
MIT は商用利用に安全ですか? はい。どの配布モデルでも安全です。MIT が求めるのは著作権表示だけで、それ以外はありません。Apache-2.0 も同じ結果になりますが、特許ライセンスの許諾と NOTICE の要件が追加されます。これらは義務ですが、配布方法によって変わるものではありません。
静的リンクにすると回答は変わりますか?
LGPL の場合に限り、またコンパイル言語の場合に限ります。LGPL は、ユーザーがライブラリを置き換えられる限り、プロプライエタリな作品でライブラリを使えるように設計されています。動的リンクなら置き換えられますが、静的リンクではできません。Go と Rust はデフォルトで静的リンクし、Cargo.lock や go.sum のどこにもそのことは記載されません。
同じライセンスなのに、プロジェクトによって回答が異なるのはなぜですか? コピーレフトの義務は、コードが存在することではなく、配布やネットワーク経由でのユーザーとのやり取りといった出来事に伴って発生するためです。そうした出来事が起きるかどうかは、リポジトリではなく事業に関する事実です。そのため、ロックファイルだけを読み取るスキャナーでは判断できません。
コーディングエージェントから使う
これはウェブを検索するときではなく、依存関係を追加するときに必要になります。そのため、主な利用方法は検索結果ではなく MCP ツールです。
ホスト型 — インストール不要です:
claude mcp add licenseguard --transport http https://license-guard.rcc-aoki.workers.dev/mcp
ローカル(stdio) — マニフェストがマシンの外に出ることはありません。ライセンスを調べるために、パッケージ名とバージョンだけが公開レジストリに送信されます:
claude mcp add licenseguard -- docker run -i --rm ghcr.io/rccaoki-wq/license-guard:1.1.0
イメージは各リリースで公開され、公式 MCP レジストリに OCI パッケージとして登録されるため、レジストリを読み取るクライアントは、これらの手順なしでインストールできます。代わりに自分でビルドする場合:docker build -t licenseguard . && docker run -i --rm licenseguard。
どちらの方法でも同じポリシーエンジンが実行されます。判定が食い違うことはありません。エンドツーエンドのテストスイート(npm run e2e:stdio)で両者の一貫性を保っています。
ステートレスな Streamable HTTP で、認証もセッション状態もありません。
| ツール | 呼び出すタイミング |
|---|---|
check_dependency_license | 依存関係を1つ追加する前 |
check_manifest_licenses | マニフェストまたはロックファイル全体を監査するとき |
explain_license | 各配布モデルでライセンスが求める内容を確認するとき |
それ以外のものから使う
JSON API は同じ判定結果を返します:
curl "https://license-guard.rcc-aoki.workers.dev/api/pkg/pypi/pyload-ng?model=saas"
# => {"license":"AGPL-3.0-only","verdict":"blocked", ...}
ロックファイル全体をスキャンします:
curl -X POST https://license-guard.rcc-aoki.workers.dev/api/scan \
-H 'content-type: application/json' \
-d "$(jq -Rs '{content: ., distributionModel: "saas"}' package-lock.json)"
エージェント向けのインデックスは /llms.txt にあります。
対応マニフェスト
エコシステム:npm · PyPI · Go modules · crates.io · RubyGems · NuGet
| 形式 | 推移的依存関係 | レジストリの検索 |
|---|---|---|
package-lock.json | はい | なし — ライセンスが埋め込まれています |
pnpm-lock.yaml、yarn.lock | はい | はい(共有キャッシュにより償却されます) |
go.sum | はい | はい |
Cargo.lock、poetry.lock、uv.lock | はい | はい |
Gemfile.lock | はい | はい |
packages.lock.json | はい | はい |
package.json、requirements.txt、pyproject.toml、go.mod、Cargo.toml | 直接依存のみ | はい |
.csproj、Directory.Packages.props、packages.config | 直接依存のみ | はい |
| CycloneDX(JSON)、SPDX(JSON) | はい | ドキュメントにライセンスがない場合のみ |
問題となるライセンスは、通常、自分で意図的に追加したものではなく、依存関係の依存先として含まれます。そのため、重要なのはロックファイルを使った方法です。package-lock.json v2/v3 には各エントリーのライセンスが埋め込まれているため、実際にインストールされる正確なバージョンを対象に、ネットワーク検索ゼロで推移的依存関係をすべて監査できます。
不完全なスキャンがクリーンとして報告されることはありません。 解決できなかった依存関係は not-checked または review として表示され、サマリーにもカウントされます。allowed になることはありません。
1 回のスキャンで実行されるレジストリ検索は最大 300 件です。これにより、1 回のリクエストにかかるコストが上限内に収まります。キャッシュ済みパッケージはこの上限に含まれないため、上限が適用されるのは、まだ誰も検索していないパッケージだけです。約 1000 個のクレートを含む Cargo.lock を初めてスキャンすると、通常は数十件が not-checked のままになりますが、再スキャンすれば解決されます(実測値:servo の 1043 個のクレートは、2 回目のスキャンで公開済みクレートの未解決がゼロになります)。結果には短くなったリストをひそかに表示するのではなく、その状況が明示されます。
Git 依存関係と、スキャン対象のワークスペースのメンバーは、識別可能なすべての形式で not-published として報告されます。対象には Cargo.lock の source フィールド、yarn の workspace: および git+ プロトコル、pnpm の tarball URL、package-lock.json の resolved が含まれます。公開レジストリにはこれらのライセンスデータがないため、検索されることはありません。これは検索上限に達した場合とは異なります。再スキャンしても解決されず、結果にもその旨が表示されます。
これは速度だけの問題ではありません。公開パッケージにも存在する名前(utils、core などの一般的な名前)を持つワークスペースメンバーがある場合、そうしなければ無関係な公開パッケージに対して解決され、allowed と報告される可能性があります。ワークスペースのバージョン(0.0.0-use.local)に一致するものがなく、検索が最新リリースにフォールバックするためです。出所を示すことで、プライベートパッケージが見知らぬパッケージのライセンスを引き継ぐのを防ぎます。
プライベートレジストリは意図的な例外です。npmjs 以外を指す resolved URL は、実際の公開パッケージを提供する透過的な Artifactory または Nexus のプロキシである可能性も十分にありますが、ロックファイルからはそのどちらかを判別できません。そのため、これらも検索対象となり、検索に失敗した場合は unresolved として報告されます。
SBOM
CycloneDX と SPDX は JSON 形式で読み込まれます。GitHub の {"sbom": …} エンベロープにも対応しているため、gh api repos/OWNER/REPO/dependency-graph/sbom のレスポンスをそのまま貼り付けられます。ドキュメントに記録されているライセンスはそのまま使用し、記録のないコンポーネントは照合します。NOASSERTION、NONE、LicenseRef-* は宣言として扱いません。これらは、ドキュメントがライセンスを把握していないことを示すためです。
実際の SBOM については、結果の意味が変わる次の 2 点を取り繕わずに報告します。
ほとんどのコンポーネントには、使用可能なライセンス情報がありません。 公開されている 5 つの GitHub SBOM では、expressjs/express の 44 コンポーネント中 8 件、tokio-rs/tokio の 51 コンポーネント中 1 件について、ドキュメントにライセンス情報が記載されていました。残りは現時点のレジストリと照合しました。ライセンス情報がドキュメントに記載されていたかのように示すのではなく、その内訳を結果に記載します。
バージョン範囲はバージョンではありません。 GitHub の依存関係グラフのエクスポートでは、マニフェストの範囲である ^2.0.0、>= 0.2.42,< 0.3.0 が purl とバージョンフィールドの両方に記載されます。express の 44 コンポーネント中 36 件、tokio の 51 コンポーネント中 50 件が該当します。その文字列に一致するリリースは存在しないため、スキャナーがそのまま渡すと最新リリースと照合される一方で、成果物には含まれていないバージョンが表示されます。範囲はバージョンとして受け付けず、影響を受けたコンポーネント数を結果に記載します。ロックファイルではこの問題が起きないため、ロックファイルの使用が実務上推奨される理由となっています。
対象外となったコンポーネントは、単に省くのではなく、件数と名前を報告します。件数よりも、その理由が重要です。GitHub Actions は対象外による欠落ではありません。 GitHub Actions は CI で実行され、成果物には決して含まれないため、配布やネットワークに関する義務を生じさせません。そのため除外し、結果には「サポート対象外」と分類するのではなく、その理由を明記します。これは、ソフトウェアに関する事実とツールの制限との違いであり、丸め誤差ではありません。5 つの SBOM に含まれる 194 コンポーネントのうち 52 件が githubactions で、cargo に次ぐ 2 番目に多い種類です。スキャンで実際に読み取れないパッケージタイプ(maven、deb、…)は別途報告します。
チェック可能なものが何もないドキュメントは、空のクリーンレポートとして返すのではなく、理由を示して拒否します。理由は 2 種類あり、それぞれ異なります。gorilla/mux の SBOM は GitHub Actions が 100% を占めるため、このドキュメントには配布するものが何も含まれていないことが回答となります。別のスキャナーを探しても、この結果は変わりません。
ステータス
フェーズ 0 — 支払い意欲の検証。 MCP サーバーと無料のウェブツールは公開済みです。実際に使われるのは検索結果ではなくエージェントのワークフロー内であるため、測定する指標はクリックスルー率ではなく、MCP のインストール数とツールの再呼び出し数です。GitHub App(フェーズ 1)に進むのは、その指標に反応が見られた場合に限ります。
開発
npm install
npm test # unit tests
npm run typecheck
npm run coverage
npm run smoke # live registry connectivity
npm run e2e # end-to-end against production
# ui real browser (Playwright)
# a11y accessibility
# mcp official MCP SDK client
# load consistency under concurrency
# adversarial hostile input and boundaries
# correctness against known-good verdicts
# operational cross-path agreement, HTTP, caching
# stdio local and hosted paths must agree
npm run dev # http://localhost:8787
npm run signals # Phase 0 report: real usage only, test traffic excluded
次の対応を決めるのは npm run signals です。そのため、意図的に慎重な設計にしています。合成トラフィック(すべての E2E スイートが x-licenseguard-synthetic: 1 を設定)、レジストリクローラーや採点ボットからのトラフィック、アトリビューションが導入される前に書き込まれた行はすべて除外し、黙って破棄するのではなく別途報告します。アトリビューションできないものは、需要として数えません。
ユニットテストの合格だけでは不十分です。実際のレジストリデータを使って初めて判明した不具合がいくつかあったため、リリース前に smoke と e2e を実際の上流サービスに対して実行し、合格する必要があります。
デプロイ:
npm run db:migrate
npm run deploy
Cloudflare Workers + Hono + D1 を基盤としています。
ドキュメント
- 設計仕様:docs/specs/2026-08-19-license-guard-design.md(日本語)
- フェーズ 0 の実装計画:docs/superpowers/plans/2026-08-19-phase0-free-web-tool.md(日本語)
- レジストリへの公開に関するメモ:docs/PUBLISHING.md(日本語)
依存関係について
扱う内容を踏まえ、すべての依存関係は意図的に MIT または Apache-2.0 を採用しています。SaaS としてデプロイしても、ここに開示を義務付けるものはありません。
| 役割 | パッケージ | ライセンス |
|---|---|---|
| SPDX 式の解析 | spdx-expression-parse | MIT |
| Web フレームワーク | hono | MIT |
| Go ライセンスデータ | deps.dev API(フォールバック:ClearlyDefined) | Apache-2.0 |
プライバシー
ホスト型サービスは、マニフェストの内容や IP アドレスを保存しません。記録するのは利用状況の概要です。どのツールが呼び出されたか、どのエコシステムと配布モデルが対象だったか、どの判定が返されたか、そして繰り返しの利用を集計できるようにするための不透明なセッション識別子です。これらのレコードにパッケージ名は含まれません。正確なフィールドについては、src/mcp/telemetry.ts を参照してください。
パッケージ名が保存される場所は一つ あります。その場所を正確に説明します。検索に成功した結果は (ecosystem, package, version) → SPDX id としてキャッシュされ、次の呼び出しではレジストリに再アクセスしません。このテーブルの書き込み方法から、次の3点が導かれます。いずれもテストで確認されています。
- 誰が問い合わせたかを記録する列はありません。 レコードにはセッション、リクエスト、アドレスが含まれないため、キャッシュからユーザーを特定することはできません。
migrations/0001_init.sqlを参照してください。 - 解決できなかった名前は書き込まれません(
src/resolver/index.tsはキャッシュに書き込む前に処理を返します)。公開レジストリにないパッケージ(社内パッケージ)は、まさに解決に失敗するケースです。 - キャッシュは 非公開ではありません。
/sitemap.xmlの内容に使われています。キャッシュ内の情報はすべて、その名前で npm、PyPI、Go、crates.io にすでに公開されています。
セッション識別子は、仕様に定められた Mcp-Session-Id ヘッダーとして発行されます。このデータベースの外では意味を持たないランダムな値であり、必須ではなく、有効期限もありません。これを無視するクライアントも引き続き動作します。
それでも組織で共有したくない情報が含まれている場合は、ローカルの stdio サーバーを実行してください。送信するのはパッケージ名とバージョンだけで、すでにそれらを公開している公開レジストリにのみ送信されます。
誰かが気付くまで伏せておくのではなく、明記しておきたい点が一つあります。ホストされたサイトの HTML ページには Cloudflare Web Analytics が含まれています。サイトが現在置かれているゾーンで有効になっているためです。Cookie は使用せず、集計データのみを扱いますが、サードパーティーのスクリプトであり、ドメイン移転前にはありませんでした。HTML のみに挿入されるため、/mcp、/api/*、/llms.txt、/sitemap.xml には影響せず、エージェントや API 呼び出し元が読み込むことはありません。
免責事項
LicenseGuard が提供するのは、公開されたライセンステキストと宣言された依存関係のメタデータに基づく 情報です。法律上の助言ではなく、利用しても弁護士と依頼者の関係が生じることはありません。判定はパッケージが宣言するライセンス情報に基づくものであり、あらゆる義務や違反を特定すると主張するものではありません。
ライセンス
Apache-2.0
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。