Files
agent-news/mcp_server/bin/agent_news_mcp.dart
matt2dev be09de2ad7 Initial agent-news: Dart Telegram bot + Claude Code runner + MCP bridge
/news spawns claude-code as a local subprocess (single pod, no cross-container
exec on K3s); Claude delivers the digest itself via the send_to_telegram MCP tool.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 20:40:32 +03:00

83 lines
2.8 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'dart:convert';
import 'dart:io';
import 'package:mcp_dart/mcp_dart.dart';
final _token = Platform.environment['TELEGRAM_BOT_TOKEN'] ?? '';
final _http = HttpClient();
CallToolResult _ok(String text) => CallToolResult(content: [TextContent(text: text)]);
CallToolResult _err(String text) =>
CallToolResult(content: [TextContent(text: 'Ошибка: $text')], isError: true);
List<String> _splitMessage(String text) {
const maxLen = 4000;
if (text.length <= maxLen) return [text];
final chunks = <String>[];
var start = 0;
while (start < text.length) {
final end = (start + maxLen).clamp(0, text.length);
chunks.add(text.substring(start, end));
start = end;
}
return chunks;
}
Future<void> _sendMessage(int chatId, String text) async {
for (final chunk in _splitMessage(text)) {
final req = await _http.postUrl(
Uri.parse('https://api.telegram.org/bot$_token/sendMessage'),
);
req.headers.contentType = ContentType.json;
req.write(jsonEncode({
'chat_id': chatId,
'text': chunk,
'parse_mode': 'Markdown',
}));
final res = await req.close();
final body = await res.transform(utf8.decoder).join();
if (res.statusCode >= 400) {
throw Exception('Telegram sendMessage → ${res.statusCode}: $body');
}
}
}
void main() {
final server = McpServer(
const Implementation(name: 'agent-news', version: '0.1.0'),
options: const McpServerOptions(
capabilities: ServerCapabilities(tools: ServerCapabilitiesTools()),
),
);
server.registerTool(
'send_to_telegram',
description:
'Отправляет готовый текст (Markdown) в указанный Telegram-чат. '
'Единственный способ доставить результат ресёрча пользователю — '
'вызывай этот тул с финальным оформленным текстом.',
inputSchema: JsonSchema.object(
properties: {
'chat_id': JsonSchema.integer(description: 'ID чата Telegram, куда отправить сообщение'),
'text': JsonSchema.string(description: 'Готовый текст в Markdown-разметке Telegram'),
},
required: ['chat_id', 'text'],
),
callback: (args, _) async {
if (_token.isEmpty) {
return _err('TELEGRAM_BOT_TOKEN не задан в окружении MCP-сервера');
}
try {
final chatId = args['chat_id'] as int;
final text = args['text'].toString();
await _sendMessage(chatId, text);
return _ok('Отправлено в чат $chatId (${text.length} символов).');
} catch (e) {
return _err('$e');
}
},
);
server.connect(StdioServerTransport());
}