Update Unstructured Transform MCP tool names and add structured data extraction - #31
Open
simoncoombes wants to merge 3 commits into
Open
Update Unstructured Transform MCP tool names and add structured data extraction#31simoncoombes wants to merge 3 commits into
simoncoombes wants to merge 3 commits into
Conversation
Signed-off-by: Simon Coombes <simon@unstructured.io>
Signed-off-by: Simon Coombes <simon@unstructured.io>
…ve test Signed-off-by: Simon Coombes <simon@unstructured.io>
willkill07
approved these changes
Jul 28, 2026
Member
|
/ok to test 8b1777c |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #30.
Two things, both driven by the same Unstructured Transform server release.
The rename (the part that breaks the example today)
Three MCP tools were renamed after the example landed, and the example names the old ones in its
includelists, itsTransformToolsfields, the README, and the flow diagram.resolve_toolsfails fast on a missing tool, so the example does not start.transform_filesis nowstart_transform_jobcheck_transform_statusis nowcheck_job_statusget_transform_resultsis nowget_job_resultsrequest_file_upload_urlis unchanged. Verified against the live server (Unstructured Transform 0.7.2) via itsget_instructionstool, not from a changelog.Structured data extraction (new)
The same release added structured data extraction, so this adds a second function,
extract_structured_data, which returns named fields as JSON instead of the whole document as text. It fits the example's existing point: the extractor consumes the Element JSON a parse produces rather than a raw file, so it is a chain of two dependent async jobs, which is a stronger case for deterministic composition than the single job the example already wraps.Three details in the implementation that reviewers may want to check:
output_refnext to thedownload_url, present whichever output format is rendered, so the function passes the reference on and never downloads the Markdown. A test asserts noGETis issued.vlmfor PDFs, images, and PowerPoint;fastotherwise), because extraction quality is bounded by parse quality and the wrong strategy degrades silently rather than erroring.extracted_datawithfilename,filetype,processed_date_utc, andsource_file_uri, and the function returns the wrapper rather than the bare data.The agent-facing argument is
extraction_schema, notschema: these parameter names become fields of a generated Pydantic model, andschemashadows aBaseModelattribute, which makes the generated model emit a warning. A test pins the field names so that does not regress.resolve_toolsis now parameterized by which tool bundle to resolve, sotransform_documentstill requires only the four parse tools and does not gain a dependency on tools it never calls.Verification
53 unit tests pass (26 existing, 27 new); they mock the MCP tools and HTTP transfers, so no network or credentials.
yapf --diffclean,ruff checkclean,ci/scripts/copyright.pypasses, Vale passes on the README,markdown-link-checkpasses (9 links).I ran the parse-then-extract flow by hand against the live production server first (parse an image with
strategy=vlm, draft a schema from theoutput_ref, extract, read back provenance-wrapped JSON), so the orchestration matches real server behaviour rather than my reading of the docs.A live integration test for the new function is included alongside the existing ones, marked
slow/integrationand skipped withoutUNSTRUCTURED_API_KEY. Both integration tests pass against production (pytest -k "not full_workflow" --run_integration --run_slow, about 73s for the extraction one).test_full_workflow_liveis unchanged and also passes.I drove the ReAct agent against the new tool by hand (
nat run, the shipped config, nemotron-3-nano-30b-a3b) to check that a small model can handle a multi-argument tool input. It selects the tool and emits valid JSON for the generated schema:Omitting the optional arguments takes the intended path: the function calls
suggest_extraction_schema_for_file, thenstart_extraction_job, and the whole chain (upload, parse, poll, suggest, extract, poll) completes in about 76 seconds.That live test asserts the shape of the result rather than the extracted value, and the reason is worth stating. The fixture is a synthetic one-sentence PDF. The parse reads it correctly (verified: both
vlmandfastreturn the exact sentence), but what the extractor fills in for so degenerate a document is not stable: with amagic_wordfield against the sentence "The magic word is xylophone." it returned"magic", and with an invoice-shaped schema on a similar fixture it returned empty strings. Asserting a value would make the test flaky for reasons that have nothing to do with this code, so it asserts the contract the function owns instead: the parse hands itsoutput_refto the extractor, the supplied schema shapes the output, and the provenance wrapper survives.One incidental observation while checking that: for this synthetic PDF the server reported
partitioner_type: fast_partitioneven when asked forvlm, which is the documented silent-fallback behaviour. The strategy choice in_partition_strategy_forstill follows the server's guidance for real PDFs and images; it just is not exercised by this fixture.Happy to split the extraction work into a follow-up PR if you would rather land the rename on its own, since that one is a straight bug fix.