Skip to content

feat(python): add Python MCP client library for GridCraft automation - #444

Open
dronov-dmitry wants to merge 3 commits into
storytold:mainfrom
dronov-dmitry:feat-python-mcp-client
Open

dronov-dmitry wants to merge 3 commits into
storytold:mainfrom
dronov-dmitry:feat-python-mcp-client

Conversation

@dronov-dmitry

Copy link
Copy Markdown

This PR introduces a new Python library (libs/mcp-python) that enables programmatic control of GridCraft via the MCP/TCP control channel. This allows users and AI agents to automate spreadsheet tasks using Python.

Key Features

  • GridCraft MCP Client: A native Python library for the GridCraft TCP control protocol.
    • Supports workbook creation (new_workbook), data manipulation (set_cell, read_range), formula evaluation, and charting.
  • CI/CD Pipeline: Added GitHub Actions workflow (.github/workflows/gridcraft-python-ci.yml) to automatically test, lint, and format Python code.
  • Testing Infrastructure: Comprehensive test suite with unit, integration, and example validation tests (89% code coverage).
  • Automation Scripts: Added run_tests.sh and run_ci.sh for easy development and CI execution.
  • Documentation & Demos: Includes installation guides, developer documentation, and interactive demonstration scripts.

Demo

https://youtu.be/nV-wnZiPR-M

Why this is useful

This library opens GridCraft to the Python data science and automation ecosystem (Pandas, NumPy, etc.), making it easier for users to perform complex data workflows and integrate GridCraft into their existing Python-based pipelines.

@FredApps FredApps left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Read the whole diff at 58b6c9c. Changes needed:

  1. The library does not do what the README, docs and examples say. gridcraft_mcp/client.py has five methods (execute_command, new_workbook, set_cell, get_cell, read_range), but the shipped examples call client.evaluate_formula (16 times), format_range (16), insert_chart (5), save_workbook (5), create_table (3), write_range (4) and sort_range, none of which exist, so those examples fail with AttributeError. The PR text promises charting and formula evaluation. The tests only mock the socket, so nothing runs against a real control port. Please either implement the documented methods or cut the examples and docs down to what exists, and add at least one test against gridcraft-cli or a real control port.

  2. read_range sends engine.execute with command "read_range". docs/control-protocol.md has no such method or command: reading a range is the sheet.read method (and cell.get is its own method too). Please use the documented method names and reply shape, and add a test that checks the request/response against the protocol doc.

  3. Scope/policy: AGENTS.md says the repo is Rust only, and this adds about 5,000 lines of Python, docs and a new CI workflow under libs/. That is a maintainer decision; a separate repo may be the better home. docs/testing.md (718 lines) and docs/development.md are largely generic templates (unittest.mock examples with mock_post, a clone path of gridcraft/gridcraft-python), not about this library.

  4. The new workflow pins actions by tag (actions/checkout@v4, setup-python@v5); the other workflows pin full commit SHAs.

Validation was source reading only. No hosted checks have run on this head, and no local tests were run (builds are paused).

@Harrison-Booth

Copy link
Copy Markdown
Contributor

Review notes (comment only). I read the whole diff and compared the client with main's control server docs and source; I did not run the Python tests or build GridCraft, and no Excel check applies here.

  • The client cannot connect to current main. docs/control-protocol.md on main says every connection's first line must be {"id":0,"method":"auth","params":{"token":"…"}}, with the token from $XDG_RUNTIME_DIR/gridcraft/control-<port>.token or GRIDCRAFT_CONTROL_TOKEN; any other first line closes the connection. gridcraft_mcp/client.py start() only calls connect(), and _send_request sends engine.execute straight away, so the first request is refused. It needs a token argument/env lookup and the auth line after connect.
  • _send_request adds "jsonrpc": "2.0", but the channel's lines are {"id","method","params"} and replies are {"id","ok","result"} (or an error). Reading response.get("result", response) works by accident for replies; checking ok would be more reliable.
  • read_range is sent as a command id, and no command with that id exists in crates/engine/src on main; the read command is sheet.read ({range?, sheet?, formulas?, formatted?}).
  • The client has a _testing mode that skips connecting; I did not read the tests, but anything that mocks the socket cannot catch the points above, and a real integration test needs a running app with --control and its token.
  • Scope: +5,280 lines across 28 files (README, a CI workflow, demo scripts, a video link). Whether a handwritten Python library belongs in this repo is for the maintainers (CLAUDE.md says "Rust only (no handwritten JS/TS)" and does not mention Python).

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants