Module: LocalVault::MCP::Tools

Defined in:
lib/localvault/mcp/tools.rb

Constant Summary collapse

VAULT_PARAM =
{
  "vault" => {
    "type" => "string",
    "description" => "Vault name to use (uses default vault if omitted)"
  }
}.freeze
DEFINITIONS =

MCP tool definitions conforming to the MCP tools/list schema. Each entry specifies a tool name, description, and JSON Schema for input.

[
  {
    "name" => "get_secret",
    "description" => "Retrieve a secret value by key from a localvault vault",
    "inputSchema" => {
      "type" => "object",
      "properties" => {
        "key"   => { "type" => "string", "description" => "The secret key to retrieve" },
        **VAULT_PARAM
      },
      "required" => ["key"]
    }
  },
  {
    "name" => "list_secrets",
    "description" => "List all secret keys in a localvault vault",
    "inputSchema" => {
      "type" => "object",
      "properties" => {
        "prefix" => { "type" => "string", "description" => "Only return keys starting with this prefix" },
        "query" => { "type" => "string", "description" => "Case-insensitive substring filter for key names" },
        **VAULT_PARAM
      },
      "required" => []
    }
  },
  {
    "name" => "localvault_whoami",
    "description" => "Show which localvault home, vault, and unlocked sessions the MCP server can see",
    "inputSchema" => {
      "type" => "object",
      "properties" => { **VAULT_PARAM },
      "required" => []
    }
  },
  {
    "name" => "set_secret",
    "description" => "Store a secret key-value pair in a localvault vault. Use dot-notation (project.KEY) for namespaced secrets.",
    "inputSchema" => {
      "type" => "object",
      "properties" => {
        "key"   => { "type" => "string", "description" => "The secret key (supports dot-notation: project.KEY)" },
        "value" => { "type" => "string", "description" => "The secret value" },
        **VAULT_PARAM
      },
      "required" => ["key", "value"]
    }
  },
  {
    "name" => "delete_secret",
    "description" => "Delete a secret by key from a localvault vault",
    "inputSchema" => {
      "type" => "object",
      "properties" => {
        "key"   => { "type" => "string", "description" => "The secret key to delete" },
        **VAULT_PARAM
      },
      "required" => ["key"]
    }
  }
].freeze

Class Method Summary collapse

Class Method Details

.call(name, arguments, vault_resolver, status_resolver = nil) ⇒ Hash

Dispatch an MCP tool call by name.

Resolves the target vault via the provided callable, then executes the requested tool (get_secret, list_secrets, set_secret, or delete_secret).

Parameters:

  • name (String)

    tool name (must match a DEFINITIONS entry)

  • arguments (Hash)

    tool arguments (e.g. => "API_KEY", "vault" => "prod")

  • vault_resolver (#call)

    callable that accepts a vault name (String or nil) and returns a Vault instance or nil

Returns:

  • (Hash)

    MCP content result with "content" array and optional "isError"

Raises:

  • (ArgumentError)

    if the tool name is unknown



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/localvault/mcp/tools.rb', line 90

def self.call(name, arguments, vault_resolver, status_resolver = nil)
  unless DEFINITIONS.any? { |t| t["name"] == name }
    raise ArgumentError, "Unknown tool: #{name}"
  end

  return error_result("Invalid arguments; expected object") unless arguments.is_a?(Hash)

  vault_name = arguments["vault"]
  return whoami(status_resolver.call(vault_name)) if name == "localvault_whoami"

  vault = vault_resolver.call(vault_name)

  unless vault
    hint = vault_name ? "localvault show -v #{vault_name}" : "localvault show"
    return error_result("No unlocked vault session. Run: #{hint}")
  end

  case name
  when "get_secret"    then get_secret(arguments["key"], vault)
  when "list_secrets"  then list_secrets(vault, prefix: arguments["prefix"], query: arguments["query"])
  when "set_secret"    then set_secret(arguments["key"], arguments["value"], vault)
  when "delete_secret" then delete_secret(arguments["key"], vault)
  end
rescue StandardError => e
  error_result(e.message)
end