keycardai-mcp 0.1.0 → 0.1.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 598ccfb7138983e92a8e17d1b139689b313a9e7b2ebc4c0e422a47c9730f73a8
4
- data.tar.gz: 5f0828148a2565f81fa33574639418aeae0c0f64540cbda9e3e20cf7749070fe
3
+ metadata.gz: e7fc6bb3654a0b2a8e00298d2d36cd551786982bbae2404600a5d9a8d01b479f
4
+ data.tar.gz: 34c7ed0e14be12c111614ab20c7667ef5de9c2882873fbb03c1c8d951dcf5791
5
5
  SHA512:
6
- metadata.gz: 38a310adbe756ab5f33bd3989235cdaa6873cb89b5b99e18e342f56d881d032ed461c2209988f45b0952d77243631c997f401e60f85245a0a045fad031c1a8e3
7
- data.tar.gz: 63256d53e222d04096c844e371721341c44891e42bdd1dd3202ad405d216908500f658f8380a294a19236231fd639895ae25c028d710a7c1f1ddc9e46b27a6e6
6
+ metadata.gz: deefc119bca708aff1721536932f0fc9b6c09ab463e0c2c980e8702c8fec3eced345b59473956ff4cd873358d8f59ea0c4e24059fe7edb36b61e99d1c953548a
7
+ data.tar.gz: f6c15892df3b646cddbc87c6f5c02f328b4da569f190b8c54da22e4a145a3b6d20780cc0d878c662148b68cfd38eba2aba657532e7e4cd7d8fcf228b1a064959
data/CHANGELOG.md CHANGED
@@ -13,3 +13,44 @@ verification with RFC 6750 challenges, OAuth metadata endpoints (RFC 9728
13
13
  protected-resource with path insertion, an RFC 8414 authorization-server proxy,
14
14
  and JWKS), and an AuthProvider whose `grant` middleware exchanges the caller's
15
15
  token per resource into an AccessContext. Wraps no MCP SDK.
16
+
17
+ ## 0.1.1-keycardai-mcp (2026-09-16)
18
+
19
+
20
+ - fix(keycardai-mcp): retire the 2025-03-26 metadata rewrites (SDK-3) (#37)
21
+ - MetadataApp no longer rewrites authorization_servers to the request origin
22
+ for MCP-Protocol-Version: 2025-03-26 and no longer appends resource=<origin>
23
+ to the proxied authorization_endpoint. Both documents match keycard-sdk-spec
24
+ oauth-metadata-endpoints spec-version 2.
25
+ - Co-authored-by: devin-ai-keycard <devin-ai@keycard.ai>
26
+ Co-authored-by: Larry Osakwe <larry@keycard.ai>
27
+
28
+ ## 0.1.0-keycardai-mcp (2026-08-19)
29
+
30
+
31
+ - feat(keycardai-mcp): Rack bearer middleware, metadata endpoints, AuthProvider grant (#8)
32
+ - Phase 2: the MCP server integration at the Rack seam, implementing
33
+ specs/server-bearer-auth/{bearer-token-verification-middleware,
34
+ oauth-metadata-endpoints,route-level-auth-gating}.md and
35
+ specs/delegated-access/grant-decorator.md:
36
+ - - RequireBearerAuth: fail-closed Rack middleware; 401 RFC 6750
37
+ challenge with the RFC 9728 resource_metadata URL, 400 on malformed
38
+ headers, 401 invalid_token on non-bearer schemes (TS/Go position),
39
+ 403 insufficient_scope on missing required_scopes (all-of; gating is
40
+ this middleware re-applied per route, the TS/Go idiom), verified
41
+ AccessToken in the Rack env, construction error on a nil verifier
42
+ - MetadataApp: RFC 9728 protected-resource metadata with path
43
+ insertion, the 2025-03-26 MCP-version shim, RFC 8414 AS proxy with
44
+ the resource=<origin> rewrite (replace, not append), optional
45
+ /.well-known/jwks.json, permissive CORS + preflight, 502 on upstream
46
+ failure
47
+ - AuthProvider: zone + credential holder; token_verifier with
48
+ multi-zone issuers inferred from a self-describing credential;
49
+ grant(resources, user_identifier:, request_scopes:) middleware that
50
+ fails fast 401 without a verified token, never aborts on per-resource
51
+ errors, and merges stacked grants into one AccessContext;
52
+ exchange_tokens + exchange_tokens_for_zone
53
+ - Env accessors Keycardai::MCP.auth_info / .access_context
54
+ - No MCP SDK dependency, per the plan: compatibility with the official
55
+ mcp gem is proven by the phase 4 example server. Conformance suites map
56
+ to all four spec Testing tables (28 examples).
data/README.md CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  Keycard integration for MCP servers in Ruby, attached at the Rack seam.
4
4
 
5
- > **Preview.** APIs may change between minor versions while the surface settles.
6
5
  > Conformance against the cross-SDK contract is tracked in the
7
6
  > [conformance report](https://github.com/keycardai/ruby-sdk/blob/main/docs/conformance-report.md).
8
7
 
@@ -1,14 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "uri"
4
-
5
3
  module Keycardai
6
4
  module MCP
7
5
  # Rack app serving the resource server's OAuth discovery surface
8
6
  # (RFC 9728 / RFC 8414): the protected-resource metadata (with path
9
7
  # insertion for sub-path mounts), a server-side proxy of the zone's
10
- # authorization-server metadata (with the resource= rewrite shim for
11
- # pre-RFC-8707 MCP clients), and optionally the server's own public JWKS.
8
+ # authorization-server metadata (returned unmodified), and optionally
9
+ # the server's own public JWKS.
12
10
  # Responses carry permissive CORS so browser clients can read them.
13
11
  #
14
12
  # run Keycardai::MCP::MetadataApp.new(issuer: zone_url, scopes_supported: ["mcp:tools"])
@@ -16,7 +14,6 @@ module Keycardai
16
14
  PROTECTED_RESOURCE_PATH = "/.well-known/oauth-protected-resource"
17
15
  AUTHORIZATION_SERVER_PATH = "/.well-known/oauth-authorization-server"
18
16
  JWKS_PATH = "/.well-known/jwks.json"
19
- LEGACY_MCP_PROTOCOL_VERSION = "2025-03-26"
20
17
 
21
18
  # @param issuer [String] the zone's issuer URL
22
19
  # @param scopes_supported [Array<String>, nil]
@@ -46,7 +43,7 @@ module Keycardai
46
43
  when %r{\A#{Regexp.escape(PROTECTED_RESOURCE_PATH)}(/.*)?\z}
47
44
  protected_resource_response(env, Regexp.last_match(1).to_s)
48
45
  when AUTHORIZATION_SERVER_PATH
49
- authorization_server_response(env)
46
+ authorization_server_response
50
47
  when JWKS_PATH
51
48
  jwks_response
52
49
  else
@@ -68,10 +65,9 @@ module Keycardai
68
65
  # origin + /mcp.
69
66
  def protected_resource_response(env, resource_path)
70
67
  origin = RackSupport.origin(env)
71
- legacy = env["HTTP_MCP_PROTOCOL_VERSION"] == LEGACY_MCP_PROTOCOL_VERSION
72
68
  document = {
73
69
  "resource" => "#{origin}#{resource_path}",
74
- "authorization_servers" => [legacy ? origin : @issuer],
70
+ "authorization_servers" => [@issuer],
75
71
  "bearer_methods_supported" => ["header"],
76
72
  "scopes_supported" => @scopes_supported,
77
73
  "resource_name" => @resource_name,
@@ -81,32 +77,17 @@ module Keycardai
81
77
  RackSupport.json_response(document)
82
78
  end
83
79
 
84
- # RFC 8414 proxy of the zone's metadata, rewriting the
85
- # authorization_endpoint to carry resource=<origin> (replacing any
86
- # resource parameter already present in the upstream value).
87
- def authorization_server_response(env)
80
+ # RFC 8414 proxy of the zone's metadata, returned unmodified. MCP
81
+ # 2025-06-18 clients send the RFC 8707 resource parameter themselves.
82
+ def authorization_server_response
88
83
  metadata = Keycardai::OAuth.fetch_authorization_server_metadata(
89
84
  @issuer, http_client: @http_client, timeout: @timeout
90
85
  )
91
- document = metadata.raw.dup
92
- if document["authorization_endpoint"]
93
- document["authorization_endpoint"] =
94
- with_resource_param(document["authorization_endpoint"], RackSupport.origin(env))
95
- end
96
- RackSupport.json_response(document)
86
+ RackSupport.json_response(metadata.raw)
97
87
  rescue Keycardai::Error
98
88
  RackSupport.json_response({ "error" => "bad_gateway" }, status: 502)
99
89
  end
100
90
 
101
- def with_resource_param(endpoint, resource)
102
- uri = URI(endpoint)
103
- params = URI.decode_www_form(uri.query.to_s)
104
- params.delete_if { |pair| pair.first == "resource" }
105
- params << ["resource", resource]
106
- uri.query = URI.encode_www_form(params)
107
- uri.to_s
108
- end
109
-
110
91
  def jwks_response
111
92
  return RackSupport.json_response({ "error" => "not_found" }, status: 404) unless @public_jwks
112
93
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Keycardai
4
4
  module MCP
5
- VERSION = "0.1.0"
5
+ VERSION = "0.1.1"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: keycardai-mcp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Keycard