krita-mcp 1.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- krita_mcp-1.4.0/.gitignore +30 -0
- krita_mcp-1.4.0/LICENSE +121 -0
- krita_mcp-1.4.0/PKG-INFO +108 -0
- krita_mcp-1.4.0/README.md +88 -0
- krita_mcp-1.4.0/docs/capabilities.jpg +0 -0
- krita_mcp-1.4.0/docs/development.md +90 -0
- krita_mcp-1.4.0/docs/usage.md +128 -0
- krita_mcp-1.4.0/docs/workflows.md +169 -0
- krita_mcp-1.4.0/install.ps1 +26 -0
- krita_mcp-1.4.0/install.sh +11 -0
- krita_mcp-1.4.0/mcp_server.py +1239 -0
- krita_mcp-1.4.0/painter_schema.py +35 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/__init__.py +7 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/compat.py +141 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/extension.py +160 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/feedback.py +73 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/filter_parameters.py +106 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/httpserver.py +395 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/imaging.py +246 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/mainthread.py +120 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/native_commands.py +406 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/operations/__init__.py +8 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/operations/animation.py +234 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/operations/capabilities.py +143 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/operations/common.py +101 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/operations/correction.py +364 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/operations/dialogs.py +23 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/operations/editing.py +177 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/operations/feedback.py +122 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/operations/painting.py +232 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/operations/patches.py +134 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/operations/repair_preview.py +97 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/operations/selections.py +220 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/operations/transforms.py +148 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/operations/warp.py +183 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/ops.py +1951 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/sessions.py +31 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/stroke_planner.py +151 -0
- krita_mcp-1.4.0/pykrita/krita_mcp/targeting.py +40 -0
- krita_mcp-1.4.0/pykrita/krita_mcp.desktop +8 -0
- krita_mcp-1.4.0/pyproject.toml +58 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*.egg-info/
|
|
5
|
+
.venv/
|
|
6
|
+
venv/
|
|
7
|
+
|
|
8
|
+
# Local client configuration
|
|
9
|
+
/.codex/
|
|
10
|
+
|
|
11
|
+
# Package build output
|
|
12
|
+
dist/
|
|
13
|
+
build/
|
|
14
|
+
|
|
15
|
+
# Output from the example scripts
|
|
16
|
+
poster.png
|
|
17
|
+
poster_preview.png
|
|
18
|
+
banner.png
|
|
19
|
+
docs/banner_preview.png
|
|
20
|
+
|
|
21
|
+
# Krita
|
|
22
|
+
*.kra~
|
|
23
|
+
*.kra-autosave.kra
|
|
24
|
+
|
|
25
|
+
# Local verification captures and receipts
|
|
26
|
+
artifacts/
|
|
27
|
+
native/build/
|
|
28
|
+
pykrita/krita_mcp/libkrita_mcp_native.*
|
|
29
|
+
pykrita/krita_mcp/libkrita_mcp_native_*.so
|
|
30
|
+
pykrita/krita_mcp/native_manifest.json
|
krita_mcp-1.4.0/LICENSE
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
Creative Commons Legal Code
|
|
2
|
+
|
|
3
|
+
CC0 1.0 Universal
|
|
4
|
+
|
|
5
|
+
CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
|
|
6
|
+
LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
|
|
7
|
+
ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
|
|
8
|
+
INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
|
|
9
|
+
REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
|
|
10
|
+
PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
|
|
11
|
+
THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
|
|
12
|
+
HEREUNDER.
|
|
13
|
+
|
|
14
|
+
Statement of Purpose
|
|
15
|
+
|
|
16
|
+
The laws of most jurisdictions throughout the world automatically confer
|
|
17
|
+
exclusive Copyright and Related Rights (defined below) upon the creator
|
|
18
|
+
and subsequent owner(s) (each and all, an "owner") of an original work of
|
|
19
|
+
authorship and/or a database (each, a "Work").
|
|
20
|
+
|
|
21
|
+
Certain owners wish to permanently relinquish those rights to a Work for
|
|
22
|
+
the purpose of contributing to a commons of creative, cultural and
|
|
23
|
+
scientific works ("Commons") that the public can reliably and without fear
|
|
24
|
+
of later claims of infringement build upon, modify, incorporate in other
|
|
25
|
+
works, reuse and redistribute as freely as possible in any form whatsoever
|
|
26
|
+
and for any purposes, including without limitation commercial purposes.
|
|
27
|
+
These owners may contribute to the Commons to promote the ideal of a free
|
|
28
|
+
culture and the further production of creative, cultural and scientific
|
|
29
|
+
works, or to gain reputation or greater distribution for their Work in
|
|
30
|
+
part through the use and efforts of others.
|
|
31
|
+
|
|
32
|
+
For these and/or other purposes and motivations, and without any
|
|
33
|
+
expectation of additional consideration or compensation, the person
|
|
34
|
+
associating CC0 with a Work (the "Affirmer"), to the extent that he or she
|
|
35
|
+
is an owner of Copyright and Related Rights in the Work, voluntarily
|
|
36
|
+
elects to apply CC0 to the Work and publicly distribute the Work under its
|
|
37
|
+
terms, with knowledge of his or her Copyright and Related Rights in the
|
|
38
|
+
Work and the meaning and intended legal effect of CC0 on those rights.
|
|
39
|
+
|
|
40
|
+
1. Copyright and Related Rights. A Work made available under CC0 may be
|
|
41
|
+
protected by copyright and related or neighboring rights ("Copyright and
|
|
42
|
+
Related Rights"). Copyright and Related Rights include, but are not
|
|
43
|
+
limited to, the following:
|
|
44
|
+
|
|
45
|
+
i. the right to reproduce, adapt, distribute, perform, display,
|
|
46
|
+
communicate, and translate a Work;
|
|
47
|
+
ii. moral rights retained by the original author(s) and/or performer(s);
|
|
48
|
+
iii. publicity and privacy rights pertaining to a person's image or
|
|
49
|
+
likeness depicted in a Work;
|
|
50
|
+
iv. rights protecting against unfair competition in regards to a Work,
|
|
51
|
+
subject to the limitations in paragraph 4(a), below;
|
|
52
|
+
v. rights protecting the extraction, dissemination, use and reuse of data
|
|
53
|
+
in a Work;
|
|
54
|
+
vi. database rights (such as those arising under Directive 96/9/EC of the
|
|
55
|
+
European Parliament and of the Council of 11 March 1996 on the legal
|
|
56
|
+
protection of databases, and under any national implementation
|
|
57
|
+
thereof, including any amended or successor version of such
|
|
58
|
+
directive); and
|
|
59
|
+
vii. other similar, equivalent or corresponding rights throughout the
|
|
60
|
+
world based on applicable law or treaty, and any national
|
|
61
|
+
implementations thereof.
|
|
62
|
+
|
|
63
|
+
2. Waiver. To the greatest extent permitted by, but not in contravention
|
|
64
|
+
of, applicable law, Affirmer hereby overtly, fully, permanently,
|
|
65
|
+
irrevocably and unconditionally waives, abandons, and surrenders all of
|
|
66
|
+
Affirmer's Copyright and Related Rights and associated claims and causes
|
|
67
|
+
of action, whether now known or unknown (including existing as well as
|
|
68
|
+
future claims and causes of action), in the Work (i) in all territories
|
|
69
|
+
worldwide, (ii) for the maximum duration provided by applicable law or
|
|
70
|
+
treaty (including future time extensions), (iii) in any current or future
|
|
71
|
+
medium and for any number of copies, and (iv) for any purpose whatsoever,
|
|
72
|
+
including without limitation commercial, advertising or promotional
|
|
73
|
+
purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
|
|
74
|
+
member of the public at large and to the detriment of Affirmer's heirs and
|
|
75
|
+
successors, fully intending that such Waiver shall not be subject to
|
|
76
|
+
revocation, rescission, cancellation, termination, or any other legal or
|
|
77
|
+
equitable action to disrupt the quiet enjoyment of the Work by the public
|
|
78
|
+
as contemplated by Affirmer's express Statement of Purpose.
|
|
79
|
+
|
|
80
|
+
3. Public License Fallback. Should any part of the Waiver for any reason
|
|
81
|
+
be judged legally invalid or ineffective under applicable law, then the
|
|
82
|
+
Waiver shall be preserved to the maximum extent permitted taking into
|
|
83
|
+
account Affirmer's express Statement of Purpose. In addition, to the
|
|
84
|
+
extent the Waiver is so judged Affirmer hereby grants to each affected
|
|
85
|
+
person a royalty-free, non transferable, non sublicensable, non exclusive,
|
|
86
|
+
irrevocable and unconditional license to exercise Affirmer's Copyright and
|
|
87
|
+
Related Rights in the Work (i) in all territories worldwide, (ii) for the
|
|
88
|
+
maximum duration provided by applicable law or treaty (including future
|
|
89
|
+
time extensions), (iii) in any current or future medium and for any number
|
|
90
|
+
of copies, and (iv) for any purpose whatsoever, including without
|
|
91
|
+
limitation commercial, advertising or promotional purposes (the
|
|
92
|
+
"License"). The License shall be deemed effective as of the date CC0 was
|
|
93
|
+
applied by Affirmer to the Work. Should any part of the License for any
|
|
94
|
+
reason be judged legally invalid or ineffective under applicable law, such
|
|
95
|
+
partial invalidity or ineffectiveness shall not invalidate the remainder
|
|
96
|
+
of the License, and in such case Affirmer hereby affirms that he or she
|
|
97
|
+
will not (i) exercise any of his or her remaining Copyright and Related
|
|
98
|
+
Rights in the Work or (ii) assert any associated claims and causes of
|
|
99
|
+
action with respect to the Work, in either case contrary to Affirmer's
|
|
100
|
+
express Statement of Purpose.
|
|
101
|
+
|
|
102
|
+
4. Limitations and Disclaimers.
|
|
103
|
+
|
|
104
|
+
a. No trademark or patent rights held by Affirmer are waived, abandoned,
|
|
105
|
+
surrendered, licensed or otherwise affected by this document.
|
|
106
|
+
b. Affirmer offers the Work as-is and makes no representations or
|
|
107
|
+
warranties of any kind concerning the Work, express, implied,
|
|
108
|
+
statutory or otherwise, including without limitation warranties of
|
|
109
|
+
title, merchantability, fitness for a particular purpose, non
|
|
110
|
+
infringement, or the absence of latent or other defects, accuracy, or
|
|
111
|
+
the present or absence of errors, whether or not discoverable, all to
|
|
112
|
+
the greatest extent permissible under applicable law.
|
|
113
|
+
c. Affirmer disclaims responsibility for clearing rights of other persons
|
|
114
|
+
that may apply to the Work or any use thereof, including without
|
|
115
|
+
limitation any person's Copyright and Related Rights in the Work.
|
|
116
|
+
Further, Affirmer disclaims responsibility for obtaining any necessary
|
|
117
|
+
consents, permissions or other rights required for any use of the
|
|
118
|
+
Work.
|
|
119
|
+
d. Affirmer understands and acknowledges that Creative Commons is not a
|
|
120
|
+
party to this document and has no duty or obligation with respect to
|
|
121
|
+
this CC0 or use of the Work.
|
krita_mcp-1.4.0/PKG-INFO
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: krita-mcp
|
|
3
|
+
Version: 1.4.0
|
|
4
|
+
Summary: MCP server that lets agents drive Krita
|
|
5
|
+
Project-URL: Homepage, https://github.com/thuanlm215/krita-mcp
|
|
6
|
+
Project-URL: Repository, https://github.com/thuanlm215/krita-mcp
|
|
7
|
+
Project-URL: Issues, https://github.com/thuanlm215/krita-mcp/issues
|
|
8
|
+
Author: thuanlm215
|
|
9
|
+
License-Expression: CC0-1.0
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Keywords: krita,mcp,model-context-protocol
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Topic :: Multimedia :: Graphics
|
|
18
|
+
Requires-Python: >=3.8
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
# Krita MCP
|
|
22
|
+
|
|
23
|
+
Give an agent a real Krita file. It can build the layer stack, select a part, turn it around a pivot, lay down a pressure stroke, step through raster frames, and look at the PNG it just made.
|
|
24
|
+
|
|
25
|
+

|
|
26
|
+
|
|
27
|
+
Read the picture from the back of the desk forward. The three sheets are a layer stack: wash, line, color. The dashed loop and the pins are a selection swung around a pivot. The bristle mark is one native stroke that starts light and ends heavy. The four cells are raster frames. The split lens is a repair: the crack on one side, the same pane whole on the other.
|
|
28
|
+
|
|
29
|
+
[thuanlm215](https://github.com/thuanlm215) maintains this tree. The stdio transport and the first document tools come from [SanSaSane/krita-mcp](https://github.com/SanSaSane/krita-mcp) at `93f485d`. Version **1.4.0** adds native Undo, brushes, transforms, animation frames, and bounded repair. Fifty-two tools, sixty-one bridge operations. The full list is in [docs/usage.md](docs/usage.md). The call order for a pose, a warp, a frame, and a repair is in [docs/workflows.md](docs/workflows.md).
|
|
30
|
+
|
|
31
|
+
## What has to be installed
|
|
32
|
+
|
|
33
|
+
Krita 5.2 or newer covers documents, layers, geometric drawing, filters, and export. Brush pressure, native pixel Undo, warp, batches, and exact raster frames need **Linux, Krita 6.0.4, Qt6, little-endian**, plus the helper in [native/README.md](native/README.md). Anywhere else those calls return `unsupported`.
|
|
34
|
+
|
|
35
|
+
The server is Python 3.8 or newer and the standard library. Krita loads a plugin in its own process. The MCP client runs `krita-mcp` beside it. Install the plugin once.
|
|
36
|
+
|
|
37
|
+
Close Krita before the installer writes `kritarc`. Krita rewrites that file on exit.
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# pure Python plugin, no clone
|
|
41
|
+
uvx --from git+https://github.com/thuanlm215/krita-mcp krita-mcp install
|
|
42
|
+
|
|
43
|
+
# Linux / Krita 6.0.4, from a clone, when you need the native helper
|
|
44
|
+
python3 build_native.py
|
|
45
|
+
python3 mcp_server.py install
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`./install.sh` and `install.ps1` call the same installer. `--force` writes the enable flag while Krita is still open. By hand, copy `pykrita/krita_mcp/` and `pykrita/krita_mcp.desktop` into Krita's `pykrita` folder and enable **MCP Bridge** under *Settings → Configure Krita → Python Plugin Manager*.
|
|
49
|
+
|
|
50
|
+
Start Krita. *Tools → Scripts* should show **Start/Stop MCP Bridge** and **MCP Bridge Status…**.
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
uvx --from git+https://github.com/thuanlm215/krita-mcp krita-mcp --selftest
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
A GitHub release publishes the package. After `krita-mcp` is on PyPI, drop the `--from` argument and use `uvx krita-mcp`. The release steps are in [docs/development.md](docs/development.md#release).
|
|
57
|
+
|
|
58
|
+
## Point a client at it
|
|
59
|
+
|
|
60
|
+
Restart the client after editing its config. Krita has to be running before a tool can touch a document.
|
|
61
|
+
|
|
62
|
+
Codex, `~/.codex/config.toml`:
|
|
63
|
+
|
|
64
|
+
```toml
|
|
65
|
+
[mcp_servers.krita]
|
|
66
|
+
command = "uvx"
|
|
67
|
+
args = ["--from", "git+https://github.com/thuanlm215/krita-mcp", "krita-mcp"]
|
|
68
|
+
startup_timeout_sec = 30
|
|
69
|
+
tool_timeout_sec = 360
|
|
70
|
+
enabled = true
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Claude Code:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
claude mcp add krita -- uvx --from git+https://github.com/thuanlm215/krita-mcp krita-mcp
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Claude Desktop and any other JSON config:
|
|
80
|
+
|
|
81
|
+
```json
|
|
82
|
+
{
|
|
83
|
+
"mcpServers": {
|
|
84
|
+
"krita": {
|
|
85
|
+
"command": "uvx",
|
|
86
|
+
"args": ["--from", "git+https://github.com/thuanlm215/krita-mcp", "krita-mcp"]
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
A checkout works the same way with `python3` and an absolute path to `mcp_server.py`.
|
|
93
|
+
|
|
94
|
+
## A session
|
|
95
|
+
|
|
96
|
+
Ask for the open layer tree and set the top layer to multiply at 60%. Ask to cut a forearm onto its own layer, rotate it around the elbow, and paint the seam with a dry bristle. Ask to duplicate three raster keys, export an atlas, then repair one cracked pane on the held frame and show the before and after.
|
|
97
|
+
|
|
98
|
+
Reconnect the client after a plugin update. An open chat keeps the schema it saw at startup.
|
|
99
|
+
|
|
100
|
+
`close_document` can still bring Krita down on some teardown paths. *File → Close* can hit the same fault. Leave the file open and close it yourself when the session matters. [docs/usage.md](docs/usage.md#closing-documents) has the rest: colour space, filter types, the recovery dialog, and what a lost response means.
|
|
101
|
+
|
|
102
|
+
Build and tests: [docs/development.md](docs/development.md).
|
|
103
|
+
|
|
104
|
+
## License
|
|
105
|
+
|
|
106
|
+
The Python server, the Krita plugin, and the upstream work are [CC0 1.0](LICENSE). `native/bridge.cpp` is GPL-2.0-or-later. Vendored Krita headers keep their own GPL and LGPL notices. See [native licensing](native/README.md#sources-and-licensing) and `native/LICENSES/`.
|
|
107
|
+
|
|
108
|
+
The wheel that `uvx` installs is the CC0 server and plugin. It does not contain the helper binary or the vendored headers.
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Krita MCP
|
|
2
|
+
|
|
3
|
+
Give an agent a real Krita file. It can build the layer stack, select a part, turn it around a pivot, lay down a pressure stroke, step through raster frames, and look at the PNG it just made.
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
Read the picture from the back of the desk forward. The three sheets are a layer stack: wash, line, color. The dashed loop and the pins are a selection swung around a pivot. The bristle mark is one native stroke that starts light and ends heavy. The four cells are raster frames. The split lens is a repair: the crack on one side, the same pane whole on the other.
|
|
8
|
+
|
|
9
|
+
[thuanlm215](https://github.com/thuanlm215) maintains this tree. The stdio transport and the first document tools come from [SanSaSane/krita-mcp](https://github.com/SanSaSane/krita-mcp) at `93f485d`. Version **1.4.0** adds native Undo, brushes, transforms, animation frames, and bounded repair. Fifty-two tools, sixty-one bridge operations. The full list is in [docs/usage.md](docs/usage.md). The call order for a pose, a warp, a frame, and a repair is in [docs/workflows.md](docs/workflows.md).
|
|
10
|
+
|
|
11
|
+
## What has to be installed
|
|
12
|
+
|
|
13
|
+
Krita 5.2 or newer covers documents, layers, geometric drawing, filters, and export. Brush pressure, native pixel Undo, warp, batches, and exact raster frames need **Linux, Krita 6.0.4, Qt6, little-endian**, plus the helper in [native/README.md](native/README.md). Anywhere else those calls return `unsupported`.
|
|
14
|
+
|
|
15
|
+
The server is Python 3.8 or newer and the standard library. Krita loads a plugin in its own process. The MCP client runs `krita-mcp` beside it. Install the plugin once.
|
|
16
|
+
|
|
17
|
+
Close Krita before the installer writes `kritarc`. Krita rewrites that file on exit.
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# pure Python plugin, no clone
|
|
21
|
+
uvx --from git+https://github.com/thuanlm215/krita-mcp krita-mcp install
|
|
22
|
+
|
|
23
|
+
# Linux / Krita 6.0.4, from a clone, when you need the native helper
|
|
24
|
+
python3 build_native.py
|
|
25
|
+
python3 mcp_server.py install
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`./install.sh` and `install.ps1` call the same installer. `--force` writes the enable flag while Krita is still open. By hand, copy `pykrita/krita_mcp/` and `pykrita/krita_mcp.desktop` into Krita's `pykrita` folder and enable **MCP Bridge** under *Settings → Configure Krita → Python Plugin Manager*.
|
|
29
|
+
|
|
30
|
+
Start Krita. *Tools → Scripts* should show **Start/Stop MCP Bridge** and **MCP Bridge Status…**.
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
uvx --from git+https://github.com/thuanlm215/krita-mcp krita-mcp --selftest
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
A GitHub release publishes the package. After `krita-mcp` is on PyPI, drop the `--from` argument and use `uvx krita-mcp`. The release steps are in [docs/development.md](docs/development.md#release).
|
|
37
|
+
|
|
38
|
+
## Point a client at it
|
|
39
|
+
|
|
40
|
+
Restart the client after editing its config. Krita has to be running before a tool can touch a document.
|
|
41
|
+
|
|
42
|
+
Codex, `~/.codex/config.toml`:
|
|
43
|
+
|
|
44
|
+
```toml
|
|
45
|
+
[mcp_servers.krita]
|
|
46
|
+
command = "uvx"
|
|
47
|
+
args = ["--from", "git+https://github.com/thuanlm215/krita-mcp", "krita-mcp"]
|
|
48
|
+
startup_timeout_sec = 30
|
|
49
|
+
tool_timeout_sec = 360
|
|
50
|
+
enabled = true
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Claude Code:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
claude mcp add krita -- uvx --from git+https://github.com/thuanlm215/krita-mcp krita-mcp
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Claude Desktop and any other JSON config:
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"mcpServers": {
|
|
64
|
+
"krita": {
|
|
65
|
+
"command": "uvx",
|
|
66
|
+
"args": ["--from", "git+https://github.com/thuanlm215/krita-mcp", "krita-mcp"]
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
A checkout works the same way with `python3` and an absolute path to `mcp_server.py`.
|
|
73
|
+
|
|
74
|
+
## A session
|
|
75
|
+
|
|
76
|
+
Ask for the open layer tree and set the top layer to multiply at 60%. Ask to cut a forearm onto its own layer, rotate it around the elbow, and paint the seam with a dry bristle. Ask to duplicate three raster keys, export an atlas, then repair one cracked pane on the held frame and show the before and after.
|
|
77
|
+
|
|
78
|
+
Reconnect the client after a plugin update. An open chat keeps the schema it saw at startup.
|
|
79
|
+
|
|
80
|
+
`close_document` can still bring Krita down on some teardown paths. *File → Close* can hit the same fault. Leave the file open and close it yourself when the session matters. [docs/usage.md](docs/usage.md#closing-documents) has the rest: colour space, filter types, the recovery dialog, and what a lost response means.
|
|
81
|
+
|
|
82
|
+
Build and tests: [docs/development.md](docs/development.md).
|
|
83
|
+
|
|
84
|
+
## License
|
|
85
|
+
|
|
86
|
+
The Python server, the Krita plugin, and the upstream work are [CC0 1.0](LICENSE). `native/bridge.cpp` is GPL-2.0-or-later. Vendored Krita headers keep their own GPL and LGPL notices. See [native licensing](native/README.md#sources-and-licensing) and `native/LICENSES/`.
|
|
87
|
+
|
|
88
|
+
The wheel that `uvx` installs is the CC0 server and plugin. It does not contain the helper binary or the vendored headers.
|
|
Binary file
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# Development
|
|
2
|
+
|
|
3
|
+
Work from a checkout when you change the plugin, the native helper, or the tests. `uvx` runs the packaged server. It is not the edit loop.
|
|
4
|
+
|
|
5
|
+
## Layout
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
mcp_server.py stdio server, CLI, and plugin installer
|
|
9
|
+
painter_schema.py stroke, target, and frame schemas
|
|
10
|
+
pyproject.toml package metadata for uvx / pip
|
|
11
|
+
install.sh / install.ps1 wrappers around `mcp_server.py install`
|
|
12
|
+
build_native.py content-addressed Linux helper build
|
|
13
|
+
dev_reload.py private Krita/Xvfb runner
|
|
14
|
+
pykrita/krita_mcp/ plugin loaded by Krita
|
|
15
|
+
native/ GPL helper and vendored headers
|
|
16
|
+
examples/ animation player and painter demos
|
|
17
|
+
test_*.py live and offline suites
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
`dev_reload.py` starts a fresh private installation. It does not copy into the desktop plugin and it does not execute arbitrary Python inside Krita. Deploy to the desktop by saving work, closing Krita, running the installer, and starting Krita again.
|
|
21
|
+
|
|
22
|
+
## Native helper
|
|
23
|
+
|
|
24
|
+
On Linux with Krita 6.0.4:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
python3 build_native.py
|
|
28
|
+
python3 mcp_server.py install
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The build writes a checksummed `.so` and `native_manifest.json` under `pykrita/krita_mcp/`. Those files are gitignored and are excluded from the Python wheel. Dependencies, the ABI pin, and the GPL/LGPL split are in [native/README.md](../native/README.md).
|
|
32
|
+
|
|
33
|
+
Do not overwrite a `.so` that a running Krita has mapped. Rebuild, then start a new Krita process.
|
|
34
|
+
|
|
35
|
+
## Tests
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
python3 mcp_server.py --selftest
|
|
39
|
+
python3 test_mcp.py
|
|
40
|
+
python3 test_mcp.py -v
|
|
41
|
+
python3 test_workflow.py
|
|
42
|
+
python3 test_advanced.py
|
|
43
|
+
python3 test_shutdown.py
|
|
44
|
+
python3 -m unittest -v test_core test_shutdown test_transport
|
|
45
|
+
python3 run_isolated_tests.py
|
|
46
|
+
python3 example_poster.py
|
|
47
|
+
python3 example_banner.py
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`test_mcp.py` speaks JSON-RPC to a real `mcp_server.py` process, so a pass covers the handshake and the basic operation set against live Krita. Workflow, advanced, painter, and repair suites cover their fixtures. They do not cover every preset, mask, or platform.
|
|
51
|
+
|
|
52
|
+
Isolated examples:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
python3 run_isolated_tests.py --output artifacts/my-warp -- \
|
|
56
|
+
python3 example_deformation_workflow.py --output artifacts/my-warp
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The runner uses a private home, Xvfb, and a copy of this checkout. It does not modify the desktop Krita installation. Do not run two UI suites at the same time.
|
|
60
|
+
|
|
61
|
+
Offline suites do not need Krita. `test_shutdown.py` needs system PyQt6. The painter demos in a full isolated run also expect Pillow and ffmpeg when they encode review media. The MCP server stays on the standard library.
|
|
62
|
+
|
|
63
|
+
## Package
|
|
64
|
+
|
|
65
|
+
The wheel contains `mcp_server.py`, `painter_schema.py`, and `pykrita/`. It does not contain the native helper.
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
uv build
|
|
69
|
+
uvx --from dist/krita_mcp-1.4.0-py3-none-any.whl krita-mcp --list-tools
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Release
|
|
73
|
+
|
|
74
|
+
Publishing uses PyPI trusted publishing. GitHub Actions requests a short-lived token. There is no API token in the repository.
|
|
75
|
+
|
|
76
|
+
The workflow is `.github/workflows/publish.yml`. It runs when a GitHub release is published, and only if the tag matches `version` in `pyproject.toml`. A release tagged `v1.4.0` publishes version `1.4.0`. PyPI keeps that file set forever, so the next release needs a new version.
|
|
77
|
+
|
|
78
|
+
Before the first release, register a pending publisher at <https://pypi.org/manage/account/publishing/>:
|
|
79
|
+
|
|
80
|
+
| Field | Value |
|
|
81
|
+
| --- | --- |
|
|
82
|
+
| PyPI project name | `krita-mcp` |
|
|
83
|
+
| Owner | `thuanlm215` |
|
|
84
|
+
| Repository name | `krita-mcp` |
|
|
85
|
+
| Workflow name | `publish.yml` |
|
|
86
|
+
| Environment name | `pypi` |
|
|
87
|
+
|
|
88
|
+
On GitHub, create an environment named `pypi` under Settings → Environments. Then draft a release whose tag is `v` plus the version in `pyproject.toml`.
|
|
89
|
+
|
|
90
|
+
After that release is on PyPI, clients use `uvx krita-mcp`. The plugin install remains `krita-mcp install`, because Krita loads Python from its own resource folder.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# Using Krita MCP
|
|
2
|
+
|
|
3
|
+
Version 1.4 exposes 52 tools and 61 bridge operations. Reconnect the MCP client after a plugin update. A running chat keeps the schema it discovered at startup.
|
|
4
|
+
|
|
5
|
+
## Tools
|
|
6
|
+
|
|
7
|
+
| Tool | What it does |
|
|
8
|
+
| --- | --- |
|
|
9
|
+
| `status` | Krita version and every open document |
|
|
10
|
+
| `dismiss_recovery_dialog` | Cancel the native Recover Files dialog and keep autosaves. Other modals stay open |
|
|
11
|
+
| `inspect_document` | Canvas, colour space, layer tree, selection |
|
|
12
|
+
| `create_document` / `open_document` | Make or load a document |
|
|
13
|
+
| `save_document` / `export_document` | Save in place or save-as; export PNG, JPEG, and other formats Krita supports |
|
|
14
|
+
| `close_document` | Close a document. See [Closing documents](#closing-documents) |
|
|
15
|
+
| `transform_image` | Resize canvas, scale, rotate, crop, flatten |
|
|
16
|
+
| `create_layer` / `set_layer` / `delete_layer` | Layer stack |
|
|
17
|
+
| `duplicate_layer` / `move_layer` / `merge_layer_down` | Restack and merge |
|
|
18
|
+
| `get_image` | Render the canvas and return a PNG |
|
|
19
|
+
| `get_pixel` | Colour at one pixel |
|
|
20
|
+
| `draw` | Shapes, text, gradients, and bitmaps on a paint layer |
|
|
21
|
+
| `list_brushes` / `draw_brush` | Native presets and undoable brush or eraser strokes |
|
|
22
|
+
| `plan_stroke` / `paint_stroke` | Versioned geometry and one native pressure stroke |
|
|
23
|
+
| `sample_colors` / `compare_images` | Linear-light palette samples and aligned geometric diagnostics |
|
|
24
|
+
| `prepare_repair` / `render_repair` / `inspect_repair` | Frozen baseline and bounded candidates |
|
|
25
|
+
| `commit_repair` / `repair_status` / `discard_repair` | Idempotent commit, outcome lookup, snapshot release |
|
|
26
|
+
| `select_polygon` / `selection_to_layer` | Polygon or lasso; copy or cut the selection to a layer |
|
|
27
|
+
| `transform_layer` | Preview or apply a native transform mask around a pivot |
|
|
28
|
+
| `warp_layer` | Preview or apply one local raster pull on a preserved-source duplicate |
|
|
29
|
+
| `select_content` | Alpha, colour, contiguous region, and imported masks |
|
|
30
|
+
| `texture_patch` / `clone_stamp` | Masked texture placement and sampled cloning |
|
|
31
|
+
| `mask_layer` / `bake_layer` | Transparency masks and baked paint layers |
|
|
32
|
+
| `edit_batch` / `preview_changes` | One Undo group with rollback, and before/after/difference |
|
|
33
|
+
| `animation_frame` / `export_animation` | Raster keyframes, onion skin, FPS, PNG sequence, atlas, manifest |
|
|
34
|
+
| `import_animation` / `animation_review` | Registered PNG import and previous/current/next panels |
|
|
35
|
+
| `undo` / `redo` | Native history for the requested document |
|
|
36
|
+
| `apply_filter` | A Krita filter on a layer or a region |
|
|
37
|
+
| `set_selection` | rect, all, none, invert, grow, shrink, feather |
|
|
38
|
+
| `list_capabilities` | Filter parameters, blend-mode ids, and real helper support |
|
|
39
|
+
| `trigger_action` | Allowlisted native history and selection actions |
|
|
40
|
+
| `self_test` | End-to-end health check |
|
|
41
|
+
|
|
42
|
+
Sequences for extraction, brushes, warp, animation, and repair are in [workflows.md](workflows.md).
|
|
43
|
+
|
|
44
|
+
## Drawing
|
|
45
|
+
|
|
46
|
+
`draw` paints a list of commands, in order, onto an RGBA/8-bit paint layer:
|
|
47
|
+
|
|
48
|
+
`fill_rect`, `rect` (optional corner radius), `ellipse`, `circle`, `line`, `polyline`, `polygon`, `text`, `linear_gradient`, `radial_gradient`, `image` (base64 PNG), and `clear`.
|
|
49
|
+
|
|
50
|
+
The active selection constrains these commands, including feathered alpha. Colours accept `#rrggbb`, `#rrggbbaa`, SVG names, or `[r, g, b, a]`.
|
|
51
|
+
|
|
52
|
+
Geometry uses `w` and `h`. Outline thickness is `stroke_width`. Only the union of affected pixels is read, painted, and written back.
|
|
53
|
+
|
|
54
|
+
## Addressing layers
|
|
55
|
+
|
|
56
|
+
Listings use docker order, top first. Name a layer by its name (`"Sky"`), a path through groups (`"Background/Sky"`), an index path (`"#0/#1"`), or `"uuid:…"`. Omit the layer to use the active one. Listings return all of these forms.
|
|
57
|
+
|
|
58
|
+
## How it works
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
MCP client --stdio JSON-RPC--> krita-mcp --HTTP--> Krita plugin --> libkis
|
|
62
|
+
(stdlib) loopback (GUI thread)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Krita runs Python only inside itself, and an MCP server is a separate process. The two halves find each other through a small file in Krita's data folder. That file holds the port and a random per-session token. The bridge binds loopback only and requires the token.
|
|
66
|
+
|
|
67
|
+
libkis is not thread-safe. The HTTP server accepts connections on worker threads and marshals every Krita call onto the GUI thread, with a deadline. A modal dialog or a long filter returns `krita_busy` at the deadline. Requests do not wait forever.
|
|
68
|
+
|
|
69
|
+
## Behaviour that affects edits
|
|
70
|
+
|
|
71
|
+
**Native Undo.** On the tested Linux/Krita 6.0.4 helper, drawing and regional filters enter Krita's image command scheduler. A batch can mix those edits with brush, selection, extraction, and transform commands, then undo the group once. A new edit discards the existing redo branch, as a manual edit does. Rollback cannot restore that earlier redo branch.
|
|
72
|
+
|
|
73
|
+
**Blending modes.** Krita 5.3 has no API that enumerates composite ops, and it accepts any string. Unknown ids render as Normal. `set_layer` canonicalises the ids it knows and warns on anything else.
|
|
74
|
+
|
|
75
|
+
**Colour space.** `draw`, `get_pixel`, and per-layer `get_image` require RGBA/8-bit. The merged `get_image` works in other colour spaces.
|
|
76
|
+
|
|
77
|
+
**Filter parameters.** Call `list_capabilities(kind="filters", include_parameters=true)` and use each entry's `parameters` and `parameter_info`. QColor is `{"type":"QColor","rgba":[1,0,0,1]}` with normalized components. QByteArray is `{"type":"QByteArray","base64":"...","byte_length":123}`. Primitives keep their types. Unknown Qt types are read-only. A malformed setting leaves pixels and history intact.
|
|
78
|
+
|
|
79
|
+
A serialization fault returns HTTP 500 with `response_serialization_error`, the operation, and the exception type. The bridge keeps serving. A send/read timeout, reset, or truncated response returns `incomplete_response` with `execution_outcome: "unknown"` and is not retried, because the edit may already have completed. The client rediscovers the bridge only when TCP fails before any HTTP bytes are sent, or when it receives HTTP 401 before dispatch.
|
|
80
|
+
|
|
81
|
+
**Startup recovery.** `dismiss_recovery_dialog` with `{}` cancels the native `KisAutoSaveRecoveryDialog` and keeps the autosaves. It matches the dialog class, not a translated label. Other modals stay open. With no recovery dialog, the call is a no-op. It does not recover or discard files.
|
|
82
|
+
|
|
83
|
+
**Masked layers.** Native brush work, geometric draw, extraction, patches, clone, and warp reject masks and transformed ancestors before editing. Put a Cleanup layer at the document root above the masked ancestor, or `bake_layer` that ancestor and edit the unmasked copy. Bake preserves and hides the source. See [workflows.md](workflows.md).
|
|
84
|
+
|
|
85
|
+
## Closing documents
|
|
86
|
+
|
|
87
|
+
`close_document` can take Krita down. A fresh or lightly edited document usually closes. A long session fails more often. The fault is in Krita's C++ teardown after `Document.close()` returns, and *File → Close* can hit the same path.
|
|
88
|
+
|
|
89
|
+
The 1.2 helper drains pending `KisNodeModel` updates before view teardown on Krita 6.0.4. That covers the layer-model timer crash observed here. Other teardown faults remain possible.
|
|
90
|
+
|
|
91
|
+
Prefer to leave documents open and close them in Krita. If Krita exits, the next call returns a clear "could not reach Krita" error.
|
|
92
|
+
|
|
93
|
+
## Configuration
|
|
94
|
+
|
|
95
|
+
Krita reads these keys from `kritarc` under `[krita_mcp]`:
|
|
96
|
+
|
|
97
|
+
| Key | Default | Meaning |
|
|
98
|
+
| --- | --- | --- |
|
|
99
|
+
| `autostart` | `true` | Start the bridge when Krita starts |
|
|
100
|
+
| `port` | `9797` | First port to try. The bridge scans upward if it is taken |
|
|
101
|
+
|
|
102
|
+
| Variable | Meaning |
|
|
103
|
+
| --- | --- |
|
|
104
|
+
| `KRITA_MCP_STATE_DIR` | Override the discovery-file directory |
|
|
105
|
+
| `KRITA_MCP_TRACE` | Set to `1` before starting Krita to log every operation |
|
|
106
|
+
| `KRITA_MCP_PORT` / `KRITA_MCP_TOKEN` | Skip discovery and connect directly |
|
|
107
|
+
|
|
108
|
+
Trace lines go to `krita_mcp_trace.log` in Krita's data folder, flushed per line. Krita has no console. An entry with no matching completion names the operation that stopped the process.
|
|
109
|
+
|
|
110
|
+
## Troubleshooting
|
|
111
|
+
|
|
112
|
+
**Could not reach the Krita MCP bridge.** Krita may be stopped, or the plugin may be disabled. Check *Tools → Scripts → MCP Bridge Status…*. If the menu entries are missing, enable MCP Bridge in the Python Plugin Manager and restart Krita.
|
|
113
|
+
|
|
114
|
+
**`response_serialization_error` or `incomplete_response`.** Inspect `status` and the document before repeating an edit. These errors do not mean Krita has exited. Filter metadata requires plugin 1.3 or newer. HTTP handler changes require a Krita restart.
|
|
115
|
+
|
|
116
|
+
**Tools are missing in the client.** Restart the client after editing its config. `uvx` must be on `PATH`. A checkout config must use an absolute path to `mcp_server.py`.
|
|
117
|
+
|
|
118
|
+
**Port already in use.** The bridge scans upward from 9797 and writes the chosen port into the discovery file. Set another start port with `port=` under `[krita_mcp]` in `kritarc`.
|
|
119
|
+
|
|
120
|
+
## Diagnostics
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
krita-mcp --list-tools
|
|
124
|
+
krita-mcp --call status
|
|
125
|
+
krita-mcp --call draw --params-file commands.json
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
From a checkout, `python3 mcp_server.py` accepts the same flags. With no flag, the process speaks MCP on stdin/stdout.
|