Перейти к содержимому
RAGRAF

Гайд по настройке

Подключение RAGRAF к DeepSeek Harness

--agent-kind external MCP · stdio · JSON-RPC mcp__ragraf__ragraf_* подтверждено замерами · dsh 0.2.0-rc.2

Electron-приложение DeepSeek Harness 0.2.0-rc.2 со встроенным MCP-клиентом (плагин @deepseek-ai/dsh-mcp-client). RAGRAF подключается к нему как MCP-сервер по stdio; инструменты становятся видны под именами mcp__ragraf__ragraf_*. Связка отлажена до конца и подтверждена замерами живой сессии: всё ниже — повторяемые команды, пути и измеренные выводы.

  • dsh 0.2.0-rc.2 · Electron
  • 24 инструмента ragraf_*
  • 3 правки RAGRAF
  • 4 уровня проверки

Обозначения в командах: $repo — путь к локальному клону RAGRAF (сниппеты задают его первой строкой), $dsh — поставляемый CLI приложения. Команды и выводы приводятся как измерены — включая русские строки, которые печатает продукт.

Источник: документ интеграционной сессии «RAGRAF × DeepSeek Harness» — повторяемые команды, пути и измеренные выводы живой сессии (dsh 0.2.0-rc.2).

Как это устроено

Почему stdio, а не streamable-http

MCP-клиент HARNESS объявляет capabilities: {} — корней (roots) сервер не получает. Подними RAGRAF по HTTP как один сервис — и «какой сейчас проект» определить нечем: текущий каталог клиента до сервера не доходит. У stdio-сервера рабочий каталог процесса известен, и корпус определяется по реестру разработок.

Почему один сервер на все проекты

Клиент HARNESS не даёт инструментам RAGRAF перезапустить себя, а держать по серверу на проект значило бы держать по копии индекса в памяти на каждый. Вместо этого корпус переключается операцией mcp__ragraf__use_project, а корпус по умолчанию определяется по рабочему каталогу через реестр. Не нашёлся — сервер всё равно поднимается, честно отвечает на catalog и use_project, а остальным операциям отказывает с причиной.

ЧтоГде
Точка входа сервераtools/ragraf-mcp.py · репозиторий RAGRAF
Встроенные 24 инструментаsrc/ragraf/mcp_server.py
Фасад операций (22)src/ragraf/facade.py
Реестр корпусовcatalog/catalog.json
Слой патчей профиля%USERPROFILE%\.dsh\profiles\desktop\cordis.patch.yml
Навык%USERPROFILE%\.dsh\skills\ragraf-core\SKILL.md
Глобальные правила%USERPROFILE%\.dsh\AGENTS.md · раздел 6

Что было доработано в RAGRAF

Дефект был не «неудобно», а «не работает вовсе»: первый же ответ с русским текстом убивал сервер. Измерено запуском — три причины, каждая подтверждена замером.

Как выглядел дефект (замер)
UnicodeEncodeError: 'charmap' codec can't encode characters in position 97-105
  File "src/ragraf/mcp_server.py", line 551, in send
    sys.stdout.write(json.dumps(message, ensure_ascii=False) + "\n")
  1. Кодировка потокаMCP SDK передаёт дочернему процессу лишь 12 переменных (APPDATA, PATH, TEMP, USERPROFILE и др. — DEFAULT_INHERITED_ENV_VARS), а HARNESS дополнительно вычищает имена с PASSWORD|SECRET|TOKEN|KEY и все DSH_*. Ни PYTHONUTF8, ни PYTHONIOENCODING в набор не входят — локаль процесса остаётся cp1252. Правка: force_utf8_stdio() перенастраивает stdin, stdout, stderr на UTF-8, не полагаясь на окружение.
  2. Зависимостиfastembed, PyYAML, sqlite_vec, tree_sitter, ijson были достижимы интерпретатору из PATH только через переменную PYTHONUSERBASE — HARNESS её вычищает, и сервер рапортует «не установлен PyYAML». Решение: сервер запускается интерпретатором из .venv самого проекта — замерено, что при полностью снятых PYTHON*-переменных он импортирует все пакеты.
  3. Обязательный --projectКлиент, запускающий сервер без аргументов, не мог стартовать вообще. Правка: --project больше не обязателен — корпус определяется по рабочему каталогу через реестр (_resolve_default_project()), для ручного переключения добавлен инструмент ragraf_use_project, а --agent берётся ещё и из переменной RAGRAF_AGENT.
ФайлЧто сделано
src/ragraf/mcp_server.pyforce_utf8_stdio(); --project больше не обязателен; _resolve_default_project(); инструмент ragraf_use_project; --agent берётся ещё и из RAGRAF_AGENT; отказ при невыбранном корпусе — понятный текст вместо ConfigError
src/ragraf/cli.pyкоманда reindex теперь записывает прогон в реестр, как index
tests/test_mcp_compat.pyновый файл: проверки на урезанное окружение, автоопределение корпуса и переключение
tools/Invoke-ProjectDoctrine.ps1проверки Test-McpClientCompatibility и Test-ExternalOpsAreRecorded; правило записи в реестр смотрит каждую функцию, запускающую индексатор, а не файл целиком (16 проверок вместо 14)
README.md · INTEGRATION.md · AGENTS.mdчисла приведены к коду: 24 инструмента; задокументированы «три ловушки» с замерами

Совместимость с прежними клиентами сохранена: AutoClaw и SagaAI передают --project явно и выставляют PYTHONIOENCODING — для них ничего не изменилось.

Установка — три шага

Все три шага кладут файлы в домашний каталог HARNESS (%USERPROFILE%\.dsh или $DSH_HOME); готовые блоки лежат в каталоге harness/ репозитория RAGRAF. В командах ниже $repo — путь к локальному клону RAGRAF, $dsh — поставляемый CLI приложения.

  1. Подключите MCP-серверГотовый блок harness/ragraf-mcp.patch.yml дописывается в конец слоя патчей профиля cordis.patch.yml. Приложение хранит патчи массивом, поэтому блок вставляется отдельной строкой «- insert:». Сначала бэкап — файл принадлежит пользователю.
    Дописывание патч-блока (PowerShell)
    $repo = 'C:\AutoClaw\RAGRAF'   # путь к локальному клону RAGRAF
    $src  = Join-Path $repo 'harness\ragraf-mcp.patch.yml'
    $dst  = Join-Path ([Environment]::GetFolderPath('UserProfile')) '.dsh\profiles\desktop\cordis.patch.yml'
    
    # 1. бэкап (обязательно: файл принадлежит пользователю)
    Copy-Item $dst "$dst.bak-$(Get-Date -Format yyyyMMdd-HHmmss)"
    
    # 2. проверить, что блока ещё нет
    Select-String -LiteralPath $dst -Pattern 'mcp-ragraf'
    
    # 3. дописать блок (слой патчей — массив; блок вставляется отдельной строкой "- insert:")
    Add-Content -LiteralPath $dst -Value (Get-Content -LiteralPath $src -Raw) -Encoding utf8NoBOM

    Проверить, что патч применяется — без запуска приложения:

    Проверка через dsh --dump-config
    $dsh = Join-Path $env:LOCALAPPDATA 'Programs\DeepSeek Harness\resources\runtime\cli\bin\dsh.cmd'
    & $dsh --profile headless --patch $src --dump-config | Select-String 'serverName: ragraf' -Context 1,3

    Профиль desktop — рабочий профиль приложения; headless — одноразовые задачи из командной строки. Для профиля, отличного от desktop, блок кладётся в его cordis.patch.yml тем же способом.

  2. Установите навыкКорень навыков %USERPROFILE%\.dsh\skills читает провайдер @deepseek-ai/dsh-skill-filesystem: на верхнем уровне он ищет <имя>/SKILL.md. Навык в этом каталоге обнаруживается без перезапуска — провайдер следит за корнем.
    Установка навыка ragraf-core
    $skills = Join-Path ([Environment]::GetFolderPath('UserProfile')) '.dsh\skills\ragraf-core'
    New-Item -ItemType Directory -Path $skills -Force | Out-Null
    Copy-Item (Join-Path $repo 'harness\skills\ragraf-core\SKILL.md') "$skills\SKILL.md" -Force
  3. Добавьте правило в глобальные инструкцииHARNESS читает %USERPROFILE%\.dsh\AGENTS.md (модуль dsh-agent-instructions; dshHome = $DSH_HOME или ~/.dsh). Раздел для вставки — harness/agents-section.md; ставится перед разделом «Журнал изменений», иначе правило окажется после истории (в проверенной установке это раздел 6). Ожидаемое поведение: на вопрос «с чего начинается задача о коде» агент отвечает mcp__ragraf__ensure и ссылается на этот раздел.

Проверка — четыре уровня

От узкого к широкому: сервер сам по себе → живой запуск внутри приложения → навык → чекер проекта. Каждый уровень — команда и ожидаемый вывод, измеренные в живой сессии.

Проверка того самого дефекта: PYTHONUTF8 и PYTHONIOENCODING сняты перед запуском — так, как это делает HARNESS. Тест — tests/test_mcp_compat.py: урезанное окружение, автоопределение корпуса, переключение.

Тест совместимости (PowerShell)
cd $repo
Remove-Item Env:\PYTHONUTF8, Env:\PYTHONIOENCODING -ErrorAction SilentlyContinue
python tests\test_mcp_compat.py

Ожидаемый вывод

Text
ИТОГ: пройдено 13, провалено 0

Три ограничения, которые надо знать

Перезапуск приложения обязателен

Настройки профиля читаются при старте. Вставленный блок mcp-ragraf начнёт работать после перезапуска DeepSeek Harness; до этого инструментов mcp__ragraf__* в интерфейсе не будет. Это нормальное поведение, а не сбой.

Висящий сервер Joern при индексации

Полная индексация поднимает Joern (JVM) на порту 9500. Замерено: после первой переиндексации остался процесс java.exe на 3 ГБ, державший порт; снят вместе с родительским cmd.exe (taskkill /PID <cmd> /T /F). Перед долгой работой и после неё проверяйте процессы и порт:

Проверка висящего Joern (PowerShell)
Get-CimInstance Win32_Process -Filter "Name='java.exe'" |
  Select-Object ProcessId, @{n='MB';e={[int]($_.WorkingSetSize/1MB)}}
Get-NetTCPConnection -LocalPort 9500 -ErrorAction SilentlyContinue

# висящий сервер снимается вместе с родительским процессом:
taskkill /PID <PID родительского cmd.exe> /T /F

Команда reindex теряла запись прогона в реестре

Найдено и исправлено при работе над этой же задачей: index записывал результат в реестр, а reindex — нет. Замерено на корпусе самого RAGRAF: в индексе rev-0046, в реестре rev-0045 — из-за этого check реиндексировал корпус заново на каждой проверке, что выглядело как «RAGRAF тормозит». Признак расхождения: catalog показывает ревизию, отличную от index_status. Правило чекера теперь смотрит каждую функцию, запускающую индексатор.

Откат

HARNESS: вернуть слой патчей и AGENTS.md из бэкапов (их имена печатала установка), удалить каталог навыка ragraf-core.

Откат — настройки HARNESS (PowerShell)
$home2 = [Environment]::GetFolderPath('UserProfile')
# 1. вернуть слой патчей из бэкапа (имя печатала установка)
Copy-Item "$home2\.dsh\profiles\desktop\cordis.patch.yml.bak-<метка>" `
          "$home2\.dsh\profiles\desktop\cordis.patch.yml" -Force
# 2. вернуть глобальные правила
Copy-Item "$home2\.dsh\AGENTS.md.bak-<метка>" "$home2\.dsh\AGENTS.md" -Force
# 3. убрать навык
Remove-Item "$home2\.dsh\skills\ragraf-core" -Recurse -Force

RAGRAF: правки аддитивные — они не затрагивают индекс, схему хранилища, нумерацию ревизий и реестр, поэтому откат не требует переиндексации. Чтобы вернуть прежнее поведение, достаточно трёх изменений: убрать вызов force_utf8_stdio(), вернуть required=True у --project и удалить инструмент ragraf_use_project из TOOLS и _handlers.

Поведение HARNESS: где лежит что

ЧтоГде
Установка приложения%LOCALAPPDATA%\Programs\DeepSeek Harness
Плагины HARNESSresources\app.asar · дерево dsh/node_modules
Домашний каталог HARNESS%USERPROFILE%\.dsh
Настройки профилей%USERPROFILE%\.dsh\profiles\<имя>
Данные Electron%APPDATA%\@deepseek-ai\dsh-desktop
Реестр плагиновhttps://registry.npmjs.org/
CLIresources\runtime\cli\bin\dsh.cmd

Домашним каталогом управляют переменные DSH_HOME (явный путь важнее) и DSH_AGENTS_HOME (общий каталог навыков агентов, по умолчанию ~/.agents). Из окружения дочерних процессов HARNESS вычищает обе — на запуск MCP-сервера это не влияет: он читает только --project и рабочий каталог.

Порядок разрешения корней навыков (rank): <проект>/.dsh/skills (100), <проект>/.agents/skills (200), пользовательские customSkillDirs (300), ~/.dsh/skills (400), ~/.agents/skills (500). Проектный корень — ближайший каталог с .git.

HARNESS разрабатывается в приватном репозитории (github.com/deepseek-ai/deepseek-harness); публичной проверки API не делалось. Контракт выше описан по фактам текущей установки — lib/index.js и README пакетов внутри app.asar, — а не по документации.

Регламент агента

Регламент поставляется двумя слоями: навык ragraf-core (провайдер загружает его без перезапуска) и раздел глобальных правил %USERPROFILE%\.dsh\AGENTS.md — «задача о коде начинается с mcp__ragraf__ensure». Универсальный фрагмент регламента (страница «Интеграции») — основа навыка; он работает и сам по себе.

Телеметрия

Телеметрия идентична другим external-агентам: kind=external, хеши аргументов вместо полных текстов запросов, оценка токенов (символы/4) в usage_call — можно сравнивать экономику связки с grep-подходом. Имя агента задаёт --agent в патч-блоке или переменная RAGRAF_AGENT: сервер читает её со времён HARNESS-правок.