actionmcp 0.72.0 → 0.80.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/app/controllers/action_mcp/application_controller.rb +20 -12
- data/app/models/action_mcp/session/message.rb +31 -20
- data/app/models/action_mcp/session/resource.rb +35 -20
- data/app/models/action_mcp/session/sse_event.rb +23 -17
- data/app/models/action_mcp/session/subscription.rb +22 -15
- data/app/models/action_mcp/session.rb +42 -119
- data/config/routes.rb +0 -13
- data/db/migrate/20250727000001_remove_oauth_support.rb +59 -0
- data/lib/action_mcp/client/streamable_http_transport.rb +1 -46
- data/lib/action_mcp/client.rb +2 -25
- data/lib/action_mcp/configuration.rb +51 -24
- data/lib/action_mcp/engine.rb +0 -7
- data/lib/action_mcp/filtered_logger.rb +2 -6
- data/lib/action_mcp/gateway_identifier.rb +187 -3
- data/lib/action_mcp/gateway_identifiers/api_key_identifier.rb +56 -0
- data/lib/action_mcp/gateway_identifiers/devise_identifier.rb +34 -0
- data/lib/action_mcp/gateway_identifiers/request_env_identifier.rb +58 -0
- data/lib/action_mcp/gateway_identifiers/warden_identifier.rb +38 -0
- data/lib/action_mcp/gateway_identifiers.rb +26 -0
- data/lib/action_mcp/server/base_session.rb +2 -0
- data/lib/action_mcp/version.rb +1 -1
- data/lib/action_mcp.rb +1 -6
- data/lib/generators/action_mcp/identifier/identifier_generator.rb +189 -0
- data/lib/generators/action_mcp/identifier/templates/identifier.rb.erb +35 -0
- data/lib/generators/action_mcp/install/install_generator.rb +1 -1
- data/lib/generators/action_mcp/install/templates/application_gateway.rb +80 -31
- data/lib/generators/action_mcp/install/templates/mcp.yml +4 -21
- metadata +13 -97
- data/app/controllers/action_mcp/oauth/endpoints_controller.rb +0 -265
- data/app/controllers/action_mcp/oauth/metadata_controller.rb +0 -125
- data/app/controllers/action_mcp/oauth/registration_controller.rb +0 -201
- data/app/models/action_mcp/oauth_client.rb +0 -159
- data/app/models/action_mcp/oauth_token.rb +0 -142
- data/db/migrate/20250608112101_add_oauth_to_sessions.rb +0 -28
- data/db/migrate/20250708105124_create_action_mcp_oauth_clients.rb +0 -44
- data/db/migrate/20250708105226_create_action_mcp_oauth_tokens.rb +0 -39
- data/lib/action_mcp/client/jwt_client_provider.rb +0 -135
- data/lib/action_mcp/client/oauth_client_provider/memory_storage.rb +0 -47
- data/lib/action_mcp/client/oauth_client_provider.rb +0 -234
- data/lib/action_mcp/jwt_decoder.rb +0 -28
- data/lib/action_mcp/jwt_identifier.rb +0 -28
- data/lib/action_mcp/none_identifier.rb +0 -19
- data/lib/action_mcp/o_auth_identifier.rb +0 -34
- data/lib/action_mcp/oauth/active_record_storage.rb +0 -183
- data/lib/action_mcp/oauth/error.rb +0 -79
- data/lib/action_mcp/oauth/memory_storage.rb +0 -132
- data/lib/action_mcp/oauth/middleware.rb +0 -128
- data/lib/action_mcp/oauth/provider.rb +0 -406
- data/lib/action_mcp/oauth.rb +0 -12
- data/lib/action_mcp/omniauth/mcp_strategy.rb +0 -162
@@ -1,162 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require "omniauth-oauth2"
|
4
|
-
|
5
|
-
module ActionMCP
|
6
|
-
module Omniauth
|
7
|
-
# MCP-specific Omniauth strategy for OAuth 2.1 authentication
|
8
|
-
# This strategy integrates with ActionMCP's configuration system and provider interface
|
9
|
-
class MCPStrategy < ::OmniAuth::Strategies::OAuth2
|
10
|
-
# Strategy name used in configuration
|
11
|
-
option :name, "mcp"
|
12
|
-
|
13
|
-
# Default OAuth options with MCP-specific settings
|
14
|
-
option :client_options, {
|
15
|
-
authorize_url: "/oauth/authorize",
|
16
|
-
token_url: "/oauth/token",
|
17
|
-
auth_scheme: :request_body
|
18
|
-
}
|
19
|
-
|
20
|
-
# OAuth 2.1 compliance - PKCE is required
|
21
|
-
option :pkce, true
|
22
|
-
|
23
|
-
# Default scopes for MCP access
|
24
|
-
option :scope, "mcp:tools mcp:resources mcp:prompts"
|
25
|
-
|
26
|
-
# Use authorization code grant flow
|
27
|
-
option :response_type, "code"
|
28
|
-
|
29
|
-
# OAuth server metadata discovery
|
30
|
-
option :discovery, true
|
31
|
-
|
32
|
-
def initialize(app, *args, &block)
|
33
|
-
super
|
34
|
-
|
35
|
-
# Load configuration from ActionMCP if available
|
36
|
-
configure_from_mcp_config if defined?(ActionMCP)
|
37
|
-
end
|
38
|
-
|
39
|
-
# User info from OAuth token response or userinfo endpoint
|
40
|
-
def raw_info
|
41
|
-
@raw_info ||= if options.userinfo_url
|
42
|
-
access_token.get(options.userinfo_url).parsed
|
43
|
-
else
|
44
|
-
# Extract user info from token response or use minimal info
|
45
|
-
access_token.token
|
46
|
-
{
|
47
|
-
"sub" => access_token.params["user_id"] || access_token.token,
|
48
|
-
"scope" => access_token.params["scope"] || options.scope
|
49
|
-
}
|
50
|
-
end
|
51
|
-
rescue ::OAuth2::Error => e
|
52
|
-
log(:error, "Failed to fetch user info: #{e.message}")
|
53
|
-
{}
|
54
|
-
end
|
55
|
-
|
56
|
-
# User ID for Omniauth
|
57
|
-
uid { raw_info["sub"] || raw_info["user_id"] }
|
58
|
-
|
59
|
-
# User info hash
|
60
|
-
info do
|
61
|
-
{
|
62
|
-
name: raw_info["name"],
|
63
|
-
email: raw_info["email"],
|
64
|
-
username: raw_info["username"] || raw_info["preferred_username"]
|
65
|
-
}
|
66
|
-
end
|
67
|
-
|
68
|
-
# Extra credentials and token info
|
69
|
-
extra do
|
70
|
-
{
|
71
|
-
"raw_info" => raw_info,
|
72
|
-
"scope" => access_token.params["scope"],
|
73
|
-
"token_type" => access_token.params["token_type"] || "Bearer"
|
74
|
-
}
|
75
|
-
end
|
76
|
-
|
77
|
-
# OAuth server metadata discovery
|
78
|
-
def discovery_info
|
79
|
-
@discovery_info ||= begin
|
80
|
-
if options.discovery && options.client_options.site
|
81
|
-
discovery_url = "#{options.client_options.site}/.well-known/oauth-authorization-server"
|
82
|
-
response = client.request(:get, discovery_url)
|
83
|
-
JSON.parse(response.body)
|
84
|
-
end
|
85
|
-
rescue StandardError => e
|
86
|
-
log(:warn, "OAuth discovery failed: #{e.message}")
|
87
|
-
{}
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
|
-
# Override client to use discovered endpoints if available
|
92
|
-
def client
|
93
|
-
@client ||= begin
|
94
|
-
if discovery_info.any? && discovery_info["authorization_endpoint"] && discovery_info["token_endpoint"]
|
95
|
-
options.client_options.merge!(
|
96
|
-
authorize_url: discovery_info["authorization_endpoint"],
|
97
|
-
token_url: discovery_info["token_endpoint"]
|
98
|
-
)
|
99
|
-
end
|
100
|
-
super
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
# Token validation for API requests (not callback flow)
|
105
|
-
def self.validate_token(token, options = {})
|
106
|
-
strategy = new(nil, options)
|
107
|
-
strategy.validate_token(token)
|
108
|
-
end
|
109
|
-
|
110
|
-
def validate_token(token)
|
111
|
-
# Validate access token with OAuth server
|
112
|
-
return nil unless token
|
113
|
-
|
114
|
-
begin
|
115
|
-
response = client.request(:post, options.introspection_url || "/oauth/introspect", {
|
116
|
-
body: { token: token },
|
117
|
-
headers: { "Content-Type" => "application/x-www-form-urlencoded" }
|
118
|
-
})
|
119
|
-
|
120
|
-
token_info = JSON.parse(response.body)
|
121
|
-
return nil unless token_info["active"]
|
122
|
-
|
123
|
-
token_info
|
124
|
-
rescue StandardError => e
|
125
|
-
log(:error, "Token validation failed: #{e.message}")
|
126
|
-
nil
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
private
|
131
|
-
|
132
|
-
# Configure strategy from ActionMCP configuration
|
133
|
-
def configure_from_mcp_config
|
134
|
-
oauth_config = ActionMCP.configuration.oauth_config
|
135
|
-
return unless oauth_config.is_a?(Hash)
|
136
|
-
|
137
|
-
# Set client options from MCP config
|
138
|
-
options.client_options[:site] = oauth_config["issuer_url"] if oauth_config["issuer_url"]
|
139
|
-
|
140
|
-
options.client_id = oauth_config["client_id"] if oauth_config["client_id"]
|
141
|
-
|
142
|
-
options.client_secret = oauth_config["client_secret"] if oauth_config["client_secret"]
|
143
|
-
|
144
|
-
options.scope = Array(oauth_config["scopes_supported"]).join(" ") if oauth_config["scopes_supported"]
|
145
|
-
|
146
|
-
# Enable PKCE if required (OAuth 2.1 compliance)
|
147
|
-
options.pkce = true if oauth_config["pkce_required"]
|
148
|
-
|
149
|
-
# Set userinfo endpoint if provided
|
150
|
-
options.userinfo_url = oauth_config["userinfo_endpoint"] if oauth_config["userinfo_endpoint"]
|
151
|
-
|
152
|
-
# Set token introspection endpoint
|
153
|
-
return unless oauth_config["introspection_endpoint"]
|
154
|
-
|
155
|
-
options.introspection_url = oauth_config["introspection_endpoint"]
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
# Register the strategy with Omniauth
|
162
|
-
OmniAuth.config.add_camelization "mcp", "MCP"
|