jitora 1.1.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.
jitora-1.1.0/PKG-INFO ADDED
@@ -0,0 +1,103 @@
1
+ Metadata-Version: 2.4
2
+ Name: jitora
3
+ Version: 1.1.0
4
+ Summary: sample mcp tool
5
+ Keywords: image,management,processing,ai,organization,mcp
6
+ Author: sunshine-kjh
7
+ Author-email: sunshine-kjh <kimjihoon0@gmail.com>
8
+ License-Expression: MIT
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
13
+ Classifier: Topic :: Multimedia :: Graphics
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Classifier: Operating System :: OS Independent
16
+ Requires-Dist: fastmcp>=4.0.3
17
+ Requires-Dist: pillow>=12.3.0
18
+ Requires-Python: >=3.14
19
+ Description-Content-Type: text/markdown
20
+
21
+ # jictora
22
+
23
+ A powerful image management tool designed to work with AI systems for intelligent image organization. This tool enables AI to read, understand, and organize local image files into appropriate folders based on their content and characteristics.
24
+
25
+ ## Project Purpose
26
+
27
+ This tool is specifically designed to:
28
+ - Allow AI systems to access and analyze local image files
29
+ - Enable AI-driven image categorization and organization
30
+ - Provide a robust interface for AI to manage and process images
31
+ - Support automated image sorting and folder management
32
+ - Facilitate AI-powered image content understanding and classification
33
+
34
+ ## Installation
35
+
36
+ ### Installing uvx
37
+ If uvx is not installed on your system, please refer to the [uv installation guide](https://docs.astral.sh/uv/getting-started/installation/) to install it according to your environment.
38
+
39
+ ### Installation via MCP (Claude Desktop)
40
+
41
+ Add the following configuration to your MCP settings file:
42
+
43
+ ```json
44
+ "mcpServers": {
45
+ "jictora": {
46
+ "command": "uvx",
47
+ "args": ["jictora"]
48
+ }
49
+ }
50
+ ```
51
+
52
+ ## MCP API Features
53
+
54
+ ### Directory Management
55
+ - **create_directory**: Creates a new directory at the specified path. Can optionally create parent directories and handle existing directories. Essential for AI-driven folder organization.
56
+
57
+ ### Image File Operations
58
+ - **list_image_files**: Scans a directory and returns a formatted list of all valid image files found, including file count and alphabetical listing. Enables AI to discover and analyze available images.
59
+ - **read_image**: Reads an image file and returns it as an Image object for further processing. Allows AI to access and analyze image content.
60
+ - **copy_image**: Copies an image file to a new location while preserving all metadata. Used by AI to organize images into appropriate categories.
61
+ - **move_image**: Moves an image file to a new location, with options to handle existing files and preserve metadata. Enables AI to reorganize images based on content analysis.
62
+ - **delete_image**: Safely deletes an image file with optional confirmation. Provides AI with the ability to manage unwanted or duplicate images.
63
+ - **create_image**: Generates a new blank image with specified dimensions, color, and format. Useful for AI-generated image processing tasks.
64
+
65
+ ### Supported Image Formats
66
+ The tool supports the following image formats for AI analysis:
67
+ - JPG/JPEG
68
+ - PNG
69
+ - GIF
70
+ - BMP
71
+ - WebP
72
+ - TIFF
73
+ - ICO
74
+ - JFIF
75
+ - SVG
76
+
77
+ ### File Management Features
78
+ - Automatic directory creation for AI-driven organization
79
+ - Overwrite protection with optional override
80
+ - Comprehensive error handling and status reporting
81
+ - File metadata preservation during operations
82
+ - Validation of image files before processing
83
+ - Support for batch operations and automated organization
84
+
85
+ ## AI Integration
86
+
87
+ This tool is designed to work seamlessly with AI systems, providing:
88
+ - Direct access to local image files for AI analysis
89
+ - Tools for AI-driven image organization
90
+ - Support for automated folder creation and management
91
+ - Metadata preservation during AI-driven reorganization
92
+ - Robust error handling for automated operations
93
+
94
+ ## Error Handling
95
+ All operations include comprehensive error handling and return detailed status information including:
96
+ - Success/failure status
97
+ - Error messages (if any)
98
+ - File metadata
99
+ - Operation details
100
+
101
+ ## License
102
+
103
+ This project is distributed under the MIT License.
jitora-1.1.0/README.md ADDED
@@ -0,0 +1,83 @@
1
+ # jictora
2
+
3
+ A powerful image management tool designed to work with AI systems for intelligent image organization. This tool enables AI to read, understand, and organize local image files into appropriate folders based on their content and characteristics.
4
+
5
+ ## Project Purpose
6
+
7
+ This tool is specifically designed to:
8
+ - Allow AI systems to access and analyze local image files
9
+ - Enable AI-driven image categorization and organization
10
+ - Provide a robust interface for AI to manage and process images
11
+ - Support automated image sorting and folder management
12
+ - Facilitate AI-powered image content understanding and classification
13
+
14
+ ## Installation
15
+
16
+ ### Installing uvx
17
+ If uvx is not installed on your system, please refer to the [uv installation guide](https://docs.astral.sh/uv/getting-started/installation/) to install it according to your environment.
18
+
19
+ ### Installation via MCP (Claude Desktop)
20
+
21
+ Add the following configuration to your MCP settings file:
22
+
23
+ ```json
24
+ "mcpServers": {
25
+ "jictora": {
26
+ "command": "uvx",
27
+ "args": ["jictora"]
28
+ }
29
+ }
30
+ ```
31
+
32
+ ## MCP API Features
33
+
34
+ ### Directory Management
35
+ - **create_directory**: Creates a new directory at the specified path. Can optionally create parent directories and handle existing directories. Essential for AI-driven folder organization.
36
+
37
+ ### Image File Operations
38
+ - **list_image_files**: Scans a directory and returns a formatted list of all valid image files found, including file count and alphabetical listing. Enables AI to discover and analyze available images.
39
+ - **read_image**: Reads an image file and returns it as an Image object for further processing. Allows AI to access and analyze image content.
40
+ - **copy_image**: Copies an image file to a new location while preserving all metadata. Used by AI to organize images into appropriate categories.
41
+ - **move_image**: Moves an image file to a new location, with options to handle existing files and preserve metadata. Enables AI to reorganize images based on content analysis.
42
+ - **delete_image**: Safely deletes an image file with optional confirmation. Provides AI with the ability to manage unwanted or duplicate images.
43
+ - **create_image**: Generates a new blank image with specified dimensions, color, and format. Useful for AI-generated image processing tasks.
44
+
45
+ ### Supported Image Formats
46
+ The tool supports the following image formats for AI analysis:
47
+ - JPG/JPEG
48
+ - PNG
49
+ - GIF
50
+ - BMP
51
+ - WebP
52
+ - TIFF
53
+ - ICO
54
+ - JFIF
55
+ - SVG
56
+
57
+ ### File Management Features
58
+ - Automatic directory creation for AI-driven organization
59
+ - Overwrite protection with optional override
60
+ - Comprehensive error handling and status reporting
61
+ - File metadata preservation during operations
62
+ - Validation of image files before processing
63
+ - Support for batch operations and automated organization
64
+
65
+ ## AI Integration
66
+
67
+ This tool is designed to work seamlessly with AI systems, providing:
68
+ - Direct access to local image files for AI analysis
69
+ - Tools for AI-driven image organization
70
+ - Support for automated folder creation and management
71
+ - Metadata preservation during AI-driven reorganization
72
+ - Robust error handling for automated operations
73
+
74
+ ## Error Handling
75
+ All operations include comprehensive error handling and return detailed status information including:
76
+ - Success/failure status
77
+ - Error messages (if any)
78
+ - File metadata
79
+ - Operation details
80
+
81
+ ## License
82
+
83
+ This project is distributed under the MIT License.
@@ -0,0 +1,39 @@
1
+ [project]
2
+ name = "jitora"
3
+ version = "1.1.0"
4
+ license = "MIT"
5
+ description = "sample mcp tool"
6
+ readme = "README.md"
7
+ requires-python = ">=3.14"
8
+ keywords = [
9
+ "image",
10
+ "management",
11
+ "processing",
12
+ "ai",
13
+ "organization",
14
+ "mcp",
15
+ ]
16
+ classifiers = [
17
+ "Development Status :: 5 - Production/Stable",
18
+ "Intended Audience :: Developers",
19
+ "Programming Language :: Python :: 3",
20
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
21
+ "Topic :: Multimedia :: Graphics",
22
+ "Topic :: Software Development :: Libraries :: Python Modules",
23
+ "Operating System :: OS Independent",
24
+ ]
25
+ dependencies = [
26
+ "fastmcp>=4.0.3",
27
+ "pillow>=12.3.0",
28
+ ]
29
+
30
+ [[project.authors]]
31
+ name = "sunshine-kjh"
32
+ email = "kimjihoon0@gmail.com"
33
+
34
+ [project.scripts]
35
+ jitora = "jitora:main"
36
+
37
+ [build-system]
38
+ requires = ["uv_build>=0.12.3,<0.13.0"]
39
+ build-backend = "uv_build"
@@ -0,0 +1,31 @@
1
+ [project]
2
+ name = "jitora"
3
+ version = "1.1.0"
4
+ license = "MIT"
5
+ description = "sample mcp tool"
6
+ readme = "README.md"
7
+ requires-python = ">=3.14"
8
+ authors = [
9
+ { name = "sunshine-kjh", email = "kimjihoon0@gmail.com" }
10
+ ]
11
+ keywords = ["image", "management", "processing", "ai", "organization", "mcp"]
12
+ classifiers = [
13
+ "Development Status :: 5 - Production/Stable",
14
+ "Intended Audience :: Developers",
15
+ "Programming Language :: Python :: 3",
16
+ "Topic :: Scientific/Engineering :: Artificial Intelligence",
17
+ "Topic :: Multimedia :: Graphics",
18
+ "Topic :: Software Development :: Libraries :: Python Modules",
19
+ "Operating System :: OS Independent"
20
+ ]
21
+ dependencies = [
22
+ "fastmcp>=4.0.3",
23
+ "pillow>=12.3.0",
24
+ ]
25
+
26
+ [project.scripts]
27
+ jitora = "jitora:main"
28
+
29
+ [build-system]
30
+ requires = ["uv_build>=0.12.3,<0.13.0"]
31
+ build-backend = "uv_build"
@@ -0,0 +1,355 @@
1
+ from fastmcp import FastMCP
2
+ from fastmcp.utilities.types import Image
3
+ import os
4
+ import shutil
5
+ from PIL import Image as PILImage
6
+ from io import BytesIO
7
+ from typing import Dict, Any
8
+
9
+ mcp = FastMCP("Jitora")
10
+
11
+ SUPPORTED_IMAGE_EXTENSIONS = {
12
+ '.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp',
13
+ '.tiff', '.tif', '.ico', '.jfif', '.svg'
14
+ }
15
+
16
+ def is_valid_image(filepath: str) -> bool:
17
+ """
18
+ Check if the file is a valid image file.
19
+
20
+ Args:
21
+ filepath (str): File path to check
22
+
23
+ Returns:
24
+ bool: True if the file is an image, False otherwise.
25
+ """
26
+ try:
27
+ _, ext = os.path.splitext(filepath.lower())
28
+ if ext in SUPPORTED_IMAGE_EXTENSIONS:
29
+ with PILImage.open(filepath) as _:
30
+ return True
31
+
32
+ except Exception:
33
+ pass
34
+ return False
35
+
36
+
37
+ @mcp.tool()
38
+ def create_directory(
39
+ directory_path: str,
40
+ exist_ok: bool = True,
41
+ parents: bool = True
42
+ ) -> Dict[str, Any]:
43
+ """
44
+ Creates a directory at the specified path.
45
+ Creates a new directory if it doesn't exist and handles existing directories according to settings.
46
+
47
+ Args:
48
+ directory_path (str): Path of the directory to create
49
+ exist_ok (bool): Whether to ignore errors if directory exists (default: True)
50
+ parents (bool): Whether to create parent directories if needed (default: True)
51
+
52
+ Returns:
53
+ Dict[str, Any]: Directory creation result information
54
+ """
55
+
56
+ try:
57
+ directory_path = os.path.abspath(directory_path) # 절대경로로 변환. 포맷 동일화
58
+ already_exists = os.path.exists(directory_path)
59
+
60
+ if already_exists:
61
+ if not os.path.isdir(directory_path): # not directory
62
+ return {
63
+ "success": False,
64
+ "error": f"Path exists but is not a directory: {directory_path}"
65
+ }
66
+ elif not exist_ok: # exist_ok = False
67
+ return {
68
+ "success": False,
69
+ "error": f"Directory already exists: {directory_path}"
70
+ }
71
+ else:
72
+ return {
73
+ "success": True,
74
+ "message": f"Directory already exists: {directory_path}",
75
+ "path": directory_path,
76
+ "created": False
77
+ }
78
+ if parents:
79
+ os.makedirs(directory_path)
80
+ else:
81
+ try:
82
+ os.mkdir(directory_path)
83
+ except FileNotFoundError:
84
+ return {
85
+ "success": False,
86
+ "error": f"Parent path does not exist. Set parents = True: {directory_path}"
87
+ }
88
+ return {
89
+ "success": True,
90
+ "message": f"Directory created successfully: {directory_path}",
91
+ "path": directory_path,
92
+ "created": True
93
+ }
94
+
95
+ except Exception as e:
96
+ return {
97
+ "success": False,
98
+ "error": str(e)
99
+ }
100
+
101
+ @mcp.tool()
102
+ def list_image_files(folder: str) -> str:
103
+ """
104
+ Return a text list of image files in the specified folder.
105
+
106
+ Args:
107
+ folder (Str): Folder path to search for image files.
108
+
109
+ Returns:
110
+ str: Text list of image files.
111
+ """
112
+
113
+ try:
114
+ folder = os.path.abspath(folder)
115
+
116
+ if not os.path.exists(folder):
117
+ return f"Error: Folder dose not exist: {folder}"
118
+
119
+ if not os.path.isdir(folder):
120
+ return f"Error: Specified path is not a directory: {folder}"
121
+
122
+ image_files = []
123
+ for filename in os.listdir(folder):
124
+ filepath = os.path.join(folder, filename)
125
+ if os.path.isfile(filepath) and is_valid_image:
126
+ image_files.append(filename)
127
+
128
+ if not image_files:
129
+ return f"No image files found in folder: {folder}"
130
+
131
+ result_lines = [
132
+ f"Folder: {folder}",
133
+ f"Number of image files: {len(image_files)}",
134
+ "---",
135
+ *[f"{i+1}. {name}" for i, name in enumerate(image_files)]
136
+ ]
137
+
138
+ return "\n".join(result_lines)
139
+
140
+ except Exception as e:
141
+ return f"Error occurred: {str(e)}"
142
+
143
+ @mcp.tool()
144
+ def read_image(image_path: str) -> Image:
145
+ """
146
+ Read an image file and return it as an Image odject.
147
+
148
+ Args:
149
+ image_path (str) : Path to the image file
150
+
151
+ Returns:
152
+ Image: Image object
153
+ """
154
+ img = PILImage.open(image_path)
155
+ buffer = BytesIO()
156
+ img_format = img.format.lower() if img.format else "png"
157
+ img.save(buffer, format=img_format)
158
+ return Image(data=buffer.getvalue(), format=img_format)
159
+
160
+ @mcp.tool()
161
+ def copy_image(
162
+ source_path: str,
163
+ destination_path: str,
164
+ overwrite: bool = False
165
+ ) -> Dict[str, Any]:
166
+ """
167
+ Copy an image file to a new location.
168
+
169
+ Args:
170
+ source_path (str): Source image file path
171
+ destination_path (str): Destination image file path (including filename)
172
+ overwrite (bool): Whether to overwrite if destination file exists
173
+
174
+ Returns:
175
+ Dict[str, Any]: Copy result information
176
+
177
+
178
+ """
179
+ try:
180
+ source_path = os.path.abspath(source_path)
181
+ destination_path = os.path.abspath(destination_path)
182
+
183
+ if not os.path.exists(source_path):
184
+ return {
185
+ "success": False,
186
+ "error": f"Source file does not exist: {source_path}"
187
+ }
188
+
189
+ if not is_valid_image(source_path):
190
+ return {
191
+ "success": False,
192
+ "error": f"Source file is not a valid image: {source_path}"
193
+ }
194
+
195
+ destination_dir = os.path.dirname(destination_path)
196
+ if not os.path.exists(destination_dir):
197
+ os.makedirs(destination_dir)
198
+
199
+ shutil.copy2(source_path, destination_path)
200
+
201
+ file_size = os.path.getsize(destination_path)
202
+ with PILImage.open(destination_path) as img:
203
+ width, height = img.size
204
+ format_name = img.format
205
+
206
+ return {
207
+ "success": True,
208
+ "message": "Image file copied successfully.",
209
+ "source_path": source_path,
210
+ "destination_path": destination_path,
211
+ "file_size": file_size,
212
+ "width": width,
213
+ "height": height,
214
+ "format": format_name
215
+ }
216
+
217
+ except Exception as e:
218
+ return {
219
+ "success": False,
220
+ "error": str(e)
221
+ }
222
+
223
+ @mcp.tool()
224
+ def move_image(
225
+ source_path: str,
226
+ destination_path: str,
227
+ overwrite: bool = False
228
+ ) -> Dict[str, Any]:
229
+ """
230
+ Move an image file.
231
+ Can move to the same or different path, with the same or different filename.
232
+
233
+ Args:
234
+ source_path (str): Source image file path
235
+ destination_path (str): Destination image file path (including filename)
236
+ overwrite (bool): Whether to overwrite if destination file exists
237
+
238
+ Returns:
239
+ Dict[str, Any]: Move result information
240
+ """
241
+
242
+ try:
243
+ source_path = os.path.abspath(source_path)
244
+ destination_path = os.path.abspath(destination_path)
245
+
246
+ if not os.path.exists(source_path):
247
+ return {
248
+ "success": False,
249
+ "error": f"Source file does not exists: {source_path}"
250
+ }
251
+
252
+ if not is_valid_image(source_path):
253
+ return {
254
+ "success": False,
255
+ "error": f"Source file is not a valid image: {source_path}"
256
+ }
257
+
258
+ if os.path.exists(destination_path) and not overwrite:
259
+ return {
260
+ "success": False,
261
+ "error": f"Destination file already exists and overwrite is not allowed: {destination_path}"
262
+ }
263
+
264
+ file_name = os.path.basename(source_path)
265
+ file_size = os.path.getsize(source_path)
266
+ with PILImage.open(source_path) as img:
267
+ width, height = img.size
268
+ format_name = img.format
269
+
270
+ destination_dir = os.path.dirname(destination_path)
271
+ if not os.path.exists(destination_dir):
272
+ os.makedirs(destination_dir)
273
+
274
+ shutil.move(source_path, destination_path)
275
+
276
+ return {
277
+ "success": True,
278
+ "message" : "Image file moved successfully.",
279
+ "source_path": source_path,
280
+ "destination_path": destination_path,
281
+ "file_name": file_name,
282
+ "file_size": file_size,
283
+ "width": width,
284
+ "height": height,
285
+ "format": format_name
286
+ }
287
+
288
+ except Exception as e:
289
+ return{
290
+ "success": False,
291
+ "error": str(e)
292
+ }
293
+
294
+ @mcp.tool()
295
+ def delete_image(
296
+ image_path: str,
297
+ confirm: bool = True
298
+ ) -> Dict[str, Any]:
299
+ """
300
+ Delete an image file:
301
+
302
+ Args:
303
+ image_path (str): Path to the image file to delete
304
+ confirm (bool): Confirmation for deletion (default: True, prevents accidental deletion)
305
+
306
+ Returns:
307
+ Dict[str, Any]: Deletion result information
308
+
309
+ """
310
+
311
+ try:
312
+ image_path = os.path.abspath(image_path)
313
+
314
+ if not os.path.exists(image_path):
315
+ return {
316
+ "success": False,
317
+ "error": f"File does not exist: {image_path}"
318
+ }
319
+ if not is_valid_image(image_path):
320
+ return {
321
+ "succcess": False,
322
+ "error": f"File is not a valid image: {image_path}"
323
+ }
324
+
325
+ if not confirm:
326
+ return {
327
+ "success": False,
328
+ "error": "File deletion not confirmed. Set conform=True to conform deletion."
329
+ }
330
+
331
+ file_size = os.path.getsize(image_path)
332
+ file_name = os.path.basename(image_path)
333
+
334
+ os.remove(image_path)
335
+
336
+ return {
337
+ "success": True,
338
+ "message": "Image file deleted successfully.",
339
+ "deleted_path": image_path,
340
+ "file_name": file_name,
341
+ "file_size": file_size
342
+ }
343
+
344
+ except Exception as e:
345
+ return {
346
+ "success": False,
347
+ "error": str(e)
348
+ }
349
+
350
+ def main():
351
+ mcp.run(transport="stdio")
352
+
353
+
354
+
355
+ # 23차시
@@ -0,0 +1,6 @@
1
+ import sys
2
+ from . import main
3
+
4
+ sys.exit(main())
5
+
6
+ # https://pypi.org/