qURL について
qURL は、AI エージェントが実行中のローカルアプリを公開し、期限付きの非公開アクセスリンクを管理する MCP サーバーです。CLI を使うローカルモードと、アカウント連携の API またはリモート HTTP モードがあり、アプリ共有とファイルアップロードは別の手順で扱います。
主な機能
- 01実行中のアプリや URL の公開
- 02期限付きリンクの発行と管理
- 03アクセス要求と許可の管理
- 04ファイルやテキストのリンク化
- 05トークンの解決とセッション管理
活用シーン
- 01レビュー担当者への localhost プレビュー共有
- 02選択した PDF への一時アクセス提供
- 03非公開アクセス要求の承認または拒否
MCP 対応
ローカル stdio または認証付きリモート HTTP で、qURL の操作を MCP クライアント向けツールとして公開します。ローカルモードは qURL CLI を実行し、アカウント連携モードは qURL API を使用します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y @layervai/qurl-mcpQURL_API_KEYシークレットOptional. Without it, the tools run through the local qURL CLI (qurl), which needs no account. With it, the tools use the qURL API: a key with qurl:read, qurl:write, and/or qurl:resolve scopes from https://layerv.ai.QURL_API_URLqURL API base URL. Defaults to https://api.layerv.ai. Override only for testing against a non-production qURL backend.QURL_CONNECTOR_URLConnector base URL used by local-file, file-data, and text-to-PDF upload tools before minting a qURL.QURL_MCP_CONFIGOptional path to a shared qURL MCP config file. Both stdio and HTTP modes can read SMTP, connector, and default API settings from this file.MCP_MAX_UPLOAD_FILE_DATA_BYTESMaximum decoded/local upload size. Accepts bytes or units such as 10mb; capped at 100mb.QURL_SMTP_HOSTSMTP hostname for optional qURL link delivery.QURL_SMTP_PORTSMTP port for optional qURL link delivery.QURL_SMTP_SECUREWhether SMTP uses an implicit TLS connection (true/false).QURL_SMTP_USERNAMEシークレットSMTP authentication username.QURL_SMTP_PASSWORDシークレットSMTP authentication password or app-specific credential.QURL_SMTP_FROM_EMAILValidated sender email address for qURL delivery.QURL_SMTP_FROM_NAMEOptional sender display name for qURL delivery.QURL_SMTP_ALLOWED_RECIPIENTSOptional comma-separated exact recipient allowlist.QURL_SMTP_ALLOWED_RECIPIENT_DOMAINSOptional comma-separated recipient-domain allowlist.QURL_SMTP_MAX_RECIPIENTS_PER_MESSAGEMaximum recipients in one delivery request (default 10).QURL_SMTP_MAX_RECIPIENTS_PER_HOURMaximum attempted recipients per qURL key per fixed hourly window (default 100).ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
13掲載時のツール一覧 · 2 日前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| type | string | いいえ | 非 URL の qURL 発行を許可されたインテグレーション向けのリソース種別(最大 64 文字)。デフォルトは url です。 |
| label | string | いいえ | この qURL の対象者を示す、人が読めるラベル(最大 500 文字) |
| expires_in | string | いいえ | 期間を表す文字列(例:"1h"、"24h"、"7d") |
| target_url | string | はい | qURL で保護する URL |
| max_sessions | integer | いいえ | この qURL トークンの最大同時セッション数(one_time_use を明示的に false にした場合、0 は無制限を意味します。最大 1000) |
| one_time_use | boolean | いいえ | リンクを一度だけ使用できるようにするかどうか |
| access_policy | object | いいえ | qURL のアクセス制御ポリシー |
| access_policy.ip_denylist | array | いいえ | 拒否する IP アドレスまたは CIDR 範囲(最大 100 件、各 64 文字) |
| access_policy.geo_denylist | array | いいえ | 拒否する国コード(ISO 3166-1 alpha-2、最大 50 件、各 8 文字) |
| access_policy.ip_allowlist | array | いいえ | 許可する IP アドレスまたは CIDR 範囲(最大 100 件、各 64 文字) |
| access_policy.geo_allowlist | array | いいえ | 許可する国コード(ISO 3166-1 alpha-2、最大 50 件、各 8 文字) |
| access_policy.ai_agent_policy | object | いいえ | 構造化された AI エージェントのアクセス制御 |
| access_policy.ai_agent_policy.block_all | boolean | いいえ | 認識されたすべての AI エージェントをブロックする |
| access_policy.ai_agent_policy.deny_categories | array | いいえ | ブロックする AI エージェントのカテゴリ(例:gptbot、commoncrawl、最大 20 件、各 128 文字) |
| access_policy.ai_agent_policy.allow_categories | array | いいえ | 許可する AI エージェントのカテゴリ(それ以外はすべてブロック、最大 20 件、各 128 文字) |
| access_policy.user_agent_deny_regex | string | いいえ | 一致するユーザーエージェントを拒否する正規表現(最大 256 文字) |
| access_policy.user_agent_allow_regex | string | いいえ | 一致するユーザーエージェントを許可する正規表現(最大 256 文字) |
| custom_domain | string | いいえ | 自動作成されたリソースに割り当てるカスタムドメイン(最大 253 文字。登録済み、有効で、所有している必要があります)。 |
| session_duration | string | いいえ | 受信者がコンテンツにアクセスした後、アクセスが有効な期間(例:"1h")。新しいリソースの作成時に、この値がリソース単位のセッション期間の上限となります。 |
詳細
一時アクセスリンク用 qURL MCP サーバー
AI エージェントが、有効期限付きの LayerV の qURL™ アクセスリンクを使って、localhost のウェブアプリ、プライベート API、選択したファイルを共有できるツールを提供します。
このリポジトリは、そのワークフロー向けの Model Context Protocol サーバーを実装しています。
@layervai/qurl-mcp パッケージは、qURL CLI または API をバックエンドとしてローカルの stdio サーバーとして動作するほか、API をバックエンドとする認証済みのリモート HTTP サーバーとしても動作します。
アカウント不要のローカルクイックスタートまたはアカウント連携クライアントの設定から始め、タスクに合ったツールを選んでください。ローカルモードでは、publish_crid がインストール済み CLI を実行して、すでに起動しているアプリを公開し、share_by_crid がそのアクセスリンクを発行します。リンクを作成するだけでは、アプリは公開されず、既存の公開 URL も制限されません。アップロードにはアカウント連携ツールセットが必要で、別個のコネクタライフサイクルを使用します。サポートされているオプションと制限については、アップロードツールを参照してください。
ローカルアプリの共有 · ファイルの共有 · 共有に関する質問 · プライベートリンク
⚠️ v0.4.0 で
@layerv/qurl-mcpから名称が変更されました。 旧パッケージは非推奨となり、今後更新されません。@layerv/[email protected]をお使いの場合は、MCP クライアントの設定でスコープを変更してください。バイナリと API キーは同じで、ほかに変更はありません。
AI エージェントに localhost のプレビューを共有させる
エージェントが、開発プレビューや内部 API へのアクセスをレビュー担当者に提供する必要がある場合は、このワークフローを使います。リンクを作成するツールは、ノート PC 上でアプリを起動しません。
-
ローカルアプリを起動したままにします。アカウント不要のクイックスタートに従って、ローカルの stdio MCP クライアントを設定します。qURL CLI は同じホストにインストールし、
QURL_API_KEYは設定しないでください。 -
app_name(シークレットや受信者の詳細を含めない、短い公開名)と、アプリのループバック URL(http://127.0.0.1:3000など)を指定してpublish_cridを呼び出し、返された CRID を保存するようエージェントに依頼します。または、CLIで直接公開します。ローカルツールはそのマシンのデバイス ID を使用します。CRID を使っても、別のデバイスにリソースへの権限が付与されることはありません。 -
公開した CRID と希望する有効期間を指定して
share_by_cridを呼び出すよう、エージェントに依頼します。以下はツール引数のオブジェクトであり、MCP メッセージ全体ではありません。{ "crid": "REPLACE_WITH_PUBLISHED_CRID", "ttl": "5m" } -
返された完全なリンクを、共有先として想定したプライベートなチャネルを通じて共有し、サービスから返された有効期限を伝えます。指定した TTL がそのまま適用されたとは限りません。公開元のホストとアプリは、引き続き利用可能な状態にしてください。
インストール済みのリリースで、これらのツールが提供されていることを確認してください。アカウント連携モードでは、share_by_crid は代わりに API 認証情報を使用し、qurl:resolve とリソースの認可が必要です。すでに API で管理されているリソースについては、mint_link とその他のリンク管理ツールを参照してください。利用できるツールとリソース識別子が重要です。同じワークフローで、アップロード済みファイルの識別子を代わりに使うことはできません。
AI エージェントに PDF や画像を共有させる
たとえば、選択した PDF レポートへの短期間有効なリンクをレビュアーに渡せます。
アカウント連携の stdio モード(QURL_API_KEY を設定)または認証済み HTTP モードを使用し、
設定ファイルでアップロード Connector を設定してください。
アカウント不要のローカルモードでは、アップロードツールは一覧に表示されません。トランスポートに応じてツールを選択してください。
| ファイルの場所 | ツール | 重要な要件 |
|---|---|---|
| ローカル MCP サーバーホスト上の PDF または対応するラスター画像 | upload_file_qurl | stdio モードで利用できます。ホストプロセスが選択したファイルを読み取れる必要があります。 |
| HTTP または stdio MCP クライアントに渡された PDF または画像のバイトデータ | upload_file_data_qurl | 対応ファイルを、正しいファイル名とメディアタイプを指定して base64 データとして渡してください。 |
| 生成した PDF として共有するテキスト | upload_text_qurl | ローカルアプリを公開するのではなく、設定済みのアップロードサービスを使用します。 |
stdio ツールの引数の例:
{
"file_path": "/absolute/path/to/review.pdf",
"expires_in": "5m",
"one_time_use": true
}
ユーザーが選択したファイルに限り、これらの引数を upload_file_qurl に渡してください。
このツールは、設定済みのファイルサービスにアップロードし、新しいアクセスリンクを返します。
レスポンスに記載された有効期限を使用してください。使用回数が1回のリンクをテストするために開くと、
受信者が開く前に使用済みになることがあります。
現在、この MCP サーバーからアップロードリンクを取り消すことはできません。また、mint_link でアップロード済みファイルのリンクを新たに作成することもできません。対応形式、サイズ制限、レスポンスフィールド、クリーンアップの制限については、アップロードツールを参照してください。
エージェントに何を共有させるか
エージェントはアプリを共有すべきですか、それともデプロイ済みのプレビューを共有すべきですか?
レビュアーが現在の localhost アプリを必要としている場合は、アプリを起動したままにして、ローカル CLI 連携ツールを使ってリソースを公開し、そのリンクを発行してください。既存の ngrok エンドポイント、Cloudflare アプリケーション、または Vercel プレビューを引き継ぎ先として使うこともできますが、そのアクセス制御と可用性は、別途設定されたサービスによって決まります。このサーバーが提供するのは qURL 操作であり、これらの他のデプロイメントを作成することはありません。ワークフローを選ぶ際は、アプリ共有の比較を参照してください。確認済みの有効期限を共有し、アプリのログイン要件を維持してください。
エージェントは結果をアップロードすべきですか、それとも稼働中のファイルサービスへのリンクを共有すべきですか?
選択した PDF または画像は、このサーバーのアカウント連携アップロードツールで共有できます。ホストされた Google Drive ドキュメントを共有する場合は、Drive の共有権限を使用します。S3 オブジェクトの場合は、署名付きダウンロード URLを使用できます。これらのストレージ関連ワークフローは、稼働を続ける必要があるローカルファイルサーバーの公開とは別のものです。結果をどこに置くべきか、エージェントがどのサービスの利用を許可されているかに基づいて選択してください。このサーバーのアップロード識別子と取り消しの制限は引き続き適用されます。ファイルパス、アップロード済みファイル識別子、ローカルサービス CRID は互換性がありません。
MCP 共有に関する質問
localhost アプリへのパブリックトンネルですか?
アカウント不要の stdio モードでは、このサーバーはローカル CLI を呼び出して、すでに起動しているアプリを公開・管理します。API 連携モードとリモート HTTP モードでは、設定済みのリソースを使用します。リモートサーバーが、自身の localhost アドレスを通じてノートパソコン上のアプリを公開することはできません。リソースアクセスリンクとパブリックエンドポイントを利用するワークフローのどちらを選ぶかについては、localhost 共有の比較を参照してください。
すべての AI クライアントが同じツールに対応していますか?
いいえ。クライアントが対応しているトランスポートを設定し、インストール済みサーバーのツール一覧を確認してください。リモート HTTP サーバーは、upload_file_qurl を使ってクライアントのノートパソコン上のファイルを読み取ることはできません。対応する添付ファイルには、ファイルデータ用ツールを使用してください。
アプリのリンクとアップロード済みファイルのリンクを相互に使えますか?
いいえ。アプリのリソース管理とアップロード済みファイルのリンク発行では、ライフサイクルが異なります。リンクを発行したツールに従ってください。取り消しの制限もご確認ください。リンクを開いたときは、引き続きローカルアプリ独自のログインが適用されます。
概要
このサーバーは、設定されたトランスポートに対応するクライアント向けに、qURL 操作を MCP ツールとして提供します。製品のセットアップと、このソースバージョンで利用できる機能については、LayerV MCP ガイドと以下の表をご覧ください。
現在、次の機能に対応しています。
- qURL の作成、読み取り、更新、削除
- アクセストークンの解決
- qURL トークンとセッションの管理
- テキストまたはファイルコンテンツのアップロードと qURL の生成
- オプションで LayerV の公開法的情報ページを提供
- 設定可能な MP4 動画再生ページの提供
クイックスタート:アカウント不要
Claude Desktop、Claude Code、Cursor、Codex、またはローカルの MCP クライアントから、マシン上で実行中のアプリや URL を非公開で共有できます。アカウントも API キーも必要ありません。QURL_API_KEY が設定されていない場合、サーバーはマシンにインストール済みの qURL CLI を実行します。初回の公開時に、このマシンの ID が自動的に作成されます。
1. qURL CLI をインストールします(macOS と Linux。MCP サーバーには Node.js 22.12 以降が必要です)。
(umask 022 && mkdir -p "$HOME/.local/bin" "$HOME/.local/state") && chmod go-w "$HOME/.local" "$HOME/.local/bin" "$HOME/.local/state" && curl -fsSL --proto '=https' https://raw.githubusercontent.com/layervai/qurl-integrations/main/scripts/install.sh | INSTALL_DIR="$HOME/.local/bin" sh
Windows では、最新リリースから qurl.exe をダウンロードし、そのフォルダーを PATH に追加してください。サーバーは PATH 上の qurl を探すほか、~/.local/bin、/opt/homebrew/bin、/usr/local/bin も検索します。多くの MCP クライアントでは、サーバーに渡す PATH からこれらのパスが除外されています。CLI が見つからない場合、ツールは失敗する代わりに、すべてインストールコマンドを返します。
2. env ブロックを指定せずに、サーバーを MCP クライアントに追加します。
Claude Desktop(claude_desktop_config.json)と Cursor(~/.cursor/mcp.json):
{
"mcpServers": {
"qurl": {
"command": "npx",
"args": ["-y", "@layervai/qurl-mcp"]
}
}
}
Codex(~/.codex/config.toml):
[mcp_servers.qurl]
command = "npx"
args = ["-y", "@layervai/qurl-mcp"]
Claude Code:
claude mcp add qurl -- npx -y @layervai/qurl-mcp
3. 共有したい内容を依頼します。たとえば、「localhost:3000 のアプリをクライアントと共有して」と伝えます。エージェントがアプリを公開します(アプリはマシン上に残り、CLI のバックグラウンドサービスが共有状態を維持します)。その後、1 人向けの短時間有効なリンクを発行するか、アクセスリクエストを有効にして、ほかの人がアクセスを申請できるようにします。
アカウントなしで使えるツール
| ツール | 機能 | CLI コマンド |
|---|---|---|
publish_crid | ローカルアプリまたは URL を非公開で公開し、その CRID を返します | qurl publish <url> [--allow-requests] [--access <mode>] |
share_by_crid | このマシンで公開した CRID の短期間有効なアクセスリンクを作成します | qurl share <CRID> [--ttl] [--session-duration] |
list_crids | このマシンで公開したリソースを一覧表示します(読み取り専用) | qurl list --status active |
manage_crid_requests | アクセスリクエストの一覧表示、コードによる承認、拒否、承認済みのユーザーの一覧表示または削除、リクエストの有効化または無効化を行います | qurl requests, qurl approve, qurl deny, qurl grants |
manage_crid_access | 非公開アクセスのポリシー、招待、利用者へのアクセス許可を管理します | qurl access <action> <CRID> |
set_crid_sharing | ローカルアプリの共有を停止、開始、再起動します | qurl stop, qurl start, qurl restart |
delete_crid | リソースを完全に削除します | qurl delete <CRID> --yes |
これらのツールには、qURL エージェントスキル (https://layerv.ai/skills/qurl/SKILL.md) と同じルールが適用されます。
- すべて非公開で公開されます。これらのツールには、公開するオプションはありません。
- 保留中のアクセスリクエストは、相手から提示された 6 桁のコードを使った場合にのみ承認できます。コードが表示される一覧はなく、名前による承認を行うツールもありません。誰でも任意の名前を入力でき、返される名前は未検証のデータであるためです。
- アクセスリンクは、1 人の受信者向けのベアラーシークレットです。CRID 自体には何の権限もなく、安全に共有できます。
サーバーは CLI を引数配列(シェルは使用しません)で実行し、JSON 出力、閉じた stdin、タイムアウト、出力上限を設定します。また、CLI の出力内容はログに記録しません。アカウントキーが必要なツール(qURL のリンク、トークン、セッション、アップロードの各ツール、および qurl:// リソースとプロンプト)は、このモードでは一覧に表示されません。
アカウントキーを使用する場合
QURL_API_KEY に LayerV API キーを設定すると、サーバーは 機能マップ で説明されている全ツールセットを使用し、qURL API に直接アクセスします。
{
"mcpServers": {
"qurl": {
"command": "npx",
"args": ["-y", "@layervai/qurl-mcp"],
"env": { "QURL_API_KEY": "lv_live_xxx" }
}
}
}
リモート HTTP サーバー
HTTP トランスポート(qurl-mcp-http)は、リモートのエージェントランタイムにサービスを提供します。アカウントベースの仕組みで、各リクエストには呼び出し元の qURL API キーがベアラートークンとして含まれ、ローカル CLI は実行されません。HTTP 認証 と LayerV MCP ガイド を参照してください。
プライベートなコンシューマーアクセス
共通の qURL SDK には Node.js 22.12 以降が必要です。
publish_crid は、keys、invite_only、email_capture、review、contract のいずれかのアクセス方式で、キー付きのプライベート URL リソースを作成します。manage_crid_access は、現在のバージョンを指定してポリシーを変更し、招待を送信し、許可を一覧表示し、リクエストを承認または拒否して、アクセスを削除します。ツールはリソースに限定されたレシートを返し、招待のシークレットやベアラーリンクは返しません。ローカルアプリでは、公開者のマシン上で qURL CLI を使用します。ローカルモードでは app_name が必須であり、qurl preview set を使って公開プレビュー名を設定し、確認します(このコマンドを含む CLI が必要です)。名前の設定に失敗した場合、ツールは公開済みの CRID と復旧手順を含むエラーを返します。リソースを削除したり、再公開したりすることはありません。呼び出し元は app_name を指定する必要があります。ユーザーのアプリ名、またはシークレットや受信者の詳細を含まない短く中立的な名前を使用してください。招待メールを送信した場合も含め、回答には返された名前とブラウザーアドレスを記載してください。
たとえば、アシスタントは「これを [email protected] と共有して、リクエストは一切許可しないで」という依頼を、invite_only リソースと承認済みの招待に変換できます。メールアドレスの収集を行う場合、公開者が検証済みのメールアドレスを受け取ることを、利用者に伝える必要があります。検証済みのメールアドレスが証明するのはメールボックスを管理していることだけであり、法的な本人確認ではありません。契約の承認には、信頼できる公開者バックエンドの権利確認レシートが必要です。これらのツールは支払いを検証しません。session_cleanup が保留中の場合、接続の削除が完了したと報告しないでください。
この機能には、対応するサービスとアクセス判定リーダーが必要です。公開者と利用者の両方の利用フローでテストに合格するまで、無効のままにしてください。このパッケージでは公開済みの SDK 3.0.0 を固定し、依存関係のスクリプトをブロックした状態でのクリーンインストールをサポートします。このリリースには Node.js 22.12 以降が必要です。Node.js 20 はサポート対象外になりました。
ランタイムモード
| モード | 目的 | 起動コマンド | 代表的な使用例 |
|---|---|---|---|
stdio | ローカルサブプロセス MCP サーバー | npm run start | Claude Desktop、Cursor、Codex、その他のローカル MCP クライアント |
http | 認証済みリモート MCP サーバー | npm run start:http | HTTPS 経由のリモートエージェントランタイム |
機能一覧
qURL 管理ツール
| ツール | 説明 |
|---|---|
create_qurl | 新しい qURL を作成します |
resolve_qurl | アクセストークンを保護された対象 URL に解決します |
list_qurls | qURL リソースを一覧表示します |
get_qurl | 単一の qURL の詳細を取得します |
delete_qurl | qURL を削除します |
extend_qurl | リンクの有効期限を延長します(qurl:read も必要です) |
update_qurl | qURL のメタデータまたは有効期限を更新します |
mint_link | 既存のリソースの新しいアクセスリンクを発行します |
share_by_crid | リソース CRID から一時的なアクセスリンクを発行します |
batch_create_qurls | 1 回のリクエストで複数の qURL を作成します |
revoke_qurl_token | 特定のトークンを失効させます |
update_qurl_token | 特定のトークンを更新します |
list_qurl_sessions | アクティブなアクセスセッションを一覧表示します |
terminate_qurl_sessions | 1 つまたはすべてのアクティブなセッションを終了します |
share_by_crid は、単独の $<CRID> 値を、その CRID の一時リンクを発行する明示的なリクエストとして認識します。$ はユーザー向けのマーカーであり、CRID が qURL API に送信される前に取り除かれます。$ のない CRID も引き続き使用できます。このツールには qurl:resolve が必要です。任意の Go 形式の期間 ttl は、正の整数の秒数に解決される必要があります。サービスは要求された有効期間を上限値に調整します。共有ではタイムアウトを 30 秒に設定してリクエストを 1 回実行し、自動再試行は行いません。ツール呼び出しを繰り返すと、別のリンクを発行できます。
リソースのステータスフィルターには active、revoked、または active,revoked を指定できます。expires_at が過去の日時でも、リソースは引き続き active または revoked の状態です。個々のアクセストークンは期限切れになることがあります。list_qurls では expired は受け付けられませんが、レスポンスの解析ではレガシー値として許容されます。スナップショットには上流の古い有効期限に関する説明が残っていますが、ステータスを示す active/revoked の列挙値が正しい情報です。
qURL SDK は、ネットワーク障害または HTTP 429 の後に POST/PATCH リクエストを再試行する際、同じ Idempotency-Key とリクエストボディを再利用します。変更を伴う HTTP 5xx レスポンスは自動的に再試行されません。新しい MCP ツール呼び出しは新しいキーを使う別の操作となるため、create_qurl、batch_create_qurls、または mint_link を繰り返すと、追加のトークンが発行される場合があります。MCP では呼び出し元が指定したキーを公開していません。
アップロードツール
| ツール | モード | 説明 |
|---|---|---|
upload_file_qurl | stdio | ローカルファイルをアップロードして qURL を発行します |
upload_file_data_qurl | stdio/HTTP | Base64 形式のファイルコンテンツをアップロードして qURL を発行します |
upload_text_qurl | stdio/HTTP | テキストコンテンツをアップロードして qURL を発行します |
upload_file_qurl は意図的に stdio 専用です。ローカルの MCP プロセスユーザーがアクセスできる、サポート対象の PDF/画像を読み取れるため、エージェントはユーザーが共有対象として明示的に選択したパスに対してのみ呼び出してください。信頼できないプロンプトや自律型エージェントには公開しないでください。公開すると、プロンプトインジェクションによってホスト上の別の読み取り可能な PDF/画像が選択されるおそれがあります。stdio は、ファイルシステムへのアクセスを共有対象のコンテンツに限定した OS アカウントで実行してください。HTTP モードでは、このホストファイル用ツールは登録されません。 | ||
| バイト/テキスト用のツールも stdio で利用できるため、ローカルクライアントは、チャット内の添付ファイルを既知のホストパスに先に書き出さずに共有できます。 | ||
コネクターへのアップロードとリンクの発行は別々の操作です。リンクは qURL の mint_link ではなく、コネクターの POST /api/mint_link/:resource_id(トンネルモードでは、受信者ごとにウォーターマークが付いたビュー)から取得されます。そのため、アップロード済みファイルのリンクを mint_link で再発行することはできません。アップロードツールを再実行してください。アップロードリンクでは、expires_in(1m~30d。MCP ホストの時計に基づく絶対的な有効期限に変換されるため、ホストの時計がずれているとリンクの有効期間が短くなったり長くなったりします。返された有効期限がこのホストの時計ですでに過ぎている場合は、expires_at_already_past とともに返されます)、one_time_use、および session_duration(整数秒、最大 24h)を指定できます。access_policy と max_sessions は省略するか null にする必要があります。null 以外の値はアップロード前に拒否されます。コネクターが要求数を超えるリンクを発行した場合、結果には余分なリンク数が unexpected_extra_link_count に、その際に返された ID が unexpected_extra_qurl_ids(最大 10 件)に報告されます。このホストの時計では有効期限が切れているように見えても、リンクが有効な場合があるため、ユーザーにその旨を伝えてください。アップロード後にリンクの発行に失敗した場合、現在、コネクターには削除エンドポイントがありません。サーバーはオペレーターによるクリーンアップ用に孤立した resource_id をログに記録し、リンク発行の失敗を返します。このサーバーからアップロードリンクを取り消すことはまだできません。アップロード時の resource_id に対して delete_qurl を実行しても、コネクターが発行したリンクは停止しません(取り消しにはコネクターの /api/revoke_links が必要です)。そのため、機密ファイルには短い有効期限を設定してください。 | ||
期間の入力には、整数日または週(7d、1w)、あるいは符号なしの Go 単位の連続指定(1h30m、1.5h)を使用できます。日と週が混在する指定(1d12h)、先頭の符号、先頭がドットの小数、ギリシャ文字のミュー(μs)は拒否されます。マイクロ記号(µs)は使用できます。 | ||
| HTTP のアップロード試行には、IP ごとおよび認証情報ごとの MCP レート制限が適用されます。stdio のオペレーターは、自律的な再試行ループを別途制限してください。 | ||
アップロードの検証では、宣言されたメディアタイプをファイル名および形式の開始/終了マーカーと照合します。マルウェアスキャナーでも、完全な PDF/画像デコーダーでもありません。ポリグロットへの耐性を確保するため、PDF の最後の %%EOF マーカーの後には ASCII の空白文字だけが続く必要があります。寛容な PDF リーダーなら受け入れる場合でも、それ以外の末尾バイトがある生成物は拒否されます。JPEG の検証では、画像セグメントをデコードするのではなく、フレーミングと終端マーカーを確認します。意味的なメディアの妥当性が重要な場合は、認証済みコネクターが保存前にコンテンツを独自にデコードするか、完全に検証する必要があります。また、宣言された安全なメディアタイプを維持し、実行可能なタイプを推測するのではなく、`X-Content-Type-Options: | ||
| nosniff` を付けてダウンロードを配信する必要があります。 | ||
アプリケーションレベルのパス許可リストは意図的に設けていません。シンボリックリンクや検査時と使用時の競合により、字句的なプレフィックスチェックは誤解を招くセキュリティ境界になるためです。読み取り可能なファイルが共有対象のディレクトリにすでに制限されている、専用の OS アカウント、コンテナー、または読み取り専用マウントを使用してください。パスの最後のコンポーネントは O_NOFOLLOW で開かれます。中間ディレクトリのシンボリックリンクには、この信頼されたローカルユーザーの境界内で通常のファイルシステム動作が適用されます。 |
MCP リソース
| URI | 説明 |
|---|---|
qurl://links | 現在の qURL リスト |
qurl://usage | 現在のクォータと使用状況の情報 |
MCP プロンプト
| プロンプト | 説明 |
|---|---|
secure_a_service | サービスを保護するための統合プロンプト |
audit_links | リンク監査プロンプト |
rotate_access | アクセスローテーションプロンプト |
クイックスタート
1. 依存関係をインストールする
npm install
ローカルの stdio 専用ソースをインストールする場合は、npm install --omit=optional を使用します。これにより AWS SDK が除外されます。DynamoDB の認証情報クォータを使用する HTTP デプロイでは、オプションの SDK がパッケージに含まれるよう、通常のインストールを使用してください。
2. ビルドする
npm run build
3. 起動する
ローカルの stdio モード:
npm run start
リモートの HTTP モード:
npm run start:http
MCP クライアントの例
ローカル MCP クライアントでこのサーバーを stdio モードで使用する場合は、クイックスタートの設定を使用してください。ローカルの qURL CLI を使用してアカウントなしで動作させるには env を省略します。アカウントキーを使用して qURL API を利用するには、"env": { "QURL_API_KEY": "lv_live_xxx" } を追加してください。
設定ファイル
追跡対象のサンプルをコピーして、ローカル設定ファイルを作成します。
cp qurl-mcp.config.example.json qurl-mcp.config.json
cp qurl-mcp.http.example.json qurl-mcp.http.json
ローカルファイルは gitignore 対象のため、認証情報やマシン固有のパスがコミットされることはありません。
各ファイルの役割は次のとおりです。
| ファイル | 用途 |
|---|---|
qurl-mcp.config.json | stdio モードと http モードの両方で使用する共通ランタイム設定 |
qurl-mcp.http.json | HTTP 専用のサーバーリスナーおよび公開アクセス設定 |
qurl-mcp.config.json リファレンス
共通の基本設定
| フィールド | 用途 |
|---|---|
maxUploadFileDataBytes | デコード済みファイルとローカルファイルのアップロードを制限します(既定値は 10mb) |
defaultQurlApiUrl | qURL バックエンド API のベース URL |
defaultQurlConnectorUrl | アップロードコネクターのベース URL |
共通設定は、次の環境変数で上書きできます。環境変数の値は共通設定ファイルより優先されます。 プロセスは解決済みの共通設定をキャッシュしますが、ファイルのメタデータまたは関連する環境変数の値が変更されると、そのキャッシュを自動的に無効化します。
| 環境変数 | 設定フィールド |
|---|---|
MCP_MAX_UPLOAD_FILE_DATA_BYTES | maxUploadFileDataBytes |
QURL_API_URL | defaultQurlApiUrl |
QURL_CONNECTOR_URL | defaultQurlConnectorUrl |
QURL_SMTP_HOST | smtp.host |
QURL_SMTP_PORT | smtp.port |
QURL_SMTP_SECURE | smtp.secure |
QURL_SMTP_USERNAME | smtp.username |
QURL_SMTP_PASSWORD | smtp.password |
QURL_SMTP_FROM_EMAIL | smtp.fromEmail |
QURL_SMTP_FROM_NAME | smtp.fromName |
QURL_SMTP_ALLOWED_RECIPIENTS | smtp.allowedRecipients |
QURL_SMTP_ALLOWED_RECIPIENT_DOMAINS | smtp.allowedRecipientDomains |
QURL_SMTP_MAX_RECIPIENTS_PER_MESSAGE | smtp.maxRecipientsPerMessage |
QURL_SMTP_MAX_RECIPIENTS_PER_HOUR | smtp.maxRecipientsPerHour |
QURL_PUBLIC_VIDEO_FILE_PATH | publicVideo.filePath |
QURL_PUBLIC_VIDEO_TITLE | publicVideo.title |
QURL_PUBLIC_VIDEO_PAGE_PATH | publicVideo.pagePath |
QURL_API_KEY は意図的に環境変数のみで設定でき、設定ファイル用のフィールドはありません。 | |
SMTP のシークレットにも QURL_SMTP_PASSWORD を使用することを推奨します。POSIX ホストで smtp.password を設定ファイルに保存する場合は、ファイルのアクセス権を所有者のみに制限してください(例:chmod 600)。グループまたはその他のユーザーに読み取り権限がある場合、起動時に警告が表示されます。このチェックは意図的に助言のみを目的としており、アップグレード後に既存のデプロイが失敗することはありません。また、Windows では POSIX のアクセス権ビットを利用できないため、このチェックはスキップされます。 | |
メール配信は、smtp.allowedRecipients の完全一致するエントリー、または smtp.allowedRecipientDomains のエントリーが少なくとも 1 つ設定されていない限り、フェイルクローズとなります。このポリシーが設定されていない場合、SMTP 認証情報がすべて揃っていると起動時に警告が表示されます。 |
maxUploadFileDataBytes を引き上げると、HTTP JSON パーサーのリクエストごとのメモリ上限も、この値の約 1.5 倍に引き上げられます(上限の 100 MB では約 150 MB)。その後、Base64 のデコード時に正確なバイト数の上限が適用されます。セッションで下流の qURL API 呼び出しが正常に完了するまでは(アップロード完了後のリンク発行も完了に含まれます)、パーサーの上限は小さい方のデフォルトアップロード設定である 10 MB のままです。最初のアップロードにより大きなサイズを設定するクライアントは、先に小さな qURL API 呼び出しを行うか、より小さなファイルをアップロードしてセッションを検証する必要があります。
設定する最大サイズとリバースプロキシの同時実行数の上限は、あわせて調整してください。
stdio モードで qURL API を使用するには、環境変数に QURL_API_KEY を設定してください。設定しない場合、stdio モードはローカルの qURL CLI を使用するため、アカウントは不要です(クイックスタートを参照してください)。HTTP モードでは、各クライアントリクエストで、独自の qURL API キーをベアラートークンとして指定します。
defaultQurlApiUrl と QURL_API_URL では、ループバック以外のホストに HTTPS が必要です。qURL API キーとデータが、その宛先にベアラー認証付きで送信されるためです。平文の HTTP が許可されるのは、リテラルなループバック開発用エンドポイントのみです。アップロードコネクターの URL にも、同じ HTTPS(ループバックを除く)の規則が適用されます。
ループバックとは 127.0.0.0/8 または ::1 を指します。0.0.0.0 や :: などのワイルドカードバインドアドレスは、外向き HTTP の宛先として意図的に許可されていません。コネクターの宛先は、呼び出し元からの入力ではなく、信頼された運用者の設定です。そのため、プライベートアドレスと DNS 解決は許可されます。デプロイ環境の DNS でコネクターのホスト名を固定し、メタデータサービスを宛先に指定しないでください。呼び出し元の qURL ベアラー認証情報はこのホストに転送されるため、コネクターの URL と DNS の管理は、認証情報の信頼境界の一部として扱ってください。
アップロード用ルートではなく、コネクターサービスのベース URL を設定してください。qurl-mcp は通常のベースパスに /api/upload を追加し、このエンドポイントに完全一致するサフィックスを受け入れます。また、/upload や /api/upload/v2 など、曖昧なアップロード形式のパスは拒否します。
MCP サーバーが行うのは、ファイルのフレーミングに関する限定的なチェックであり、メディアの完全な解析ではありません。コネクターは、アップロードされたコンテンツを保存または配信する前に、独自に再検証する必要があります。また、配信時には、信頼できる型判定の境界として nosniff の動作を維持してください。
API とコネクターのベース URL に埋め込み認証情報、クエリ文字列、またはフラグメントが含まれている場合、起動時に拒否されるようになりました。以前にこうした特殊な形式の URL を使用していたデプロイでは、認証情報を QURL_API_KEY に移し、設定するサービス URL はオリジンと任意のパスプレフィックスに限定してください。
SMTP の設定
| フィールド | 目的 |
|---|---|
smtp.host | SMTP サーバーのホスト名 |
smtp.port | SMTP サーバーのポート |
smtp.secure | 暗黙的な TLS の場合は true、必須の STARTTLS の場合は false |
smtp.username | SMTP ログインのユーザー名 |
smtp.password | SMTP ログインのパスワードまたはアプリ固有のコード |
smtp.fromEmail | 送信者のメールアドレス |
smtp.fromName | 送信者の表示名 |
smtp.allowedRecipients | 任意で指定する、完全一致の許可リスト |
smtp.allowedRecipientDomains | 任意で指定する、完全一致のドメイン許可リスト(サブドメインは含まれません) |
smtp.maxRecipientsPerMessage | 1 メッセージあたりの受信者数の上限(デフォルトは 10) |
smtp.maxRecipientsPerHour | qURL キーごとの固定 1 時間枠における送信試行受信者数の上限(デフォルトは 100) |
次のようなツールでメール配信がリクエストされた場合、これらの設定が使用されます。
create_qurlmint_linkupload_text_qurlupload_file_qurlupload_file_data_qurlいずれかの宛先許可リストが設定されている場合、一致するアドレスまたはドメインが完全一致した場合にのみ配信されます。両方とも空の場合でも、メッセージ数と時間あたりの上限は適用されます。 ドメインのエントリーは完全一致です。example.comを指定してもmail.example.comは暗黙的に許可されないため、許可するサブドメインはそれぞれ明示的に登録してください。 比較と配信の前に、アドレスとドメインは小文字の NFC/IDNA ASCII 形式に正規化され、末尾の DNS ルートドットは削除されます。 各宛先許可リストに設定できるエントリーは最大 1,000 件です。メッセージあたりの宛先上限は、許可リストによるフィルタリングの前に、要求された配信先全体の重複を除いた件数に適用されるため、ブロックされるアドレスを使って過大なバッチを送信することはできません。 HTTP モードでは、有効な qURL API キーを持つ呼び出し元なら誰でも、サーバー側の SMTP 配信を要求できます。インターネットに公開する HTTP デプロイメントで SMTP を有効にする前に、allowedRecipientsまたはallowedRecipientDomainsを設定してください。許可リストが空の場合、クォータの範囲内で、構文上有効な任意のアドレスへの配信が許可されます。 SMTP トランスポートには上限付きの接続/ソケットタイムアウトが設定され、配信バッチごとに閉じられます。一時的な障害で配信数がゼロになった場合も含め、SMTP の試行失敗もクォータを消費するため、失敗を繰り返して不正利用の上限を回避することはできません。 各配信リクエストには、合計 60 秒の期限も設定されています。この期限までに処理が開始されなかった宛先はスキップとして報告されます。より大規模な配信や時間のかかる配信には、プロバイダー側のキューを利用してください。 トランスポートの暗号化は必須です。smtp.secure: trueは暗黙的 TLS を使用し、smtp.secure: falseの場合は STARTTLS へのアップグレードが正常に完了する必要があります。ポート 465 は暗黙的 TLS 用に予約されているため、smtp.secure: trueが必要です。 時間あたりのクォータの状態はサーバープロセスごとに管理されます。再起動するとリセットされ、レプリカ間では共有されません。複数のインスタンスを運用する場合は、SMTP プロバイダーまたはゲートウェイで、それに対応する合計上限を適用してください。 したがって、プロセス内クォータは不正利用を防ぐための最後の手段であり、永続的なグローバル安全境界ではありません。再起動やスケールアウト時に制限が機能しなくなる挙動については、プロバイダー側の上限で対処する必要があります。 1 つのプロセスで保持されるプリンシパルが 10,000 件に達すると、新しいプリンシパルの追跡はフェイルクローズとなります。既存のプリンシパルは、期限切れのエントリーが削除されるまで、現在のバケットを引き続き使用します。 qURL API キーの発行を制限し、新しいプリンシパルのクォータ上限による拒否を監視してください。有効なキーを多数切り替えると、共有テーブルを最大 1 クォータ期間にわたって意図的に容量上限に保つことができます。 クォータでは固定の 1 時間ウィンドウが使用され、直前のウィンドウの期限が切れた後、最初の配信試行時に新しいウィンドウが始まります。 固定ウィンドウでは、境界の直前と直後のトラフィックの合計が、設定した時間あたりの上限のほぼ 2 倍になることがあります。レプリカ間で境界付近の急増を防ぐ必要がある場合は、プロバイダー側のスライディング制限またはローリング制限を使用してください。
HTTP SMTP 配信は、QURL_API_KEY で設定された運用者の認証情報に限定されます。別の顧客が有効な qURL キーを持っていても、運用者の SMTP アカウントの使用は許可されません。この運用者キーを明示的に設定しない場合、HTTP によるメール配信は無効です。stdio では、ローカルの運用者信頼モデルが維持されます。どちらのモードでも、宛先許可リストとクォータが適用されます。
生成された qURL リンクは、メール本文のプレーンテキストに含まれます。リンクの機密性が重要な場合は、SMTP の許可リストで宛先を制限し、SMTP サーバー/プロバイダーでトランスポート暗号化を設定してください。
SMTP の認証情報とポリシーには、環境変数を使用することを推奨します。
QURL_SMTP_USERNAME、QURL_SMTP_PASSWORD、QURL_SMTP_FROM_EMAIL、
QURL_SMTP_ALLOWED_RECIPIENTS、QURL_SMTP_ALLOWED_RECIPIENT_DOMAINS、
QURL_SMTP_MAX_RECIPIENTS_PER_MESSAGE、および
QURL_SMTP_MAX_RECIPIENTS_PER_HOUR。
公開動画ページの設定
| フィールド | 目的 |
|---|---|
publicVideo.title | 公開動画ページに表示するタイトル |
publicVideo.pagePath | 動画再生ページの公開パス |
publicVideo.filePath | MP4 ファイルのサーバー上の絶対パス |
設定すると、HTTP サーバーはさらに次のものを公開します。
- 公開動画再生ページ
- MP4 ファイルのストリーミングエンドポイント
publicVideo.filePath は、信頼されたオペレーター設定です。最後のパス要素はシンボリックリンクではない通常の .mp4 ファイルである必要があります。中間ディレクトリのシンボリックリンクは通常のファイルシステム解決を維持するため、オペレーターの管理下に置く必要があります。起動時にこの任意のアセットを検査し、存在しない場合、空の場合、または通常のファイルでない場合は警告しますが、MCP サービスと /healthz は引き続き利用可能にします。動画ファイルのルートは、アセットが修正されるまで引き続き安全側に倒して 404 を返します。
qurl-mcp.http.json リファレンス
ローカルで状態を保持する開発には、qurl-mcp.http.example.json を使用してください。qurl-mcp.http.stateless.example.json には、デプロイ済みのステートレスサービスに必要なすべてのストアおよびメトリクスのフィールドが示されています。
| フィールド | 目的 |
|---|---|
port | HTTP MCP リスナーのポート |
host | HTTP MCP のバインドアドレス |
baseUrl | サービスの公開ベース URL |
allowedHosts | Host ヘッダー検証用のホスト許可リスト |
trustProxyHops | 信頼するリバースプロキシの正確なホップ数(デフォルト 0) |
stateless | セッションアフィニティのない、リクエストスコープの HTTP トランスポート(デフォルト false) |
maxConcurrentRequests | プロセスごとのステートレス POST/パーサーの同時実行数上限(デフォルト 20) |
credentialRateLimitStore | 認証情報カウンターのバックエンド:memory または dynamodb(デフォルト memory) |
rateLimitDynamoDbTable | 共有認証情報カウンターに使用する DynamoDB テーブル |
metricsNamespace | ステートレスサービスの飽和度メトリクス用 CloudWatch EMF 名前空間 |
metricsService | 安定した CloudWatch EMF Service ディメンション |
metricsEnvironment | 安定した CloudWatch EMF Environment ディメンション |
maxSessions | 有効な MCP セッション数の上限(デフォルト 1000) |
maxSessionsPerCredential | ベアラーごとの有効および初期化中のセッション数の上限(デフォルト 20) |
maxUnvalidatedSessions | 下流の qURL API 呼び出しが完了していないセッション数の上限(デフォルト 100) |
sessionIdleTtlMs | 接続済みセッションのアイドル状態による削除期間(デフォルト 15 分) |
sessionAbsoluteTtlMs | アクティブな SSE/ツールリクエストを含むセッションの絶対有効期間(デフォルト 24 時間) |
unvalidatedSessionTtlMs | 検証が一度も行われていないベアラーセッションの絶対検証期限(デフォルト 1 分) |
mcpRateLimitPerMinute | クライアントごとの /mcp リクエスト制限(デフォルト 120) |
publicFileRateLimitPerMinute | クライアントごとの公開ルートリクエスト制限(デフォルト 300) |
HTTP フィールドには、対応する環境変数による上書き設定があります。
| Environment variable | Config field |
|---|---|
MCP_PORT | port |
MCP_HOST | host |
MCP_BASE_URL | baseUrl |
MCP_ALLOWED_HOSTS | allowedHosts |
MCP_TRUST_PROXY_HOPS | trustProxyHops |
MCP_HTTP_STATELESS | stateless |
MCP_MAX_CONCURRENT_REQUESTS | maxConcurrentRequests |
MCP_CREDENTIAL_RATE_LIMIT_STORE | credentialRateLimitStore |
MCP_SERVE_LAYERV_LEGAL_PAGES | serveLayerVLegalPages (default false) |
MCP_RATE_LIMIT_DYNAMODB_TABLE | rateLimitDynamoDbTable |
MCP_METRICS_NAMESPACE | metricsNamespace |
MCP_METRICS_SERVICE | metricsService |
MCP_METRICS_ENVIRONMENT | metricsEnvironment |
MCP_MAX_SESSIONS | maxSessions |
MCP_MAX_SESSIONS_PER_CREDENTIAL | maxSessionsPerCredential |
MCP_MAX_UNVALIDATED_SESSIONS | maxUnvalidatedSessions |
MCP_SESSION_IDLE_TTL_MS | sessionIdleTtlMs |
MCP_SESSION_ABSOLUTE_TTL_MS | sessionAbsoluteTtlMs |
MCP_UNVALIDATED_SESSION_TTL_MS | unvalidatedSessionTtlMs |
MCP_RATE_LIMIT_PER_MINUTE | mcpRateLimitPerMinute |
MCP_PUBLIC_FILE_RATE_LIMIT_PER_MINUTE | publicFileRateLimitPerMinute |
MCP_MAX_UPLOAD_FILE_DATA_BYTES | maxUploadFileDataBytes (shared) |
リスナーのデフォルトは 127.0.0.1 です。allowedHosts が明示的に設定されていない場合、ループバック以外の host は拒否されます。信頼するプロキシのホップ数を正確に trustProxyHops(または MCP_TRUST_PROXY_HOPS)に設定してください。直接接続の場合は 0 のままにし、転送された IP ヘッダーでレート制限キーを偽装できないようにします。リクエスト時の検証を、異常な運用者設定のもとでも確実に有限時間内に完了できるよう、Host 許可リストのエントリー数は 1,000 件に制限されています。
/mcp では、設定されたリクエスト許容量が、クライアント IP と認証済みベアラーの SHA-256 ダイジェストの両方に個別に適用されます。メモリストアはプロセス内でのみ有効です。DynamoDB ストアでは、認証情報のダイジェストと UTC の分をキーとするアトミックな固定ウィンドウカウンターを使用します。ベアラーは保存されません。他の固定ウィンドウ方式と同様に、分の境界付近では、リクエスト数が設定された許容量のほぼ 2 倍に達する場合があります。テーブルの仕様では、パーティションキーの名前を rate_key とし、型を文字列にします。アトミック更新では、数値の request_count カウンターと、数値の expires_at TTL タイムスタンプを書き込みます。期限切れの行が蓄積しないよう、expires_at で DynamoDB TTL を有効にしてください。TTL は非同期のクリーンアップをスケジュールするだけであり、有効なウィンドウは物理削除ではなく、キー内の分によってリセットされます。タスクロールには、起動時の dynamodb:DescribeTable と、リクエスト処理時の dynamodb:UpdateItem が必要です。オンデマンドキャパシティを使用するか、想定されるフリート全体のリクエストレートに十分な書き込みキャパシティをプロビジョニングしてください。スロットリングが発生した場合はフェイルクローズで 503 を返し、メモリにはフォールバックしません。クライアントは標準のリトライモードを使用し、試行回数は最大 2 回、接続タイムアウトは 1 秒、リクエストタイムアウトは 2 秒で、タイムアウト時には例外をスローします。これらの明示的な上限により、ストアの部分的な障害中にリクエストが並行処理許可を保持する時間を制限します。オプションの AWS SDK 依存関係には、トップレベルで完全一致のバージョンが固定されています。また、コミット済みのパッケージロックファイルで、推移的な @aws-sdk/* および @smithy/* の依存関係グラフも固定されています。SDK を更新する場合は、ロックファイルも更新し、実際の NodeHttpHandler を使ったタイムアウト実体化の回帰テストをパスさせる必要があります。この依存関係が読み込まれるのは、DynamoDB ストアが選択された場合のみです。そのため、stdio のみを使用する場合は --omit=optional を指定してインストールできます。デプロイする HTTP イメージには、オプションの依存関係を含める必要があります。SDK がない場合、またはランタイムサーフェスに互換性がない場合は、リスニング開始前に起動が失敗します。クライアントは標準の AWS_REGION と認証情報プロバイダーチェーンを使用します。ECS デプロイでは、通常、タスク環境とタスクロールから両方が取得されます。リバースプロキシ経由でデプロイする場合は、正しいホップ数を設定してください。設定しないと、プロキシの背後にいるすべての呼び出し元が、プロキシの単一の IP バケットを共有します。フリート全体で共有されるのは DynamoDB の認証情報クォータのみです。IP リミッターはプロセス内でのみ有効なため、フリート全体での実効許容量はタスク数に応じて増加し、共有エッジ制限で補完する必要があります。qurl-integrations-infra PR #1305 のマネージドデプロイでは、送信元 IP ごとの WAF 制限と、より低い /mcp のフリート全体の上限の両方が適用されます。稼働中の余裕の検証は issue #1306 で追跡されています。認証情報バケットは、送信元 IP を切り替えても、1 つのキーがリクエスト許容量を回避できないようにします。また、maxSessionsPerCredential により、そのキーがセッションプール全体を占有することも防ぎます。個別のベアラー値ごとに、現在の 1 分間のウィンドウで認証情報バケットのエントリーが 1 つ保持されます。IP リミッターは先に実行されるため、1 つの送信元からのトークンローテーションによって、mcpRateLimitPerMinute より速くエントリーが作成されることはありません。悪意のある分散トラフィックへの対策には、ドキュメントに記載された共有エッジ制限が引き続き必要です。検証されていないベアラー文字列はそれぞれ別の認証情報バケットを占有するため、任意のベアラーのローテーションに対するプロセス内の主な防御手段は IP バケットです。
ステートフルモードでは、保留中セッションのパーサーメモリとして、maxUnvalidatedSessions に、およそ 1.5 倍した maxUploadFileDataBytes と 10 MB の小さいほうを掛けた量(さらにリクエストごとに約 64 KiB)を見込んでください。デフォルト設定では、理論上の同時使用量の上限は約 1.5 GiB です。デプロイ環境のメモリ予算がこれより小さい場合は、maxUnvalidatedSessions と共有エッジ同時実行数の上限を併せて引き下げてください。
ベアラー認証情報が有効かどうかは、最初の downstream qURL API 呼び出しの成功によって確定します。それまでは、セッションに対してより小さい保留セッション上限と 1 分間の検証期限が適用されるため、任意の空でないベアラー文字列が通常の 15 分の TTL の間、セッションプール全体を占有することはできません。MCP のイントロスペクションのみを行うクライアントは、設計上、保留状態のままです。期限後に削除された場合は、次のリクエストの前に再初期化する必要があります。イントロスペクションからツール呼び出しまでの間隔が長いクライアント向けに、セッション上限と検証期限を設定できます。期限は絶対的なものであり、オープン中の SSE ストリームや長時間実行される最初のツール呼び出しを含め、アクティビティの有無にかかわらず適用されます。検証済みのクライアントが DELETE /mcp を送信せずに切断した場合、セッションスロットは 30 秒間の再接続猶予期間中、上限のある状態で保持されます。再接続すると期限が解除されます。それ以外の場合、より長いアイドル TTL を待たずにセッションが削除されます。接続を維持していても明示的なセッション終了を行わないクライアントに合わせて、maxSessions とアイドル TTL のサイズを設定してください。
検証済みのセッションも、アクティブな SSE ストリームやツールリクエストの最中であっても、sessionAbsoluteTtlMs(デフォルトでは 24 時間)で期限切れになります。これにより、キープアライブによってグローバルまたは認証情報ごとのセッションスロットが無期限に占有されるのを防ぎます。
そのため、最初の downstream qURL 操作は、この期限までに完了する必要があります。最初の API 呼び出しが異常に遅い場合は中断されることがあり、クライアントは再初期化する必要があります。このフェイルクローズの動作により、無効な認証情報が意図的に長時間実行されるリクエストを使って保留スロットの期限を延長するのを防ぎます。
未検証セッションの上限に達している場合、新しい初期化によって最も古いアイドル状態の未検証セッションが置き換えられるため、不正なハンドシェイクによってすべてのスロットが検証 TTL の間ずっと占有されることはありません。検証済みセッションとアクティブなリクエストは削除されず、保留中の初期化と非同期の終了処理にも上限があります。継続的なトラフィックによって未検証セッションが入れ替わり続ける可能性はあるため、パブリック環境ではステートレスモードとエッジでのアクセス制御を使用してください。
MCP の初期化時に空でないベアラーを受け入れるのは意図的な仕様です。これにより、最初の qURL 操作より前でもプロトコルのイントロスペクションを利用できる一方、グローバルセッション上限、認証情報ごとのセッション上限、保留中のセッション上限、絶対期限、リクエストレート制限によって、無効なキーによるスロットの使用が制限されます。MCP ミドルウェア自体はキーを検証しません。セッションが昇格するのは、後続の qURL API から正常な応答が返された場合のみです。
認証済みに見える非 2xx 応答を含め、後続処理からエラーが返された場合、セッションは昇格しません。仲介者が qURL API によるベアラーの認証前にエラーを生成した可能性があるためです。
したがって、セッションの昇格は、設定された HTTPS qURL API エンドポイントと、すべての信頼できる仲介者が、認証済みの成功応答をキャッシュまたは生成しないことを前提としています。その経路上のリバースプロキシは、qURL API のトラフィックについて認証情報を転送し、応答のキャッシュを無効にする必要があります。
そのため、空でないベアラーを持つ呼び出し元であれば誰でも、公開されているツール/リソース/プロンプトのカタログを列挙し、上限付きの保留中セッション状態を短時間保持できます。悪意のあるネットワーク上では、ループバック以外のデプロイメントを、/mcp の認可に使用する呼び出し元の qURL ベアラー認証情報を保持する、ID を認識するプロキシの背後に配置してください。
初期化とカタログ一覧の取得で返されるのは、サーバーが保持する静的メタデータのみです。ツール/リソース/プロンプトのハンドラーを呼び出したり、ホスト上のファイルを読み込んだり、qURL API やコネクターに接続したり、メールを送信したりすることはありません。ハンドラーの呼び出しでは、データの返却や操作の実行前に、設定された qURL API が転送されたベアラーを認証することを前提としています。設定されたコネクターは第 2 の認証情報の検証主体です。アップロードされたバイト列を受け入れたり保存したりする前に、転送された qURL ベアラーを認証する必要があります。認証されていないコネクターのデプロイメントはサポートされません。未検証の MCP 呼び出し元がコネクター側の状態を作成できてしまうためです。
ステートフルモードは互換性を保つためのデフォルトであり、既存の MCP セッションレジストリ、GET SSE、明示的な DELETE の動作、および 3 つすべての MCP メソッドに対するプロセス内の認証情報クォータ課金を維持します。ステートレスモードでは POST ごとにサーバーとトランスポートを作成して終了し、mcp-session-id を無視し、GET と DELETE に対して JSON-RPC 形式の 405 応答を返します。プロセス内アフィニティに依存するリクエストがないため、ロードバランサーまたは自動スケーリングサービスの背後では、このモードが必須です。同時実行許可は JSON の解析前に取得され、すべての応答/エラー/切断の経路で解放されます。ステートレスモードでは、解析前の同時実行許可によってメモリ増幅が抑制されるため、設定された maxUploadFileDataBytes の解析上限を直接使用します。プロセスごとのメモリ量は、おおよそ maxConcurrentRequests に(maxUploadFileDataBytes の 1.5 倍と 64 KiB を足した値)を掛けた値を見込んでください。アップロード上限が 100 MB の場合、デフォルトの同時実行数では、後続処理の前に約 3 GiB が必要です。保守的に見積もった解析用メモリ量が 4 GiB を超える設定では、ステートレスモードの起動が拒否されます。ECS タスクのメモリ上限がこれより小さい場合は、いずれかの設定値をさらに下げてください。一方、デフォルトの上限を超えるステートフルセッションでは、まず後続の qURL API 呼び出しを成功させる必要があります。
悪意のあるネットワーク上では、認証済みのエッジでのリクエストサイズ制限を、設定された解析上限以下にすることがデプロイメントの要件です。許可によってメモリの合計量は制限されますが、空でないベアラーが正式に検証されるのは、解析された操作が後続の qURL API に到達した後です。
ステートレスリスナーでは、ヘッダーの受信時間が15秒、リクエスト全体の受信時間とソケットのアイドル状態の存続時間がそれぞれ120秒に制限されます。同時実行許可は解析からレスポンスの完了まで保持されるため、停止したクライアントが許可プール全体を無期限に占有することはありません。120秒間ソケット通信が発生しないツール呼び出しは意図的に中断されます。無通信状態がより長く続く処理を必要とする連携では、このフリート全体の保持時間上限を引き上げるのではなく、その処理を非同期 API の背後に移してください。
デプロイ済みの(ループバック以外の)ステートレスモードでは、DynamoDB 認証情報ストアと、3つすべての安定したメトリクス ID フィールドが必須です。30秒間隔の EMF ハートビートを出力します。McpConcurrencyUtilization は、その間隔中にリクエスト受付時とハートビート時に観測された許可の使用率のピーク値です(ハートビートの間に開始して完了するリクエストも含みます)。一方、McpConcurrencyRejected と McpRateLimitStoreErrors は、明示的なゼロを含む、スナップショット取得後にゼロへ戻す間隔ごとの差分です。セッション上限とメール受信者のクォータはインメモリです。DynamoDB の認証情報クォータはフリート全体に適用され、初期化、検出、ツール呼び出しを含む、認証済みのすべての HTTP POST をカウントします。そのため、ツール呼び出しだけでなく、想定されるリクエストパターン全体に合わせてクォータを設定してください。許可は、上限付きの DynamoDB インクリメント処理中も保持されます。ストアの障害時には、許可された各リクエストが失敗するまで約4秒(2秒の試行を2回)許可を1つ保持する場合がありますが、超過したリクエストには高速の同時実行 503 が返されます。固定ウィンドウカウンターは、認証情報の上限をすでに超えている試行も含め、すべての試行でインクリメントされます。そのため、エッジのレート制限と DynamoDB の書き込み/スロットリングアラームによって、悪意ある書き込み増幅を抑える必要があります。
デプロイ担当者は、両方のアラームと、上限超過時の書き込み増幅プローブを、任意のオブザーバビリティとして扱うのではなく、昇格の必須条件にしてください。
qurl-integrations-infra#1305 のマネージドデプロイでは、これらのアラームがプロビジョニングされます。昇格前のライブ検証は、同デプロイのロールアウト台帳と issue #1306 で追跡されています。
認証情報ストアの実装を注入する createHttpRuntime の直接の埋め込み側でも、ループバック以外のステートレスモードでは credentialRateLimitStore: "dynamodb" を宣言する必要があります。汎用の注入インターフェースでは、カスタムバックエンドがレプリカ間で共有されていることを証明できないため、意図的に、注入をデプロイ要件の抜け道として利用できないようにしています。
ステートフルモードではメトリクス ID フィールドを拒否し、同時実行ゲージが誤解を招くゼロを暗黙に報告しないようにしています。
ステートレスの各 POST では、新しい MCP サーバーとトランスポートを用意し、あるリクエストが別の認証情報のハンドラー状態を引き継がないようにします。レスポンス完了後のティアダウンは非同期で追跡されます。その処理待ちが maxConcurrentRequests に達すると、新たな受付を停止します。その時点ですでに処理中のリクエストは完了できるため、処理待ちは一時的にその数の2倍近くになる場合がありますが、上限内に収まります。受付ガードが閉じている間、新しいリクエストには 503 が返され、ティアダウンによるメモリ使用量が無制限に増える代わりに McpConcurrencyRejected がインクリメントされます。このカウンターは、処理中のリクエストの飽和とティアダウンのバックプレッシャーのどちらによる場合も、意図的に受付失敗を表します。オートスケーリングには McpConcurrencyUtilization のみを使用してください。拒否カウンターは引き続きページ通知の対象とし、使用率が低いのに拒否が発生している場合は、ティアダウンの遅延を示します。
これらのオブジェクトをプールするとリクエストの分離性が損なわれるため、登録処理の負荷が計測されていない限り、パフォーマンス最適化として採用しないでください。
/healthz と公開動画ファイルエンドポイントは、それぞれ独立した publicFileRateLimitPerMinute バケットを使用します。これらのバケットは、法律関連ページや動画ページへのトラフィック、および互いのトラフィックから分離されています。ロードバランサー、ライブネスプローブ、想定される動画のレンジリクエストの頻度は、ソース IP ごとの上限(デフォルトでは1分あたり300リクエスト)を下回るようにしてください。通常より頻度の高いクライアントを使用する場合は、上限を引き上げてください。
設定の優先順位
デフォルトでは、設定は前述の 2 つのローカル JSON ファイルから読み込まれます。
ファイルが存在しない場合は、組み込みのデフォルト値と環境変数が使用されます。
デフォルトを含む相対パスの設定ファイルは、プロセスの作業ディレクトリを基準に解決されます。
スーパーバイザー、npx、または MCP ホストが別のディレクトリからサーバーを起動する場合は、以下の明示的なパス変数を設定してください。
以下の環境変数は、それぞれ独立して設定ファイルのパスを上書きします。
QURL_MCP_CONFIGQURL_MCP_HTTP_CONFIG
QURL_MCP_HTTP_CONFIG が共有ランタイム設定のパスを置き換えることはありません。
これにより、リスナー設定が SMTP、コネクター、または API の設定を意図せず上書きすることを防ぎます。
server.json と smithery.yaml は公開されている stdio トランスポートについて記述しているため、共有のアップロード/SMTP 設定を含みますが、QURL_MCP_HTTP_CONFIG や MCP_MAX_SESSIONS など、HTTP 専用のリスナー変数は意図的に含めていません。
API キー、SMTP 認証情報、または非公開のファイルシステムパスをコミットしないでください。
HTTP ルート
http モードで起動すると、共通ルートは次のとおりです。
| ルート | 用途 |
|---|---|
/mcp | メインのリモート MCP エンドポイント |
/healthz | ヘルスチェックエンドポイント |
/legal/privacy | 公開プライバシーポリシーページ |
/legal/terms | 公開利用規約ページ |
publicVideo.pagePath | 公開動画再生ページ |
publicVideo.pagePath + /file | MP4 ストリーミングエンドポイント |
/healthz はすべての呼び出し元に対して意図的に認証不要かつ Host 検証対象外となっており、{ "ok": true } のみを公開します。また、ヘルスプローブが法務/動画ルートの許容量を消費しないよう、設定済みの公開ルート用リクエスト制限を別のバケットで使用します。このルートからの 429 は、プローブ元が publicFileRateLimitPerMinute を超過したことを意味し、アプリケーションの稼働状態チェックに失敗したということではありません。プローブの頻度はこの制限を下回るようにしてください。ALB のターゲットプローブではタスクの IP アドレスとポートが Host として使用されるため、このルートは Host 検証より前に登録されます。公開 MCP ルートとブラウザールートでは、引き続き Host 検証が行われます。
HTTP 認証
/mcp エンドポイントでは、すべてのリクエストに Authorization: Bearer <qURL API key> が必要です。ステートフルモードでは、ベアラートークンは確立された MCP セッションに紐付けられるため、セッション ID を別の認証情報で再利用することはできません。ステートレスモードでは、ベアラーはリクエスト単位で扱われ、レスポンスが閉じると破棄されます。
オペレーター認証の境界: 初期化時には、空でない任意のベアラートークンが受け付けられ、最初の下流 qURL API 呼び出しで正式に検証される前に、公開ツール/リソース/プロンプトのカタログを読み取れます。このカタログは静的なスキーマと説明から構成され、ベアラートークン、SMTP 認証情報、その他のオペレーター設定は含まれません。未検証セッションの上限、短い検証期限、リクエストのレート制限によって、検証前の状態を制限します。提供されたトークンは、設定された qURL API と、アップロードツールの場合は設定された qURL Connector にのみ転送されます。イントロスペクションのみを行うセッションは未検証のままなので、unvalidatedSessionTtlMs で閉じられます。より長期間セッションを維持する必要があるクライアントは、再初期化できます。セッションが昇格するのは、qURL API の呼び出しが成功した場合、または設定されたコネクターを介して配信可能なアップロードリンクが発行された場合(このコネクターはベアラーを qURL API に転送します)に限られます。拒否された呼び出しやレート制限された呼び出しでは、認証情報の有効性は証明されません。そのため、コネクターもこの信頼境界の一部です。QURL_CONNECTOR_URL には、ベアラーを認証するコネクターのみを指定してください。アップロード時のエラーテキスト(1 KiB 以内に制限され、制御文字は平坦化されます)と発行されたリンクはエージェントに返され、発行されたリンクはメールで送信される場合があります。切断されたセッションは、SSE 再接続のための猶予期間である 30 秒間、登録された状態を維持します。maxSessions と maxSessionsPerCredential により、接続の頻繁な切り替え時にもこの許容量を制限します。
Origin ヘッダーがないリクエストは、ブラウザー以外の MCP クライアントからのリクエストとして受け付けられます。Origin がある場合は、baseUrl のオリジンと一致する必要があります。不正な値またはクロスオリジンの値は /mcp で拒否されます。公開ヘルス、法的文書、設定済みの動画ルートではブラウザーのオリジン状態を使用しないため、このチェックの対象外です。
リモート MCP クライアントは、次のように設定してください。
| 設定 | 値 |
|---|---|
| MCP サーバー URL | 公開 HTTPS URL に /mcp を追加したもの |
| 認証 | ベアラートークン |
| トークン | 呼び出し元の qURL API キー |
クライアントが OAuth ディスカバリーにしか対応していない場合は、認証なしで /mcp を公開するのではなく、このサーバーの前段に OAuth 対応ゲートウェイを配置してください。
デプロイの確認方法
サービスレベルの確認
まず、次を確認します。
/healthz/mcp
LayerV の法的文書は、デフォルトでは無効です。LayerV が運営するサービスのみ、MCP_SERVE_LAYERV_LEGAL_PAGES=true(または HTTP 設定の serveLayerVLegalPages: true)を設定してください。セルフホストするオペレーターは、それぞれ独自のポリシーを公開する必要があります。
公開ページの確認
有効にした場合は、法的文書のページと設定済みの動画ページを確認してください。
/legal/privacy/legal/terms- 設定済みの公開動画ページのパス
ドメインの確認
OpenAI Platform を使用する予定がある場合は、次のルートレベルのパスが存在することを確認してください。
/.well-known/openai-apps-challenge
この確認ファイルは、
/mcpの下ではなく、ドメインルートの.well-knownパスの下に配置する必要があります。
Docker
このリポジトリには、コンテナ化されたデプロイ用の Dockerfile が含まれています。
例:
docker build -t qurl-mcp .
docker run -i -e QURL_API_KEY=lv_live_xxx qurl-mcp
Docker でデプロイする場合は、コンテナから正しい設定ファイルにアクセスできることを確認するか、環境変数で設定ファイルのパスを上書きしてください。
Docker で HTTP リスナーをローカル実行する場合:
イメージのデフォルトのエントリーポイントは stdio で、HTTP サーバーのデフォルトのバインド先はコンテナ内のループバックアドレスです。HTTP でデプロイする場合は、コマンドを上書きし、明示的な Host 許可リストと HTTPS の公開オリジンを指定して 0.0.0.0 にバインドする必要があります。この例ではホストのループバックアドレスにのみポートを公開します。設定された https://mcp.example.com オリジンを使用するには、その手前に TLS リバースプロキシを配置してください。
docker run --rm -p 127.0.0.1:3000:3000 \
-e MCP_HOST=0.0.0.0 \
-e MCP_BASE_URL=https://mcp.example.com \
-e MCP_ALLOWED_HOSTS=mcp.example.com,127.0.0.1,localhost \
qurl-mcp node dist/http.js
信頼できる単一の本番用リバースプロキシの場合は、MCP_TRUST_PROXY_HOPS=1 を設定し、MCP_BASE_URL に公開 HTTPS オリジンを指定し、MCP_ALLOWED_HOSTS に公開ホスト名を設定してください。プロキシの信頼を有効にした状態で、コンテナのリスナーを直接公開しないでください。
よく使うコマンド
| コマンド | 用途 |
|---|---|
npm run build | TypeScript をコンパイルします |
npm test | テストを実行します |
npm run test:coverage | 強制適用されるカバレッジを実行します |
npm run lint | ESLint を実行します |
npm run dev | TypeScript のウォッチモード |
npm run format | ソースコードを整形します |
npm run format:check | 整形状態を確認します |
npm run start | stdio モードを起動します |
npm run start:http | HTTP モードを起動します |
推奨されるデプロイ手順
- 2 つの設定ファイルのサンプルをコピーして更新します
- 環境変数で認証情報を設定します
npm installを実行しますnpm run buildを実行しますnpm run start:httpを実行します/healthzを確認します- 認証されていない
/mcpリクエストに401が返ることを確認します - HTTPS リバースプロキシを設定します
- 認証済みの MCP 初期化と、オプションの公開ページを確認します
サードパーティのアセット
テキストから PDF を生成するため、オフラインで多言語の文字を表示できるよう、通常ウェイトの Noto Sans SC フォントを TrueType 形式(約 10 MB)でバンドルしています。静的フォントには、元の可変フォントに含まれるすべての文字が保持されています。PDFKit は各ドキュメントで使用される文字のみを埋め込みます。ダウンロードや追加のランタイム依存関係は不要です。SIL Open Font License と著作権表示は assets/fonts/OFL.txt に含まれており、変換の詳細は assets/fonts/README.md に記載されています。
ライセンス
MIT -- LayerV AI
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。