Module: Mcpeye::RequestCapability

Defined in:
lib/mcpeye/request_capability.rb

Overview

The active missing-capability contract — the reserved ‘mcpeye_request_capability` tool the SDK adds to the server’s tool registry.

The passive ‘mcpeyeIntent` param (see intent.rb) only sees a missing capability when the agent still calls SOME tool and self-reports the gap in the intent text. Its blind spot is the silent miss: when no tool fits, the correct behavior is to call no tool at all — so there is no intent string and no tool_call row, yet that is the highest-value roadmap signal (a user need with zero matching tool).

This closes the gap actively: the SDK adds a reserved tool the agent can call to voice a capability the available tools do not cover. The SDK answers it locally (the host never sees it), returns a friendly acknowledgement, and records it as a normal tool_call with tool_name = “mcpeye_request_capability”. The report folds these explicit calls into topMissingCapabilities as high-confidence entries.

Keep these strings byte-for-byte in sync with @mcpeye/core (packages/core/src/request-capability.ts) and the Python SDK (packages/sdk-python/src/mcpeye/request_capability.py). spec/request_capability_spec.rb asserts them against the canonical text.

Constant Summary collapse

TOOL_NAME =
"mcpeye_request_capability"
TOOL_DESCRIPTION =

Byte-for-byte identical to packages/core/src/request-capability.ts. The lower-the-bar framing (“even if an existing tool could be a fallback”) is what pulls calls; a timid framing leaves the signal near zero. Change all SDKs together.

"Use this tool whenever the user wants something the available tools do not cover, " \
"or whenever the task might benefit from a more specialized capability, even if an " \
"existing tool (or the server's own 'more tools' feature) could be used as a fallback. " \
"Describe the capability the user actually needs, in their own words (for example: " \
"'export the report as a PDF'). If this server has its own way to request more tools or " \
"capabilities, use that for its normal flow and still call this tool once for the same " \
"gap; the two are complementary, not alternatives. This signal is used only to improve " \
"which tools are offered; calling it has no side effects and does not perform the action."
CAPABILITY_DESCRIPTION =
"The capability the user needs that the available tools do not provide, in the user's " \
"own words (for example: 'export the report as a PDF')."
CONTEXT_DESCRIPTION =
"Optional: what the user was trying to accomplish when they reached for this capability."
ACK =
"Thanks. This capability request has been recorded for the server's maintainers. " \
"If this server has its own way to request more tools or capabilities, use that as well. " \
"Continue helping the user with the available tools as best you can."

Class Method Summary collapse

Class Method Details

.descriptorObject

The full { name, description, inputSchema } descriptor, as a fresh Hash.



66
67
68
69
70
71
72
# File 'lib/mcpeye/request_capability.rb', line 66

def self.descriptor
  {
    "name" => TOOL_NAME,
    "description" => TOOL_DESCRIPTION,
    "inputSchema" => input_schema
  }
end

.input_schemaObject

The reserved tool’s input schema: ‘capability` required, `context` optional. Returns a fresh Hash each call so a caller mutating it can never corrupt the shared contract. Carries NO mcpeyeIntent property — the ask lives in `capability`.



54
55
56
57
58
59
60
61
62
63
# File 'lib/mcpeye/request_capability.rb', line 54

def self.input_schema
  {
    "type" => "object",
    "properties" => {
      "capability" => { "type" => "string", "description" => CAPABILITY_DESCRIPTION },
      "context" => { "type" => "string", "description" => CONTEXT_DESCRIPTION }
    },
    "required" => ["capability"]
  }
end