gfp-mcp 0.2.1__tar.gz → 0.2.4__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.
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/PKG-INFO +25 -8
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/README.md +22 -7
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/gfp_mcp.egg-info/PKG-INFO +25 -8
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/gfp_mcp.egg-info/requires.txt +2 -0
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/mcp_standalone/__init__.py +1 -1
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/mcp_standalone/client.py +57 -19
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/mcp_standalone/config.py +3 -9
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/mcp_standalone/mappings.py +246 -67
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/mcp_standalone/registry.py +0 -4
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/mcp_standalone/resources.py +0 -3
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/mcp_standalone/server.py +9 -21
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/mcp_standalone/tools.py +6 -70
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/pyproject.toml +3 -1
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/tests/test_mcp_integration.py +71 -27
- gfp_mcp-0.2.4/tests/test_mcp_mappings.py +571 -0
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/tests/test_mcp_tools.py +3 -34
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/tests/test_registry.py +0 -12
- gfp_mcp-0.2.1/tests/test_mcp_mappings.py +0 -320
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/LICENSE +0 -0
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/gfp_mcp.egg-info/SOURCES.txt +0 -0
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/gfp_mcp.egg-info/dependency_links.txt +0 -0
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/gfp_mcp.egg-info/entry_points.txt +0 -0
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/gfp_mcp.egg-info/top_level.txt +0 -0
- {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gfp-mcp
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Model Context Protocol (MCP) server for GDSFactory+ photonic IC design
|
|
5
5
|
Author: GDSFactory+ Team
|
|
6
6
|
License: MIT
|
|
@@ -33,13 +33,15 @@ Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
|
33
33
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
34
34
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
35
35
|
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
36
|
+
Requires-Dist: bump-my-version>=0.26.0; extra == "dev"
|
|
37
|
+
Requires-Dist: build>=1.4.0; extra == "dev"
|
|
36
38
|
Dynamic: license-file
|
|
37
39
|
|
|
38
40
|
# GDSFactory+ MCP Server
|
|
39
41
|
|
|
40
42
|
[](https://pypi.org/project/gfp-mcp/)
|
|
41
43
|
[](https://pypi.org/project/gfp-mcp/)
|
|
42
|
-
[](https://github.com/doplaydo/gfp-mcp/actions)
|
|
43
45
|
[](https://opensource.org/licenses/MIT)
|
|
44
46
|
|
|
45
47
|
Model Context Protocol (MCP) server for GDSFactory+ that enables AI assistants like Claude to design and build photonic integrated circuits.
|
|
@@ -57,15 +59,32 @@ This MCP server connects AI assistants to [GDSFactory+](https://gdsfactory.com),
|
|
|
57
59
|
|
|
58
60
|
### 2. Install the MCP Server
|
|
59
61
|
|
|
62
|
+
**With uv (recommended):**
|
|
63
|
+
|
|
64
|
+
If you don't have `uv` installed, see the [uv installation guide](https://docs.astral.sh/uv/getting-started/installation/).
|
|
65
|
+
|
|
60
66
|
```bash
|
|
61
|
-
|
|
67
|
+
uv tool install gfp-mcp
|
|
62
68
|
```
|
|
63
69
|
|
|
64
|
-
|
|
70
|
+
<details>
|
|
71
|
+
<summary>Ephemeral approach</summary>
|
|
72
|
+
|
|
73
|
+
Run without installing:
|
|
65
74
|
|
|
66
75
|
```bash
|
|
67
76
|
uvx --from gfp-mcp gfp-mcp-serve
|
|
68
77
|
```
|
|
78
|
+
</details>
|
|
79
|
+
|
|
80
|
+
<details>
|
|
81
|
+
<summary><strong>Alternative: pip install</strong></summary>
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install gfp-mcp
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
</details>
|
|
69
88
|
|
|
70
89
|
### 3. Connect to Your AI Assistant
|
|
71
90
|
|
|
@@ -143,14 +162,12 @@ Try these commands with your AI assistant:
|
|
|
143
162
|
|
|
144
163
|
## Available Tools
|
|
145
164
|
|
|
146
|
-
- **
|
|
147
|
-
- **build_cells** - Build multiple GDS cells in batch
|
|
165
|
+
- **build_cells** - Build one or more GDS cells by name (pass a list, can be single-item)
|
|
148
166
|
- **list_cells** - List all available photonic components
|
|
149
167
|
- **get_cell_info** - Get detailed component metadata
|
|
150
|
-
- **download_gds** - Download built GDS files
|
|
151
168
|
- **list_projects** - List all running GDSFactory+ server instances
|
|
152
169
|
- **get_project_info** - Get detailed information about a specific project
|
|
153
|
-
- **check_drc** - Run Design Rule Check verification
|
|
170
|
+
- **check_drc** - Run Design Rule Check verification (returns structured format with all violations including simplified location data for LLM-friendly troubleshooting)
|
|
154
171
|
- **check_connectivity** - Run connectivity verification
|
|
155
172
|
- **check_lvs** - Run Layout vs. Schematic verification
|
|
156
173
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://pypi.org/project/gfp-mcp/)
|
|
4
4
|
[](https://pypi.org/project/gfp-mcp/)
|
|
5
|
-
[](https://github.com/doplaydo/gfp-mcp/actions)
|
|
6
6
|
[](https://opensource.org/licenses/MIT)
|
|
7
7
|
|
|
8
8
|
Model Context Protocol (MCP) server for GDSFactory+ that enables AI assistants like Claude to design and build photonic integrated circuits.
|
|
@@ -20,15 +20,32 @@ This MCP server connects AI assistants to [GDSFactory+](https://gdsfactory.com),
|
|
|
20
20
|
|
|
21
21
|
### 2. Install the MCP Server
|
|
22
22
|
|
|
23
|
+
**With uv (recommended):**
|
|
24
|
+
|
|
25
|
+
If you don't have `uv` installed, see the [uv installation guide](https://docs.astral.sh/uv/getting-started/installation/).
|
|
26
|
+
|
|
23
27
|
```bash
|
|
24
|
-
|
|
28
|
+
uv tool install gfp-mcp
|
|
25
29
|
```
|
|
26
30
|
|
|
27
|
-
|
|
31
|
+
<details>
|
|
32
|
+
<summary>Ephemeral approach</summary>
|
|
33
|
+
|
|
34
|
+
Run without installing:
|
|
28
35
|
|
|
29
36
|
```bash
|
|
30
37
|
uvx --from gfp-mcp gfp-mcp-serve
|
|
31
38
|
```
|
|
39
|
+
</details>
|
|
40
|
+
|
|
41
|
+
<details>
|
|
42
|
+
<summary><strong>Alternative: pip install</strong></summary>
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
pip install gfp-mcp
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
</details>
|
|
32
49
|
|
|
33
50
|
### 3. Connect to Your AI Assistant
|
|
34
51
|
|
|
@@ -106,14 +123,12 @@ Try these commands with your AI assistant:
|
|
|
106
123
|
|
|
107
124
|
## Available Tools
|
|
108
125
|
|
|
109
|
-
- **
|
|
110
|
-
- **build_cells** - Build multiple GDS cells in batch
|
|
126
|
+
- **build_cells** - Build one or more GDS cells by name (pass a list, can be single-item)
|
|
111
127
|
- **list_cells** - List all available photonic components
|
|
112
128
|
- **get_cell_info** - Get detailed component metadata
|
|
113
|
-
- **download_gds** - Download built GDS files
|
|
114
129
|
- **list_projects** - List all running GDSFactory+ server instances
|
|
115
130
|
- **get_project_info** - Get detailed information about a specific project
|
|
116
|
-
- **check_drc** - Run Design Rule Check verification
|
|
131
|
+
- **check_drc** - Run Design Rule Check verification (returns structured format with all violations including simplified location data for LLM-friendly troubleshooting)
|
|
117
132
|
- **check_connectivity** - Run connectivity verification
|
|
118
133
|
- **check_lvs** - Run Layout vs. Schematic verification
|
|
119
134
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: gfp-mcp
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.4
|
|
4
4
|
Summary: Model Context Protocol (MCP) server for GDSFactory+ photonic IC design
|
|
5
5
|
Author: GDSFactory+ Team
|
|
6
6
|
License: MIT
|
|
@@ -33,13 +33,15 @@ Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
|
33
33
|
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
34
34
|
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
35
35
|
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
36
|
+
Requires-Dist: bump-my-version>=0.26.0; extra == "dev"
|
|
37
|
+
Requires-Dist: build>=1.4.0; extra == "dev"
|
|
36
38
|
Dynamic: license-file
|
|
37
39
|
|
|
38
40
|
# GDSFactory+ MCP Server
|
|
39
41
|
|
|
40
42
|
[](https://pypi.org/project/gfp-mcp/)
|
|
41
43
|
[](https://pypi.org/project/gfp-mcp/)
|
|
42
|
-
[](https://github.com/doplaydo/gfp-mcp/actions)
|
|
43
45
|
[](https://opensource.org/licenses/MIT)
|
|
44
46
|
|
|
45
47
|
Model Context Protocol (MCP) server for GDSFactory+ that enables AI assistants like Claude to design and build photonic integrated circuits.
|
|
@@ -57,15 +59,32 @@ This MCP server connects AI assistants to [GDSFactory+](https://gdsfactory.com),
|
|
|
57
59
|
|
|
58
60
|
### 2. Install the MCP Server
|
|
59
61
|
|
|
62
|
+
**With uv (recommended):**
|
|
63
|
+
|
|
64
|
+
If you don't have `uv` installed, see the [uv installation guide](https://docs.astral.sh/uv/getting-started/installation/).
|
|
65
|
+
|
|
60
66
|
```bash
|
|
61
|
-
|
|
67
|
+
uv tool install gfp-mcp
|
|
62
68
|
```
|
|
63
69
|
|
|
64
|
-
|
|
70
|
+
<details>
|
|
71
|
+
<summary>Ephemeral approach</summary>
|
|
72
|
+
|
|
73
|
+
Run without installing:
|
|
65
74
|
|
|
66
75
|
```bash
|
|
67
76
|
uvx --from gfp-mcp gfp-mcp-serve
|
|
68
77
|
```
|
|
78
|
+
</details>
|
|
79
|
+
|
|
80
|
+
<details>
|
|
81
|
+
<summary><strong>Alternative: pip install</strong></summary>
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pip install gfp-mcp
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
</details>
|
|
69
88
|
|
|
70
89
|
### 3. Connect to Your AI Assistant
|
|
71
90
|
|
|
@@ -143,14 +162,12 @@ Try these commands with your AI assistant:
|
|
|
143
162
|
|
|
144
163
|
## Available Tools
|
|
145
164
|
|
|
146
|
-
- **
|
|
147
|
-
- **build_cells** - Build multiple GDS cells in batch
|
|
165
|
+
- **build_cells** - Build one or more GDS cells by name (pass a list, can be single-item)
|
|
148
166
|
- **list_cells** - List all available photonic components
|
|
149
167
|
- **get_cell_info** - Get detailed component metadata
|
|
150
|
-
- **download_gds** - Download built GDS files
|
|
151
168
|
- **list_projects** - List all running GDSFactory+ server instances
|
|
152
169
|
- **get_project_info** - Get detailed information about a specific project
|
|
153
|
-
- **check_drc** - Run Design Rule Check verification
|
|
170
|
+
- **check_drc** - Run Design Rule Check verification (returns structured format with all violations including simplified location data for LLM-friendly troubleshooting)
|
|
154
171
|
- **check_connectivity** - Run connectivity verification
|
|
155
172
|
- **check_lvs** - Run Layout vs. Schematic verification
|
|
156
173
|
|
|
@@ -43,6 +43,21 @@ class FastAPIClient:
|
|
|
43
43
|
self._client: httpx.AsyncClient | None = None
|
|
44
44
|
self._registry = ServerRegistry()
|
|
45
45
|
|
|
46
|
+
def _has_available_servers(self) -> bool:
|
|
47
|
+
"""Check if any servers are available in the registry."""
|
|
48
|
+
return len(self._registry.list_servers()) > 0
|
|
49
|
+
|
|
50
|
+
def _get_default_server_url(self) -> str | None:
|
|
51
|
+
"""Get the first available server URL from registry if no base_url configured."""
|
|
52
|
+
if self.base_url:
|
|
53
|
+
return self.base_url
|
|
54
|
+
|
|
55
|
+
servers = self._registry.list_servers()
|
|
56
|
+
if servers:
|
|
57
|
+
return f"http://localhost:{servers[0].port}"
|
|
58
|
+
|
|
59
|
+
return None
|
|
60
|
+
|
|
46
61
|
async def __aenter__(self) -> Self:
|
|
47
62
|
"""Enter async context."""
|
|
48
63
|
await self.start()
|
|
@@ -55,12 +70,17 @@ class FastAPIClient:
|
|
|
55
70
|
async def start(self) -> None:
|
|
56
71
|
"""Start the HTTP client with connection pooling."""
|
|
57
72
|
if self._client is None:
|
|
73
|
+
base_url = self.base_url or "http://localhost"
|
|
74
|
+
|
|
58
75
|
self._client = httpx.AsyncClient(
|
|
59
|
-
base_url=
|
|
76
|
+
base_url=base_url,
|
|
60
77
|
timeout=httpx.Timeout(self.timeout),
|
|
61
78
|
limits=httpx.Limits(max_keepalive_connections=5, max_connections=10),
|
|
62
79
|
)
|
|
63
|
-
logger.debug(
|
|
80
|
+
logger.debug(
|
|
81
|
+
"HTTP client started with base URL: %s (resolved per-request if needed)",
|
|
82
|
+
self.base_url or "from registry",
|
|
83
|
+
)
|
|
64
84
|
|
|
65
85
|
async def close(self) -> None:
|
|
66
86
|
"""Close the HTTP client."""
|
|
@@ -79,22 +99,46 @@ class FastAPIClient:
|
|
|
79
99
|
Base URL for the request
|
|
80
100
|
|
|
81
101
|
Raises:
|
|
82
|
-
ValueError: If
|
|
102
|
+
ValueError: If base URL cannot be resolved
|
|
83
103
|
"""
|
|
84
|
-
|
|
85
|
-
|
|
104
|
+
if project is not None:
|
|
105
|
+
server_info = self._registry.get_server_by_project(project)
|
|
106
|
+
if server_info is None:
|
|
107
|
+
available = self._registry.list_servers()
|
|
108
|
+
if available:
|
|
109
|
+
project_list = ", ".join([s.project_name for s in available[:3]])
|
|
110
|
+
if len(available) > 3:
|
|
111
|
+
project_list += f", ... and {len(available) - 3} more"
|
|
112
|
+
msg = (
|
|
113
|
+
f"Project '{project}' not found in registry. "
|
|
114
|
+
f"Available projects: {project_list}. "
|
|
115
|
+
"Use list_projects tool to see all running servers."
|
|
116
|
+
)
|
|
117
|
+
else:
|
|
118
|
+
msg = (
|
|
119
|
+
f"Project '{project}' not found. No GDSFactory+ servers are running. "
|
|
120
|
+
"Please open a GDSFactory+ project in VSCode with the extension installed."
|
|
121
|
+
)
|
|
122
|
+
raise ValueError(msg)
|
|
123
|
+
|
|
124
|
+
return f"http://localhost:{server_info.port}"
|
|
125
|
+
|
|
126
|
+
if self.base_url:
|
|
86
127
|
return self.base_url
|
|
87
128
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
f"Project '{project}' not found in registry. "
|
|
93
|
-
"Make sure the server is running for this project."
|
|
129
|
+
default_url = self._get_default_server_url()
|
|
130
|
+
if default_url:
|
|
131
|
+
logger.info(
|
|
132
|
+
"No project specified, using first available server: %s", default_url
|
|
94
133
|
)
|
|
95
|
-
|
|
134
|
+
return default_url
|
|
96
135
|
|
|
97
|
-
|
|
136
|
+
msg = (
|
|
137
|
+
"No project specified and no GDSFactory+ servers are running. "
|
|
138
|
+
"Either: (1) Start a server by opening a GDSFactory+ project in VSCode, "
|
|
139
|
+
"(2) Specify a project parameter, or (3) Set GFP_API_URL environment variable."
|
|
140
|
+
)
|
|
141
|
+
raise ValueError(msg)
|
|
98
142
|
|
|
99
143
|
async def request(
|
|
100
144
|
self,
|
|
@@ -125,7 +169,6 @@ class FastAPIClient:
|
|
|
125
169
|
if self._client is None:
|
|
126
170
|
await self.start()
|
|
127
171
|
|
|
128
|
-
# Resolve the base URL for this request
|
|
129
172
|
base_url = self._resolve_base_url(project)
|
|
130
173
|
|
|
131
174
|
last_error = None
|
|
@@ -143,7 +186,6 @@ class FastAPIClient:
|
|
|
143
186
|
base_url,
|
|
144
187
|
)
|
|
145
188
|
|
|
146
|
-
# Build full URL with the resolved base URL
|
|
147
189
|
full_url = f"{base_url}{path}"
|
|
148
190
|
|
|
149
191
|
response = await self._client.request( # type: ignore[union-attr]
|
|
@@ -155,7 +197,6 @@ class FastAPIClient:
|
|
|
155
197
|
)
|
|
156
198
|
response.raise_for_status()
|
|
157
199
|
|
|
158
|
-
# Try to parse JSON, fall back to text
|
|
159
200
|
try:
|
|
160
201
|
return response.json()
|
|
161
202
|
except (ValueError, TypeError):
|
|
@@ -165,19 +206,16 @@ class FastAPIClient:
|
|
|
165
206
|
last_error = e
|
|
166
207
|
logger.warning("Request failed (attempt %d): %s", attempt + 1, e)
|
|
167
208
|
|
|
168
|
-
# Don't retry on client errors (4xx)
|
|
169
209
|
if (
|
|
170
210
|
isinstance(e, httpx.HTTPStatusError)
|
|
171
211
|
and 400 <= e.response.status_code < 500
|
|
172
212
|
):
|
|
173
213
|
raise
|
|
174
214
|
|
|
175
|
-
# Exponential backoff for retries
|
|
176
215
|
if attempt < MCPConfig.MAX_RETRIES - 1:
|
|
177
216
|
await asyncio.sleep(backoff)
|
|
178
217
|
backoff *= 2
|
|
179
218
|
|
|
180
|
-
# All retries failed
|
|
181
219
|
logger.error("All %d attempts failed", MCPConfig.MAX_RETRIES)
|
|
182
220
|
raise last_error # type: ignore[misc]
|
|
183
221
|
|
|
@@ -15,34 +15,28 @@ class MCPConfig:
|
|
|
15
15
|
that proxies requests to the FastAPI backend.
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
# This default is primarily for backward compatibility.
|
|
20
|
-
# The MCP server automatically discovers running servers via the registry.
|
|
21
|
-
API_URL: Final[str] = os.getenv("GFP_API_URL", "http://localhost:8787")
|
|
18
|
+
API_URL: Final[str | None] = os.getenv("GFP_API_URL")
|
|
22
19
|
|
|
23
|
-
# Timeout for tool calls in seconds (default: 300 = 5 minutes)
|
|
24
20
|
TIMEOUT: Final[int] = int(os.getenv("GFP_MCP_TIMEOUT", "300"))
|
|
25
21
|
|
|
26
|
-
# Enable debug logging
|
|
27
22
|
DEBUG: Final[bool] = os.getenv("GFP_MCP_DEBUG", "false").lower() in (
|
|
28
23
|
"true",
|
|
29
24
|
"1",
|
|
30
25
|
"yes",
|
|
31
26
|
)
|
|
32
27
|
|
|
33
|
-
# Retry configuration
|
|
34
28
|
MAX_RETRIES: Final[int] = 3
|
|
35
29
|
RETRY_BACKOFF: Final[float] = 0.5 # Initial backoff in seconds
|
|
36
30
|
|
|
37
31
|
@classmethod
|
|
38
|
-
def get_api_url(cls, override: str | None = None) -> str:
|
|
32
|
+
def get_api_url(cls, override: str | None = None) -> str | None:
|
|
39
33
|
"""Get the FastAPI base URL.
|
|
40
34
|
|
|
41
35
|
Args:
|
|
42
36
|
override: Optional URL to override the environment variable
|
|
43
37
|
|
|
44
38
|
Returns:
|
|
45
|
-
The API base URL
|
|
39
|
+
The API base URL or None if not configured
|
|
46
40
|
"""
|
|
47
41
|
return override or cls.API_URL
|
|
48
42
|
|