blocksnet-mcp
by Eynor-K
README.md
# blocksnet-mcp
`blocksnet-mcp` - локальный MCP-сервер городской аналитики поверх `BlocksNetAgent`.
Сервер предоставляет один основной инструмент `analyze_urban_question(...)`: принимает вопрос на
естественном языке, запускает полный рассуждающий агент BlocksNet на локальной модели города и
возвращает строгий машиночитаемый JSON.
Проект следует подходу **WIKI-LLM**: документация и директории индексируются так, чтобы LLM могла быстро
понять назначение репозитория, выбрать нужные файлы и не загружать весь проект в контекст.
Главный навигационный индекс: [docs/WIKI-LLM.md](docs/WIKI-LLM.md).
## Концепция
Выбран **Вариант 2**: не выносить 33 внутренних инструмента `blocksnet` как отдельные MCP-tools, а
обернуть агента целиком.
Причина: ценность системы не только в расчетах, а в рассуждающем слое агента:
1. PTR-цикл `predict -> test -> revise`: фальсифицируемые гипотезы до расчетов и классификация исхода.
2. RAG по инструментам: короткие описания плюс полные карточки через `find_tools` / `get_tool_help`.
3. Инварианты качества M1-M3, C1/C2/C3, C-Hyp: проверка заземленности, измеренности и самосогласованности.
4. Измеренные предложения развития: TPE-оптимизация зон и сценарная проверка `before -> after`.
MCP-слой остается тонким: читает настройки, вызывает `BlocksNetAgent.run(...)`, сериализует результат.
## Текущий объем
Текущий MVP рассчитан на локальную работу:
| Область | Решение |
|---|---|
| Транспорт | `stdio`, сервер запускается MCP-клиентом как подпроцесс |
| Данные | локальная папка `data/` через `DATA_DIR` |
| LLM | внешний OpenAI-совместимый API (`CHAT_URL`, `API_KEY`, `MODEL`) |
| Инструмент | `analyze_urban_question(question, max_iterations?)` |
| Выход | JSON с планом, результатом, гипотезами, измеренными эффектами, ограничениями и артефактами |
Вне текущего объема: UrbanDB-контекст (`scenario_id` / `project_id`), HTTP-транспорт, Bearer-авторизация,
Docker-деплой и регистрация в MAS. В этом репозитории реализован только локальный stdio MCP.
## Архитектура MVP
```text
Локальный MCP-клиент
-> stdio
-> blocksnet_mcp.server
-> tools_mcp.analyze_urban_question
-> BlocksNetAgent.run(question)
-> serialize.to_json(result)
-> JSON-ответ MCP-клиенту
```
Структура репозитория:
```text
blocksnet-mcp/
├── README.md
├── .env.example
├── .gitignore
├── requirements.txt
├── .python310/ # локальный Python 3.10.11, gitignored
├── .venv/ # локальное окружение Python 3.10.11, gitignored
├── docs/
│ ├── README.md
│ ├── WIKI-LLM.md
│ ├── overview_and_concept.md
│ ├── architecture.md
│ ├── tool_contract.md
│ ├── deployment.md
│ ├── mcp_repository_plan.md
│ ├── mas_integration_reference.md # 🕘 Future-справка, gitignored
│ └── mas_registration.md # 🕘 Future-справка, gitignored
├── blocksnet_mcp/
│ ├── README.md
│ ├── server.py
│ ├── tools_mcp.py
│ ├── serialize.py
│ ├── settings.py
│ └── __init__.py
├── blocksnet_agent/
│ ├── README.md
│ └── ... ядро агента из blocksnet-agent (agent.py / hypotheses.py / metrics.py / tools/...)
├── data/
│ ├── README.md # опц., локальный индекс
│ ├── service_type.json
│ ├── archetypes.csv
│ ├── service_aliases.json
│ ├── blocks_with_services.gpkg # gitignored
│ ├── acc_mx.pickle # gitignored
│ └── <local-city-sandbox>/ # gitignored (например, saint_petersburg/)
├── tests/
│ ├── README.md
│ ├── test_serialize.py
│ ├── test_tool_contract.py
│ ├── test_async_mcp_contract.py
│ ├── test_confidence_signals.py
│ ├── test_overlay_candidates.py
│ ├── test_ptr_classifier.py
│ ├── test_runtime.py
│ ├── test_provision_cache.py
│ ├── test_numeric_metric_resolution.py
│ ├── test_provision_summaries.py
│ ├── test_target_block_selection.py
│ ├── test_tool_failure_dedup.py
│ ├── test_no_data_grounding.py
│ └── test_experiment_harness.py
├── scripts/
│ ├── README.md
│ └── smoke_client.py
├── examples/
│ ├── README.md
│ ├── test_visualization.ipynb
│ ├── saint_petersburg/main.py
│ ├── saint_petersburg/data/ # gitignored
│ └── yuzhno-sakhalinsk/ # gitignored
├── docs/
│ ├── reports/
│ │ ├── test_report_20260618.md
│ │ └── run_quality_report_20260706_spb.md
│ ├── mcp_repository_plan.md # 🕘 локальный план, gitignored
│ ├── mas_integration_reference.md # 🕘 Future-справка, gitignored
│ └── mas_registration.md # 🕘 Future-справка, gitignored
└── outputs/ # runtime-артефакты, gitignored
```
## Контракт инструмента
`analyze_urban_question(question: str, max_iterations: int | None = None)` возвращает **структурный JSON**
(P1.1 — payload терминального `submit_answer` агента, P1.2 — авторитетная `confidence` + самооценка
+ basis, P1.6 — `overlay_candidates` как fallback для `recommendation_blocks`):
```jsonc
{
"question": "...",
"analysis_plan": "...",
"result": "...",
"reflection": "...",
"recommendations": [
{ "block_id": 4940, "service_type": "school", "added_capacity": null, "rationale": "..." }
],
"measured_effects": [
{ "service_type": "pitch", "strong_before": 0.732, "strong_after": 0.781,
"missing_before": 785, "missing_after": 769, "source": "compute_scenario_provision" }
],
"recommendation_blocks": [4940],
"confidence": 0.55,
"confidence_self": 0.78,
"confidence_basis": ["hypotheses=2/2_supported*0.25=+0.25", "data_basis=1.0*0.30=+0.30"],
"overlay_candidates": [...],
"overlay_meta": { "hard_passed": 5, "hard_total": 5, "diagnostic_layers": 1, "nondiagnostic_layers": 0 },
"limitations": ["..."],
"artifacts": ["maps/provision.png", "scenario.csv"],
"run_id": "run_20260706_...",
"run_dir": "outputs/run_20260706_...",
"status": "ok", // "ok" | "partial" | "failed"
"salvaged": false
}
```
Полная спецификация: [docs/tool_contract.md](docs/tool_contract.md). Regex-fallback-поля
(`measured` / `hypotheses` как строковый массив) описаны там же — в fallback-пути с
`salvaged: true` и `limitations += ["SALVAGED_ANSWER"]`.
## Локальный запуск
Рабочее локальное окружение уже создано в репозитории:
| Путь | Назначение | Git |
|---|---|---|
| `.python310/` | portable Python `3.10.11` для проекта | ignored |
| `.venv/` | виртуальное окружение на Python `3.10.11` | ignored |
| `requirements.txt` | зависимости локального MCP и BlocksNetAgent | yes |
```bash
.\.venv\Scripts\python.exe -m pytest tests
.\.venv\Scripts\python.exe scripts\smoke_client.py
.\.venv\Scripts\python.exe -m blocksnet_mcp.server
```
Минимальный `.env` (текущий шаблон — Ollama Cloud; для OpenAI-совместимых endpoint'ов можно
подставить `CHAT_URL` и `MODEL` оттуда):
```env
CHAT_URL=https://ollama.com/v1
API_KEY=your_ollama_cloud_api_key_here
MODEL=minimax-m3:cloud
DATA_DIR=./data
OUTPUT_DIR=./outputs
MAX_ITERATIONS=10
```
Опционально (имеют дефолты в `settings.py`): `DEADLINE_SEC=480` — серверный дедлайн прогона,
`PROGRESS_INTERVAL_SEC=10.0` — интервал `notifications/progress`.
Пример конфигурации MCP-клиента:
```jsonc
{
"mcpServers": {
"blocksnet": {
"command": "P:/AI_asistent/ITMO/blocksnet-mcp/.venv/Scripts/python.exe",
"args": ["-m", "blocksnet_mcp.server"],
"cwd": "P:/AI_asistent/ITMO/blocksnet-mcp",
"env": {
"CHAT_URL": "https://ollama.com/v1",
"API_KEY": "your_ollama_cloud_api_key_here",
"MODEL": "minimax-m3:cloud",
"DATA_DIR": "./data",
"OUTPUT_DIR": "./outputs",
"MAX_ITERATIONS": "10"
}
}
}
}
```
Подробнее: [docs/deployment.md](docs/deployment.md).
## Индексация WIKI-LLM
| Индекс | Назначение |
|---|---|
| [docs/WIKI-LLM.md](docs/WIKI-LLM.md) | Главная карта проекта для LLM-навигации |
| [docs/README.md](docs/README.md) | Человекочитаемый индекс документации |
| [blocksnet_mcp/README.md](blocksnet_mcp/README.md) | Индекс реализованного MCP-слоя |
| [blocksnet_agent/README.md](blocksnet_agent/README.md) | Индекс переносимого ядра агента |
| [data/README.md](data/README.md) (опц.) | Локальный индекс данных |
| [tests/README.md](tests/README.md) | Индекс контрактных тестов |
| [scripts/README.md](scripts/README.md) | Индекс локальных smoke-проверок MCP |
| [examples/README.md](examples/README.md) | Индекс интерактивных блокнотов и локальных примеров |
## Документация
| Документ | О чем |
|---|---|
| [docs/overview_and_concept.md](docs/overview_and_concept.md) | что строится, зачем MCP-обертка целиком, границы локального режима |
| [docs/architecture.md](docs/architecture.md) | структура, модули, поток запроса, транспорт |
| [docs/tool_contract.md](docs/tool_contract.md) | вход и выход `analyze_urban_question` |
| [docs/deployment.md](docs/deployment.md) | локальная установка и подключение MCP-клиента |
| [docs/mcp_repository_plan.md](docs/mcp_repository_plan.md) (опц.) | план переноса ядра агента и реализации MVP (локальный, gitignored) |
| [examples/test_visualization.ipynb](examples/test_visualization.ipynb) | интерактивная визуализация тестов, run logs, артефактов и карт |
| `examples/<local-city-example>/` | локальные городские примеры/датасеты (например, Санкт-Петербург, Южно-Сахалинск); данные и артефакты держать вне Git |
| `docs/mas_integration_reference.md` 🕘 | future-справка по MAS/UrbanDB, локальная и gitignored |
| `docs/mas_registration.md` 🕘 | future-строки реестра Urban services, локальная и gitignored |
## Статус
Локальный MVP реализован: ядро `BlocksNetAgent` перенесено, stdio MCP-сервер добавлен, JSON-сериализация
и контрактные тесты находятся в `tests/`. Окружение собрано на Python `3.10.11`; `pip check` чистый,
`pytest` проходит (контрактные + сериализация + P1.1/P1.2/P1.6 unit-тесты), MCP stdio smoke проходит
через `scripts/smoke_client.py`. Текущий LLM-провайдер — **Ollama Cloud** (`minimax-m3:cloud`);
контракт ответа использует P1.1 `submit_answer`, P1.2 авторитетную `confidence` + `confidence_self`
+ `confidence_basis`, P1.6 `overlay_candidates` как fallback для `recommendation_blocks`. Сводный
отчёт по результатам качества прогонов от 06.07.2026: [docs/reports/run_quality_report_20260706_spb.md](docs/reports/run_quality_report_20260706_spb.md).
Источник истины по текущему объему - этот README, [docs/WIKI-LLM.md](docs/WIKI-LLM.md), код
`blocksnet_mcp/`, контракт [docs/tool_contract.md](docs/tool_contract.md) и архитектура
[docs/architecture.md](docs/architecture.md).
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues