fiftyone-mcp-server 0.1.0__py3-none-any.whl
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.
- fiftyone_mcp/__init__.py +11 -0
- fiftyone_mcp/config/settings.json +15 -0
- fiftyone_mcp/server.py +127 -0
- fiftyone_mcp/tools/__init__.py +7 -0
- fiftyone_mcp/tools/datasets.py +210 -0
- fiftyone_mcp/tools/operators.py +575 -0
- fiftyone_mcp/tools/plugins.py +289 -0
- fiftyone_mcp/tools/session.py +352 -0
- fiftyone_mcp/tools/utils.py +112 -0
- fiftyone_mcp_server-0.1.0.dist-info/METADATA +174 -0
- fiftyone_mcp_server-0.1.0.dist-info/RECORD +13 -0
- fiftyone_mcp_server-0.1.0.dist-info/WHEEL +4 -0
- fiftyone_mcp_server-0.1.0.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Utility functions for FiftyOne MCP tools.
|
|
3
|
+
|
|
4
|
+
| Copyright 2017-2025, Voxel51, Inc.
|
|
5
|
+
| `voxel51.com <https://voxel51.com/>`_
|
|
6
|
+
|
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
import logging
|
|
10
|
+
|
|
11
|
+
import fiftyone as fo
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def format_response(data, success=True, error=None, **kwargs):
|
|
18
|
+
"""Formats a standardized response for MCP tools.
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
data: the response data
|
|
22
|
+
success (True): whether the operation succeeded
|
|
23
|
+
error (None): an optional error message if operation failed
|
|
24
|
+
**kwargs: additional fields to include in the response
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
a formatted response dict
|
|
28
|
+
"""
|
|
29
|
+
response = {"success": success, "data": data}
|
|
30
|
+
|
|
31
|
+
if error:
|
|
32
|
+
response["error"] = error
|
|
33
|
+
|
|
34
|
+
for key, value in kwargs.items():
|
|
35
|
+
if value is not None:
|
|
36
|
+
response[key] = value
|
|
37
|
+
|
|
38
|
+
return response
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
def safe_serialize(obj):
|
|
42
|
+
"""Safely serializes FiftyOne objects to JSON-compatible formats.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
obj: an object to serialize
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
a JSON-serializable object
|
|
49
|
+
"""
|
|
50
|
+
if isinstance(obj, (str, int, float, bool, type(None))):
|
|
51
|
+
return obj
|
|
52
|
+
|
|
53
|
+
if isinstance(obj, dict):
|
|
54
|
+
return {k: safe_serialize(v) for k, v in obj.items()}
|
|
55
|
+
|
|
56
|
+
if isinstance(obj, (list, tuple)):
|
|
57
|
+
return [safe_serialize(item) for item in obj]
|
|
58
|
+
|
|
59
|
+
if hasattr(obj, "to_dict"):
|
|
60
|
+
return safe_serialize(obj.to_dict())
|
|
61
|
+
|
|
62
|
+
if hasattr(obj, "__dict__"):
|
|
63
|
+
return safe_serialize(obj.__dict__)
|
|
64
|
+
|
|
65
|
+
return str(obj)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_dataset_safe(name):
|
|
69
|
+
"""Safely loads a FiftyOne dataset by name.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
name: the name of the dataset
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
a :class:`fiftyone.core.dataset.Dataset`, or None
|
|
76
|
+
"""
|
|
77
|
+
try:
|
|
78
|
+
return fo.load_dataset(name)
|
|
79
|
+
except Exception as e:
|
|
80
|
+
logger.warning(f"Failed to load dataset '{name}': {e}")
|
|
81
|
+
return None
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def dataset_to_summary(dataset):
|
|
85
|
+
"""Converts a FiftyOne dataset to a summary dictionary.
|
|
86
|
+
|
|
87
|
+
Args:
|
|
88
|
+
dataset: a :class:`fiftyone.core.dataset.Dataset`
|
|
89
|
+
|
|
90
|
+
Returns:
|
|
91
|
+
a summary dict
|
|
92
|
+
"""
|
|
93
|
+
summary = {
|
|
94
|
+
"name": dataset.name,
|
|
95
|
+
"media_type": dataset.media_type,
|
|
96
|
+
"num_samples": len(dataset),
|
|
97
|
+
"persistent": dataset.persistent,
|
|
98
|
+
"tags": dataset.tags,
|
|
99
|
+
"sample_fields": {},
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
for field_name, field in dataset.get_field_schema().items():
|
|
103
|
+
summary["sample_fields"][field_name] = {
|
|
104
|
+
"type": str(type(field).__name__),
|
|
105
|
+
"description": getattr(field, "description", None),
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if len(dataset) > 0:
|
|
109
|
+
first_sample = dataset.first()
|
|
110
|
+
summary["first_sample_id"] = first_sample.id
|
|
111
|
+
|
|
112
|
+
return summary
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fiftyone-mcp-server
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: MCP server exposing FiftyOne dataset analysis tools
|
|
5
|
+
License: MIT
|
|
6
|
+
Keywords: mcp,fiftyone,computer-vision,ai,datasets,model-context-protocol
|
|
7
|
+
Author: Adonai Vera
|
|
8
|
+
Author-email: adonai.vera@gmail.com
|
|
9
|
+
Requires-Python: >=3.10,<3.14
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Image Recognition
|
|
22
|
+
Requires-Dist: fiftyone (>=1.0,<2.0)
|
|
23
|
+
Requires-Dist: mcp (>=0.9.0,<0.10.0)
|
|
24
|
+
Requires-Dist: torch (>=2.9.1,<3.0.0)
|
|
25
|
+
Requires-Dist: torchvision (>=0.24.1,<0.25.0)
|
|
26
|
+
Requires-Dist: ultralytics (>=8.3.240,<9.0.0)
|
|
27
|
+
Project-URL: Documentation, https://github.com/AdonaiVera/fiftyone-mcp-server#readme
|
|
28
|
+
Project-URL: Homepage, https://github.com/AdonaiVera/fiftyone-mcp-server
|
|
29
|
+
Project-URL: Repository, https://github.com/AdonaiVera/fiftyone-mcp-server
|
|
30
|
+
Description-Content-Type: text/markdown
|
|
31
|
+
|
|
32
|
+
# FiftyOne MCP Server
|
|
33
|
+
|
|
34
|
+
<div align="center">
|
|
35
|
+
<p align="center">
|
|
36
|
+
|
|
37
|
+
<!-- prettier-ignore -->
|
|
38
|
+
<img src="https://user-images.githubusercontent.com/25985824/106288517-2422e000-6216-11eb-871d-26ad2e7b1e59.png" height="55px">
|
|
39
|
+
<img src="https://user-images.githubusercontent.com/25985824/106288518-24bb7680-6216-11eb-8f10-60052c519586.png" height="50px">
|
|
40
|
+
|
|
41
|
+

|
|
42
|
+
|
|
43
|
+
> Control FiftyOne datasets through AI assistants using the Model Context Protocol
|
|
44
|
+
|
|
45
|
+
</p>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
## Overview
|
|
49
|
+
|
|
50
|
+
Enable ChatGPT and Claude to explore datasets, execute operators, and build computer vision workflows through natural language. This server exposes FiftyOne's operator framework (80+ built-in operators) through 16 MCP tools.
|
|
51
|
+
|
|
52
|
+
## Features
|
|
53
|
+
|
|
54
|
+
- **Dataset Management (3 tools)** - List, load, and summarize datasets
|
|
55
|
+
- **Operator System (5 tools)** - Execute any FiftyOne operator dynamically
|
|
56
|
+
- Context management (dataset/view/selection)
|
|
57
|
+
- Operator discovery and schema resolution
|
|
58
|
+
- Dynamic execution interface
|
|
59
|
+
- **Plugin Management (5 tools)** - Discover and install FiftyOne plugins
|
|
60
|
+
- List available plugins and their operators
|
|
61
|
+
- Install plugins from GitHub on demand
|
|
62
|
+
- Enable/disable plugins dynamically
|
|
63
|
+
- **Session Management (3 tools)** - Control FiftyOne App for delegated execution
|
|
64
|
+
- Launch/close FiftyOne App server
|
|
65
|
+
- Required for background operators (brain, evaluation, etc.)
|
|
66
|
+
- Session info and status monitoring
|
|
67
|
+
- **Natural Language Workflows** - Multi-step operations through conversation
|
|
68
|
+
- **ChatGPT & Claude Compatible** - Works with desktop apps
|
|
69
|
+
|
|
70
|
+
## Installation
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
git clone https://github.com/AdonaiVera/fiftyone-mcp-server.git
|
|
74
|
+
cd fiftyone-mcp-server
|
|
75
|
+
poetry install
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Requirements:** Python 3.10-3.13, Poetry, FiftyOne
|
|
79
|
+
|
|
80
|
+
## Configuration
|
|
81
|
+
|
|
82
|
+
Add to MCP config:
|
|
83
|
+
|
|
84
|
+
- ChatGPT: `~/Library/Application Support/ChatGPT/config.json`
|
|
85
|
+
- Claude: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"mcpServers": {
|
|
90
|
+
"fiftyone": {
|
|
91
|
+
"command": "poetry",
|
|
92
|
+
"args": ["run", "fiftyone-mcp"],
|
|
93
|
+
"cwd": "/absolute/path/to/fiftyone-mcp-server"
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Restart your AI assistant.
|
|
100
|
+
|
|
101
|
+
## Usage
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
# Run
|
|
105
|
+
poetry run fiftyone-mcp
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
And then you can query directly the agent:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
"List all my datasets"
|
|
112
|
+
"Load quickstart dataset and show summary"
|
|
113
|
+
"What operators are available for managing samples?"
|
|
114
|
+
"Set context to my dataset, then tag high-confidence samples"
|
|
115
|
+
"What plugins are available? Install the brain plugin"
|
|
116
|
+
"Find similar images in my dataset"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Example of functionality:
|
|
120
|
+
|
|
121
|
+
The server starts with 50 built-in operators. Install plugins to expand functionality - the AI can discover and install plugins automatically when needed (brain, zoo, annotation, evaluation, and more).
|
|
122
|
+
|
|
123
|
+
## Architecture
|
|
124
|
+
|
|
125
|
+
**Operator-Based Design:**
|
|
126
|
+
|
|
127
|
+
- Exposes 80+ FiftyOne operators through unified interface
|
|
128
|
+
- Dynamic schema resolution based on current context
|
|
129
|
+
- Context state management (dataset, view, selection)
|
|
130
|
+
|
|
131
|
+
**Plugin Architecture:**
|
|
132
|
+
|
|
133
|
+
- AI discovers plugins on demand through `list_plugins`
|
|
134
|
+
- Installs plugins automatically when needed
|
|
135
|
+
- All plugin operators immediately available after installation
|
|
136
|
+
- Self-expanding capability set
|
|
137
|
+
|
|
138
|
+
**Session Architecture:**
|
|
139
|
+
|
|
140
|
+
- AI can launch FiftyOne App when needed for delegated operators
|
|
141
|
+
- Enables background execution for compute-intensive operations
|
|
142
|
+
- Automatic session management through natural conversation
|
|
143
|
+
|
|
144
|
+
**Design Philosophy:**
|
|
145
|
+
|
|
146
|
+
- Minimal tool count (16 tools total)
|
|
147
|
+
- Maximum flexibility (access to full operator & plugin ecosystem)
|
|
148
|
+
- Mirrors FiftyOne App's execution model
|
|
149
|
+
|
|
150
|
+
## Development
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
# Run tests
|
|
154
|
+
poetry run pytest
|
|
155
|
+
|
|
156
|
+
# Code quality
|
|
157
|
+
poetry run black -l 79 src/
|
|
158
|
+
poetry run pylint --errors-only src/
|
|
159
|
+
|
|
160
|
+
# Test with MCP Inspector
|
|
161
|
+
npx @modelcontextprotocol/inspector poetry run fiftyone-mcp
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Resources
|
|
165
|
+
|
|
166
|
+
- [FiftyOne Docs](https://docs.voxel51.com/)
|
|
167
|
+
- [FiftyOne Operators](https://docs.voxel51.com/plugins/developing_plugins.html)
|
|
168
|
+
- [Model Context Protocol](https://modelcontextprotocol.io)
|
|
169
|
+
- [MCP Inspector](https://github.com/modelcontextprotocol/inspector)
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
Built with [FiftyOne](https://voxel51.com/fiftyone) and [Model Context Protocol](https://modelcontextprotocol.io)
|
|
174
|
+
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
fiftyone_mcp/__init__.py,sha256=YfZLPWQjpAhU3cuTk1O5Yaas22luCnIGxM8JtZbb1EM,191
|
|
2
|
+
fiftyone_mcp/config/settings.json,sha256=gmaex1G-kj8crQGiuSIiIROX8aqv04Xv8ef5Y2K9SYs,284
|
|
3
|
+
fiftyone_mcp/server.py,sha256=pF5pmzJUAVwyMvNGDXLQTnwr1MDn056QJpDTxZdROBE,3417
|
|
4
|
+
fiftyone_mcp/tools/__init__.py,sha256=3U-GgTeVSkxdYB0Fpx4NCHjxuRy1i9GtUfDVAQYWM80,108
|
|
5
|
+
fiftyone_mcp/tools/datasets.py,sha256=3rMZoGWeuKzTB_JhXlPfFzojtiteSDwu090-6dkMPsk,6300
|
|
6
|
+
fiftyone_mcp/tools/operators.py,sha256=bek1o1GjOsy8o4WAtv1DcMm35wvLbi2fcsOKsnIY9qA,19548
|
|
7
|
+
fiftyone_mcp/tools/plugins.py,sha256=nwITl1k2cbhsP4hjuZvbwVOFe5-GQARrqghltpWOwUY,10509
|
|
8
|
+
fiftyone_mcp/tools/session.py,sha256=AYBaj6pugyC1w-hHf4EZJ149Edvy0amweZeoZ4h71Fw,10721
|
|
9
|
+
fiftyone_mcp/tools/utils.py,sha256=kAswqiJugRBuC4ZFaeA8mKPchDVQzic7mrSMR1zGTug,2660
|
|
10
|
+
fiftyone_mcp_server-0.1.0.dist-info/METADATA,sha256=fN33anNo53vLQGV15clsqddob10M-BzYXBY4V_sF-xg,5649
|
|
11
|
+
fiftyone_mcp_server-0.1.0.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
12
|
+
fiftyone_mcp_server-0.1.0.dist-info/entry_points.txt,sha256=SaZqYMrreTAYdbR5Dtle_pMKL5hFpi95dVPWMmlDXHs,56
|
|
13
|
+
fiftyone_mcp_server-0.1.0.dist-info/RECORD,,
|