Ctx Markitdown¶
Ctx MarkItDown — mvp.ctx_markitdown
Cluster: Context & Retrieval | Type: component | MCP Tools: 26
Overview¶
Document-to-Markdown converter backed by the MarkItDown library, supporting PDF, DOCX, HTML, image files, and URLs as input sources. The converted Markdown text is returned in MarkdownOutput.content alongside the source path and character count. If MarkItDown is not installed, infer() returns a clear error rather than silently producing empty output.
Outputs expose the canonical G6 degradation envelope: completion_state, warning_card, evidence, request_id, task_id, and run_id. Conversions that actually extract text are verified; missing MarkItDown, blocked sources, conversion exceptions, and conversions that ran without error but extracted no text (empty or whitespace-only) are surfaced as blocked-escalated with stable G6_E_* warning-card codes rather than cosmetic completion. Batch conversion can be qualified-draft when useful partial work exists but sources were skipped or degraded.
When to use:
- Converting diverse document formats to Markdown before feeding into an LLM or RAG pipeline
- Extracting readable text from PDFs or Office files without manual pre-processing
- Building a normalised text corpus from a mixed-format document collection
Example:
from mvp.ctx_markitdown import CtxMarkitdownBlock, DocumentInput
block = CtxMarkitdownBlock(name="md")
result = block.infer(DocumentInput(source="/reports/q1.pdf"))
# result.value.content → Markdown text of the PDF
Works well with: ctx_langextract, ctx_rag, ctx_scrapling
Launch Readiness Caveat¶
Pinned runtime dependencies are necessary, not sufficient
ctx_markitdown depends on markitdown==0.1.5 for document conversion and the MCP server path depends on fastmcp==2.14.6. These are pinned in the workspace, development environment, and projects/g6_mcp package metadata. A missing markitdown install returns a clear [MARKITDOWN_ERROR] markitdown is not installed error instead of silently producing empty output.
Before presenting document conversion as part of a first-user workflow, still run a clean-machine MCP smoke test using the deployable MCP requirements: install the server, call md_info, convert one small allow-listed file, and verify the result appears in conversion history. Component tests prove the logic path; they do not prove the user's package environment has no unrelated dependency conflicts.
State Surface and Degradation Envelope¶
The MCP tier stores conversion history, source names, content previews, errors, templates, jobs, and pipelines in SQLite at $MARKITDOWN_DB_PATH (default ~/.markitdown/markitdown.db). Rows persist until explicit delete or purge operations, or until the database is removed. Adapter-level encryption and content sanitization are not enforced; callers handling sensitive documents should treat the database path as sensitive state.
info, list_formats, resource_check, convert, and batch_convert include capability evidence describing static format support versus live optional dependency availability (markitdown, OCR, transcription, and LLM rerank). This is the component's weakest-link disclosure: conversion usefulness is constrained by source policy, MarkItDown availability, and format-specific optional backends.
Public API¶
MarkitdownRerankDecision¶
Validated advisory rerank verdict over a returned search-record set.
| Field | Type | Default |
|---|---|---|
ordered_indices | tuple[int, ...] | required |
dropped_indices | tuple[int, ...] | () |
rationale | str | '' |
eligible_fingerprint | str | '' |
confidence | float | 0.0 |
degraded | bool | False |
raw_response | str | '' |
LLMMarkitdownRerankRuntime¶
Provider-neutral search-result-rerank runtime backed by G6's LLM caller.
Constructor:
| Parameter | Type | Default |
|---|---|---|
llm | LLMCaller \| None | None |
Methods:
rerank(query: str, records: list[Any]) -> MarkitdownRerankDecision¶
CtxMarkitdownRerankPatternRuntime¶
Stateless, load-bearing returned-set-ceiling enforcement.
Methods:
enforce_eligibility(decision: MarkitdownRerankDecision, records: list[Any]) -> tuple[list[Any], bool, bool]¶
CtxMarkitdownPlanner¶
Runtime-first advisory result-rerank facade with returned-order fallback.
Constructor:
| Parameter | Type | Default |
|---|---|---|
runtime | MarkitdownRerankRuntime \| None | None |
pattern_runtime | CtxMarkitdownRerankPatternRuntime \| None | None |
Methods:
rerank(query: str, records: list[Any]) -> list[Any]¶
CtxMarkitdownBlock(AIBlock[DocumentInput, MarkdownOutput, None])¶
Converts documents (PDF, DOCX, HTML, URLs, images, …) to Markdown text
| Field | Type | Default |
|---|---|---|
name | str | 'ctx_markitdown' |
resource_bounds | ResourceBounds \| None | None |
usage | ResourceUsage | field(default_factory=ResourceUsage) |
Methods:
infer(data: DocumentInput) -> Result[MarkdownOutput]¶
DocumentInput(BaseModel)¶
Input for CtxMarkitdownBlock — a path or URL to convert.
| Field | Type | Default |
|---|---|---|
source | str | required |
source_type | str | '' |
extra_options | dict[str, str] | Field(default_factory=dict) |
run_mode | Literal['beta', 'production'] | 'beta' |
reviewer_signature | str | '' |
MarkdownOutput(BaseModel)¶
Markdown text produced from a document.
| Field | Type | Default |
|---|---|---|
content | str | required |
source | str | required |
char_count | int | 0 |
metadata | dict[str, str] | Field(default_factory=dict) |
degraded | bool | False |
degradation_reason | str \| None | None |
completion_state | Literal['verified', 'qualified-draft', 'blocked-escalated'] | 'qualified-draft' |
warning_card | dict[str, Any] | Field(default_factory=dict) |
evidence | dict[str, Any] | Field(default_factory=dict) |
request_id | str | '' |
task_id | str | '' |
run_id | str | '' |
Methods:
model_post_init(__context: Any) -> None¶
CtxMarkitdownMCPBlock(AIBlock[MCPMarkitdownInput, MCPMarkitdownOutput, dict])¶
Full-featured markitdown block with SQLite persistence.
| Field | Type | Default |
|---|---|---|
name | str | 'ctx_markitdown_mcp' |
state | dict \| None | None |
db_path | str | ':memory:' |
resource_bounds | ResourceBounds \| None | None |
usage | ResourceUsage | field(default_factory=ResourceUsage) |
agentic_planner | CtxMarkitdownPlanner \| None | None |
Methods:
infer(data: MCPMarkitdownInput) -> Result[MCPMarkitdownOutput]¶
MCPMarkitdownRecord(BaseModel)¶
| Field | Type | Default |
|---|---|---|
id | str | required |
record_type | str | required |
key | str | required |
value | str | required |
tags | list[str] | Field(default_factory=list) |
timestamp | str | required |
metadata | dict[str, Any] | Field(default_factory=dict) |
MCPMarkitdownInput(BaseModel)¶
| Field | Type | Default |
|---|---|---|
op | Literal['convert', 'batch_convert', 'detect_type', 'list_formats', 'resource_check', 'record_conversion', 'query_conversions', 'get_conversion_stats', 'delete_conversion', 'export_history', 'purge_old', 'save_template', 'get_template', 'list_templates', 'delete_template', 'submit_job', 'get_job_status', 'list_jobs', 'cancel_job', 'create_pipeline', 'run_pipeline', 'list_pipelines', 'delete_pipeline', 'search', 'info', 'list_patterns'] | required |
source | str | '' |
source_type | str | '' |
sources_json | str | '' |
llm_model | str | '' |
llm_prompt | str | '' |
max_execution_seconds | int | 60 |
max_disk_bytes | int | 0 |
max_files | int | 10 |
key | str | '' |
value | str | '' |
tags | list[str] | Field(default_factory=list) |
query | str | '' |
limit | int | 50 |
top_k | int | 5 |
conversion_id | str | '' |
detected_type | str | '' |
content_preview | str | '' |
char_count | int | 0 |
success | bool | True |
error_message | str | '' |
engine | str | 'markitdown' |
duration_ms | int | 0 |
metadata_json | str | '' |
days | int | 30 |
name | str | '' |
description | str | '' |
source_type_filter | str | '' |
extra_options_json | str | '' |
job_id | str | '' |
status | str | '' |
pipeline_name | str | '' |
steps_json | str | '' |
agentic_rerank | bool \| None | None |
run_mode | Literal['beta', 'production'] | 'beta' |
reviewer_signature | str | '' |
MCPMarkitdownOutput(BaseModel)¶
| Field | Type | Default |
|---|---|---|
op | str | required |
key | str | '' |
value | str | '' |
found | bool | False |
count | int | 0 |
records | list[MCPMarkitdownRecord] | Field(default_factory=list) |
retrieved | list[str] | Field(default_factory=list) |
scores | list[float] | Field(default_factory=list) |
summary | str | '' |
message | str | '' |
content | str | '' |
metadata | dict[str, Any] | Field(default_factory=dict) |
degraded | bool | False |
degradation_reason | str | '' |
completion_state | Literal['verified', 'qualified-draft', 'blocked-escalated'] | 'qualified-draft' |
warning_card | dict[str, Any] | Field(default_factory=dict) |
evidence | dict[str, Any] | Field(default_factory=dict) |
request_id | str | '' |
task_id | str | '' |
run_id | str | '' |
agentic_evidence | dict[str, Any] | Field(default_factory=dict) |
capabilities | dict[str, bool] | Field(default_factory=lambda: {'markitdown': False, 'sklearn': False, 'llm': False, 'ocr': False, 'transcription': False}) |
Methods:
model_post_init(__context: Any) -> None¶
MarkitdownStore¶
Sync SQLite markitdown store with 5 tables.
Constructor:
| Parameter | Type | Default |
|---|---|---|
db_path | str | ':memory:' |
Methods:
add_conversion(source: str, source_type: str, detected_type: str, content_preview: str, char_count: int, success: bool, error_message: str, engine: str, llm_model: str, duration_ms: int, tags: list[str], metadata_json: str) -> str¶
query_conversions(source_type: str = '', success: bool | None = None, limit: int = 50) -> list[dict[str, Any]]¶
get_conversion_stats() -> dict[str, Any]¶
delete_conversion(conversion_id: str) -> bool¶
export_history(limit: int = 1000) -> list[dict[str, Any]]¶
purge_old(days: int = 30) -> int¶
add_error(conversion_id: str, source: str, source_type: str, error_type: str, error_message: str, engine: str) -> str¶
upsert_template(name: str, description: str, source_type_filter: str, engine: str, llm_model: str, llm_prompt: str, max_execution_seconds: int, extra_options_json: str, tags: list[str]) -> str¶
get_template(name: str) -> dict[str, Any] | None¶
list_templates(tag: str = '', limit: int = 50) -> list[dict[str, Any]]¶
delete_template(name: str) -> bool¶
increment_template_use(name: str) -> None¶
create_job(input_sources_json: str, engine: str, total_files: int) -> str¶
get_job(job_id: str) -> dict[str, Any] | None¶
update_job(job_id: str, **kwargs: Any) -> bool¶
list_jobs(status: str = '', limit: int = 50) -> list[dict[str, Any]]¶
upsert_pipeline(name: str, description: str, steps_json: str, tags: list[str]) -> str¶
get_pipeline(name: str) -> dict[str, Any] | None¶
list_pipelines(limit: int = 50) -> list[dict[str, Any]]¶
delete_pipeline(name: str) -> bool¶
increment_pipeline_use(name: str) -> None¶
text_search(query: str, top_k: int = 5) -> list[dict[str, Any]]¶
TF-IDF search across conversions, templates, pipelines, and errors.
count_all() -> dict[str, int]¶
Functions¶
agentic_planner_enabled(default_enabled: bool) -> bool¶
Decide whether the agentic search-result-rerank planner should be used.
eligible_fingerprint(records: list[Any]) -> str¶
sha256 over the returned record texts (order-sensitive).
validate_markitdown_rerank_decision(decision: MarkitdownRerankDecision, n_eligible: int, expected_fingerprint: str) -> None¶
Returned-set / anti-injection guard for a search-result-rerank decision.
planner_is_llm_trusted(planner: Any) -> bool¶
Whether the BLOCK may report
llm_used=Trueforplanner.
MCP Tools¶
| Operation | Source |
|---|---|
convert | markitdown_mcp |
batch_convert | markitdown_mcp |
detect_type | markitdown_mcp |
list_formats | markitdown_mcp |
resource_check | markitdown_mcp |
record_conversion | markitdown_mcp |
query_conversions | markitdown_mcp |
get_conversion_stats | markitdown_mcp |
delete_conversion | markitdown_mcp |
export_history | markitdown_mcp |
purge_old | markitdown_mcp |
save_template | markitdown_mcp |
get_template | markitdown_mcp |
list_templates | markitdown_mcp |
delete_template | markitdown_mcp |
submit_job | markitdown_mcp |
get_job_status | markitdown_mcp |
list_jobs | markitdown_mcp |
cancel_job | markitdown_mcp |
create_pipeline | markitdown_mcp |
run_pipeline | markitdown_mcp |
list_pipelines | markitdown_mcp |
delete_pipeline | markitdown_mcp |
search | markitdown_mcp |
info | markitdown_mcp |
list_patterns | markitdown_mcp |