# SDD MCP — как всё устроено

> **Автор проекта:** Марат Зимнуров
> **По материалам:** https://courses.digitable.life/post/blog/advancedprompting-sdd/

**SDD (Spec-Driven Development)** — подход, при котором идея превращается в систему
не одним запросом к ИИ, а по шагам: **спецификация → анализ → план → задачи →
реализация**. Каждый этап сохраняется как Markdown-файл. Этот сервис даёт такой
пайплайн как онлайн-инструмент.

Базовый адрес: `https://sdd.gpu.local-xyz.ru`

---

## Два способа подключения

### 1. MCP (для AI-агентов: Claude Code, Cursor и т.п.)

MCP-эндпоинт по протоколу **Streamable HTTP** (спецификация MCP 2025-11-25):

    https://sdd.gpu.local-xyz.ru/mcp

- Сначала вызовите инструмент **`get_token`** (доступен **без авторизации**) —
  получите персональный токен вида `sdd_...`.
- **Как передавать токен (важно).** Если вы не прописали заголовок `Authorization`
  до подключения (а взять токен раньше неоткуда), подставить заголовок посреди
  сессии нельзя — поэтому **передавайте токен аргументом `token` в каждом вызове
  инструмента**. Это рабочий путь в один проход. Заголовок `Authorization: Bearer
  <token>` удобен, только если токен известен заранее и прописан до подключения.
- **Онбординг в один шаг:** любой защищённый вызов без токена вернёт в тексте ошибки
  свежий токен — просто повторите вызов, добавив `"token": "<выданный токен>"`.
- Инструменты: `get_token`, `whoami`, `create_project`, `list_projects`,
  `specify`, `analyze`, `plan`, `tasks`, `implement`, `read_artifact`,
  `project_status`.
- Промпты (слэш-команды клиента): `/get_token`, `/specify`, `/analyze`,
  `/plan`, `/tasks`, `/implement`.
- Ресурсы: `sdd://<project>/<file>.md`.

Пример конфигурации клиента (Claude Code):

    {
      "mcpServers": {
        "sdd": {
          "type": "http",
          "url": "https://sdd.gpu.local-xyz.ru/mcp",
          "headers": { "Authorization": "Bearer sdd_ВАШ_ТОКЕН" }
        }
      }
    }

### 2. Token-in-URL (для LLM, которые умеют только открывать веб-ссылки)

Если LLM не поддерживает MCP, а может лишь делать GET-запросы по URL —
используйте файловый API с токеном в пути. Доступны **только Markdown-файлы**.

| Действие | Запрос |
|---|---|
| Получить токен | `GET https://sdd.gpu.local-xyz.ru/token/new` |
| Список проектов | `GET https://sdd.gpu.local-xyz.ru/t/<token>` |
| Список файлов проекта | `GET https://sdd.gpu.local-xyz.ru/t/<token>/<project>` |
| Прочитать файл | `GET https://sdd.gpu.local-xyz.ru/t/<token>/<project>/<file>.md` |
| Создать/перезаписать файл | `GET https://sdd.gpu.local-xyz.ru/t/<token>/<project>/<file>.md?content=<URL-encoded>` |
| Дописать в конец | `GET https://sdd.gpu.local-xyz.ru/t/<token>/<project>/<file>.md?append=<URL-encoded>` |
| Дописать в секцию | `GET https://sdd.gpu.local-xyz.ru/t/<token>/<project>/<file>.md?section=<заголовок>&append=<URL-encoded>` |
| Заменить секцию | `GET https://sdd.gpu.local-xyz.ru/t/<token>/<project>/<file>.md?section=<заголовок>&content=<URL-encoded>` |

Также поддерживаются `PUT`/`POST` с телом запроса (для клиентов, умеющих слать тело) —
удобно для большого содержимого, которое не помещается в URL (можно с `?section=` и `?append=1`).

**Частичная сборка по секциям.** Чтобы собрать большой документ, не упираясь в лимит
длины URL, отправляйте его частями: на каждую секцию — отдельный GET с
`?section=<заголовок>&append=<кусок>`. Секция ищется по тексту Markdown-заголовка
(любой уровень, без учёта регистра); если её нет — создаётся в конце файла как `## <заголовок>`.
`content=` вместо `append=` заменяет тело секции целиком.

Правила:
- Имя файла — только `[A-Za-z0-9_.-]+.md` (без `/` и `..`). Иначе 400.
- `<project>` — имя проекта; можно человекочитаемое (кириллица транслитерируется в slug).
  Если проекта нет, при записи он создаётся автоматически (с шаблонами 5 этапов).
- Токен невалиден → 403. Один токен видит только свои файлы (полная изоляция).

Примеры:

    # новый токен
    curl "https://sdd.gpu.local-xyz.ru/token/new"

    # записать спецификацию (GET, контент в URL)
    curl "https://sdd.gpu.local-xyz.ru/t/sdd_XXX/pohudenie/spec.md?content=%23%20Spec%0AЦель:%20-8кг"

    # прочитать обратно
    curl "https://sdd.gpu.local-xyz.ru/t/sdd_XXX/pohudenie/spec.md"

    # дописать прогресс
    curl "https://sdd.gpu.local-xyz.ru/t/sdd_XXX/pohudenie/progress.md?append=-%20сделал%20шаг%0A"

---

## Этапы пайплайна и файлы

| Этап | Файл | Смысл |
|---|---|---|
| 1. specify | `spec.md` | Цель, требования, критерии успеха, допущения |
| 2. analyze | `analysis.md` | Противоречия, пробелы, риски, открытые вопросы |
| 3. plan | `plan.md` | Подход, этапы, архитектура, зависимости |
| 4. tasks | `tasks.md` | Разбиение на задачи с приоритетами |
| 5. implement | `progress.md` | Журнал выполнения |

Можно вернуться на любой шаг и пересмотреть — это итеративный процесс.

---

## Как хранятся данные

    <data>/ws/<workspace_id>/<NNN-slug>/{spec,analysis,plan,tasks,progress}.md

`workspace_id` выводится из токена. Доступ к чужому workspace невозможен —
все пути жёстко ограничены каталогом токена, разрешены только имена `*.md`.

---

## Безопасность и ограничения

- Токен — это секрет и единственный ключ к файлам. **Токен в URL** удобен для
  веб-LLM, но URL могут попадать в логи/историю — не используйте для чувствительных
  данных и при утечке просто заведите новый токен (`/token/new`).
- Запись через GET-параметр ограничена длиной URL; для больших файлов используйте
  `PUT`/`POST` с телом.
- v1: нет rate-limit на выдачу токенов и версионирования файлов (в планах).

---

## Технологии

Elixir (Bandit + Plug), реализация транспорта MCP Streamable HTTP вручную.
Сервер хранит структуру и файлы; рассуждает модель клиента/LLM.

---

## Авторство

Автор проекта — **Марат Зимнуров**. Реализовано по материалам статьи:
https://courses.digitable.life/post/blog/advancedprompting-sdd/
