Skip to main content
Glama
borovkov-d

BuildWindow

by borovkov-d

BuildWindow

MCP ラボプロジェクト:エージェントが 2 つの MCP サーバーを使用して、実際の天気予報に対して建設作業を計画します。

これは KSE AI Agentic School のコース課題です(MCP 統合課題):実際のドメイン問題に対するカスタム MCP サーバーを構築し、それを既存のサードパーティ MCP サーバーとともに、両方を一緒に使用して単一のツールではできないことを行うエージェントに接続します。

概要

BuildWindow は、具体的なスケジューリング問題を中心に構築された MCP(Model Context Protocol)ラボプロジェクトです:依存関係を持つ建設作業のリストと都市の天気予報が与えられたとき、両方を尊重するスケジュールを生成します。この計画を実行するエージェントは、同時に 2 つの別々の MCP 接続を保持します。1 つ目は、外部の Go ベースの OpenWeather MCP サーバー(github.com/mschneider82/mcp-openweather)で、エージェントは実行ごとに 1 回呼び出して、要求された都市の現在のライブ状況と 5 日間の予報を取得します — これはプロジェクト全体でネットワーク呼び出しが発生する唯一の場所です。2 つ目は、このリポジトリ独自の BuildWindow MCP サーバーです:実行時にネットワーク呼び出しを行わない完全に決定論的なローカルサーバーで、建設作業の種類とその気象制限のローカル JSON データセットに基づいており、建設ドメインのルールをエンコードする 4 つのツール(気象適合性の判定、養生時間の推定、複数作業のスケジューリング)を公開します。

2 つのサーバーは意図的に責任範囲が重複していません。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 に明示的にリストされています)— ただし、システムプロンプトに従って、最終レポートの現在の状況に関する 1 文のみです。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 を編集し、openweathermap.org/api(無料ティア)から取得した実際のキーで OWM_API_KEY を設定します。.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 に MCP_OPENWEATHER_PATH を設定してください(.env.example を参照)— 両方の方法がライブで動作確認済みです。

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 をバイナリのフルパスに設定してください(上記参照)— このリポジトリ自身のセットアップは後者を使用しています。

@latest ではなく @main を使用する理由: go install ...@latest はタグ v1.0.0 に解決されますが、これはリポジトリの main ブランチより 1 コミット(「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": []}]'

オプションの 2 番目の引数は、デモリストと同じ形式の作業の 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 セッションを開始する前に終了します — 無駄なモデル呼び出しも、捏造されたスケジュールもありません。これは 3 つの実際の障害モードで検証されました:mcp-openweather バイナリがまったく到達不能、無効な OWM_API_KEY、無効な都市名 — 最後の 2 つはこの上流ツールを通じて実際には区別できず(理由は docs/tool-contracts.md を参照)、同じ環境の他の場所で本当に有効なキーがアクティブであっても、両方とも同じクリーンな方法で失敗することが確認されました。

OpenWeather レート制限: 1 回の成功したライブ実行では、weather ツールへの実際の呼び出しは正確に2 回行われます(ライブで数えて確認済み)— セッション前の決定論的フェッチと、モデル自身の単一の現在の状況呼び出し(上記の概要を参照)。失敗したライブ実行(利用可能な予報がない場合)は、LLM セッションが開始されないため、正確に 1 回です。リプレイモード(--forecast-from-file)ではゼロ回です — 日別予報と現在の状況メモの両方が記録されたファイルから取得され、このモードでは 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

1 つの作業タイプを 1 日の天気に対してチェックし、項目別の判定結果を返します。

estimate_curing_time

一連の日別気温が与えられたとき、養生中の作業タイプが実際にいつ完了するかを推定します。

plan_work_schedule

複数の依存する作業を 1 回の呼び出しで複数日の予報全体に配置します。

完全な契約 — すべてのツールの正確な JSON スキーマと実際にキャプチャされた例(このプロジェクトで使用される外部の weather ツールを含む)— は docs/tool-contracts.md にあります。

テスト

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

現在、このリポジトリでは3つすべてが問題なくパスしています。51件のテストがパスし(仕様で要求される38ケース、いくつかの補足的なアサーション、agent/normalize.pyの天気解析モジュールの8件のテスト(実フィクスチャ2件と現在の気象条件2件を含む)をカバー)、ruffとblackの両方で問題は報告されていません。

制限事項

これらの各項目の完全な根拠はdocs/design-rationale.mdにあります。このリストは意図的に簡潔にしています。

  • データセットの閾値は実在のДБН/ДСТУ規格から導出されたものではなく、説明用のものです。

  • プランナーにはリソース/クルーの制約がありません。作業は日付が重複する可能性があります。

  • 実際の計画期間はOpenWeatherプロバイダーによって5日間に制限されています。

  • 養生時間は簡略化されたNurse-Saul成熟度モデルを使用しています。

  • 1つの作業は1つの連続したブロックを占有します。分割スケジューリングはありません。

  • OpenWeather MCPサーバーのweatherツール(推測ではなくソースを読んで確認済み)は、3時間ごとの予報エントリごとに気温のみを公開しています。風速と湿度は単一の現在の気象条件スナップショットでのみ利用可能で、ここではすべての予報日にわたって定数として適用されます。また、降水量はまったく公開されていないため、この統合を通じてprecipitation_mmは常に0.0になります。つまり、BuildWindowの降水ルール(precipitation_allowed=falseの作業は、precipitation_mm > 0の場合にハード違反となる)は、この統合を通じたライブ実行から実際にトリガーされることは決してありません。これは実際の正しいコードであり、構築されたデータに対するユニットテスト(tests/test_validate.py、仕様ケース#16-17)でカバーされていますが、非ゼロの降水量へのライブパスがないため、ライブデモで示すことはできません。このプロジェクトは、そのデモを作り出すために偽の雨データをシミュレートまたは注入することはありません。同じ上流ツールは、不正なAPIキーと認識されない都市と到達不能なプロバイダーを区別することもできません。3つすべてが同じ構文上は成功するが空のレスポンスとして返されるため、agent/main.pyはこれら3つのケースのいずれについても「予報が利用できません」としか報告できず、特定の原因を報告できません。完全なソース検証済みの詳細はdocs/tool-contracts.mdを参照してください。

  • 真正なOWM_API_KEYが機能することが現在確認されています。実際のキエフの天気に対する完全なライブ実行は、エンドツーエンドで実際のスケジュールを生成し、実際の寒冷地の都市(ロングイェールビエン)が見つかり、ライブ予報が実際に作業をunschedulableにし、validate_work_windowが実数で発火します。docs/demo-checklist.mdのステップ4を参照してください。このREADMEで説明されているすべては、欠落したキーだけでなく、実際の動作するキーに対して検証されています。その実データに対するライブ実行がコードで何を変更し、何を変更しなかったかについてはDECISIONS.mdを参照してください。

ドキュメント

  • docs/tool-contracts.md — 4つすべてのBuildWindowツールと、このプロジェクトで使用される外部OpenWeather weatherツールの正確なJSON Schema契約。それぞれに実際にキャプチャされた例が付いています。

  • docs/design-rationale.md — 各ツールが存在する理由、ツールセットがワークフローにどのようにマッピングされるか、コンポーネント間の境界、行われたトレードオフ、およびプロジェクトの制限事項の完全な説明。

  • 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