feat(mcp): remote MCP servers per chat with sealed keys and owner-only commands
Streamable HTTP/SSE servers from the workspace's .volcanic/mcp/servers.json. Headers are sealed with AES-GCM; the chat and the visible fields are the associated data, so only /mcp_add|remove|tools change servers. Tools <server>__<tool> go live in the session. An unreachable server is skipped and reported in the system prompt. Keys are redacted from tool results, and Telegram deletes messages that carry one.
This commit is contained in:
@@ -107,6 +107,10 @@ tasks by push, subscribe or poll, persists them in `.volcanic/a2a/pending.json`
|
||||
- Tests replay recorded CLI output from `tests/Volcanic.AgenticCore.Extensions.Tests/ClaudeCode/Fixtures/*.jsonl`.
|
||||
- `Mcp`: the tool catalogue is discovered once per host process (`McpCatalogCache.Shared`), each session starts its own
|
||||
server process on the first call, and tests run `tests/Volcanic.AgenticCore.Extensions.Tests.FakeMcpServer`.
|
||||
`Mcp/Remote/RemoteMcpExtension` is separate: remote servers (Streamable HTTP/SSE) per chat from the workspace's
|
||||
`.volcanic/mcp/servers.json`, headers sealed (AES-GCM, chat + visible fields as associated data) with a host secret
|
||||
so only the owner's `/mcp_add|remove|tools|list` change them; tools `<server>__<tool>` are registered and
|
||||
(de)activated in the live session; tests use an in-memory ASP.NET MCP server (`Mcp/Remote/RemoteMcpTestHost`).
|
||||
|
||||
### Telegram host (`hosts/Volcanic.AgenticCore.Telegram`)
|
||||
|
||||
@@ -134,6 +138,8 @@ writes there. Each private chat's `trigger` tool manages its topic triggers (`Tr
|
||||
`noul` question per trigger, 3 retries) about every message and logs one line per message; matches are batched for 10 s
|
||||
by `TriggerDispatcher` and delivered as follow-up prompts (`TelegramTriggerDelivery`); snoozed triggers queue messages
|
||||
(`SnoozeQueue`) and check them as one batch when the snooze ends. `/triggers` lists them.
|
||||
`RemoteMcpSetup` adds `RemoteMcpExtension` to chat sessions (secret `MCP_ENCRYPTION_SECRET`, else the bot token); the
|
||||
router deletes a `/mcp_add` carrying a key and any answer to a `UiRequestOptions.Secret` question.
|
||||
`ADMIN_USER_ID` (`Telegram:AdminUserId`) may `/impersonate <user_id>` (`Chats/Impersonation`, in memory, `0` stops): the
|
||||
router then handles the admin's updates as the target's, and the target chat's renderer delivers to the admin's chat
|
||||
(`ChatRenderer.DeliveryChatId`); the target's own updates get `Impersonation.BlockedNotice` instead. Answers go out complete, not streamed (`Rendering/`). Tests drive the host through `Support/FakeBotClient` and `ChatHost`.
|
||||
|
||||
Reference in New Issue
Block a user