Skip to content

Tools: Documentation

Documentation tools — URLs, search, and full-text retrieval for EnergyPlus docs.

build_documentation_urls(object_type, version=None)

Build documentation URLs for an object type.

Source code in src/idfkit_mcp/tools/docs.py
def build_documentation_urls(object_type: str, version: str | None = None) -> LookupDocumentationResult:
    """Build documentation URLs for an object type."""
    from idfkit.docs import engineering_reference_url, io_reference_url, search_url
    from idfkit.versions import LATEST_VERSION

    state = get_state()
    ver_tuple = _parse_version(version)
    schema = state.get_or_load_schema(ver_tuple)
    effective_version = ver_tuple or LATEST_VERSION

    io_url = io_reference_url(object_type, effective_version, schema)
    eng_url = engineering_reference_url(effective_version)
    s_url = search_url(object_type, effective_version)

    ver_str = f"{effective_version[0]}.{effective_version[1]}.{effective_version[2]}"
    return LookupDocumentationResult(
        object_type=object_type,
        version=ver_str,
        io_reference_url=io_url.url if io_url else None,
        engineering_reference_url=eng_url.url if eng_url else None,
        search_url=s_url.url if s_url else None,
    )

get_doc_section(location, version=None, max_length=8000)

Read full content of a doc section from search_docs results.

Source code in src/idfkit_mcp/tools/docs.py
@tool(annotations=_READ_ONLY)
def get_doc_section(
    location: Annotated[str, Field(description="Section location key from search_docs results.")],
    version: Annotated[str | None, Field(description='EnergyPlus version as "X.Y".')] = None,
    max_length: Annotated[int, Field(description="Maximum characters of text to return.")] = 8000,
) -> GetDocSectionResult:
    """Read full content of a doc section from search_docs results."""
    state = get_state()
    items, separator, docs_version = state.get_or_load_docs_index(version)

    pc = _get_precomputed(items, separator, docs_version)

    logger.debug("get_doc_section: location=%r version=%s", location, version)
    for i, item in enumerate(items):
        if item.get("location") == location:
            text = pc.stripped_texts[i]
            truncated = len(text) > max_length
            if truncated:
                text = text[:max_length] + "..."
            return GetDocSectionResult(
                location=str(item.get("location", "")),
                title=str(item.get("title", "")),
                path=item.get("path", []),  # type: ignore[arg-type]
                tags=item.get("tags", []),  # type: ignore[arg-type]
                text=text,
                doc_url=_build_doc_url(docs_version, str(item.get("location", ""))),
                version=docs_version,
                truncated=truncated,
            )

    msg = f"Documentation section not found: '{location}'. Use search_docs to find valid locations."
    raise ToolError(msg)

search_docs(query, version=None, tags=None, limit=5)

Search EnergyPlus docs by keyword.

Source code in src/idfkit_mcp/tools/docs.py
@tool(annotations=_READ_ONLY)
def search_docs(
    query: Annotated[str, Field(description='Search query (e.g. "zone heat balance").')],
    version: Annotated[str | None, Field(description='EnergyPlus version as "X.Y".')] = None,
    tags: Annotated[str | None, Field(description='Filter by doc set (e.g. "Input Output Reference").')] = None,
    limit: Annotated[int, Field(description="Maximum results.")] = 5,
) -> SearchDocsResult:
    """Search EnergyPlus docs by keyword."""
    state = get_state()
    items, separator, docs_version = state.get_or_load_docs_index(version)

    limit = min(limit, 10)

    if not query.strip():
        return SearchDocsResult(query=query, version=docs_version, count=0, results=[])

    query_tokens = _tokenize(query, separator)
    if not query_tokens:
        return SearchDocsResult(query=query, version=docs_version, count=0, results=[])

    pc = _get_precomputed(items, separator, docs_version)
    scored = _rank_items(items, query_tokens, pc, tags)
    results = _build_hits(scored[:limit], items, pc, docs_version)

    logger.debug("search_docs: query=%r version=%s matched=%d", query, docs_version, len(results))
    return SearchDocsResult(
        query=query,
        version=docs_version,
        count=len(results),
        results=results,
    )