omni_agent 0.1.9 → 0.1.11
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/CHANGELOG.md +19 -0
- data/README.md +50 -0
- data/exe/omni_agent +22 -6
- data/lib/generators/omni_agent/agent/agent_generator.rb +1 -0
- data/lib/generators/omni_agent/install/install_generator.rb +1 -0
- data/lib/generators/omni_agent/mcp_server/mcp_server_generator.rb +155 -0
- data/lib/omni_agent/agent.rb +33 -29
- data/lib/omni_agent/configuration.rb +4 -1
- data/lib/omni_agent/engine.rb +4 -0
- data/lib/omni_agent/errors.rb +2 -0
- data/lib/omni_agent/mcp/authenticator.rb +85 -0
- data/lib/omni_agent/mcp/handler.rb +128 -0
- data/lib/omni_agent/mcp/oauth/access_token.rb +60 -0
- data/lib/omni_agent/mcp/oauth/http_client.rb +52 -0
- data/lib/omni_agent/mcp/oauth/introspection_verifier.rb +43 -0
- data/lib/omni_agent/mcp/oauth/jwt_verifier.rb +122 -0
- data/lib/omni_agent/mcp/oauth/resource_server.rb +166 -0
- data/lib/omni_agent/mcp/oauth.rb +18 -0
- data/lib/omni_agent/mcp/rack_app.rb +131 -0
- data/lib/omni_agent/mcp/request.rb +24 -0
- data/lib/omni_agent/mcp/routing.rb +57 -0
- data/lib/omni_agent/mcp/server.rb +255 -0
- data/lib/omni_agent/mcp/stdio.rb +56 -0
- data/lib/omni_agent/mcp/tool_adapter.rb +45 -0
- data/lib/omni_agent/mcp.rb +31 -0
- data/lib/omni_agent/tool.rb +25 -0
- data/lib/omni_agent/version.rb +1 -1
- data/lib/omni_agent.rb +4 -1
- data/lib/tasks/omni_agent_mcp_tasks.rake +9 -0
- metadata +18 -1
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
require "active_support/core_ext/string/inflections"
|
|
2
|
+
|
|
3
|
+
module OmniAgent
|
|
4
|
+
module MCP
|
|
5
|
+
class Server
|
|
6
|
+
TOOL_NAME_PATTERN = /\A[A-Za-z0-9_.-]{1,128}\z/
|
|
7
|
+
|
|
8
|
+
class << self
|
|
9
|
+
def server_name(value = nil)
|
|
10
|
+
@server_name = value.to_s if value
|
|
11
|
+
setting(:@server_name) || default_server_name
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def server_version(value = nil)
|
|
15
|
+
@server_version = value.to_s if value
|
|
16
|
+
setting(:@server_version) || "0.1.0"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def instructions(text = nil)
|
|
20
|
+
@instructions = text if text
|
|
21
|
+
setting(:@instructions)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def tools(*tool_classes)
|
|
25
|
+
tool_classes.flatten.each { |tool_class| tool(tool_class) }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def tool(tool_class, as: nil)
|
|
29
|
+
add_tool_declaration(type: :tool, tool_class: tool_class, name: as&.to_s)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def tools_from(*agent_classes)
|
|
33
|
+
agent_classes.flatten.each do |agent_class|
|
|
34
|
+
add_tool_declaration(type: :agent_tools, agent_class: agent_class)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def expose_agent(agent_class, as:, description: nil, run_alias: nil, forward: [])
|
|
39
|
+
unless agent_class.is_a?(Class) && agent_class <= OmniAgent::Agent
|
|
40
|
+
raise ArgumentError, "expose_agent requires an OmniAgent::Agent subclass"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
tool_class = OmniAgent::Agent.build_delegated_tool_class(
|
|
44
|
+
agent_class,
|
|
45
|
+
description: description,
|
|
46
|
+
run_alias: run_alias,
|
|
47
|
+
forward: forward
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
add_tool_declaration(type: :tool, tool_class: tool_class, name: as.to_s)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def authenticate(strategy = nil, tokens: nil, **oauth_options, &block)
|
|
54
|
+
if strategy != :oauth && oauth_options.any?
|
|
55
|
+
raise ArgumentError, "unknown keywords for authenticate: #{oauth_options.keys.map(&:inspect).join(', ')}"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
@authentication = if strategy == :oauth
|
|
59
|
+
raise ArgumentError, "authenticate :oauth does not take tokens:" unless tokens.nil?
|
|
60
|
+
|
|
61
|
+
# The block, if any, maps the validated access token to the principal.
|
|
62
|
+
{ strategy: :oauth, resource_server: OAuth::ResourceServer.new(**oauth_options, &block) }
|
|
63
|
+
elsif block
|
|
64
|
+
{ strategy: :custom, block: block }
|
|
65
|
+
elsif strategy == :none
|
|
66
|
+
{ strategy: :none }
|
|
67
|
+
elsif strategy == :bearer
|
|
68
|
+
raise ArgumentError, "authenticate :bearer requires tokens:" if tokens.nil?
|
|
69
|
+
|
|
70
|
+
{ strategy: :bearer, tokens: tokens }
|
|
71
|
+
else
|
|
72
|
+
raise ArgumentError, "authenticate expects :bearer (with tokens:), :oauth, :none, or a block"
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def authorize_tool(&block)
|
|
77
|
+
raise ArgumentError, "authorize_tool requires a block" unless block
|
|
78
|
+
|
|
79
|
+
@authorize_tool_block = block
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def context(&block)
|
|
83
|
+
raise ArgumentError, "context requires a block" unless block
|
|
84
|
+
|
|
85
|
+
@context_block = block
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def stdio_principal(&block)
|
|
89
|
+
raise ArgumentError, "stdio_principal requires a block" unless block
|
|
90
|
+
|
|
91
|
+
@stdio_principal_block = block
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def allowed_origins(*origins)
|
|
95
|
+
@allowed_origins = (@allowed_origins || []) + origins.flatten
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def configured_tool_declarations; list_setting(:@tool_declarations); end
|
|
99
|
+
def configured_authentication; setting(:@authentication); end
|
|
100
|
+
def configured_authorize_tool_block; setting(:@authorize_tool_block); end
|
|
101
|
+
def configured_context_block; setting(:@context_block); end
|
|
102
|
+
def configured_stdio_principal_block; setting(:@stdio_principal_block); end
|
|
103
|
+
def configured_allowed_origins; list_setting(:@allowed_origins); end
|
|
104
|
+
|
|
105
|
+
def configured_oauth_resource_server
|
|
106
|
+
authentication = configured_authentication
|
|
107
|
+
authentication[:resource_server] if authentication && authentication[:strategy] == :oauth
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
# Ordered { "ToolName" => tool_class }: for each server in the
|
|
111
|
+
# inheritance chain, its <Server>::Tools namespace first, then its
|
|
112
|
+
# declared tools. Resolved on every call so lazily referenced tools
|
|
113
|
+
# (strings, tools_from, the Tools namespace) pick up code reloads.
|
|
114
|
+
def tool_registry
|
|
115
|
+
server_ancestors.reverse.each_with_object({}) do |server_class, registry|
|
|
116
|
+
entries = server_class.namespace_tool_classes.map { |tool_class| [ default_tool_name(tool_class), tool_class ] }
|
|
117
|
+
entries += (server_class.instance_variable_get(:@tool_declarations) || []).flat_map do |declaration|
|
|
118
|
+
resolve_declaration(declaration)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
entries.each { |name, tool_class| register_tool(registry, name, tool_class) }
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
# Tools defined under this server's own namespace, e.g.
|
|
126
|
+
# app/mcp_servers/support_server/tools/*.rb -> SupportServer::Tools::*.
|
|
127
|
+
def namespace_tool_classes
|
|
128
|
+
return [] unless const_defined?(:Tools, false)
|
|
129
|
+
|
|
130
|
+
namespace = const_get(:Tools, false)
|
|
131
|
+
return [] unless namespace.is_a?(Module)
|
|
132
|
+
|
|
133
|
+
namespace.constants.sort.filter_map do |const_name|
|
|
134
|
+
const = namespace.const_get(const_name, false)
|
|
135
|
+
const if const.is_a?(Class) && const < OmniAgent::Tool
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def resolve_stdio_principal
|
|
140
|
+
configured_stdio_principal_block&.call
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
private
|
|
144
|
+
|
|
145
|
+
# Servers inherit settings from parent servers (e.g. an ApplicationMCPServer
|
|
146
|
+
# that declares `authenticate` once). Scalars: nearest wins. Lists: concatenated.
|
|
147
|
+
def server_ancestors
|
|
148
|
+
ancestors.select { |klass| klass.is_a?(Class) && klass < OmniAgent::MCP::Server }
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def setting(ivar)
|
|
152
|
+
server_ancestors.each do |klass|
|
|
153
|
+
value = klass.instance_variable_get(ivar)
|
|
154
|
+
return value unless value.nil?
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
nil
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def list_setting(ivar)
|
|
161
|
+
server_ancestors.reverse.flat_map { |klass| klass.instance_variable_get(ivar) || [] }
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def default_server_name
|
|
165
|
+
return "omni_agent" if name.nil?
|
|
166
|
+
|
|
167
|
+
base = name.demodulize.underscore
|
|
168
|
+
base = base.delete_suffix("_server") unless base == "server"
|
|
169
|
+
base
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def add_tool_declaration(declaration)
|
|
173
|
+
@tool_declarations = (@tool_declarations || []) + [ declaration ]
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def resolve_declaration(declaration)
|
|
177
|
+
case declaration[:type]
|
|
178
|
+
when :tool
|
|
179
|
+
tool_class = resolve_constant(declaration[:tool_class])
|
|
180
|
+
[ [ declaration[:name] || default_tool_name(tool_class), tool_class ] ]
|
|
181
|
+
when :agent_tools
|
|
182
|
+
agent_class = resolve_constant(declaration[:agent_class])
|
|
183
|
+
agent_class.tool_classes.map { |tool_class| [ default_tool_name(tool_class), tool_class ] }
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def resolve_constant(value)
|
|
188
|
+
return value if value.is_a?(Class)
|
|
189
|
+
|
|
190
|
+
Object.const_get(value.to_s)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
def default_tool_name(tool_class)
|
|
194
|
+
if tool_class.name.nil?
|
|
195
|
+
raise OmniAgent::MCPError, "Anonymous tool classes need an explicit name: `tool klass, as: \"name\"`"
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
tool_class.name.demodulize
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def register_tool(registry, name, tool_class)
|
|
202
|
+
unless tool_class.is_a?(Class) && tool_class < OmniAgent::Tool
|
|
203
|
+
raise OmniAgent::MCPError, "#{tool_class.inspect} is not an OmniAgent::Tool subclass"
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
unless name.match?(TOOL_NAME_PATTERN)
|
|
207
|
+
raise OmniAgent::MCPError,
|
|
208
|
+
"Invalid MCP tool name #{name.inspect} in #{self.name}: use 1-128 characters from A-Z, a-z, 0-9, _, -, ."
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
if registry.key?(name)
|
|
212
|
+
raise OmniAgent::MCPError,
|
|
213
|
+
"Duplicate MCP tool name #{name.inspect} in #{self.name}. Use `tool klass, as: \"other_name\"` to rename one."
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
registry[name] = tool_class
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# access_token is the OAuth::AccessToken for `authenticate :oauth`, nil otherwise.
|
|
221
|
+
attr_reader :principal, :request, :transport, :access_token
|
|
222
|
+
|
|
223
|
+
def initialize(principal: nil, request: nil, transport: :http, access_token: nil)
|
|
224
|
+
@principal = principal
|
|
225
|
+
@request = request
|
|
226
|
+
@transport = transport
|
|
227
|
+
@access_token = access_token
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def visible_tools
|
|
231
|
+
authorizer = self.class.configured_authorize_tool_block
|
|
232
|
+
registry = self.class.tool_registry
|
|
233
|
+
return registry unless authorizer
|
|
234
|
+
|
|
235
|
+
registry.select do |name, tool_class|
|
|
236
|
+
instance_exec(tool_class, principal, name, &authorizer)
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def find_tool(name)
|
|
241
|
+
visible_tools[name.to_s]
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def tool_context
|
|
245
|
+
base = { mcp_principal: principal, mcp_request: request }
|
|
246
|
+
base[:mcp_access_token] = access_token if access_token
|
|
247
|
+
context_block = self.class.configured_context_block
|
|
248
|
+
return base unless context_block
|
|
249
|
+
|
|
250
|
+
extra = instance_exec(principal, request, &context_block)
|
|
251
|
+
extra.is_a?(Hash) ? base.merge(extra) : base
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
end
|
|
255
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
module OmniAgent
|
|
4
|
+
module MCP
|
|
5
|
+
# stdio transport: newline-delimited JSON-RPC over stdin/stdout. Runs as a
|
|
6
|
+
# local subprocess of the client, so it skips HTTP authentication and takes
|
|
7
|
+
# its principal from the server's `stdio_principal` block instead.
|
|
8
|
+
class Stdio
|
|
9
|
+
# Entry point for `omni_agent mcp` and `rake omni_agent:mcp`. Keeps a
|
|
10
|
+
# private handle on the real stdout for the protocol, then points fd 1
|
|
11
|
+
# at stderr so stray `puts` or logger output cannot corrupt the stream.
|
|
12
|
+
def self.start(server, input: $stdin)
|
|
13
|
+
server_class = MCP.resolve_server_class(server)
|
|
14
|
+
|
|
15
|
+
protocol_output = $stdout.dup
|
|
16
|
+
$stdout.flush
|
|
17
|
+
$stdout.reopen($stderr)
|
|
18
|
+
|
|
19
|
+
new(server_class, input: input, output: protocol_output).run
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def initialize(server, input:, output:)
|
|
23
|
+
@server_class = MCP.resolve_server_class(server)
|
|
24
|
+
@input = input
|
|
25
|
+
@output = output
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def run
|
|
29
|
+
server = @server_class.new(principal: @server_class.resolve_stdio_principal, transport: :stdio)
|
|
30
|
+
handler = Handler.new(server)
|
|
31
|
+
|
|
32
|
+
@input.each_line do |line|
|
|
33
|
+
line = line.strip
|
|
34
|
+
next if line.empty?
|
|
35
|
+
|
|
36
|
+
message = begin
|
|
37
|
+
JSON.parse(line)
|
|
38
|
+
rescue JSON::ParserError
|
|
39
|
+
write(jsonrpc: JSONRPC_VERSION, id: nil, error: { code: PARSE_ERROR, message: "Parse error" })
|
|
40
|
+
next
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
response = handler.call(message)
|
|
44
|
+
write(response) if response
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
private
|
|
49
|
+
|
|
50
|
+
def write(payload)
|
|
51
|
+
@output.write("#{JSON.generate(payload)}\n")
|
|
52
|
+
@output.flush
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
require "json"
|
|
2
|
+
|
|
3
|
+
module OmniAgent
|
|
4
|
+
module MCP
|
|
5
|
+
module ToolAdapter
|
|
6
|
+
module_function
|
|
7
|
+
|
|
8
|
+
def definition(name, tool_class)
|
|
9
|
+
definition = { name: name }
|
|
10
|
+
definition[:title] = tool_class.title if tool_class.title
|
|
11
|
+
definition[:description] = tool_class.description
|
|
12
|
+
definition[:inputSchema] = tool_class.json_schema
|
|
13
|
+
|
|
14
|
+
annotations = tool_class.mcp_annotations
|
|
15
|
+
definition[:annotations] = annotations unless annotations.empty?
|
|
16
|
+
|
|
17
|
+
definition
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def result(value)
|
|
21
|
+
case value
|
|
22
|
+
when nil
|
|
23
|
+
{ content: [ text_content("") ] }
|
|
24
|
+
when String
|
|
25
|
+
{ content: [ text_content(value) ] }
|
|
26
|
+
when Hash
|
|
27
|
+
json = JSON.generate(value)
|
|
28
|
+
{ content: [ text_content(json) ], structuredContent: JSON.parse(json) }
|
|
29
|
+
when Array
|
|
30
|
+
{ content: [ text_content(JSON.generate(value)) ] }
|
|
31
|
+
else
|
|
32
|
+
{ content: [ text_content(value.to_s) ] }
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def error_result(message)
|
|
37
|
+
{ content: [ text_content(message) ], isError: true }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def text_content(text)
|
|
41
|
+
{ type: "text", text: text }
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
module OmniAgent
|
|
2
|
+
module MCP
|
|
3
|
+
SUPPORTED_PROTOCOL_VERSIONS = [ "2025-11-25", "2025-06-18", "2025-03-26" ].freeze
|
|
4
|
+
LATEST_PROTOCOL_VERSION = SUPPORTED_PROTOCOL_VERSIONS.first
|
|
5
|
+
|
|
6
|
+
JSONRPC_VERSION = "2.0".freeze
|
|
7
|
+
|
|
8
|
+
PARSE_ERROR = -32_700
|
|
9
|
+
INVALID_REQUEST = -32_600
|
|
10
|
+
METHOD_NOT_FOUND = -32_601
|
|
11
|
+
INVALID_PARAMS = -32_602
|
|
12
|
+
INTERNAL_ERROR = -32_603
|
|
13
|
+
|
|
14
|
+
def self.logger
|
|
15
|
+
return unless defined?(Rails) && Rails.respond_to?(:logger)
|
|
16
|
+
|
|
17
|
+
Rails.logger
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.resolve_server_class(server)
|
|
21
|
+
return server if server.is_a?(Class)
|
|
22
|
+
|
|
23
|
+
server_class = Object.const_get(server.to_s)
|
|
24
|
+
unless server_class.is_a?(Class) && server_class < OmniAgent::MCP::Server
|
|
25
|
+
raise OmniAgent::MCPError, "#{server} is not an OmniAgent::MCP::Server subclass"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
server_class
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
data/lib/omni_agent/tool.rb
CHANGED
|
@@ -11,6 +11,31 @@ module OmniAgent
|
|
|
11
11
|
@metadata || {}
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
+
def title(text = nil)
|
|
15
|
+
@title = text if text
|
|
16
|
+
@title
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def annotations(read_only: nil, destructive: nil, idempotent: nil, open_world: nil)
|
|
20
|
+
@annotations = {
|
|
21
|
+
read_only: read_only,
|
|
22
|
+
destructive: destructive,
|
|
23
|
+
idempotent: idempotent,
|
|
24
|
+
open_world: open_world
|
|
25
|
+
}.compact
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def mcp_annotations
|
|
29
|
+
hints = @annotations || {}
|
|
30
|
+
|
|
31
|
+
{
|
|
32
|
+
readOnlyHint: hints[:read_only],
|
|
33
|
+
destructiveHint: hints[:destructive],
|
|
34
|
+
idempotentHint: hints[:idempotent],
|
|
35
|
+
openWorldHint: hints[:open_world]
|
|
36
|
+
}.compact
|
|
37
|
+
end
|
|
38
|
+
|
|
14
39
|
def tags(*tag_names)
|
|
15
40
|
return @tags || [] if tag_names.empty?
|
|
16
41
|
|
data/lib/omni_agent/version.rb
CHANGED
data/lib/omni_agent.rb
CHANGED
|
@@ -3,7 +3,10 @@ require "omni_agent/engine" if defined?(Rails)
|
|
|
3
3
|
require "zeitwerk"
|
|
4
4
|
|
|
5
5
|
loader = Zeitwerk::Loader.for_gem
|
|
6
|
-
loader.inflector.inflect(
|
|
6
|
+
loader.inflector.inflect(
|
|
7
|
+
"openai" => "OpenAI", "cli" => "CLI", "mcp" => "MCP",
|
|
8
|
+
"oauth" => "OAuth", "jwt_verifier" => "JWTVerifier", "http_client" => "HTTPClient"
|
|
9
|
+
)
|
|
7
10
|
loader.ignore(File.expand_path("generators", __dir__))
|
|
8
11
|
loader.setup
|
|
9
12
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
namespace :omni_agent do
|
|
2
|
+
desc 'Run an MCP server over stdio. Usage: rake "omni_agent:mcp[SupportServer]"'
|
|
3
|
+
task :mcp, [ :server ] => :environment do |_task, args|
|
|
4
|
+
server = args[:server].to_s.strip
|
|
5
|
+
abort 'Please provide a server class. Example: bin/rails "omni_agent:mcp[SupportServer]"' if server.empty?
|
|
6
|
+
|
|
7
|
+
OmniAgent::MCP::Stdio.start(server)
|
|
8
|
+
end
|
|
9
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: omni_agent
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.11
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ACR1209
|
|
@@ -62,6 +62,7 @@ files:
|
|
|
62
62
|
- lib/generators/omni_agent/agent/agent_generator.rb
|
|
63
63
|
- lib/generators/omni_agent/eval/eval_generator.rb
|
|
64
64
|
- lib/generators/omni_agent/install/install_generator.rb
|
|
65
|
+
- lib/generators/omni_agent/mcp_server/mcp_server_generator.rb
|
|
65
66
|
- lib/omni_agent.rb
|
|
66
67
|
- lib/omni_agent/agent.rb
|
|
67
68
|
- lib/omni_agent/configuration.rb
|
|
@@ -81,6 +82,21 @@ files:
|
|
|
81
82
|
- lib/omni_agent/eval/run.rb
|
|
82
83
|
- lib/omni_agent/eval/runner.rb
|
|
83
84
|
- lib/omni_agent/eval/tool_call_assertion.rb
|
|
85
|
+
- lib/omni_agent/mcp.rb
|
|
86
|
+
- lib/omni_agent/mcp/authenticator.rb
|
|
87
|
+
- lib/omni_agent/mcp/handler.rb
|
|
88
|
+
- lib/omni_agent/mcp/oauth.rb
|
|
89
|
+
- lib/omni_agent/mcp/oauth/access_token.rb
|
|
90
|
+
- lib/omni_agent/mcp/oauth/http_client.rb
|
|
91
|
+
- lib/omni_agent/mcp/oauth/introspection_verifier.rb
|
|
92
|
+
- lib/omni_agent/mcp/oauth/jwt_verifier.rb
|
|
93
|
+
- lib/omni_agent/mcp/oauth/resource_server.rb
|
|
94
|
+
- lib/omni_agent/mcp/rack_app.rb
|
|
95
|
+
- lib/omni_agent/mcp/request.rb
|
|
96
|
+
- lib/omni_agent/mcp/routing.rb
|
|
97
|
+
- lib/omni_agent/mcp/server.rb
|
|
98
|
+
- lib/omni_agent/mcp/stdio.rb
|
|
99
|
+
- lib/omni_agent/mcp/tool_adapter.rb
|
|
84
100
|
- lib/omni_agent/providers.rb
|
|
85
101
|
- lib/omni_agent/providers/base.rb
|
|
86
102
|
- lib/omni_agent/providers/mock.rb
|
|
@@ -96,6 +112,7 @@ files:
|
|
|
96
112
|
- lib/omni_agent/tool/schema_builder.rb
|
|
97
113
|
- lib/omni_agent/version.rb
|
|
98
114
|
- lib/tasks/omni_agent_eval_tasks.rake
|
|
115
|
+
- lib/tasks/omni_agent_mcp_tasks.rake
|
|
99
116
|
homepage: https://github.com/ACR1209/omni_agent
|
|
100
117
|
licenses:
|
|
101
118
|
- MIT
|