Module: OdataDuty::McpServerBuilder
- Extended by:
- McpServerBuilder
- Included in:
- McpServerBuilder
- Defined in:
- lib/odata_duty/mcp_server_builder.rb
Instance Method Summary collapse
- #build(schema) ⇒ Object
-
#define_tool(server, schema, action, url_for:, **tool_args) ⇒ Object
On the .mutant.yml ignore list:
server_context[:context]has only equivalent mutants ([]vsfetch/dig); the key is always present, so no public-API test distinguishes them. -
#keyed_url_for(endpoint) ⇒ Object
Builds the
<url>('<key>')locator from the tool arguments. - #register_collection_tools(server, schema, endpoint) ⇒ Object
- #register_count_tool(server, schema, endpoint) ⇒ Object
- #register_create_tool(server, schema, endpoint) ⇒ Object
- #register_delete_tool(server, schema, endpoint) ⇒ Object
- #register_endpoint_tools(server, schema, endpoint) ⇒ Object
- #register_get_tool(server, schema, endpoint) ⇒ Object
- #register_key_tool(server, schema, endpoint, action, verb) ⇒ Object
- #register_list_tool(server, schema, endpoint) ⇒ Object
- #register_update_tool(server, schema, endpoint) ⇒ Object
-
#run_tool(action, url:, schema:, context:, query_options:) ⇒ Object
On the .mutant.yml ignore list:
e.messagehas only an equivalent mutant (e), since an OdataDuty::Error renders identically to its message in the text content block.
Instance Method Details
#build(schema) ⇒ Object
8 9 10 11 12 13 14 15 16 |
# File 'lib/odata_duty/mcp_server_builder.rb', line 8 def build(schema) server = MCP::Server.new( name: schema.title, version: schema.version, capabilities: { tools: {} } ) schema.endpoints.each { |endpoint| register_endpoint_tools(server, schema, endpoint) } server end |
#define_tool(server, schema, action, url_for:, **tool_args) ⇒ Object
On the .mutant.yml ignore list: server_context[:context] has only equivalent mutants
([] vs fetch/dig); the key is always present, so no public-API test distinguishes them.
89 90 91 92 93 94 95 |
# File 'lib/odata_duty/mcp_server_builder.rb', line 89 def define_tool(server, schema, action, url_for:, **tool_args) server.define_tool(**tool_args) do |server_context:, **args| McpServerBuilder.run_tool(action, url: url_for.call(args), schema: schema, context: server_context[:context], query_options: args.transform_keys(&:to_s)) end end |
#keyed_url_for(endpoint) ⇒ Object
Builds the <url>('<key>') locator from the tool arguments. The dynamic args[key] lookup
has no mutation-testable equivalent (the key is always present, enforced by the SDK's
required-argument check), so this is the one MCP subject left on the .mutant.yml ignore list.
82 83 84 85 |
# File 'lib/odata_duty/mcp_server_builder.rb', line 82 def keyed_url_for(endpoint) key = endpoint.entity_type.property_refs.first.name ->(args) { "#{endpoint.url}('#{args[key]}')" } end |
#register_collection_tools(server, schema, endpoint) ⇒ Object
26 27 28 29 |
# File 'lib/odata_duty/mcp_server_builder.rb', line 26 def register_collection_tools(server, schema, endpoint) register_list_tool(server, schema, endpoint) register_count_tool(server, schema, endpoint) if endpoint.supports_count? end |
#register_count_tool(server, schema, endpoint) ⇒ Object
47 48 49 50 51 52 53 |
# File 'lib/odata_duty/mcp_server_builder.rb', line 47 def register_count_tool(server, schema, endpoint) input_schema = McpInputSchemas.count_input_schema(supports_search: endpoint.supports_search?) define_tool(server, schema, :execute, url_for: ->(_args) { "#{endpoint.url}/$count" }, name: "count_#{endpoint.name}", description: "Count #{endpoint.name} records", input_schema: input_schema) end |
#register_create_tool(server, schema, endpoint) ⇒ Object
55 56 57 58 59 60 61 |
# File 'lib/odata_duty/mcp_server_builder.rb', line 55 def register_create_tool(server, schema, endpoint) define_tool(server, schema, :create, url_for: ->(_args) { endpoint.url }, name: "create_#{endpoint.name}", description: "Create a new #{endpoint.name} record", input_schema: McpInputSchemas.create_input_schema(endpoint.entity_type)) end |
#register_delete_tool(server, schema, endpoint) ⇒ Object
35 36 37 |
# File 'lib/odata_duty/mcp_server_builder.rb', line 35 def register_delete_tool(server, schema, endpoint) register_key_tool(server, schema, endpoint, :delete, 'Delete an existing') end |
#register_endpoint_tools(server, schema, endpoint) ⇒ Object
18 19 20 21 22 23 24 |
# File 'lib/odata_duty/mcp_server_builder.rb', line 18 def register_endpoint_tools(server, schema, endpoint) register_collection_tools(server, schema, endpoint) if endpoint.supports_collection? register_get_tool(server, schema, endpoint) if endpoint.supports_individual? register_create_tool(server, schema, endpoint) if endpoint.supports_create? register_update_tool(server, schema, endpoint) if endpoint.supports_update? register_delete_tool(server, schema, endpoint) if endpoint.supports_delete? end |
#register_get_tool(server, schema, endpoint) ⇒ Object
63 64 65 66 67 68 69 |
# File 'lib/odata_duty/mcp_server_builder.rb', line 63 def register_get_tool(server, schema, endpoint) define_tool(server, schema, :execute, url_for: keyed_url_for(endpoint), name: "get_#{endpoint.name}", description: "Get a single #{endpoint.name} record by ID", input_schema: McpInputSchemas.get_input_schema(endpoint.entity_type)) end |
#register_key_tool(server, schema, endpoint, action, verb) ⇒ Object
71 72 73 74 75 76 77 |
# File 'lib/odata_duty/mcp_server_builder.rb', line 71 def register_key_tool(server, schema, endpoint, action, verb) input_schema = McpInputSchemas.public_send("#{action}_input_schema", endpoint.entity_type) define_tool(server, schema, action, url_for: keyed_url_for(endpoint), name: "#{action}_#{endpoint.name}", description: "#{verb} #{endpoint.name} record", input_schema: input_schema) end |
#register_list_tool(server, schema, endpoint) ⇒ Object
39 40 41 42 43 44 45 |
# File 'lib/odata_duty/mcp_server_builder.rb', line 39 def register_list_tool(server, schema, endpoint) input_schema = McpInputSchemas.list_input_schema(supports_search: endpoint.supports_search?) define_tool(server, schema, :execute, url_for: ->(_args) { endpoint.url }, name: "list_#{endpoint.name}", description: "List #{endpoint.name} records", input_schema: input_schema) end |
#register_update_tool(server, schema, endpoint) ⇒ Object
31 32 33 |
# File 'lib/odata_duty/mcp_server_builder.rb', line 31 def register_update_tool(server, schema, endpoint) register_key_tool(server, schema, endpoint, :update, 'Update an existing') end |
#run_tool(action, url:, schema:, context:, query_options:) ⇒ Object
On the .mutant.yml ignore list: e.message has only an equivalent mutant (e), since an
OdataDuty::Error renders identically to its message in the text content block.
99 100 101 102 103 104 105 |
# File 'lib/odata_duty/mcp_server_builder.rb', line 99 def run_tool(action, url:, schema:, context:, query_options:) result = Executor.public_send(action, url: url, context: context, query_options: , schema: schema) MCP::Tool::Response.new([{ type: 'text', text: result.to_s }]) rescue OdataDuty::Error => e MCP::Tool::Response.new([{ type: 'text', text: e. }], error: true) end |