Agent-first parameter extraction from technical datasheets.
datasheetindex is meant to be handed to an external agent in two parts:
- Enriched ToC JSON - Hierarchical section tree with page ranges, table hints, pre-computed breadcrumbs, boilerplate flags (revision history, disclaimers, etc.), and a preamble (pages 1-2 raw text) for agent orientation
- Page-matched text file - Full document text with
--- PAGE N ---markers aligned to the JSON, with column-aware reading order for two-column layouts
All page numbers are 1-indexed across the JSON, the text file markers, and
inspect_page(page=...).
The library also exposes create_datasheet_tools_server(), which packages
artifact-building, ToC/text access, text search, text-to-coordinate grounding
(locate_text), and inspect_page as the MCP/tool-server surface the agent can
mount. The server starts without a bound PDF; the agent loads one at runtime by
calling the build_datasheet tool with a pdf_source.
The library doesn't extract parameters. The agent does. All intelligence lives in the agent; the library provides the best possible starting context and the right tools for edge cases.
datasheetindex is product-agnostic: it works with any PDF datasheet, including
the full Infineon product portfolio
(for example
microcontrollers,
power, sensors, and connectivity devices). It has no dependency on a specific
product line or family.
- Infineon Developer Community - forums and knowledge base
- Infineon Developer Center - tools and software packages
- How to contribute
- Code of Conduct
- Support
- License
uv sync
uv run pre-commit installOptional integrations:
# LLM fallback / summaries (`create_llm_client`, `--model`, and automatic
# low-quality ToC fallback when credentials are available)
uv sync --extra llm
# Local MCP server testing (`datasheetindex-mcp-server`)
uv sync --extra mcp
# MCP server handoff to a consuming agent (`create_datasheet_tools_server`)
uv pip install claude-agent-sdkFor LLM-backed ToC fallback and summaries, configure LITELLM_BASE_URL and
LITELLM_MASTER_KEY (see .env.example).
claude-agent-sdk is only required for the SDK-flavored handoff
(create_datasheet_tools_server). The tool logic itself is framework-neutral --
non-SDK hosts get it via create_datasheet_tool_defs() with no SDK import (see
"Realize the tools without the Claude Agent SDK").
The mcp extra is only required if you want to run a local stdio/HTTP MCP
server from this repository.
uv run pytest # run tests
uv run ruff check src/ # lint
uv run ruff format src/ # format
uv run ty check # type checkThe pre-commit pytest hook runs the fast subset only:
uv run pytest -q -m "not integration and not real_pdf". Run
uv run pytest for the full suite, including real-PDF and integration tests.
DatasheetIndex and DatasheetTools accept either:
- a local PDF file path, or
- an
http(s)URL pointing to a PDF datasheet.
from datasheetindex import create_datasheet_tools_server
# The server starts WITHOUT a bound PDF and takes no arguments. The agent loads a
# document at runtime by calling the build_datasheet tool with a pdf_source (local
# path or URL) before using any other tool.
datasheet_tools_server = create_datasheet_tools_server()
# Pass datasheet_tools_server into your agent runtime's MCP server configuration.
# The exact wiring depends on the host agent framework; this server object is the
# concrete handoff point from datasheetindex to the agent.
agent = SomeAgentRuntime(
mcp_servers={"datasheet-tools": datasheet_tools_server},
system_prompt="...tell the agent to call build_datasheet first...",
)Hosts that are not on the Claude Agent SDK (pydantic-ai, plain function-calling
agents, custom MCP servers) can get the same tools as framework-neutral
definitions -- no claude-agent-sdk import required -- via
create_datasheet_tool_defs():
from datasheetindex import create_datasheet_tool_defs
# One call == one session. build_datasheet binds the document; the other tools
# read it. Each def is a frozen dataclass: name, description, input_schema
# (JSON Schema), and an async handler.
tool_defs = create_datasheet_tool_defs()
for d in tool_defs:
register_with_your_host(
name=d.name,
description=d.description,
input_schema=d.input_schema,
# async (args: dict) -> {"content": [...], "is_error": bool}
handler=d.handler,
)create_datasheet_tools_server() is a thin adapter over this factory -- it wraps
each def with the SDK @tool decorator -- so the two surfaces expose identical
tool names, descriptions, and schemas.
If you want direct Python access instead of an MCP server, use DatasheetTools
to build artifacts, search text, and call inspect_page() on the bound
instance.
from datasheetindex import DatasheetTools
with DatasheetTools("datasheet.pdf") as tools:
artifacts = tools.build_datasheet(output_dir="output")
toc = artifacts.json_data["toc"] # enriched ToC tree (with breadcrumbs)
# Search one term, or several in a single call. Each match carries the
# breadcrumb of the section that contains its page; list searches also tag
# each match with the `pattern` that produced it.
matches = tools.search_text("supply voltage")
matches = tools.search_text(["V_DS max", "junction temperature"])
# Read a page range; the text opens with a "=== Pages X-Y of N ===" header.
section_text = tools.get_section_text(12, 13)
image = tools.inspect_page(
page=12,
region={"top": 0.15, "bottom": 0.55, "left": 0.05, "right": 0.95},
)
# Map a located string to its bounding box(es) - returned as percentages
# (to crop inspect_page) and PDF points (to annotate the PDF). Matching is
# hybrid: verbatim search with a normalized fallback for dash/case/spacing
# variation. A string occurring multiple times yields multiple results.
hits = tools.locate_text("supply voltage", page=12)
if hits:
tight = tools.inspect_page(page=12, region=hits[0]["region"]["pct"])The optional region crop uses percentages from 0.0 to 1.0.
You can run the local MCP server directly from the repository. It exposes these tools for the bound PDF source:
build_datasheet- build and save the.json/.txtartifacts, and return the manifest: source info, total pages, ToC quality, and the full enriched ToCget_section_text- return extracted text for a page range from the latest build, opening with a=== Pages X-Y of N ===position headersearch_text- find page-aware text snippets in the latest build (pass a single pattern or a list of patterns), even when labels wrap across lines or table values interrupt the phrase; each hit carries the section breadcrumbinspect_page- render a page image when visual confirmation is neededlocate_text- map a string to its bounding-box coordinates (percentages + PDF points) on a page, for highlighting or to cropinspect_pagepreciselyextract_table_markdown- re-extract a page as layout-aware Markdown tables
Build once, then use get_section_text, search_text, inspect_page,
locate_text, and extract_table_markdown together. search_text prefers exact matches, then
falls back to whitespace-normalized and ordered-token matching for line-wrapped
table rows.
The server takes no PDF argument; it starts unbound and the client loads a
document at runtime by calling build_datasheet with a pdf_source.
# stdio transport (for Claude Code or another MCP client)
uv run --extra mcp datasheetindex-mcp-server
# then call build_datasheet(pdf_source="datasheet.pdf", output_dir="output")
# from the MCP clientYou can also expose it over HTTP:
# streamable HTTP transport (useful with MCP Inspector)
uv run --extra mcp datasheetindex-mcp-server \
--transport streamable-http --port 8000With streamable-http, the default MCP endpoint is
http://127.0.0.1:8000/mcp.
Every tool returns its result as a single JSON string in a TextContent block
(except inspect_page, which returns an image); read it with
json.loads(result.content[0].text). This matches the SDK tool surface exactly.
This local server is for direct MCP testing. If you need an in-process SDK
server object inside another Python runtime, use
create_datasheet_tools_server() instead; it exposes the same tool surface, with
the document loaded at runtime via the build_datasheet tool.
from datasheetindex import DatasheetIndex, build_batch
artifacts = DatasheetIndex("datasheet.pdf").build(output_dir="output")
batch_result = build_batch(
["part-a.pdf", "part-b.pdf"],
output_dir="batch-output",
)In batch mode, output filenames are suffixed as needed to keep them unique when multiple inputs would otherwise resolve to the same stem.
# Local file
datasheetindex build path/to/datasheet.pdf --output-dir output
# Remote URL
datasheetindex build https://example.com/datasheet.pdf --output-dir output
# With explicit LLM model for ToC fallback and summaries
datasheetindex build datasheet.pdf --model gpt-4.1 --include-summariesBy default, datasheetindex first uses native PDF ToC extraction. If ToC
quality is low, it automatically attempts LLM fallback with the default model
(gpt-4.1) when LLM credentials are available. Pass --model to choose the
LLM model explicitly; --include-summaries requires --model.
src/datasheetindex/
core/
structure.py # ToC extraction + enriched tree JSON
textfile.py # PDF -> page-matched text file (column-aware)
_textmatch.py # Shared dash/token normalization + matcher
locate.py # locate_text: text -> bounding-box coordinates
preamble.py # Pages 1-2 raw text extraction
quality.py # ToC quality assessment
annotations.py # Footnote and cross-reference enrichment
boilerplate.py # Title-pattern boilerplate classification
tools/
vision.py # inspect_page (page -> image)
bound.py # DatasheetTools (document-bound tool logic)
defs.py # create_datasheet_tool_defs (framework-neutral defs)
registry.py # Claude Agent SDK adapter (re-exports DatasheetTools)
mcp_server.py # Local stdio/HTTP MCP server entry point
llm/
client.py # LLM client factory
toc_fallback.py # LLM-based ToC generation fallback
summarizer.py # Optional section summaries
cli.py # CLI entry point
index.py # Main DatasheetIndex class
models.py # Data models
Licensed under the MIT License.
Copyright (c) 2026 Infineon Technologies AG