Package io.meeds.mcp.server.service
Class McpToolApprovalService
java.lang.Object
io.meeds.mcp.server.service.McpToolApprovalService
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.-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionclassReads card answers published by the chat onCOMETD_CHANNEL. -
Field Summary
Fields -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidinit()Listens to answers on the CometD channel and starts the periodic timeout check of pending cards.voidreceiveAnswer(String id, String wsClientId, boolean approved) Records a plain approve or deny answer.voidreceiveAnswer(String id, String wsClientId, boolean approved, boolean always, McpToolGrantChoice choice) Records an answer to a pending card.booleanrequestApproval(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.booleanrequestApproval(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.voidshutdown()Stops the periodic timeout check.voidtraceToolExecution(UserToolExecution toolExecution) Publishes one step of a tool call to the user's chat and to the platform listeners (ai-agent-tool-execution).
-
Field Details
-
COMETD_CHANNEL
- See Also:
-
-
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 identifierconversationId- the chat conversation showing the cardtoolName- the tool name shown on the cardtoolInput- the call input shown on the cardusername- 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 identifierconversationId- the chat conversation showing the cardtoolName- the tool name shown on the cardtoolInput- the call input shown on the cardusername- the user askedgrantRequest- the call as the server resolved it, the only source of a grant created from this cardgrantable- 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 identifierwsClientId- the CometD client that sent the answerapproved- 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 identifierwsClientId- the CometD client that sent the answerapproved- whether the call is approvedalways- 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
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; a call whose acting identity is known carries who acted, for whom, through which agents and on which trigger. The event's source stays the subject of the call.- Parameters:
toolExecution- the step to publish
-