Когда вы работаете с AI-ассистентами вроде Claude Code или Kilo Code, рано или поздно замечаете одну особенность: модель отлично пишет код, но почти ничего не знает о среде, в которой этот код работает. Где находится пользователь? Какая у него операционная система? Сколько сейчас времени? Чему точно должно равняться вычисленное значение функции на тесте?
Эти "простые" вопросы ставят AI в тупик. А ведь ответы на них критически важны для качественной разработки. Представьте: агент предлагает путь к файлу в стиле Windows, а вы работаете на Linux, или несмотря на запреты и напоминания пытается вызвать команды для другой операционной системы.
Решение - MCP (Model Context Protocol) сервер, который дает AI-агентам базовое "самосознание", ориентацию в окружающем мире.
Model Context Protocol - это открытый протокол для подключения внешних инструментов к LLM. Если упростить: это способ дать модели "руки" - возможность вызывать функции, читать файлы, работать с API.
Для AI-агентов, занимающихся разработкой, MCP становится мостом между абстрактными знаниями модели на которых она обучалась и конкретной реальностью окружения. Без этого моста агент работает вслепую, полагаясь только на предположения.
Self-Aware MCP Server предоставляет четыре простых, но фундаментальных инструмента, отвечающие на вопросы Что, Где, Когда и Сколько:
get_current_location - возвращает местоположение, переданное при запуске сервера. Это не GPS-координаты, а скорее контекст: "Москва, Россия" или "Home office, Bali". Для AI это сигнал учитывать часовой пояс, язык интерфейса, региональные форматы дат.
get_current_date_time - текущие дата и время. Звучит тривиально, но модели не знают "когда сейчас". Это важно для планирования задач, работы с логами, генерации отчетов с актуальными датами.
get_current_system - информация об операционной системе: имя, версия, человекочитаемое название (Windows 11, macOS Sonoma, Ubuntu 22.04), платформа и архитектура процессора. Критически важно для тестирования, командной строки и кроссплатформенной разработки.
calculate - безопасный калькулятор математических выражений. Поддерживает тригонометрические, гиперболические, логарифмические функции, статистику (mean, median, stdev, variance) и константы (pi, e). Безопасность достигается валидацией выражений и изолированной средой выполнения. Без инструментов точного счета LLM может банально выдавать неправильные значения, а про галлюцинации знают примерно все.
Один и тот же сервер реализован на трех языках: TypeScript/Node.js, Python и C#. Это не упражнение в программировании, а прагматичное решение реальной проблемы.
У каждого языка своя экосистема. Node.js разработчику проще запустить npm-пакет, Python-инженер предпочтет pip-модуль, а в корпоративной .NET-среде нужен будет NuGet-пакет или скомпилированный бинарник.
Гибкость выбора языка означает:
Минимальные зависимости - не нужно ставить Node.js, если вы работаете только с Python
Интеграция в существующие workflows - CI/CD пайплайны уже используют определенный стек
Знакомая среда отладки - разработчик знает инструменты своего языка
TypeScript/Node.js использует классическую структуру с package.json, компиляцией в dist/, и типами в .d.ts файлах. Типичный Node.js проект.
Python следует стандарту pyproject.toml с пакетом в src/self_aware/. Современный Python-проект с правильной структурой.
C# реализован как single-file приложение - весь код в одном Program.cs (~960 строк). Компилируется в один бинарник, что упрощает деплой.
TypeScript:
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: "get_current_location", description: "Returns the current location...", inputSchema: { type: "object", properties: {} } }, // ... ] }));
Python:
@app.list_tools() async def list_tools() -> list[Tool]: return [ Tool( name="get_current_location", description="Returns the current location...", inputSchema={"type": "object", "properties": {}} ), # ... ]
C#:
new Tool { Name = "get_current_location", Description = "Returns the current location...", InputSchema = new { type = "object", properties = new { } } }
Разница минимальна - каждый язык использует идиоматичный для себя синтаксис, но структура данных одна и та же.
TypeScript использует switch-case в обработчике:
server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; switch (name) { case "get_current_location": return { content: [{ type: "text", text: locationArg }] }; case "calculate": return { content: [{ type: "text", text: String(calculate(args.expression)) }] }; // ... } });
Python применяет декоратор и условные ветки:
@app.call_tool() async def call_tool(name: str, arguments: dict) -> list[TextContent]: if name == "get_current_location": return [TextContent(type="text", text=get_current_location())] elif name == "calculate": result = calculate(arguments.get("expression", "")) return [TextContent(type="text", text=str(result))] # ...
C# использует паттерн-матчинг:
await foreach (var message in reader.ReadAllAsync()) { if (message.Method == "tools/call") { var result = request.Params.Name switch { "get_current_location" => GetLocation(), "calculate" => Calculate(GetExpression(request.Params.Arguments)), // ... }; } }
Здесь реализации расходятся сильнее всего.
TypeScript и Python используют встроенные возможности:
// TypeScript - используется объект Math и eval с ограничением области видимости const result = new Function( 'scope', `with(scope) { return ${expression}; }` )(safeScope);
# Python - eval с ограниченным scope result =
C# не имеет встроенного eval, поэтому реализован собственный рекурсивный парсер выражений. Это ~400 строк кода, но дает полный контроль над безопасностью.
Все три версии используют похожий подход с платформо-зависимыми особенностями:
Windows: парсинг build number для определения версии (build >= 22000 = Windows 11)
macOS: вызов sw_vers -productVersion и маппинг на имена (14 = Sonoma, 15 = Sequoia)
Linux: чтение /etc/os-release для получения PRETTY_NAME
|
Язык |
Строк кода |
Размер бинарника/пакета |
|---|---|---|
|
TypeScript |
~640 |
~19KB (JS) + зависимости |
|
Python |
~380 |
~14KB (source) + зависимости |
|
C# |
~960 |
~50KB (self-contained) |
Python компактнее благодаря богатой стандартной библиотеке и встроенному eval. TypeScript занимает промежуточное положение. C# требует больше кода из-за собственного парсера выражений, но выигрывает в деплое - один бинарник без зависимостей.
После установки сервер настраивается в конфигурационном файле:
{ "mcpServers": { "self-aware": { "command": "node", "args": ["/path/to/self-aware/dist/index.js", "Москва, Россия"] } } }
После перезапуска Claude Desktop модель получит доступ к инструментам. При запросе "Какая у меня ОС?" или "Посчитай среднее значение массива [1,2,3,4,5]" модель автоматически вызовет соответствующий MCP-инструмент.
Сценарий 1: Кроссплатформенная разработка
Пользователь просит: "Напиши скрипт для бэкапа базы данных". Агент вызывает get_current_system, узнает что это Linux, и генерирует bash-скрипт с правильными путями вместо PowerShell.
Сценарий 2: Временные зоны
"Запланируй задачу на 9 утра завтра". Агент получает текущее время через get_current_date_time, учитывает локацию через get_current_location, и корректно формирует cron-выражение или команду планировщика.
Сценарий 3: Вычисления в контексте
"Рассчитай площадь круга с радиусом, равным среднему значению из массива [3, 5, 7]". Агент использует calculate("pi * mean([3,5,7])**2") в одном выражении, комбинируя константы и статистику.
Функция calculate работает с пользовательским вводом, поэтому безопасность - приоритет.
Все реализации проверяют выражение на запрещенные паттерны:
forbidden = [ "import", "exec", "eval", "compile", "open", "file", "__", "getattr", "setattr", "globals", "locals", # ... ]
Допускаются только математические операции и функции из белого списка. Никакого доступа к файловой системе, сети, или системе.
Self-Aware MCP Server - это шаг к тому, чтобы AI-агенты работали не в вакууме, а в контексте реального мира. Три строки информации: местоположение, время, ОС, плюс точные вычисления - кардинально меняют качество взаимодействия.
Конечно, в контекст реального мира можно добавить еще много чего, только нужно помнить, что текстовые описания инструментов - это багаж токенов, которые LLM, надо или нет, почти всегда таскает с собой при каждом новом промпте. И каждый токен не только занимает время на обработку, но и имеет стоимость. Поэтому в запрос стоит включать только действительно важную информацию.
Мультиязычная реализация показывает, что MCP - не привязка к одной экосистеме. Можно выбрать на свое усмотрение: Python для быстрого прототипирования, TypeScript для веб-проектов, C# для enterprise-окружения. Протокол один для всех - инструменты одинаковы.
Код проекта доступен на GitHub: https://github.com/vuguzum/self-aware-mcp-server и написан в агентском режиме с использованием модели GLM-5 от z.ai.
Источник

