Skip to main content
Glama
borovkov-d

BuildWindow

by borovkov-d

BuildWindow

MCP 실습 프로젝트: 에이전트가 두 개의 MCP 서버를 사용하여 실제 날씨 예보를 바탕으로 공사 일정을 계획합니다.

이 프로젝트는 KSE AI 에이전틱 스쿨의 수업 과제입니다(MCP 통합 과제): 실제 도메인 문제를 위한 커스텀 MCP 서버를 구축한 다음, 기존의 서드파티 MCP 서버와 함께 에이전트에 연결하여, 단일 도구로는 할 수 없는 작업을 두 서버가 함께 수행하도록 합니다.

개요

BuildWindow는 구체적인 일정 계획 문제를 중심으로 구축된 MCP(Model Context Protocol) 실습 프로젝트입니다: 의존 관계가 있는 공사 작업 목록과 도시의 날씨 예보가 주어졌을 때, 두 가지를 모두 존중하는 일정을 생성합니다. 이 계획을 수행하는 에이전트는 두 개의 별도 MCP 연결을 동시에 유지합니다. 첫 번째는 외부 Go 기반 OpenWeather MCP 서버(github.com/mschneider82/mcp-openweather)로, 에이전트가 실행당 한 번 호출하여 요청된 도시의 실시간 현재 기상과 5일 예보를 가져옵니다 — 이 프로젝트 전체에서 네트워크 호출이 발생하는 유일한 지점입니다. 두 번째는 이 저장소 자체의 BuildWindow MCP 서버입니다: 런타임에 네트워크 호출이 전혀 없는 완전히 결정론적인 로컬 서버로, 공사 작업 유형과 날씨 제한에 대한 로컬 JSON 데이터셋을 기반으로 하며, 공사 도메인 규칙을 인코딩하는 네 가지 도구(날씨 적합성 판정, 양생 시간 추정, 다중 작업 일정 계획)를 노출합니다.

두 서버는 의도적으로 책임이 겹치지 않습니다. OpenWeather MCP는 매일 달라지는 유일한 정보 — 날씨 자체 — 의 유일한 출처입니다. BuildWindow MCP는 대신 고정된 규칙인 모든 것을 담당합니다: 주어진 작업 유형이 허용하는 온도, 바람, 습도, 강수량, 주어진 온도에서 콘크리트가 양생되는 데 걸리는 시간, 그리고 여러 의존 작업을 다일 예보에 걸쳐 가장 이른 비금지 시간대에 배치하는 방법. BuildWindow 서버는 공식 Python MCP SDK(패키지 mcp, v2.0.0+)의 MCPServer 클래스를 사용하여 구축되었습니다 — 참고로 이 클래스는 이전 SDK 버전에서는 FastMCP라는 이름이었으며 SDK v2.0.0부터 MCPServer로 이름이 변경되었습니다. 두 연결을 모두 구동하는 에이전트는 Claude Agent SDK(PyPI의 claude-agent-sdk)로 구축되었습니다.

일정에 중요한 OpenWeather 호출은 의도적으로 LLM이 수행하지 않습니다. 업스트림 도구의 실제 출력(소스 코드를 읽어 확인 — docs/tool-contracts.md 참조)은 JSON이 아닌 일반 텍스트 보고서이며, 어떤 실패(잘못된 키, 인식되지 않은 도시, 공급자에 연결할 수 없음)에 대해 제공하는 유일한 신호는 구문상 성공했지만 빈 응답입니다 — 반응할 오류 텍스트가 없습니다. 따라서 agent/main.py는 저수준 MCP 클라이언트를 통해 직접 호출하고, 작고 단위 테스트된 함수(agent/normalize.py)로 파싱한 다음에야 LLM 세션을 시작합니다 — 모델에게 원시 공급자 텍스트를 해석하도록 요청하는 대신 이미 정리된 일일 수치를 전달합니다. LLM 세션은 두 MCP 서버 모두에 연결되며(get_mcp_status() 검색은 두 연결을 모두 표시), 모델은 실제로 날씨 도구를 직접 호출할 수 있습니다(allowed_tools에 명시적으로 나열됨) — 그러나 시스템 프롬프트에 따라 최종 보고서의 현재 기상 한 문장에만 사용됩니다. plan_work_schedule을 구동하는 일일 예보는 항상 세션 전 결정론적 가져오기에서 오며, 모델 자체 호출에서 오지 않습니다. 두 서버 모두 에이전트 자체 흐름에서 실제로 사용되며, 단지 표시만 되는 것이 아닙니다.

engineer input (city + work list)
  -> agent/main.py calls OpenWeather MCP directly (not via the LLM) for
     the schedule-critical daily forecast
  -> agent/normalize.py parses the plain-text response into daily figures
  -> (if no usable forecast: report plainly, stop -- no LLM session started)
  -> LLM session starts, connected to BOTH MCP servers; may itself call
     the weather tool once for current-conditions color commentary only
  -> given the daily forecast + works as plain JSON (the only input that
     ever drives scheduling)
  -> BuildWindow MCP  (plan_work_schedule, validate_work_window,
     estimate_curing_time, ...)
  -> schedule + explanation

Related MCP server: condensation-mcp

사전 요구 사항

  • Python 3.12+ — 이 저장소는 3.12.3에서 빌드 및 테스트되었습니다.

  • uv — 이 프로젝트의 의존성 관리자로 사용됩니다.

  • Go 1.24+ — OpenWeather MCP 서버를 직접 빌드하려는 경우에만 필요합니다(여기서는 winget install --id GoLang.Go로 설치, 현재 Go 1.26.7). BuildWindow 서버를 사용하거나 테스트를 실행하는 데는 필요하지 않습니다.

  • OpenWeather API 키 — 실제 날씨에 대한 라이브 에이전트 실행에만 필요합니다. 무료 티어는 openweathermap.org/api에서 제공됩니다.

설치

저장소 루트에서:

uv sync

이렇게 하면 .venv가 생성되고 런타임 의존성(mcp, pydantic, claude-agent-sdk, python-dotenv)과 개발 의존성(pytest, ruff, black)이 모두 설치됩니다.

구성

예제 환경 파일을 복사하고 키를 입력하세요:

Copy-Item .env.example .env

bash: cp .env.example .env

그런 다음 .env를 편집하고 OWM_API_KEY를 openweathermap.org/api(무료 티어)에서 받은 실제 키로 설정하세요. .env는 gitignore되어 있습니다 — 커밋되지 않습니다.

agent/mcp_config.json은 두 MCP 서버 구성의 단일 소스입니다. openweather 항목은 ${OWM_API_KEY}를 플레이스홀더로 참조하며, agent/main.py가 시작 시 프로세스 환경에서 대체합니다. 참고로 agent/main.py는 .env를 직접 읽지 않습니다 — main()이 먼저 python-dotenv의 load_dotenv()를 호출하고, 그 호출이 실제로 .env의 값을 대체가 발생하기 전에 프로세스 환경에 도달하게 합니다.

openweather.command 필드 자체도 플레이스홀더인 ${MCP_OPENWEATHER_PATH}입니다 — agent/main.py는 MCP_OPENWEATHER_PATH 환경 변수가 설정된 경우 이를 확인하고, 그렇지 않은 경우 기본 명령 mcp-openweather(PATH에 의존)로 대체합니다. 바이너리의 디렉터리를 PATH에 추가하고 싶지 않다면 .env(.env.example 참조)에서 MCP_OPENWEATHER_PATH를 바이너리의 절대 경로로 설정하세요 — 둘 다 라이브로 작동하는 것이 확인되었습니다.

OpenWeather MCP 서버 빌드(실제 날씨에 대한 라이브 실행을 원하는 경우에만 필요). 이 저장소의 자체 개발 환경에서 빌드 및 검증하는 데 사용된 정확한 명령은 다음과 같습니다:

winget install --id GoLang.Go -e --accept-source-agreements --accept-package-agreements
# open a new shell so PATH picks up the Go toolchain, then:
go install github.com/mschneider82/mcp-openweather@main

이렇게 하면 $(go env GOPATH)\bin\mcp-openweather.exe에 설치됩니다 — Windows에서는 일반적으로 %USERPROFILE%\go\bin\mcp-openweather.exe입니다. 중요: Go MSI 설치 프로그램은 Go 툴체인(C:\Program Files\Go\bin)을 PATH에 추가하지만, go install이 실제로 빌드된 바이너리를 배치하는 %USERPROFILE%\go\bin은 추가하지 않습니다. 해당 디렉터리를 직접 PATH에 추가하거나, MCP_OPENWEATHER_PATH를 바이너리의 전체 경로로 설정하세요(위 참조) — 이 저장소의 자체 설정은 후자를 사용합니다.

@main이지 @latest가 아닌 이유: go install ...@latest는 태그 v1.0.0으로 확인되는데, 이는 저장소의 main 브랜치보다 한 개의 실제 커밋("Fix #5") 뒤에 있습니다. 이 프로젝트에서 둘 다 빌드하고 라이브로 비교했습니다: v1.0.0은 선택적 units/lang 인수를 완전히 생략했을 때 폴백 없이 읽으므로, 도구 자체 스키마가 기본값을 선언함에도 불구하고 lang을 생략하면 language unavailable로 실패합니다. main의 "Fix #5" 커밋은 방어적 처리를 추가하며 동일한 호출이 성공합니다. 예보 템플릿 자체는 그 외에는 두 버전 간에 동일합니다(두 버전의 소스를 읽어 확인) — main에서 빌드해도 일별 바람/습도/강수량이 추가되지 않으며, 인수 버그만 수정됩니다. agent/main.py는 어떤 경우든 항상 city, units="c", lang="en"을 명시적으로 전달하므로 이 버그는 이 프로젝트를 통해 어느 쪽이든 실제로 표면화될 수 없습니다 — 그러나 도구를 다른 방식으로 호출한다면 main이 의존하기에 더 견고한 바이너리입니다.

일부 업스트림 README 예제에 표시된 -o mcp-weather 플래그를 사용하지 마십시오 — 자체 구성 예제와 일치하지 않는 바이너리 이름이 생성됩니다. 기본 이름인 mcp-openweather로 빌드하세요.

MCP 서버 실행

uv run python -m server.main

이렇게 하면 에이전트 프로세스와 독립적으로 BuildWindow MCP 서버가 stdio를 통해 실행됩니다 — 완전히 단독으로 시작하고 실행할 수 있습니다. 성공하면 stderr에 정확히 다음 줄이 출력됩니다:

BuildWindow MCP server ready: 4 tools, 12 work types loaded

에이전트 실행

uv run python -m agent.main

인수 없이 실행하면 내장 데모 도시("Kyiv")와 내장 데모 작업 목록을 사용합니다: excavation, 그 다음 concrete_pour(이에 의존), 그 다음 concrete_finishing(그에 의존).

둘 다 재정의할 수 있습니다:

uv run python -m agent.main "CityName"
uv run python -m agent.main "CityName" '[{"work_code": "excavation", "duration_days": 1, "depends_on": []}]'

선택적 두 번째 인수는 데모 목록과 동일한 형태의 작업 JSON 배열입니다.

재생 모드 — --forecast-from-file <path>는 완전히 오프라인입니다: 라이브 호출에 사용되는 것과 동일한 결정론적 파서(normalize_forecast, parse_current_conditions)를 통해 기록된 파일에서 읽은 데이터로 일일 예보와 현재 기상 메모를 모두 대체합니다. 이 모드에서는 openweather가 전혀 연결되지 않으므로(get_mcp_status()로 확인 — buildwindow만 표시), 실행에 네트워크 액세스나 API 키가 전혀 필요하지 않습니다 — 의도적으로 깨진 OWM_API_KEY와 연결할 수 없는 MCP_OPENWEATHER_PATH를 동시에 사용하여 라이브로 검증했으며, 실행은 여전히 정상적으로 완료되었습니다:

uv run python -m agent.main "Longyearbyen" '[{"work_code": "excavation", "duration_days": 1, "depends_on": []}, {"work_code": "exterior_painting", "duration_days": 2, "depends_on": []}]' --forecast-from-file fixtures/weather_longyearbyen.txt

fixtures/weather_kyiv.txt와 fixtures/weather_longyearbyen.txt는 이 프로젝트에서 라이브로 캡처한 실제 응답입니다(각각 3일 전체 실제 달력일로 트리밍, 내부에 키 없음) — 합성 또는 제조된 예제가 아닙니다. 데모 도시의 실제 날씨가 실행 시점에 변경되었거나 데모 시점에 네트워크가 전혀 없는 경우 유용합니다.

실제 날씨에 대한 전체 라이브 실행은 진정으로 유효한 OWM_API_KEY(위 구성 참조)가 필요합니다 — 이 저장소의 자체 개발 환경에서 작동이 확인되었습니다: uv run python -m agent.main "Kyiv"는 실제 예보에서 실제 일정을 생성하고, uv run python -m agent.main "Longyearbyen" '[...]'는 실제 날씨가 실제로 일정 변경을 강제하는 것을 보여줍니다(docs/demo-checklist.md 4단계 참조). 작동하는 키가 없으면 agent/main.py는 예보를 직접 가져오고(LLM 경유 아님), 빈 결과를 받고, Forecast unavailable for '<city>' (...)를 출력하고, LLM 세션을 시작하기 전에 종료합니다 — 낭비되는 모델 호출도, 조작된 일정도 없습니다. 이는 세 가지 실제 실패 모드로 검증되었습니다: mcp-openweather 바이너리에 전혀 연결할 수 없음, 잘못된 OWM_API_KEY, 잘못된 도시 이름 — 마지막 두 가지는 이 업스트림 도구를 통해 실제로 구분할 수 없으며(이유는 docs/tool-contracts.md 참조) 둘 다 동일한 깔끔한 방식으로 실패하는 것이 확인되었습니다, 같은 환경의 다른 곳에 진정으로 유효한 키가 활성화되어 있어도 마찬가지입니다.

OpenWeather 속도 제한: 성공적인 라이브 실행 한 번은 weather 도구에 정확히 두 번의 실제 호출을 만듭니다(라이브로 카운트하여 확인) — 결정론적 세션 전 가져오기와 모델 자체의 단일 현재 기상 호출(위 개요 참조). 실패한 라이브 실행(사용 가능한 예보 없음)은 LLM 세션이 시작되지 않으므로 정확히 한 번만 호출합니다. 재생 모드(--forecast-from-file)는 0번 호출합니다 — 일일 예보와 현재 기상 메모 모두 기록된 파일에서 오며, 이 모드에서는 openweather가 전혀 연결되지 않습니다(라이브로 확인: get_mcp_status()는 buildwindow만 표시). OpenWeather 무료 티어는 분당 60회, 월 1,000,000회 호출로 문서화되어 있습니다 — 수동 데모 실행 횟수에는 충분히 넉넉합니다. 이 프로젝트는 게시된 수치 자체를 스트레스 테스트하지 않습니다.

프로젝트 구조

.
├── README.md, DECISIONS.md, pyproject.toml, uv.lock, .env.example, .gitignore
├── docs/
│   ├── tool-contracts.md
│   ├── design-rationale.md
│   └── demo-checklist.md
├── scripts/
│   └── list_tools.py      # proves both MCP connections discover fine offline
├── server/
│   ├── main.py            # MCP server entry point, registers the 4 tools
│   ├── schemas.py         # Pydantic input/output models
│   ├── rules.py           # deterministic verdict/curing/planner logic
│   ├── dataset.py         # loads and validates work_types.json
│   ├── errors.py          # domain exceptions and error codes
│   └── data/work_types.json
├── agent/
│   ├── main.py             # agent entry point (Claude Agent SDK)
│   ├── normalize.py        # deterministic OpenWeather text -> daily figures
│   └── mcp_config.json     # config for both MCP servers
├── fixtures/
│   ├── weather_kyiv.txt      # real captured response, for --forecast-from-file
│   └── weather_longyearbyen.txt  # real captured response, for --forecast-from-file
└── tests/
    ├── conftest.py
    ├── test_dataset.py, test_lookup.py, test_validate.py
    ├── test_curing.py, test_planner.py, test_errors.py
    └── test_normalization.py

도구 개요

도구

요약

lookup_work_requirements

작업 유형 또는 전체 범주의 날씨 제한을 조회합니다.

validate_work_window

하나의 작업 유형을 하루의 날씨와 대조하여 항목별 판정을 반환합니다.

estimate_curing_time

일일 온도 시퀀스가 주어졌을 때 양생 작업 유형이 실제로 준비되는 시점을 추정합니다.

plan_work_schedule

여러 의존 작업을 다일 예보에 걸쳐 한 번의 호출로 배치합니다.

모든 도구의 전체 계약 — 정확한 JSON 스키마와 실제 캡처 예제, 이 프로젝트에서 사용되는 외부 weather 도구를 포함 — 은 docs/tool-contracts.md에 있습니다.

테스트

uv run pytest -v
uv run ruff check .
uv run black --check .

현재 이 저장소에서 세 가지 모두 깨끗하게 통과합니다: 51개의 테스트가 통과합니다(38개의 사양 필수 케이스, 몇 가지 추가 검증, 그리고 agent/normalize.py 날씨 파싱 모듈에 대한 8개의 테스트 — 실제 픽스처 2개와 현재 상태 케이스 2개 포함), 그리고 ruff와 black 모두 문제를 보고하지 않습니다.

제한 사항

각 항목의 전체 근거는 docs/design-rationale.md에 있습니다 — 이 목록은 의도적으로 간결합니다:

  • 데이터셋 임계값은 실제 ДБН/ДСТУ 표준에서 파생된 것이 아니라 예시용입니다.

  • 플래너에는 자원/인력 제약이 없습니다 — 작업은 날짜가 겹칠 수 있습니다.

  • 실제 계획 지평선은 OpenWeather 제공자의 5일로 제한됩니다.

  • 양생 시간은 단순화된 Nurse-Saul 모델을 사용합니다.

  • 하나의 작업은 하나의 연속 블록을 차지합니다 — 분할 일정은 없습니다.

  • OpenWeather MCP 서버의 weather 도구(소스를 읽고 확인한 것이지 추측이 아님)는 3시간 예보 항목당 온도만 노출합니다 — 풍속과 습도는 단일 현재 상태 스냅샷에서만 사용할 수 있으며, 모든 예보 일자에 상수로 적용됩니다. 강수량은 전혀 노출되지 않으므로, precipitation_mm은 이 통합을 통해서는 항상 0.0입니다. 즉, BuildWindow의 강수 규칙(precipitation_allowed=false인 작업은 precipitation_mm > 0이면 강제 위반)은 라이브 실행에서 실제로 트리거될 수 없습니다 — 실제 코드이며, 단위 테스트로 검증됩니다(구성된 데이터 기반, tests/test_validate.py, 사양 #16-17). 그러나 라이브 데모에서는 보여줄 수 없습니다. 라이브 경로에서 0이 아닌 강수량으로 이어지는 경로가 없기 때문입니다. 이 프로젝트는 가짜 비 데이터를 시뮬레이션하거나 주입하지 않아 그 데모를 만들지 않습니다. 동일한 상위 도구는 또한 잘못된 API 키와 인식할 수 없는 도시와 연결할 수 없는 제공자를 구분할 수 없습니다 — 세 경우 모두 동일한 구문상 성공하지만 빈 응답으로 돌아오며, 이것이 agent/main.py가 특정 원인 대신 "사용 가능한 예보 없음"만 보고할 수 있는 이유입니다. 세 경우 모두에 대한 전체 내용은 docs/tool-contracts.md에서 확인할 수 있습니다. 소스로 검증된 세부 사항입니다.

  • 진짜 유효한 OWM_API_KEY가 이제 확인되었습니다: 실제 키로 실제 키이우 날씨에 대한 전체 라이브 실행이 종단 간 실제 일정을 생성하며, 실제 추운 날씨 도시(롱이어뷔엔)에서 라이브 예보가 실제로 작업 unschedulable을 강제하고 validate_work_window가 실제 숫자로 실행되는 것을 발견했습니다 — 전체 내용은 docs/demo-checklist.md 4단계에서 확인할 수 있습니다. 이 README에 설명된 모든 것이 이제 실제 키로 검증되었으며, 단지 없는 키가 아닙니다. 그 라이브 실행이 코드에서 무엇을 바꾸고 무엇을 바꾸지 않았는지는 DECISIONS.md를 참조하십시오.

문서

  • docs/tool-contracts.md — 네 가지 BuildWindow 도구와 외부 OpenWeather weather 도구에 대한 정확한 JSON 스키마 계약, 각각 실제 캡처된 예시 포함.

  • docs/design-rationale.md — 각 도구가 존재하는 이유, 도구 집합이 워크플로에 매핑되는 방식, 구성 요소 간의 경계, 절충된 trade-off, 그리고 프로젝트의 제한 사항 전체.

  • docs/demo-checklist.md — 프로젝트의 라이브 데모를 실행하기 위한 단계별 체크리스트.

  • DECISIONS.md — 구현 결정의 날짜별 기록, 각각의 근거와 함께 채택되지 않은 대안 포함.

Available Tools

4 tools
estimate_curing_timeA

Estimate how long a concrete or coating work type needs to cure under a given sequence of daily temperatures, using the Nurse-Saul maturity method. Use this when a work type has a curing stage and cold weather may extend it beyond the nominal duration. Returns the ready date, or capped=true when the supplied temperature sequence is too short to reach the required maturity. Fails with no_curing_stage for work types that have no curing stage at all.

ParametersJSON Schema
NameRequiredDescriptionDefault
requestYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
cappedYesTrue if the supplied temperature sequence was too short to reach required_maturity.
work_codeYesThe work type curing was estimated for.
ready_dateYesDate the work becomes ready, or null if not reached within the supplied days.
daily_breakdownYesPer-day maturity accounting. Truncated at the ready day if one was found; includes every supplied day if capped is true.
effective_hoursYesElapsed hours (in whole days) needed to reach the ready date, or covered by the supplied days if capped.
required_maturityYesTarget Nurse-Saul maturity in degree-Celsius-hours.
accumulated_maturityYesMaturity actually accumulated over the supplied days.

TDQS

A4.4/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden and clearly discloses return behavior (ready date vs capped=true when the sequence is too short) and error behavior (no_curing_stage). It also names the calculation method, which informs the agent of the model type.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and information-dense, with the main action, method, use trigger, return modes, and error case all front-loaded. There is no filler; every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description explains the output conditions and failure mode, and an output schema exists, so the remaining gaps are acceptable. A brief note about which sibling tool to use instead would make it fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Top-level schema coverage is 0%, so the description must compensate; it does mention daily temperatures and work types in prose but does not clarify start_date semantics or the work_code enum/units. The nested schema does contain field descriptions, so this is adequate but not a strong contribution beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific action (estimate curing time), the resource class (concrete/coating work types), the input (daily temperature sequence), and the method (Nurse-Saul), which clearly distinguishes it from planning/lookup siblings. The use-case sentence also reinforces that this tool estimates curing duration rather than performing scheduling, validation, or requirements lookup.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says to use this when a work type has a curing stage and cold weather may extend duration beyond nominal, and notes that it fails with no_curing_stage for work types without one. It does not name sibling alternatives or provide a full when-not-to-use list, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

lookup_work_requirementsA

Return the normative weather constraints for construction work types. Call this first when you need to know the temperature, wind, humidity or precipitation limits that apply to a work type, or to enumerate all work types in a category. Provide either a single work_code or a category, never both. Returns an empty list with matched_count=0 when the category contains no work types; this is a successful result, not an error.

ParametersJSON Schema
NameRequiredDescriptionDefault
requestYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
requirementsYesMatching work type requirements. Empty if none matched.
matched_countYesNumber of items in requirements.

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description must disclose behavior. It does: it notes that an empty category returns an empty list with matched_count=0 and is a successful result, not an error. It also states the exclusive parameter requirement. It does not go into depth about authorization, reversible side effects, or detailed response structure, but for a read-only lookup this is adequate. The empty-result behavior is a valuable disclosure beyond what a schema would imply.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is four sentences, front-loaded with the core purpose, then usage guidance, then a constraint, then a behavioral nuance. Every sentence contributes information; there is no fluff. The structure guides the agent from 'what' to 'how' to 'edge case' efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

This is a straightforward lookup tool with two optional parameters and an output schema (not shown). The description covers the trigger conditions, the parameter rule, and the successful empty-result case. Since an output schema exists, defining the return format is not necessary. All information needed to invoke the tool correctly and interpret a common edge case is present.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already provides rich descriptions for both parameters (enums with names and descriptions), so the baseline is 3 given high schema coverage. The description adds the critical mutual-exclusivity rule ('never both') which is also in the schema description, but the tool description reinforces it in a clearer, action-oriented way. It also mentions the two parameter names, which helps an agent map the rule to the fields. Slight added value over the schema, hence 4.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource: 'Return the normative weather constraints for construction work types.' It also explains the two call patterns (by work_code or category) and clearly distinguishes this tool from siblings like validate_work_window and estimate_curing_time, which address different concerns. The phrase 'Call this first' reinforces its role as a primary lookup.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use it: 'Call this first when you need to know the temperature, wind, humidity or precipitation limits...' and also covers the alternate use case 'to enumerate all work types in a category.' It adds a strict usage constraint ('Provide either a single work_code or a category, never both') and clarifies the handling of empty results. No ambiguity remains about when to call this tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

plan_work_scheduleA

Produce a feasible day-by-day schedule for several construction works across a weather forecast, honouring declared dependencies between works. Each work is placed in the earliest window where no day is prohibited. Returns both the scheduled works and the works that could not be placed, each with an explicit reason. Use this instead of repeated validate_work_window calls when planning more than one work.

ParametersJSON Schema
NameRequiredDescriptionDefault
requestYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
scheduledYesWorks successfully placed.
horizon_endYesLast date covered by the supplied forecast.
horizon_startYesFirst date covered by the supplied forecast.
unschedulableYesWorks that could not be placed, each with a reason.

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It explains the scheduling algorithm ('earliest window where no day is prohibited'), the dependency handling, and what the return value contains (scheduled works and unplaced works, each with an explicit reason). It does not explicitly state side-effect behavior, but the tool's planning nature and return-focused wording make non-mutation reasonably clear.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is four sentences and every sentence carries useful information: purpose, algorithm, return value, and usage guidance. It is not bloated, though the algorithm and return-value sentences could potentially be tightened without losing meaning.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with a relatively complex input (multiple works, dependencies, weather windows) and an output schema, the description covers the essential behaviors: feasibility, dependency ordering, earliest placement, and the split between scheduled and unscheduled works with reasons. It does not mention input limits or detailed weather constraint logic, but those are already present in the schema and would not affect tool selection.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 0% at the top level, and the description does not directly explain the `request` parameter structure. However, it does reference the core semantic pieces: 'several construction works', 'weather forecast', and 'dependencies', which map to `works`, `forecast`, and `depends_on`. The nested schema definitions are rich, so the description adds modest context without fully compensating for the top-level coverage gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Produce a feasible day-by-day schedule for several construction works across a weather forecast' while also naming the key constraint ('honouring declared dependencies'). It clearly distinguishes this tool from the sibling validate_work_window by framing it as the multi-work planning alternative, so an agent can identify its purpose immediately.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly states when to use this tool instead of an alternative: 'Use this instead of repeated validate_work_window calls when planning more than one work.' This provides a clear condition and names the sibling tool it replaces, giving the agent actionable selection guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

validate_work_windowA

Evaluate whether one construction work type may proceed during one specific day of weather. Returns a verdict of allowed, conditional or prohibited together with the exact constraints that were breached and by how much. Use this to check a single work-day; use plan_work_schedule when you need to place several works across a forecast. The verdict is computed by deterministic rules, not estimated — treat it as authoritative.

ParametersJSON Schema
NameRequiredDescriptionDefault
requestYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
verdictYesOverall verdict for this work-day.
warningsYesNear-boundary breaches within the conditional tolerance band. Any entry here (with violations empty) forces verdict=conditional.
work_codeYesThe work type that was evaluated.
violationsYesHard constraint breaches. Any entry here forces verdict=prohibited.
window_dateYesThe date that was evaluated.

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses the output format (allowed, conditional, or prohibited verdict) and that it includes constraints breached and by how much. It also states the tool is deterministic and authoritative, setting clear expectations for behavior. It does not detail the exact conditions for each verdict, but for a validation tool this is adequate and is not a major gap.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise, consisting of two clear sentences with no redundant phrases. It efficiently conveys purpose, usage, and behavior without fluff, making it easy to parse.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description fully covers the necessary context: what the tool does, when to use it, what it returns, and how it differs from a sibling. The existence of an output schema (even if not shown) is not a barrier because the description already specifies the expected output shape. It is self-contained and sufficient for an agent to decide when and how to invoke it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema provides rich descriptions for the nested fields (work_code, window, and weather properties), so the parameter semantics are already well-defined. The description text does not add explicit parameter details beyond implicitly referencing 'work type' and 'day of weather.' Since the schema coverage is strong, the description's minimal contribution is acceptable, but it does not elevate the score beyond the baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: evaluating whether a work type may proceed under given weather. It explicitly distinguishes it from the sibling tool plan_work_schedule, making its purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use this tool versus the alternative: 'Use this to check a single work-day; use plan_work_schedule when you need to place several works across a forecast.' This leaves no ambiguity about appropriate invocation scenarios.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 4 tool updatesv0.1.0
    • First observedestimate_curing_time
    • First observedlookup_work_requirements
    • First observedplan_work_schedule
    • First observedvalidate_work_window

TDQS

A4.6/5.0

Scored across 4 tools

Disambiguation5/5

Each tool serves a distinct purpose: querying requirements, validating a single day, estimating curing, and planning schedules. No overlap in functionality; an agent can easily select the right tool for the task.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern: lookup_work_requirements, validate_work_window, estimate_curing_time, plan_work_schedule. The naming style is uniform and predictable.

Tool Count5/5

With only 4 tools, the server is well-scoped for its construction weather planning domain. Each tool is essential and there is no bloat or missing core functionality.

Completeness5/5

The server covers the full workflow from looking up constraints to validating individual days, estimating curing, and planning multi-work schedules. It also handles edge cases like capping and failures gracefully, indicating thorough domain coverage.

Maintenance

ActivitySlowing
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    B
    quality
    D
    maintenance
    Enables users to get weather alerts and forecasts through natural language interactions. Provides real-time weather information and alert notifications via MCP tools.
    2
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables users to assess condensation and mold risk for building surfaces using physics-based calculations (dew point, surface temperature, critical thresholds), with support for real-time weather data and prescription generation.
    -
  • A
    license
    Not graded
    quality
    C
    maintenance
    Enables users to check whether an Australian field-service job can be worked at a location on a given day for a specific trade, using live weather forecasts, daylight hours, and public holiday data.
    MIT
  • A
    license
    A
    quality
    B
    maintenance
    Enables construction teams to create local projects, record sourced field evidence, run deterministic quantity calculations, and draft daily logs, estimates, and change orders with visible assumptions and human approval gates. Keeps all data local and portable with no external side effects.
    10
    Apache 2.0