DB に保存 ② LINE 認証 confirm! GET /authorize (state=mcp_abc) 302 → LINE ログイン 303 /callback (code) GET /callback /token & /profile userId ① 認可開始 mcp_state と line_state を発行し DB で紐付 け ② LINE 認証 code → userId 取得・confirm(LINE トーク ンはサーバ内完結) ③ トークン発行 PKCE 検証 → Claude には Bearer Token の み渡す 💡 state を 2 つに分けることで Claude / LINE 両方の OAuth を橋渡し
body = JSON.parse(request.body.read) case body["method"] class McpController < ApplicationController def handle when "initialize" ... when "tools/list" ... when "tools/call" ... end end end ② JSON-RPC body を受信 POST /mcp のボディを JSON.parse method フィールドで分岐 Claude からのリクエストの入り口
User < ApplicationRecord # 何もしない — ActiveRecord だけ end class SessionsController < ApplicationController def create user = User.find_by(line_user_id: ...) session[:user_id] = user.id # ⚠️ 不審ログイン記録なし # ⚠️ 無操作タイムアウトなし end def current_user @current_user ||= User.find_by(id: session[:user_id]) end end ① User モデル ActiveRecord を継承するだけ ログイン記録・セッション失効・連続失敗ロ ックはすべてなし
user = User.find_by(line_user_id: ...) session[:user_id] = user.id # ⚠️ 不審ログイン記録なし # ⚠️ 無操作タイムアウトなし end class User < ApplicationRecord # 何もしない — ActiveRecord だけ end class SessionsController < ApplicationController def current_user @current_user ||= User.find_by(id: session[:user_id]) end end ② 認証済みユーザーの扱い session[:user_id] = user.id を手で代入 不審ログイン記録もセッション失効もなし
Rails.application.routes.draw do # OAuth エンドポイントを全部手書きでルーティング get "/oauth/authorize", to: "oauth#authorize" post "/oauth/token", to: "oauth#token" get "/oauth/callback", to: "oauth#callback" ... end ① routes.rb OAuth エンドポイントを自前定義
token を取得する class Line < OmniAuth::Strategies::OAuth2 require "omniauth-oauth2" module OmniAuth module Strategies option :name, "line" uid { raw_info["userId"] } ... end end end ① token 取得 OAuth2 親クラスが POST を自動実行 strategy 側に token 取得コードは書かない
def raw_info @raw_info ||= access_token.get("/v2/profile").parsed end def callback_url full_host + callback_path end require "omniauth-oauth2" module OmniAuth module Strategies class Line < OmniAuth::Strategies::OAuth2 end end end ② profile 取得 access_token.get でヘッダー自動付与 raw_info で結果を memoize
raw_info["userId"] } info do { name: raw_info["displayName"], image: raw_info["pictureUrl"] } end extra do { raw_info: raw_info } end require "omniauth-oauth2" module OmniAuth module Strategies class Line < OmniAuth::Strategies::OAuth2 ... ③ 認証情報の整形 uid / info / extra を strategy 側で宣言 controller には統一形式で届く
scope :mcp do get "/", to: "mcp#index" # discovery post "/", to: "mcp#handle" # JSON-RPC を case で自前分岐 get "/sse", to: "mcp#sse" # SSE も自前 end Rails.application.routes.draw do end ① ルーティング discovery / JSON-RPC / SSE を自前で用意 method 分岐は mcp#handle の case で自前
match "/mcp", to: "mcp#handle", via: [:get, :post, :delete] Rails.application.routes.draw do end ① ルーティング /mcp 1 本ですべてのリクエストを受ける method 分岐は gem の Transport 側