Claude Media
server.jsonの書き方 — MCP Registry公開用メタデータ形式

server.jsonの書き方 — MCP Registry公開用メタデータ形式

MCP Registryに公開するserver.jsonの必須項目・フィールドの制約・6種類のパッケージ形式・バージョン文字列のルールを、公式スキーマとサンプルで解説します。

server.jsonとは何を書くファイルか

server.json は、MCPの公式サーバーカタログであるMCP Registryにサーバーを登録するための標準メタデータファイルです。サーバーの一意な名前・説明・バージョン・実体の所在(npmパッケージなのかリモートURLなのか)・起動方法をこの1ファイルにまとめます。登録にはmcp-publisherというCLIツールを使います。

MCP Registryが持つのはメタデータだけで、パッケージ本体は預かりません。npmやPyPIなどへ先に本体を公開し、そこを指す server.json を後から登録する順番になります。

前提環境はシンプルです。必要なのは3つです。Node.js(TypeScript製サーバーの場合)、公開先のパッケージレジストリ(npmなど)のアカウント、MCP Registryへの認証手段(GitHubアカウントまたは所有ドメイン)です。認証方式の選び方はMCP Registryの認証方式3種で扱い、本記事は server.json の書き方に絞ります。

手順

npmサーバーを公開するまでの流れ

  1. 1

    package.json に mcpName を足す

    値は server.json の name と同じにします。GitHub認証なら io.github.ユーザー名/ で始めます。

  2. 2

    パッケージを npm に公開する

    npm publish --access public などで本体を先に出します。

  3. 3

    mcp-publisher init で雛形を作る

    プロジェクトの情報から server.json が生成されるので、バージョンなどを自分の値に直します。

  4. 4

    login して publish する

    mcp-publisher login github のあと mcp-publisher publish を実行します。

最小構成のserver.jsonを書く

mcp-publisher init を実行すると、プロジェクトの情報からテンプレートが生成されます。

mcp-publisher init

クイックスタートが示す生成直後のテンプレートは次のとおりです。バージョンは 1.0.0 で、ダミーの環境変数 YOUR_API_KEY が入っています。

{
  "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
  "name": "io.github.my-username/weather",
  "description": "An MCP server for weather information.",
  "repository": {
    "url": "https://github.com/my-username/mcp-weather-server",
    "source": "github"
  },
  "version": "1.0.0",
  "packages": [
    {
      "registryType": "npm",
      "identifier": "@my-username/mcp-weather-server",
      "version": "1.0.0",
      "transport": {
        "type": "stdio"
      },
      "environmentVariables": [
        {
          "description": "Your API key for the service",
          "isRequired": true,
          "format": "string",
          "isSecret": true,
          "name": "YOUR_API_KEY"
        }
      ]
    }
  ]
}

このサーバーに環境変数が要らないなら environmentVariables ごと消します。バージョンも自分のパッケージに合わせて直します。クイックスタートでは package.json を 1.0.1 に上げているため、server.json 側の2か所も 1.0.1 に書き換えています。

先頭の $schema は、このファイルが準拠するスキーマのURLです。エディタや検証ツールがこの値を見て、フィールド名の綴りミスや型の不一致をその場で警告します。

必須フィールドと値の制約

スキーマ(2025-12-11版)で必須とされているのは、トップレベルでは name・description・version の3つです。packages と remotes はどちらも必須には指定されておらず、実体の所在を書くために実質どちらか(または両方)を置きます。値の制約は次のとおりです。

フィールド制約
name制約逆引きDNS形式。スラッシュがちょうど1つで、前が名前空間、後ろがサーバー名。3〜200文字
description制約1〜100文字。実装の詳細でなく機能を書く
version制約255文字まで。範囲指定は拒否される
title制約任意。1〜100文字の表示名で、サブレジストリやクライアントが表示に使ってよい
repository制約任意。書くなら url と source の両方が必須

name は、GitHub認証なら io.github.ユーザー名/ で始め、ドメイン認証なら所有ドメインを逆引きにした名前空間(com.example.*/ のような形)を使います。GitHub認証では、個人のユーザー名のほか組織名(io.github.組織名/)も名前空間にできます。認証方式と名前空間が食い違うと、公開時に権限エラーになります。

パッケージ側(packages の各要素)では、registryType・identifier・transport が必須です。version には具体的なバージョンを書き、latest という文字列は使えません。fileSha256 が必須になるのはMCPBだけです。

environmentVariables の各項目は、name・description・isRequired・isSecret・format を持てます。format に書けるのは string・number・boolean・filepath の4つで、既定は string です。isSecret: true を付けると、APIキーのような秘匿情報として扱う手がかりをクライアントに渡せます。

npmパッケージとして配布する場合は、package.json 側にも mcpName プロパティを追加します。この値は server.json の name と完全に一致していなければなりません。

 {
   "name": "@my-username/mcp-weather-server",
   "version": "1.0.1",
+  "mcpName": "io.github.my-username/weather",
   "main": "index.js",

パッケージ種別ごとに書き方が変わる

MCP Registryは6種類のパッケージ形式に対応しています。registryType の値と、所有権の確認方法がそれぞれ違います。

registryType対応レジストリ所有権の確認方法
npm対応レジストリnpm公式レジストリのみ所有権の確認方法package.json の mcpName プロパティ
pypi対応レジストリPyPI公式のみ所有権の確認方法READMEに mcp-name: $SERVER_NAME の文字列(コメントに隠してよい)
nuget対応レジストリNuGet公式のみ所有権の確認方法READMEに mcp-name: $SERVER_NAME の文字列(コメントに隠してよい)
cargo対応レジストリcrates.ioのみ所有権の確認方法READMEに可視なMarkdownテキストで mcp-name:
oci対応レジストリDocker Hub・GHCR・Google Artifact Registry・Azure Container Registry・Microsoft Container Registry所有権の確認方法io.modelcontextprotocol.server.name のアノテーション(Dockerfileでは LABEL)
mcpb対応レジストリGitHub / GitLabのリリースに置いた成果物所有権の確認方法配布URLに"mcp"の文字列を含む + fileSha256 の明記

cargo だけコメントに隠せない理由は、crates.ioがREADMEをHTMLに変換するときにHTMLコメントを除去するためです。PyPIやNuGetで通る <!-- mcp-name: ... --> の形を流用すると、検証側が見るHTMLに文字列が残りません。リンク集の箇条書きなど、見える文として書きます。

oci の例を見てみます。

{
  "packages": [
    {
      "registryType": "oci",
      "identifier": "docker.io/yourusername/kubernetes-manager-mcp:1.0.0",
      "transport": {
        "type": "stdio"
      }
    }
  ]
}

identifier の形式は レジストリ/名前空間/リポジトリ:タグ です。タグの代わりにダイジェスト指定も使えます。

mcpb パッケージだけは他の種別と違い、MCP Registry自身がハッシュを検証しません。検証するのはMCPクライアント側で、インストール前に成果物が fileSha256 と一致するかを確かめます。公開者はこのハッシュを自分で用意します。

openssl dgst -sha256 image-processor.mcpb

Rustサーバーを作る場合は、配布方針で2つの道に分かれます。

くらべる

Rustサーバーの配布経路

ソース配布

cargo

crates.io経由で、利用者が cargo install を実行します。利用者の環境にRustツールチェーンが必要です。

ビルド済みバイナリ配布

mcpb

GitHubやGitLabのリリースに置いたバイナリを使います。利用者にツールチェーンは要りません。

どちらも正式な対応経路で、優劣ではなく選択です。cargo にはnpmの npx やPyPIの uvx に当たる実行ごとのランナーがなく、インストールは一度きり、実行はバイナリ名で呼ぶ形になります。サンプルに runtimeHint が書かれていないのはそのためです。

Filesystem MCPサーバーは @modelcontextprotocol/server-filesystem としてnpm配布されています。ここまでの npm 形式の例とほぼ同じ構造です。一方、GitHub MCPサーバーは2通りで提供されています。GitHubがホストするリモートサーバー(https://api.githubcopilot.com/mcp/)と、Dockerイメージ(ghcr.io/github/github-mcp-server)です。前者は remotes、後者は oci の書き方に当たります。

リモートサーバーの場合はpackagesでなくremotesを使う

ローカルで実行するサーバーではなく、HTTPエンドポイントとして提供するリモートサーバーの場合は、packages の代わりに remotes フィールドを使います。

{
  "name": "com.example/acme-analytics",
  "version": "2.0.0",
  "remotes": [
    {
      "type": "streamable-http",
      "url": "https://analytics.example.com/mcp"
    }
  ]
}

type には streamable-http または sse を指定します。SSE(Server-Sent Events)方式は非推奨(deprecated)です。sse を公開するのは既存クライアントを支えるときだけにして、新規なら streamable-http を選びます。両方式を別URLで同時提供することも可能です。リモートサーバーは、指定したURLで公開アクセス可能であることが必須です。

マルチテナントで提供するときは、URLに {変数名} 形式のテンプレート変数を埋め込み、同じ階層の variables で中身を定義します。

{
  "type": "streamable-http",
  "url": "https://{tenant_id}.analytics.example.com/mcp",
  "variables": {
    "tenant_id": {
      "description": "Your tenant identifier (e.g., 'us-cell1', 'emea-cell1')",
      "isRequired": true
    }
  }
}

利用者がサーバーを追加するときに tenant_id を入力すると、URLが https://us-cell1.analytics.example.com/mcp のように解決されます。テナントごとに1エントリを書かずに済みます。変数には default・choices・isSecret も付けられ、リージョンのように選択肢が決まっているものは choices で絞ります。

APIキーなどをMCPクライアントに送らせたい場合は、remotes エントリに headers を足します。name(ヘッダー名)・description・isRequired・isSecret を項目ごとに指定でき、isSecret: true の項目は秘匿情報として扱う指定になります。

{
  "remotes": [
    {
      "type": "streamable-http",
      "url": "https://analytics.example.com/mcp",
      "headers": [
        {
          "name": "X-API-Key",
          "description": "API key for authentication",
          "isRequired": true,
          "isSecret": true
        }
      ]
    }
  ]
}

packages と remotes は同時に持たせることもできます。ローカル実行版とホスト型のリモート版を両方提供しているサーバーが典型例で、MCPホストアプリケーションがどちらの導入方法を使うかを選びます。

バージョン文字列のルールとよくあるつまずき

version フィールドには、公式が明記するルールがあります。

  • 一意性が必須: 同じバージョン文字列で2回公開することはできません
  • 公開後は不変: バージョン文字列を含むメタデータは、公開後に変更できません
  • 範囲指定は禁止: ^1.2.3 ~1.2.3 >=1.2.3 1.x 1.2.* 1 - 2 のようなバージョン範囲に見える文字列は登録エラーになります

推奨はセマンティックバージョニングです。1.0.0 や 2.1.3-alpha のような形式なら、MCP Registryが解析して最新版(latest)の判定に使います。v1.0 や 2025-06-18 のような形式も許可されますが、解析に失敗した文字列は常に "latest" 扱いになります。

日付をバージョンにする運用には、公式の表が注意印を付けている落とし穴があります。2025.11.25 や 2025.6.18 はセマンティックバージョンとして解析できますが、ゼロ埋めした 2025.06.18 は非セマンティックな日付の扱いです。同じ日付でもゼロ埋めの有無で解析の結果が変わります。

つまずきやすいのが、セマンティックバージョンを使っていたサーバーが、途中で非準拠の文字列を公開した場合です。この場合、本来ならバージョン順で後方に並ぶはずの新バージョンでも "latest" として扱われてしまいます。バージョン形式を運用の途中で変えないことが、この事故を避ける最も簡単な方法です。

複数の配布先を1つの server.json にまとめるときは、直下の version を全体のリリースバージョンにします。各 packages の version は、配布先の実際のバージョンに合わせます。

{
  "version": "1.3.0",
  "packages": [
    {
      "registryType": "npm",
      "identifier": "@my-username/my-server",
      "version": "1.3.0",
      "transport": { "type": "stdio" }
    },
    {
      "registryType": "nuget",
      "identifier": "MyUsername.MyServer",
      "version": "1.0.0",
      "transport": { "type": "stdio" }
    }
  ]
}

ローカルパッケージが1つだけなら、直下の version と packages 内の version は同じ値に揃えるのが公式の推奨です。リモートサーバーでAPIバージョンがある場合は、server.json の version をそのAPIバージョンに揃えます。URLにバージョンを含むサーバー(https://api.myservice.com/mcp/v2.1 に対して 2.1.0)がその例です。

パッケージやリモートURLを変えず、メタデータだけを更新したいときは、1.2.3-1 のようなプレリリース形式を使います。この場合 packages 内の version は 1.2.3 のままです。ただし、正式版を先に公開してからプレリリース版を後追いで公開すると、セマンティックバージョニングの規則でプレリリース版のほうが古い扱いになり、"latest" にならない点には注意が必要です。

mcp-publisherで公開する

server.json を書いたら、mcp-publisher CLIで公開します。

mcp-publisher login github
mcp-publisher publish

login の部分は選んだ認証方式によってサブコマンドが変わります。GitHub認証(login github)・DNS認証(login dns)・HTTP認証(login http)の3方式があり、後者2つはドメイン所有権を鍵ペアで証明する仕組みです。GitHub認証では、端末に出るデバイスコードをブラウザーで入力して承認します。公開が成功すると、MCP RegistryのREST APIで検索できるようになります。

curl "https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.my-username/weather"

repository は必須ではありませんが、スキーマは「透明性とセキュリティ検査のために推奨」としています。これを書かないと、利用者が起動コマンドの中身をソースコードで確かめる手がかりが server.json から消えます。url にリポジトリのURL、source に github のようなホスティング元を指定します。

公開直後によく出るエラーは3つです。

エラー文言原因と対処
Registry validation failed for package原因と対処パッケージ側の検証情報(mcpName など)の不備。入っているか確かめる
Invalid or expired Registry JWT token原因と対処認証切れ。mcp-publisher login github で再ログインする
You do not have permission to publish this server原因と対処認証方式とサーバー名の名前空間が食い違っている

3つ目は、GitHub認証を選んだのに name が io.github. で始まっていない、という組み合わせミスが典型例です。

まとめ

server.json は書き方よりも制約を先に押さえると手戻りが減ります。公開後に変えられないバージョンは、とくに形式を決めてから出す項目です。ファイルを書き終えたら、公開に使う認証方式(GitHub・DNS・HTTP)を選ぶ段階です。

この記事を共有:XはてブLinkedIn
MCP をもっと見る →