Когда вы работаете с AI-ассистентами вроде Claude Code или Kilo Code, рано или поздно замечаете одну особенность: модель отлично пишет код, но почти ничего не знает о среде, в которой этот код работает. Где находится пользователь? Какая у него операционная система? Сколько сейчас времени? Чему точно должно равняться вычисленное значение функции на тесте?

Эти "простые" вопросы ставят AI в тупик. А ведь ответы на них критически важны для качественной разработки. Представьте: агент предлагает путь к файлу в стиле Windows, а вы работаете на Linux, или несмотря на запреты и напоминания пытается вызвать команды для другой операционной системы.

Решение - MCP (Model Context Protocol) сервер, который дает AI-агентам базовое "самосознание", ориентацию в окружающем мире.

Что такое MCP и зачем он нужен

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 = eval(expression, {"__builtins__": {}}, SAFE_SCOPE)

C# не имеет встроенного eval, поэтому реализован собственный рекурсивный парсер выражений. Это ~400 строк кода, но дает полный контроль над безопасностью.

Определение OS

Все три версии используют похожий подход с платформо-зависимыми особенностями:

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# требует больше кода из-за собственного парсера выражений, но выигрывает в деплое - один бинарник без зависимостей.

Использование с Claude Desktop

После установки сервер настраивается в конфигурационном файле:

{
  "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.