Class: Mcp::DynamicRegistrationController

Inherits:
ActionController::Base
  • Object
show all
Defined in:
app/controllers/mcp/dynamic_registration_controller.rb

Overview

Controller: dynamic registration.

Constant Summary collapse

SUPPORTED_AUTH_METHODS =

Supported auth methods.

%w[none client_secret_basic client_secret_post].freeze

Instance Method Summary collapse

Instance Method Details

#createObject



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'app/controllers/mcp/dynamic_registration_controller.rb', line 34

def create
  body = parse_json_body
  return if performed?

  redirect_uris = Array(body['redirect_uris']).reject(&:blank?)
  return render_error(:invalid_redirect_uri, 'redirect_uris required') if redirect_uris.empty?

  auth_method = (body['token_endpoint_auth_method'].presence || 'none').to_s
  unless SUPPORTED_AUTH_METHODS.include?(auth_method)
    return render_error(:invalid_client_metadata,
                        "unsupported token_endpoint_auth_method (allowed: #{SUPPORTED_AUTH_METHODS.join(', ')})")
  end
  confidential = auth_method != 'none'

  name = body['client_name'].to_s.strip.presence || "MCP Client #{SecureRandom.hex(4)}"

  app = Doorkeeper::Application.new(
    name: name,
    redirect_uri: redirect_uris.join("\n"),
    scopes: 'mcp',
    confidential: confidential
  )

  return render_error(:invalid_client_metadata, app.errors.full_messages.to_sentence) unless app.save

  response = {
    client_id: app.uid,
    client_id_issued_at: app.created_at.to_i,
    redirect_uris: redirect_uris,
    grant_types: %w[authorization_code refresh_token],
    response_types: %w[code],
    token_endpoint_auth_method: auth_method,
    scope: 'mcp',
    client_name: name
  }
  if confidential
    response[:client_secret] = app.secret
    response[:client_secret_expires_at] = 0 # 0 = never expires (RFC 7591 ยง3.2.1)
  end

  render json: response, status: :created
end