MCP Server

Bilig WorkPaper

io.github.proompteng/bilig-workpaper
Data & Analytics Productivity Public & reachable MCP 2025-11-25

What this MCP does

Reads and edits formula-backed workbook documents, validates formulas, recalculates dependent cells, and exports WorkPaper JSON.

export_workpaper_document
Export WorkPaper Document
Export the current WorkPaper JSON document for persistence, review, or handoff to another agent. Does not write files by itself.
Read only Idempotent
Input schema
{'type': 'object', 'properties': {'includeConfig': {'type': 'boolean', 'default': True, 'description': 'Include workbook configuration metadata in the exported JSON. Defaults to true.'}}, 'additionalProperties': False}
Output schema
{'type': 'object', 'required': ['document', 'serializedBytes'], 'properties': {'document': {'type': 'object', 'description': 'Persisted WorkPaper JSON document.'}, 'sourcePath': {'type': 'string'}, 'serializedBytes': {'type': 'number'}}, 'additionalProperties': False}
get_cell_display_value
Get WorkPaper Cell Display Value
Return the formatted display string for one cell. Use when an agent needs what a user would see, not the raw numeric value.
Read only Idempotent
Input schema
{'type': 'object', 'required': ['sheetName', 'address'], 'properties': {'address': {'type': 'string', 'description': 'Single A1 cell address such as B3.'}, 'sheetName': {'type': 'string', 'description': 'Existing sheet name.'}}, 'additionalProperties': False}
Output schema
{'type': 'object', 'required': ['address', 'displayValue'], 'properties': {'address': {'type': 'string'}, 'displayValue': {'type': 'string'}}, 'additionalProperties': False}
list_sheets
List WorkPaper Sheets
Discover sheet names and used dimensions before reading or editing a WorkPaper. Returns metadata only; use read_range or read_cell for values.
Read only Idempotent
Input schema
{'type': 'object', 'additionalProperties': False}
Output schema
{'type': 'object', 'required': ['writable', 'sheets'], 'properties': {'sheets': {'type': 'array', 'items': {'type': 'object', 'required': ['id', 'name', 'dimensions'], 'properties': {'id': {'type': 'number'}, 'name': {'type': 'string'}, 'dimensions': {'type': 'object', 'description': 'Current used rows and columns for the sheet.'}}}}, 'writable': {'type': 'boolean', 'description': 'Whether set_cell_contents persists edits back to the source JSON file.'}, 'sourcePath': {'type': 'string', 'description': 'Absolute JSON file path when the server was started with --workpaper.'}}, 'additionalProperties': False}
read_cell
Read WorkPaper Cell
Read one cell with calculated value, display text, formula text, formula diagnostics, and serialized content. Use after set_cell_contents to verify readback.
Read only Idempotent
Input schema
{'type': 'object', 'required': ['sheetName', 'address'], 'properties': {'address': {'type': 'string', 'description': 'Single A1 cell address such as B3.'}, 'sheetName': {'type': 'string', 'description': 'Existing sheet name.'}}, 'additionalProperties': False}
Output schema
{'type': 'object', 'required': ['address', 'value', 'serialized', 'formula', 'displayValue', 'formulaDiagnostics'], 'properties': {'value': {'description': 'Calculated cell value.'}, 'address': {'type': 'string', 'description': 'Canonical sheet-qualified A1 address.'}, 'formula': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'description': 'Formula text without losing the original calculated value context, or null for literal cells.'}, 'serialized': {'anyOf': [{'type': 'string'}, {'type': 'number'}, {'type': 'boolean'}, {'type': 'null'}], 'description': 'Raw serialized cell content; formulas are strings that start with =.'}, 'displayValue': {'type': 'string', 'description': 'Formatted value as a user would see it.'}, 'formulaDiagnostics': {'type': 'array', 'description': 'Structured formula diagnostics. Empty when the cell has no formula error.'}}, 'additionalProperties': False}
read_range
Read WorkPaper Range
Read calculated values plus serialized formulas/inputs for an A1 range. Use for audit readback after edits; use read_cell for one address.
Read only Idempotent
Input schema
{'type': 'object', 'required': ['range'], 'properties': {'range': {'type': 'string', 'description': 'A1 range such as Summary!A1:B5. If omitted from the range, pass sheetName separately.'}, 'sheetName': {'type': 'string', 'description': 'Default sheet name when range omits a sheet name, for example Summary.'}}, 'additionalProperties': False}
Output schema
{'type': 'object', 'required': ['range', 'values', 'serialized'], 'properties': {'range': {'type': 'string', 'description': 'Canonical A1 range including the sheet name.'}, 'values': {'type': 'array', 'description': 'Two-dimensional array of evaluated cell values.'}, 'serialized': {'type': 'array', 'description': 'Two-dimensional array of raw serialized cell contents, including formulas.'}}, 'additionalProperties': False}
set_cell_contents
Set WorkPaper Cell Contents
Write raw content to one cell and recalculate dependents in memory only. Start with --writable when the edit should persist to JSON.
Idempotent
Input schema
{'type': 'object', 'required': ['sheetName', 'address', 'value'], 'properties': {'value': {'type': 'string', 'description': 'Raw cell content. Formula strings must start with =; plain strings are stored as literals. Strict MCP hosts such as Semantic Kernel require a single parameter type, so pass evaluated numbers/booleans as formulas such as =0.4 or =TRUE(). The server still accepts JSON number, boolean, or null arguments from clients that support them.'}, 'address': {'type': 'string', 'description': 'Single A1 cell address such as B3. Ranges are not accepted.'}, 'sheetName': {'type': 'string', 'description': 'Existing sheet name, for example Inputs.'}}, 'additionalProperties': False}
Output schema
{'type': 'object', 'required': ['editedCell', 'before', 'after', 'restored', 'persistence', 'checks'], 'properties': {'after': {'type': 'object', 'required': ['address', 'value', 'serialized', 'formula', 'displayValue', 'formulaDiagnostics'], 'properties': {'value': {'description': 'Calculated cell value.'}, 'address': {'type': 'string', 'description': 'Canonical sheet-qualified A1 address.'}, 'formula': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'description': 'Formula text without losing the original calculated value context, or null for literal cells.'}, 'serialized': {'anyOf': [{'type': 'string'}, {'type': 'number'}, {'type': 'boolean'}, {'type': 'null'}], 'description': 'Raw serialized cell content; formulas are strings that start with =.'}, 'displayValue': {'type': 'string', 'description': 'Formatted value as a user would see it.'}, 'formulaDiagnostics': {'type': 'array', 'description': 'Structured formula diagnostics. Empty when the cell has no formula error.'}}, 'additionalProperties': False}, 'before': {'type': 'object', 'required': ['address', 'value', 'serialized', 'formula', 'displayValue', 'formulaDiagnostics'], 'properties': {'value': {'description': 'Calculated cell value.'}, 'address': {'type': 'string', 'description': 'Canonical sheet-qualified A1 address.'}, 'formula': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'description': 'Formula text without losing the original calculated value context, or null for literal cells.'}, 'serialized': {'anyOf': [{'type': 'string'}, {'type': 'number'}, {'type': 'boolean'}, {'type': 'null'}], 'description': 'Raw serialized cell content; formulas are strings that start with =.'}, 'displayValue': {'type': 'string', 'description': 'Formatted value as a user would see it.'}, 'formulaDiagnostics': {'type': 'array', 'description': 'Structured formula diagnostics. Empty when the cell has no formula error.'}}, 'additionalProperties': False}, 'checks': {'type': 'object', 'required': ['persisted', 'restoredMatchesAfter', 'previousSerialized', 'newSerialized'], 'properties': {'persisted': {'type': 'boolean'}, 'newSerialized': {'anyOf': [{'type': 'string'}, {'type': 'number'}, {'type': 'boolean'}, {'type': 'null'}], 'description': 'Raw serialized cell content; formulas are strings that start with =.'}, 'previousSerialized': {'anyOf': [{'type': 'string'}, {'type': 'number'}, {'type': 'boolean'}, {'type': 'null'}], 'description': 'Raw serialized cell content; formulas are strings that start with =.'}, 'restoredMatchesAfter': {'type': 'boolean', 'description': 'True when exported and re-imported JSON preserves the edited cell readback.'}}}, 'restored': {'type': 'object', 'required': ['address', 'value', 'serialized', 'formula', 'displayValue', 'formulaDiagnostics'], 'properties': {'value': {'description': 'Calculated cell value.'}, 'address': {'type': 'string', 'description': 'Canonical sheet-qualified A1 address.'}, 'formula': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'description': 'Formula text without losing the original calculated value context, or null for literal cells.'}, 'serialized': {'anyOf': [{'type': 'string'}, {'type': 'number'}, {'type': 'boolean'}, {'type': 'null'}], 'description': 'Raw serialized cell content; formulas are strings that start with =.'}, 'displayValue': {'type': 'string', 'description': 'Formatted value as a user would see it.'}, 'formulaDiagnostics': {'type': 'array', 'description': 'Structured formula diagnostics. Empty when the cell has no formula error.'}}, 'additionalProperties': False}, 'editedCell': {'type': 'string', 'description': 'Canonical sheet-qualified address that was edited.'}, 'persistence': {'type': 'object', 'required': ['persisted', 'serializedBytes'], 'properties': {'path': {'type': 'string'}, 'persisted': {'type': 'boolean'}, 'serializedBytes': {'type': 'number'}}}}, 'additionalProperties': False}
set_cell_contents_and_readback
Set WorkPaper Cell Contents And Read Back
Write raw content to one cell, recalculate dependents, read a dependent range in the same tool call, and return persistence proof. Use this for stateless MCP clients such as hosted Open WebUI integrations.
Idempotent
Input schema
{'type': 'object', 'required': ['sheetName', 'address', 'value', 'readbackRange'], 'properties': {'value': {'type': 'string', 'description': 'Raw cell content. Formula strings must start with =; plain strings are stored as literals. Strict MCP hosts require a single parameter type, so pass evaluated numbers/booleans as formulas such as =0.4 or =TRUE(). The server still accepts JSON number, boolean, or null arguments from clients that support them.'}, 'address': {'type': 'string', 'description': 'Single A1 cell address to edit, such as B3. Ranges are not accepted.'}, 'sheetName': {'type': 'string', 'description': 'Existing sheet name for the cell to edit, for example Inputs.'}, 'readbackRange': {'type': 'string', 'description': 'Dependent A1 range to read before and after the edit, for example Summary!A1:B5.'}, 'readbackSheetName': {'type': 'string', 'description': 'Default sheet name when readbackRange omits a sheet name.'}}, 'additionalProperties': False}
Output schema
{'type': 'object', 'required': ['editedCell', 'readbackRange', 'before', 'after', 'beforeReadback', 'afterReadback', 'restoredReadback', 'persistence', 'checks'], 'properties': {'after': {'type': 'object', 'required': ['address', 'value', 'serialized', 'formula', 'displayValue', 'formulaDiagnostics'], 'properties': {'value': {'description': 'Calculated cell value.'}, 'address': {'type': 'string', 'description': 'Canonical sheet-qualified A1 address.'}, 'formula': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'description': 'Formula text without losing the original calculated value context, or null for literal cells.'}, 'serialized': {'anyOf': [{'type': 'string'}, {'type': 'number'}, {'type': 'boolean'}, {'type': 'null'}], 'description': 'Raw serialized cell content; formulas are strings that start with =.'}, 'displayValue': {'type': 'string', 'description': 'Formatted value as a user would see it.'}, 'formulaDiagnostics': {'type': 'array', 'description': 'Structured formula diagnostics. Empty when the cell has no formula error.'}}, 'additionalProperties': False}, 'before': {'type': 'object', 'required': ['address', 'value', 'serialized', 'formula', 'displayValue', 'formulaDiagnostics'], 'properties': {'value': {'description': 'Calculated cell value.'}, 'address': {'type': 'string', 'description': 'Canonical sheet-qualified A1 address.'}, 'formula': {'anyOf': [{'type': 'string'}, {'type': 'null'}], 'description': 'Formula text without losing the original calculated value context, or null for literal cells.'}, 'serialized': {'anyOf': [{'type': 'string'}, {'type': 'number'}, {'type': 'boolean'}, {'type': 'null'}], 'description': 'Raw serialized cell content; formulas are strings that start with =.'}, 'displayValue': {'type': 'string', 'description': 'Formatted value as a user would see it.'}, 'formulaDiagnostics': {'type': 'array', 'description': 'Structured formula diagnostics. Empty when the cell has no formula error.'}}, 'additionalProperties': False}, 'checks': {'type': 'object', 'required': ['persisted', 'readbackChanged', 'restoredReadbackMatchesAfter', 'previousSerialized', 'newSerialized'], 'properties': {'persisted': {'type': 'boolean'}, 'newSerialized': {'anyOf': [{'type': 'string'}, {'type': 'number'}, {'type': 'boolean'}, {'type': 'null'}], 'description': 'Raw serialized cell content; formulas are strings that start with =.'}, 'readbackChanged': {'type': 'boolean', 'description': 'True when the dependent readback values differ after the edit.'}, 'previousSerialized': {'anyOf': [{'type': 'string'}, {'type': 'number'}, {'type': 'boolean'}, {'type': 'null'}], 'description': 'Raw serialized cell content; formulas are strings that start with =.'}, 'restoredReadbackMatchesAfter': {'type': 'boolean', 'description': 'True when exported and re-imported JSON preserves the dependent readback range.'}}}, 'editedCell': {'type': 'string', 'description': 'Canonical sheet-qualified address that was edited.'}, 'persistence': {'type': 'object', 'required': ['persisted', 'serializedBytes'], 'properties': {'path': {'type': 'string'}, 'persisted': {'type': 'boolean'}, 'serializedBytes': {'type': 'number'}}}, 'afterReadback': {'type': 'object', 'required': ['range', 'values', 'serialized'], 'properties': {'range': {'type': 'string', 'description': 'Canonical A1 range including the sheet name.'}, 'values': {'type': 'array', 'description': 'Two-dimensional array of evaluated cell values.'}, 'serialized': {'type': 'array', 'description': 'Two-dimensional array of raw serialized cell contents, including formulas.'}}, 'additionalProperties': False}, 'readbackRange': {'type': 'string', 'description': 'Canonical sheet-qualified range read before and after the edit.'}, 'beforeReadback': {'type': 'object', 'required': ['range', 'values', 'serialized'], 'properties': {'range': {'type': 'string', 'description': 'Canonical A1 range including the sheet name.'}, 'values': {'type': 'array', 'description': 'Two-dimensional array of evaluated cell values.'}, 'serialized': {'type': 'array', 'description': 'Two-dimensional array of raw serialized cell contents, including formulas.'}}, 'additionalProperties': False}, 'restoredReadback': {'type': 'object', 'required': ['range', 'values', 'serialized'], 'properties': {'range': {'type': 'string', 'description': 'Canonical A1 range including the sheet name.'}, 'values': {'type': 'array', 'description': 'Two-dimensional array of evaluated cell values.'}, 'serialized': {'type': 'array', 'description': 'Two-dimensional array of raw serialized cell contents, including formulas.'}}, 'additionalProperties': False}}, 'additionalProperties': False}
validate_formula
Validate WorkPaper Formula
Validate formula syntax with the WorkPaper parser before writing it to a cell. This checks syntax only; use set_cell_contents plus readback to evaluate.
Read only Idempotent
Input schema
{'type': 'object', 'required': ['formula'], 'properties': {'formula': {'type': 'string', 'description': 'Formula string including the leading =, for example =SUM(Inputs!B2:B4).'}}, 'additionalProperties': False}
Output schema
{'type': 'object', 'required': ['formula', 'valid'], 'properties': {'valid': {'type': 'boolean'}, 'formula': {'type': 'string'}}, 'additionalProperties': False}
Added
validate_formula
Sept. 17, 2026, 12:49 p.m.
Added
export_workpaper_document
Sept. 17, 2026, 12:49 p.m.
Added
get_cell_display_value
Sept. 17, 2026, 12:49 p.m.
Added
set_cell_contents_and_readback
Sept. 17, 2026, 12:49 p.m.
Added
set_cell_contents
Sept. 17, 2026, 12:49 p.m.
Added
read_cell
Sept. 17, 2026, 12:49 p.m.
Added
read_range
Sept. 17, 2026, 12:49 p.m.
Added
list_sheets
Sept. 17, 2026, 12:49 p.m.