Class McpToolApprovalService

java.lang.Object
io.meeds.mcp.server.service.McpToolApprovalService

@Component public class McpToolApprovalService extends Object
Asks the user to approve a tool call on a card in their chat, and waits for the answer. The answer travels over CometD as answer:<id>:<true|false> or, for "Always allow", answer:<id>:always:<AGENT|TOOL>:<days>:<CONSTRAINED|ANY>. Only the client subscribed as the requesting user may answer, the first answer wins, and an "Always allow" answer creates its standing approval once, from the pending call the server recorded.
  • Field Details

  • Constructor Details

    • McpToolApprovalService

      public McpToolApprovalService()
  • Method Details

    • init

      @PostConstruct public void init()
      Listens to answers on the CometD channel and starts the periodic timeout check of pending cards.
    • shutdown

      @PreDestroy public void shutdown()
      Stops the periodic timeout check.
    • requestApproval

      public boolean requestApproval(String id, String conversationId, String toolName, String toolInput, String username)
      Asks the user to approve a call on a card without "Always allow", and waits for the answer.
      Parameters:
      id - the call identifier
      conversationId - the chat conversation showing the card
      toolName - the tool name shown on the card
      toolInput - the call input shown on the card
      username - the user asked
      Returns:
      true when the user approved
    • requestApproval

      public boolean requestApproval(String id, String conversationId, String toolName, String toolInput, String username, McpToolGrantRequest grantRequest, boolean grantable, McpToolGrantConstraint offeredConstraint)
      Asks the user to approve a call on a card, offering "Always allow" when the call is grantable, and waits for the answer.
      Parameters:
      id - the call identifier
      conversationId - the chat conversation showing the card
      toolName - the tool name shown on the card
      toolInput - the call input shown on the card
      username - the user asked
      grantRequest - the call as the server resolved it, the only source of a grant created from this card
      grantable - whether the card may offer "Always allow"
      offeredConstraint - the argument limit the card may offer, or null
      Returns:
      true when the user approved, once or always
    • receiveAnswer

      public void receiveAnswer(String id, String wsClientId, boolean approved) throws IllegalAccessException
      Records a plain approve or deny answer.
      Parameters:
      id - the call identifier
      wsClientId - the CometD client that sent the answer
      approved - the answer
      Throws:
      IllegalAccessException - when the client isn't subscribed as the requesting user
    • receiveAnswer

      public void receiveAnswer(String id, String wsClientId, boolean approved, boolean always, McpToolGrantChoice choice) throws IllegalAccessException
      Records an answer to a pending card. Only the client subscribed as the requesting user may answer, and only the first answer counts: the card resends its answer every half second until it is confirmed, so a later copy changes nothing and never creates a second grant. An "Always allow" answer approves the call and, when the card was grantable and the choice valid, creates the standing approval from the pending call; otherwise it approves the call once, creates nothing, and is logged. The grant is created outside the card's lock: its store may be slow, and the lock is the one the timeout checker takes to wake every pending card.
      Parameters:
      id - the call identifier
      wsClientId - the CometD client that sent the answer
      approved - whether the call is approved
      always - whether the answer is "Always allow"
      choice - the checked "Always allow" choice, null when invalid
      Throws:
      IllegalAccessException - when the client isn't subscribed as the requesting user
    • traceToolExecution

      public void traceToolExecution(UserToolExecution toolExecution)
      Publishes one step of a tool call to the user's chat and to the platform listeners (ai-agent-tool-execution). A call run under a standing approval carries the grant id and its owner type.
      Parameters:
      toolExecution - the step to publish