Class: AgentsID::MCPMiddleware

Inherits:
Object
  • Object
show all
Defined in:
lib/agentsid/middleware.rb

Overview

MCP middleware -- validates tool calls against AgentsID.

Usage:

middleware = AgentsID::MCPMiddleware.new(project_key: "aid_proj_...")

# In your MCP tool handler:
result = middleware.validate(bearer_token, "my_tool", params)

Instance Method Summary collapse

Constructor Details

#initialize(project_key:, base_url: DEFAULT_BASE_URL_MW, skip_tools: nil, on_denied: nil) ⇒ MCPMiddleware

Returns a new instance of MCPMiddleware.

Parameters:

  • project_key (String)

    Your AgentsID project key

  • base_url (String) (defaults to: DEFAULT_BASE_URL_MW)

    AgentsID server URL

  • skip_tools (Array<String>, nil) (defaults to: nil)

    Tool names to skip validation for

  • on_denied (Proc, nil) (defaults to: nil)

    Callback invoked on denial instead of raising



54
55
56
57
58
59
# File 'lib/agentsid/middleware.rb', line 54

def initialize(project_key:, base_url: DEFAULT_BASE_URL_MW, skip_tools: nil, on_denied: nil)
  @project_key = project_key
  @base_url = base_url.chomp("/")
  @skip_tools = Set.new(skip_tools || [])
  @on_denied = on_denied
end

Instance Method Details

#allowed?(token, tool) ⇒ Boolean

Quick check -- returns true/false without raising.

Parameters:

  • token (String)
  • tool (String)

Returns:

  • (Boolean)


104
105
106
107
108
109
110
111
112
113
114
# File 'lib/agentsid/middleware.rb', line 104

def allowed?(token, tool)
  result = AgentsID.validate_tool_call(
    project_key: @project_key,
    token: token,
    tool: tool,
    base_url: @base_url
  )
  result["valid"] == true && result.dig("permission", "allowed") == true
rescue StandardError
  false
end

#validate(token, tool, params = nil) ⇒ Hash

Validate a tool call. Raises on denial unless on_denied is set.

Parameters:

  • token (String)
  • tool (String)
  • params (Hash, nil) (defaults to: nil)

Returns:

  • (Hash)


67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/agentsid/middleware.rb', line 67

def validate(token, tool, params = nil)
  if @skip_tools.include?(tool)
    return { "valid" => true, "reason" => "Tool in skip list" }
  end

  result = AgentsID.validate_tool_call(
    project_key: @project_key,
    token: token,
    tool: tool,
    params: params,
    base_url: @base_url
  )

  unless result["valid"]
    reason = result["reason"] || "Unknown"
    raise TokenExpiredError.new if reason.include?("expired")
    raise TokenRevokedError.new if reason.include?("revoked")
  end

  permission = result["permission"] || {}
  if permission.any? && !permission["allowed"]
    denial_reason = permission["reason"] || "Denied"
    if @on_denied
      @on_denied.call(tool, denial_reason)
    else
      raise PermissionDeniedError.new(tool, denial_reason)
    end
  end

  result
end