feat: give every MCP client its own token, rate limit and log name
This commit is contained in:
1 parent
3af41c06ab
commit
bfdedefae3
8 files changed
+134
-33
No files matched your search
@@ -12,12 +12,13 @@ use Symfony\Bundle\SecurityBundle\Security;
|
||||
use Symfony\Component\RateLimiter\RateLimiterFactory;
|
||||
|
||||
/**
|
||||
* What every chatbot tool call goes through: the per-token rate limit, the call log, and
|
||||
* What every chatbot tool call goes through: the per-client rate limit, the call log, and
|
||||
* the answer as compact JSON.
|
||||
*
|
||||
* The SDK would pretty-print an array result and repeat it as structured content; both
|
||||
* cost the model tokens and neither helps n8n. The log records tool, arguments, result
|
||||
* count and duration, never anything about the person chatting, which n8n does not send.
|
||||
* count, duration and the calling client (n8n, claude-desktop, …), never anything about
|
||||
* the person chatting, which n8n does not send.
|
||||
*/
|
||||
class ToolCallRunner
|
||||
{
|
||||
@@ -37,10 +38,11 @@ class ToolCallRunner
|
||||
public function run(string $tool, array $arguments, callable $call): CallToolResult
|
||||
{
|
||||
$arguments = array_filter($arguments, static fn (mixed $value): bool => null !== $value);
|
||||
$limit = $this->chatbotMcpLimiter->create($this->security->getUser()?->getUserIdentifier() ?? 'anonymous')->consume();
|
||||
$client = $this->security->getUser()?->getUserIdentifier() ?? 'anonymous';
|
||||
$limit = $this->chatbotMcpLimiter->create($client)->consume();
|
||||
|
||||
if (!$limit->isAccepted()) {
|
||||
$this->chatbotLogger->warning('MCP tool call rate-limited', ['tool' => $tool, 'arguments' => $arguments]);
|
||||
$this->chatbotLogger->warning('MCP tool call rate-limited', ['client' => $client, 'tool' => $tool, 'arguments' => $arguments]);
|
||||
|
||||
throw new ToolCallException(sprintf('Too many tool calls. Retry after %s.', $limit->getRetryAfter()->format('H:i:s')));
|
||||
}
|
||||
@@ -50,16 +52,17 @@ class ToolCallRunner
|
||||
try {
|
||||
$result = $call();
|
||||
} catch (ToolCallException $e) {
|
||||
$this->chatbotLogger->info('MCP tool call rejected', ['tool' => $tool, 'arguments' => $arguments, 'error' => $e->getMessage()]);
|
||||
$this->chatbotLogger->info('MCP tool call rejected', ['client' => $client, 'tool' => $tool, 'arguments' => $arguments, 'error' => $e->getMessage()]);
|
||||
|
||||
throw $e;
|
||||
} catch (\Throwable $e) {
|
||||
$this->chatbotLogger->error('MCP tool call failed', ['tool' => $tool, 'arguments' => $arguments, 'exception' => $e]);
|
||||
$this->chatbotLogger->error('MCP tool call failed', ['client' => $client, 'tool' => $tool, 'arguments' => $arguments, 'exception' => $e]);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
$this->chatbotLogger->info('MCP tool call', [
|
||||
'client' => $client,
|
||||
'tool' => $tool,
|
||||
'arguments' => $arguments,
|
||||
'resultCount' => is_array($result['results'] ?? null) ? count($result['results']) : 1,
|
||||
|
||||
Reference in new issue
Block a user