gfp-mcp 0.1.0__py3-none-any.whl → 0.2.1__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.
- gfp_mcp-0.2.1.dist-info/METADATA +210 -0
- gfp_mcp-0.2.1.dist-info/RECORD +14 -0
- {gfp_mcp-0.1.0.dist-info → gfp_mcp-0.2.1.dist-info}/WHEEL +1 -1
- gfp_mcp-0.2.1.dist-info/licenses/LICENSE +4 -0
- mcp_standalone/__init__.py +4 -1
- mcp_standalone/client.py +4 -0
- mcp_standalone/config.py +2 -0
- mcp_standalone/mappings.py +100 -0
- mcp_standalone/resources.py +141 -0
- mcp_standalone/server.py +73 -7
- mcp_standalone/tools.py +165 -3
- gfp_mcp-0.1.0.dist-info/METADATA +0 -360
- gfp_mcp-0.1.0.dist-info/RECORD +0 -12
- {gfp_mcp-0.1.0.dist-info → gfp_mcp-0.2.1.dist-info}/entry_points.txt +0 -0
- {gfp_mcp-0.1.0.dist-info → gfp_mcp-0.2.1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gfp-mcp
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Model Context Protocol (MCP) server for GDSFactory+ photonic IC design
|
|
5
|
+
Author: GDSFactory+ Team
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/doplaydo/gfp-mcp
|
|
8
|
+
Project-URL: Repository, https://github.com/doplaydo/gfp-mcp
|
|
9
|
+
Project-URL: Documentation, https://github.com/doplaydo/gfp-mcp#readme
|
|
10
|
+
Project-URL: Changelog, https://github.com/doplaydo/gfp-mcp/blob/main/CHANGELOG.md
|
|
11
|
+
Project-URL: Issue Tracker, https://github.com/doplaydo/gfp-mcp/issues
|
|
12
|
+
Keywords: mcp,gdsfactory,photonics,ic-design,eda,model-context-protocol,photonic-ic,gds
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: mcp>=1.7.1
|
|
28
|
+
Requires-Dist: httpx>=0.25.0
|
|
29
|
+
Requires-Dist: typing-extensions>=4.0.0; python_version < "3.11"
|
|
30
|
+
Requires-Dist: psutil>=5.9.0
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
34
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
35
|
+
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
36
|
+
Dynamic: license-file
|
|
37
|
+
|
|
38
|
+
# GDSFactory+ MCP Server
|
|
39
|
+
|
|
40
|
+
[](https://pypi.org/project/gfp-mcp/)
|
|
41
|
+
[](https://pypi.org/project/gfp-mcp/)
|
|
42
|
+
[](https://github.com/doplaydo/gfp-mcp/actions)
|
|
43
|
+
[](https://opensource.org/licenses/MIT)
|
|
44
|
+
|
|
45
|
+
Model Context Protocol (MCP) server for GDSFactory+ that enables AI assistants like Claude to design and build photonic integrated circuits.
|
|
46
|
+
|
|
47
|
+
## What is this?
|
|
48
|
+
|
|
49
|
+
This MCP server connects AI assistants to [GDSFactory+](https://gdsfactory.com), allowing you to design photonic ICs through natural language. Build components, run verification checks, and manage multiple projects directly from Claude Code or Claude Desktop.
|
|
50
|
+
|
|
51
|
+
## Quick Start
|
|
52
|
+
|
|
53
|
+
### 1. Install Prerequisites
|
|
54
|
+
|
|
55
|
+
- Python 3.10 or higher
|
|
56
|
+
- VSCode with the [GDSFactory+ extension](https://marketplace.visualstudio.com/items?itemName=gdsfactory.gdsfactoryplus) installed
|
|
57
|
+
|
|
58
|
+
### 2. Install the MCP Server
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
pip install gfp-mcp
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Or with uv:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
uvx --from gfp-mcp gfp-mcp-serve
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### 3. Connect to Your AI Assistant
|
|
71
|
+
|
|
72
|
+
<details>
|
|
73
|
+
<summary><strong>Claude Code</strong></summary>
|
|
74
|
+
|
|
75
|
+
Add to `.claude/settings.json`:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"mcpServers": {
|
|
80
|
+
"gdsfactoryplus": {
|
|
81
|
+
"command": "gfp-mcp-serve",
|
|
82
|
+
"args": [],
|
|
83
|
+
"env": {
|
|
84
|
+
"GFP_API_URL": "http://localhost:8787"
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Or use the CLI:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
claude mcp add gdsfactoryplus -- gfp-mcp-serve
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
</details>
|
|
98
|
+
|
|
99
|
+
<details>
|
|
100
|
+
<summary><strong>Claude Desktop</strong></summary>
|
|
101
|
+
|
|
102
|
+
Add to your config file:
|
|
103
|
+
|
|
104
|
+
**macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
|
|
105
|
+
|
|
106
|
+
**Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
107
|
+
|
|
108
|
+
**Linux**: `~/.config/Claude/claude_desktop_config.json`
|
|
109
|
+
|
|
110
|
+
```json
|
|
111
|
+
{
|
|
112
|
+
"mcpServers": {
|
|
113
|
+
"gdsfactoryplus": {
|
|
114
|
+
"command": "gfp-mcp-serve",
|
|
115
|
+
"args": []
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Restart Claude Desktop after adding the configuration.
|
|
122
|
+
|
|
123
|
+
</details>
|
|
124
|
+
|
|
125
|
+
<details>
|
|
126
|
+
<summary><strong>Cursor</strong></summary>
|
|
127
|
+
|
|
128
|
+
Coming soon. Follow the MCP integration instructions for Cursor when available.
|
|
129
|
+
|
|
130
|
+
</details>
|
|
131
|
+
|
|
132
|
+
### 4. Start Designing
|
|
133
|
+
|
|
134
|
+
The MCP server automatically discovers running GDSFactory+ servers via the registry (`~/.gdsfactory/server-registry.json`). On startup, it will log all discovered projects.
|
|
135
|
+
|
|
136
|
+
Try these commands with your AI assistant:
|
|
137
|
+
|
|
138
|
+
- "List all available photonic components"
|
|
139
|
+
- "Build an MZI interferometer"
|
|
140
|
+
- "Show me details about the directional coupler"
|
|
141
|
+
- "Build multiple components: mzi, coupler, and bend_euler"
|
|
142
|
+
- "List all my GDSFactory+ projects"
|
|
143
|
+
|
|
144
|
+
## Available Tools
|
|
145
|
+
|
|
146
|
+
- **build_cell** - Build a single GDS cell by name
|
|
147
|
+
- **build_cells** - Build multiple GDS cells in batch
|
|
148
|
+
- **list_cells** - List all available photonic components
|
|
149
|
+
- **get_cell_info** - Get detailed component metadata
|
|
150
|
+
- **download_gds** - Download built GDS files
|
|
151
|
+
- **list_projects** - List all running GDSFactory+ server instances
|
|
152
|
+
- **get_project_info** - Get detailed information about a specific project
|
|
153
|
+
- **check_drc** - Run Design Rule Check verification
|
|
154
|
+
- **check_connectivity** - Run connectivity verification
|
|
155
|
+
- **check_lvs** - Run Layout vs. Schematic verification
|
|
156
|
+
|
|
157
|
+
## Multi-Project Support
|
|
158
|
+
|
|
159
|
+
The MCP server automatically discovers all running GDSFactory+ projects via the server registry (`~/.gdsfactory/server-registry.json`). The registry is the source of truth for available servers. Use the `list_projects` tool to see all running projects, then specify the project name when building components:
|
|
160
|
+
|
|
161
|
+
```
|
|
162
|
+
User: "List all my GDSFactory+ projects"
|
|
163
|
+
Claude: [Uses list_projects tool to show all running servers]
|
|
164
|
+
|
|
165
|
+
User: "Build the mzi component in my_photonics_project"
|
|
166
|
+
Claude: [Routes request to the correct project]
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## Troubleshooting
|
|
170
|
+
|
|
171
|
+
<details>
|
|
172
|
+
<summary><strong>Server not appearing in Claude</strong></summary>
|
|
173
|
+
|
|
174
|
+
1. Verify installation: `gfp-mcp-serve --help`
|
|
175
|
+
2. Check Claude Code logs: `claude --debug`
|
|
176
|
+
3. Restart Claude Desktop/Code
|
|
177
|
+
4. Ensure the GDSFactory+ VSCode extension is active and a project is open
|
|
178
|
+
|
|
179
|
+
</details>
|
|
180
|
+
|
|
181
|
+
<details>
|
|
182
|
+
<summary><strong>Connection refused errors</strong></summary>
|
|
183
|
+
|
|
184
|
+
The MCP server uses the registry (`~/.gdsfactory/server-registry.json`) to discover running servers.
|
|
185
|
+
|
|
186
|
+
1. Use the `list_projects` tool in Claude to check available servers
|
|
187
|
+
2. If no servers are found, ensure the GDSFactory+ VSCode extension is running with an active project:
|
|
188
|
+
- Open VSCode with the GDSFactory+ extension installed
|
|
189
|
+
- Open a GDSFactory+ project folder
|
|
190
|
+
- The extension automatically starts the server and registers it
|
|
191
|
+
3. Check the MCP startup logs for discovered servers
|
|
192
|
+
4. Verify the registry is accessible at `~/.gdsfactory/server-registry.json`
|
|
193
|
+
5. For backward compatibility, you can set a specific server URL:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
export GFP_API_URL="http://localhost:YOUR_PORT"
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
</details>
|
|
200
|
+
|
|
201
|
+
<details>
|
|
202
|
+
<summary><strong>Tool execution timeout</strong></summary>
|
|
203
|
+
|
|
204
|
+
Increase the timeout for long-running operations:
|
|
205
|
+
|
|
206
|
+
```bash
|
|
207
|
+
export GFP_MCP_TIMEOUT=600 # 10 minutes
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
</details>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
gfp_mcp-0.2.1.dist-info/licenses/LICENSE,sha256=ixSuHdKKXzNJw_eTgAxHzaCNIds8k48hytA_eJgA8gQ,225
|
|
2
|
+
mcp_standalone/__init__.py,sha256=B6JB7U_vEMARO87RzNDesfSZdGgD1U-RC2GkL2ijOCA,1069
|
|
3
|
+
mcp_standalone/client.py,sha256=vS_mw3frp5dQr2s_uFbPH-cF4k98rOJFGZLIz1FOU7A,8371
|
|
4
|
+
mcp_standalone/config.py,sha256=1B00PLrKOz96c62lkhIgrraF-HWZ015uoPZ7okCcuKk,1525
|
|
5
|
+
mcp_standalone/mappings.py,sha256=2J2DEZzXTdmi6VmrtCeI1cg-2T7tYHkytRGrZJ62zog,10583
|
|
6
|
+
mcp_standalone/registry.py,sha256=1E61UalVot8HUS3cALjM7ejYB0qR6tI5QbQSZZeQe7Y,6401
|
|
7
|
+
mcp_standalone/resources.py,sha256=iMkYIyTxLWwWE0NLxprLabGFYbPnUaIbgwwtbvZ2av0,3606
|
|
8
|
+
mcp_standalone/server.py,sha256=jDCns5Cgb5JZahbx8pjCCDqryT-RiLCOFD5FIpgr3OA,9149
|
|
9
|
+
mcp_standalone/tools.py,sha256=totbebwVzqOej1TjmY6lOZ7raSPFIwGWmWfOFVN3IyE,18734
|
|
10
|
+
gfp_mcp-0.2.1.dist-info/METADATA,sha256=16kFH1_7TvI11tZnuXXrdTyQ6os5s7I5E7mTvSdRfVA,6858
|
|
11
|
+
gfp_mcp-0.2.1.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
12
|
+
gfp_mcp-0.2.1.dist-info/entry_points.txt,sha256=mgyus9dsB_8mjgnztuHNPqzPi-7HcPg1iYzfM5NMIjk,61
|
|
13
|
+
gfp_mcp-0.2.1.dist-info/top_level.txt,sha256=g2hRJHoDDPNtrNdXR70T7FR9Ev6DTRJiGW7ZvlvnXMc,15
|
|
14
|
+
gfp_mcp-0.2.1.dist-info/RECORD,,
|
mcp_standalone/__init__.py
CHANGED
|
@@ -23,6 +23,7 @@ from __future__ import annotations
|
|
|
23
23
|
|
|
24
24
|
from .client import FastAPIClient
|
|
25
25
|
from .config import MCPConfig
|
|
26
|
+
from .resources import get_all_resources, get_resource_content
|
|
26
27
|
from .server import create_server, main, run_server
|
|
27
28
|
from .tools import get_all_tools, get_tool_by_name
|
|
28
29
|
|
|
@@ -34,6 +35,8 @@ __all__ = [
|
|
|
34
35
|
"run_server",
|
|
35
36
|
"get_all_tools",
|
|
36
37
|
"get_tool_by_name",
|
|
38
|
+
"get_all_resources",
|
|
39
|
+
"get_resource_content",
|
|
37
40
|
]
|
|
38
41
|
|
|
39
|
-
__version__ = "0.1
|
|
42
|
+
__version__ = "0.2.1"
|
mcp_standalone/client.py
CHANGED
|
@@ -218,6 +218,10 @@ class FastAPIClient:
|
|
|
218
218
|
async def health_check(self, project: str | None = None) -> bool:
|
|
219
219
|
"""Check if the FastAPI server is reachable.
|
|
220
220
|
|
|
221
|
+
.. deprecated::
|
|
222
|
+
This method is deprecated and no longer called during MCP startup.
|
|
223
|
+
Use list_projects() for server discovery instead.
|
|
224
|
+
|
|
221
225
|
Args:
|
|
222
226
|
project: Optional project name to check specific server
|
|
223
227
|
|
mcp_standalone/config.py
CHANGED
|
@@ -16,6 +16,8 @@ class MCPConfig:
|
|
|
16
16
|
"""
|
|
17
17
|
|
|
18
18
|
# FastAPI base URL (default: http://localhost:8787)
|
|
19
|
+
# This default is primarily for backward compatibility.
|
|
20
|
+
# The MCP server automatically discovers running servers via the registry.
|
|
19
21
|
API_URL: Final[str] = os.getenv("GFP_API_URL", "http://localhost:8787")
|
|
20
22
|
|
|
21
23
|
# Timeout for tool calls in seconds (default: 300 = 5 minutes)
|
mcp_standalone/mappings.py
CHANGED
|
@@ -189,6 +189,81 @@ def _check_lvs_request(args: dict[str, Any]) -> dict[str, Any]:
|
|
|
189
189
|
}
|
|
190
190
|
|
|
191
191
|
|
|
192
|
+
def _simulate_component_request(args: dict[str, Any]) -> dict[str, Any]:
|
|
193
|
+
"""Transform simulate_component MCP args to FastAPI params.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
args: MCP tool arguments
|
|
197
|
+
|
|
198
|
+
Returns:
|
|
199
|
+
Dict with 'params' key for query parameters
|
|
200
|
+
"""
|
|
201
|
+
return {"params": {"name": args["name"]}}
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
def _get_port_center_request(args: dict[str, Any]) -> dict[str, Any]:
|
|
205
|
+
"""Transform get_port_center MCP args to FastAPI params.
|
|
206
|
+
|
|
207
|
+
Args:
|
|
208
|
+
args: MCP tool arguments
|
|
209
|
+
|
|
210
|
+
Returns:
|
|
211
|
+
Dict with 'params' key for query parameters
|
|
212
|
+
"""
|
|
213
|
+
return {
|
|
214
|
+
"params": {
|
|
215
|
+
"netlist": args["netlist"],
|
|
216
|
+
"instance": args["instance"],
|
|
217
|
+
"port": args["port"],
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
def _generate_bbox_request(args: dict[str, Any]) -> dict[str, Any]:
|
|
223
|
+
"""Transform generate_bbox MCP args to FastAPI params.
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
args: MCP tool arguments
|
|
227
|
+
|
|
228
|
+
Returns:
|
|
229
|
+
Dict with 'json_data' key for request body
|
|
230
|
+
"""
|
|
231
|
+
json_data: dict[str, Any] = {"path": args["path"]}
|
|
232
|
+
|
|
233
|
+
# Add optional parameters if provided
|
|
234
|
+
if "outpath" in args and args["outpath"]:
|
|
235
|
+
json_data["outpath"] = args["outpath"]
|
|
236
|
+
if "layers_to_keep" in args and args["layers_to_keep"]:
|
|
237
|
+
json_data["layers_to_keep"] = args["layers_to_keep"]
|
|
238
|
+
if "bbox_layer" in args and args["bbox_layer"]:
|
|
239
|
+
json_data["bbox_layer"] = args["bbox_layer"]
|
|
240
|
+
if "ignore_ports" in args:
|
|
241
|
+
json_data["ignore_ports"] = args["ignore_ports"]
|
|
242
|
+
|
|
243
|
+
return {"json_data": json_data}
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
def _freeze_cell_request(args: dict[str, Any]) -> dict[str, Any]:
|
|
247
|
+
"""Transform freeze_cell MCP args to FastAPI params.
|
|
248
|
+
|
|
249
|
+
Args:
|
|
250
|
+
args: MCP tool arguments
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
Dict with 'path' and 'json_data' for the request
|
|
254
|
+
"""
|
|
255
|
+
cell_name = args["cell_name"]
|
|
256
|
+
kwargs = args.get("kwargs", {})
|
|
257
|
+
|
|
258
|
+
# The freeze endpoint expects a JSON string in the body.
|
|
259
|
+
# httpx with json= will JSON-encode the dict and send it as the body,
|
|
260
|
+
# which FastAPI's Body() will read as a string.
|
|
261
|
+
return {
|
|
262
|
+
"path": f"/freeze/{cell_name}",
|
|
263
|
+
"json_data": kwargs, # httpx will JSON-encode this to a string
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
|
|
192
267
|
# Tool name -> Endpoint mapping
|
|
193
268
|
TOOL_MAPPINGS: dict[str, EndpointMapping] = {
|
|
194
269
|
# Phase 1: Core Building Tools
|
|
@@ -234,6 +309,31 @@ TOOL_MAPPINGS: dict[str, EndpointMapping] = {
|
|
|
234
309
|
path="/api/check-lvs",
|
|
235
310
|
request_transformer=_check_lvs_request,
|
|
236
311
|
),
|
|
312
|
+
# Phase 4: Simulation & Advanced Tools
|
|
313
|
+
"simulate_component": EndpointMapping(
|
|
314
|
+
method="GET",
|
|
315
|
+
path="/api/simulate",
|
|
316
|
+
request_transformer=_simulate_component_request,
|
|
317
|
+
),
|
|
318
|
+
"get_port_center": EndpointMapping(
|
|
319
|
+
method="GET",
|
|
320
|
+
path="/api/port-center",
|
|
321
|
+
request_transformer=_get_port_center_request,
|
|
322
|
+
),
|
|
323
|
+
"generate_bbox": EndpointMapping(
|
|
324
|
+
method="POST",
|
|
325
|
+
path="/api/bbox",
|
|
326
|
+
request_transformer=_generate_bbox_request,
|
|
327
|
+
),
|
|
328
|
+
"freeze_cell": EndpointMapping(
|
|
329
|
+
method="POST",
|
|
330
|
+
path="/freeze/{cell_name}",
|
|
331
|
+
request_transformer=_freeze_cell_request,
|
|
332
|
+
),
|
|
333
|
+
"get_pdk_info": EndpointMapping(
|
|
334
|
+
method="GET",
|
|
335
|
+
path="/info",
|
|
336
|
+
),
|
|
237
337
|
}
|
|
238
338
|
|
|
239
339
|
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
"""MCP resource definitions for GDSFactory+.
|
|
2
|
+
|
|
3
|
+
This module defines the MCP resources that are exposed to AI assistants.
|
|
4
|
+
Resources provide read-only access to documentation and instruction content.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from mcp.types import Resource
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"RESOURCES",
|
|
13
|
+
"get_all_resources",
|
|
14
|
+
"get_resource_content",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
# Define available resources
|
|
19
|
+
RESOURCES: list[Resource] = [
|
|
20
|
+
Resource(
|
|
21
|
+
uri="instructions://build_custom_cell",
|
|
22
|
+
name="Build Custom Cell Instructions",
|
|
23
|
+
description=(
|
|
24
|
+
"Comprehensive instructions for building custom photonic cells "
|
|
25
|
+
"in GDSFactory+. Covers component creation, file organization, "
|
|
26
|
+
"PDK integration, and best practices."
|
|
27
|
+
),
|
|
28
|
+
mimeType="text/markdown",
|
|
29
|
+
),
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# Resource content
|
|
34
|
+
RESOURCE_CONTENT = {
|
|
35
|
+
"instructions://build_custom_cell": """---
|
|
36
|
+
Workflow: Creating Custom Components in GDSFactory+ Projects
|
|
37
|
+
|
|
38
|
+
Overview
|
|
39
|
+
|
|
40
|
+
When users request custom photonic components, keep user-defined components separate from PDK-defined
|
|
41
|
+
objects to maintain clean project organization.
|
|
42
|
+
|
|
43
|
+
Step-by-Step Process
|
|
44
|
+
|
|
45
|
+
1. File Organization
|
|
46
|
+
|
|
47
|
+
- DO NOT add custom components to cells.py - this file is reserved for PDK-defined objects
|
|
48
|
+
- CREATE or use custom_components.py in the package directory (e.g., myph18da/custom_components.py)
|
|
49
|
+
- This keeps custom user components separate from the PDK
|
|
50
|
+
|
|
51
|
+
2. Component Creation
|
|
52
|
+
|
|
53
|
+
\"\"\"Custom user-defined components.\"\"\"
|
|
54
|
+
|
|
55
|
+
import gdsfactory as gf
|
|
56
|
+
from ph18da.cells import <relevant_pdk_functions> # Use PDK functions when available
|
|
57
|
+
|
|
58
|
+
__all__ = ["custom_component_name"]
|
|
59
|
+
|
|
60
|
+
@gf.cell
|
|
61
|
+
def custom_component_name(
|
|
62
|
+
param1: float = default_value,
|
|
63
|
+
param2: float = default_value,
|
|
64
|
+
) -> gf.Component:
|
|
65
|
+
\"\"\"Component description.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
param1: Description
|
|
69
|
+
param2: Description
|
|
70
|
+
|
|
71
|
+
Returns:
|
|
72
|
+
Component description
|
|
73
|
+
\"\"\"
|
|
74
|
+
# Implementation using PDK functions
|
|
75
|
+
c = pdk_function(parameters...)
|
|
76
|
+
return c
|
|
77
|
+
|
|
78
|
+
3. Key Implementation Guidelines
|
|
79
|
+
|
|
80
|
+
- Use @gf.cell decorator for all components
|
|
81
|
+
- Prefer using existing PDK functions (e.g., mzi_swg) over internal functions (e.g., _mzi)
|
|
82
|
+
- Import from ph18da.cells for PDK-specific components
|
|
83
|
+
- Use standard PDK component names (e.g., "c_mmi_2x2_swg", "wg_straight_swg", "wg_arc_swg")
|
|
84
|
+
- Keep component parameters clear and well-documented
|
|
85
|
+
|
|
86
|
+
4. Register the Component
|
|
87
|
+
|
|
88
|
+
Update the package __init__.py to import and expose the custom component:
|
|
89
|
+
from myph18da.custom_components import custom_component_name
|
|
90
|
+
|
|
91
|
+
5. Build the Component
|
|
92
|
+
|
|
93
|
+
Use the MCP build tool:
|
|
94
|
+
mcp__gdsfactoryplus__build_cell(
|
|
95
|
+
name="custom_component_name",
|
|
96
|
+
project="project-name"
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
6. Verification
|
|
100
|
+
|
|
101
|
+
- Check build status with get_cell_info
|
|
102
|
+
- Verify GDS file exists in build/gds/ directory
|
|
103
|
+
- Ensure status is "SUCCESS"
|
|
104
|
+
|
|
105
|
+
Troubleshooting
|
|
106
|
+
|
|
107
|
+
If build fails with import errors:
|
|
108
|
+
- Use PDK public functions instead of internal _functions
|
|
109
|
+
- Check that imports are from the correct PDK modules
|
|
110
|
+
|
|
111
|
+
If component not found:
|
|
112
|
+
- Ensure it's imported in __init__.py
|
|
113
|
+
- Rebuild the component after changes
|
|
114
|
+
|
|
115
|
+
If parameter errors occur:
|
|
116
|
+
- Check PDK component compatibility
|
|
117
|
+
- Verify parameter names match PDK expectations
|
|
118
|
+
---
|
|
119
|
+
""",
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def get_all_resources() -> list[Resource]:
|
|
124
|
+
"""Get all available MCP resources.
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
List of all resource definitions
|
|
128
|
+
"""
|
|
129
|
+
return RESOURCES
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def get_resource_content(uri: str) -> str | None:
|
|
133
|
+
"""Get resource content by URI.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
uri: Resource URI
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
Resource content string or None if not found
|
|
140
|
+
"""
|
|
141
|
+
return RESOURCE_CONTENT.get(uri)
|
mcp_standalone/server.py
CHANGED
|
@@ -13,11 +13,17 @@ from typing import Any
|
|
|
13
13
|
|
|
14
14
|
from mcp.server import Server
|
|
15
15
|
from mcp.server.stdio import stdio_server
|
|
16
|
-
from mcp.types import
|
|
16
|
+
from mcp.types import (
|
|
17
|
+
Resource,
|
|
18
|
+
TextContent,
|
|
19
|
+
Tool,
|
|
20
|
+
)
|
|
17
21
|
|
|
18
22
|
from .client import FastAPIClient
|
|
19
23
|
from .config import MCPConfig
|
|
20
24
|
from .mappings import get_mapping, transform_request, transform_response
|
|
25
|
+
from .registry import get_registry_path
|
|
26
|
+
from .resources import get_all_resources, get_resource_content
|
|
21
27
|
from .tools import get_all_tools
|
|
22
28
|
|
|
23
29
|
__all__ = ["create_server", "run_server", "main"]
|
|
@@ -51,6 +57,41 @@ def create_server(api_url: str | None = None) -> Server:
|
|
|
51
57
|
logger.info("Listing %d tools", len(tools))
|
|
52
58
|
return tools
|
|
53
59
|
|
|
60
|
+
@server.list_resources()
|
|
61
|
+
async def list_resources() -> list[Resource]:
|
|
62
|
+
"""List all available MCP resources.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
List of resource definitions
|
|
66
|
+
"""
|
|
67
|
+
resources = get_all_resources()
|
|
68
|
+
logger.info("Listing %d resources", len(resources))
|
|
69
|
+
return resources
|
|
70
|
+
|
|
71
|
+
@server.read_resource()
|
|
72
|
+
async def read_resource(uri: str) -> str:
|
|
73
|
+
"""Read a specific resource by URI.
|
|
74
|
+
|
|
75
|
+
Args:
|
|
76
|
+
uri: Resource URI
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
Resource content as string
|
|
80
|
+
|
|
81
|
+
Raises:
|
|
82
|
+
ValueError: If resource URI is not found
|
|
83
|
+
"""
|
|
84
|
+
logger.info("Resource requested: %s", uri)
|
|
85
|
+
|
|
86
|
+
# Get resource content
|
|
87
|
+
content = get_resource_content(uri)
|
|
88
|
+
if content is None:
|
|
89
|
+
error_msg = f"Unknown resource URI: {uri}"
|
|
90
|
+
logger.error(error_msg)
|
|
91
|
+
raise ValueError(error_msg)
|
|
92
|
+
|
|
93
|
+
return content
|
|
94
|
+
|
|
54
95
|
@server.call_tool()
|
|
55
96
|
async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent]: # noqa: PLR0911
|
|
56
97
|
"""Call an MCP tool.
|
|
@@ -157,6 +198,35 @@ def create_server(api_url: str | None = None) -> Server:
|
|
|
157
198
|
return server
|
|
158
199
|
|
|
159
200
|
|
|
201
|
+
def _log_server_discovery(client: FastAPIClient) -> None:
|
|
202
|
+
"""Log discovered GDSFactory+ servers at startup."""
|
|
203
|
+
try:
|
|
204
|
+
projects = client.list_projects()
|
|
205
|
+
if projects:
|
|
206
|
+
logger.info("Discovered %d GDSFactory+ server(s):", len(projects))
|
|
207
|
+
for project in projects[:3]: # Show first 3
|
|
208
|
+
logger.info(
|
|
209
|
+
" - %s (port %d, PDK: %s)",
|
|
210
|
+
project["project_name"],
|
|
211
|
+
project["port"],
|
|
212
|
+
project.get("pdk", "unknown"),
|
|
213
|
+
)
|
|
214
|
+
if len(projects) > 3:
|
|
215
|
+
logger.info(" ... and %d more", len(projects) - 3)
|
|
216
|
+
else:
|
|
217
|
+
logger.warning(
|
|
218
|
+
"No GDSFactory+ servers found. Start a server with: "
|
|
219
|
+
"gfp serve --port 8787"
|
|
220
|
+
)
|
|
221
|
+
logger.info("Registry location: %s", get_registry_path())
|
|
222
|
+
except Exception as e:
|
|
223
|
+
logger.warning("Could not read server registry: %s", e)
|
|
224
|
+
logger.info(
|
|
225
|
+
"If GDSFactory+ is running, ensure registry is accessible at: %s",
|
|
226
|
+
get_registry_path(),
|
|
227
|
+
)
|
|
228
|
+
|
|
229
|
+
|
|
160
230
|
async def run_server(api_url: str | None = None) -> None:
|
|
161
231
|
"""Run the MCP server with STDIO transport.
|
|
162
232
|
|
|
@@ -182,12 +252,8 @@ async def run_server(api_url: str | None = None) -> None:
|
|
|
182
252
|
# Start HTTP client
|
|
183
253
|
await client.start()
|
|
184
254
|
|
|
185
|
-
#
|
|
186
|
-
|
|
187
|
-
if not healthy:
|
|
188
|
-
logger.warning(
|
|
189
|
-
"FastAPI server health check failed. Server may not be running."
|
|
190
|
-
)
|
|
255
|
+
# Discover available servers
|
|
256
|
+
_log_server_discovery(client)
|
|
191
257
|
|
|
192
258
|
# Run server with STDIO transport
|
|
193
259
|
async with stdio_server() as (read_stream, write_stream):
|
mcp_standalone/tools.py
CHANGED
|
@@ -58,7 +58,7 @@ PROJECT_PARAM_SCHEMA = {
|
|
|
58
58
|
"type": "string",
|
|
59
59
|
"description": (
|
|
60
60
|
"Optional project name or path to route this request to a specific "
|
|
61
|
-
"server. If not provided,
|
|
61
|
+
"server. If not provided, routes to the default server. "
|
|
62
62
|
"Use list_projects to see available projects."
|
|
63
63
|
),
|
|
64
64
|
},
|
|
@@ -331,8 +331,170 @@ VERIFICATION_TOOLS: list[Tool] = [
|
|
|
331
331
|
# Phase 3: SPICE Workflow Tools (to be implemented)
|
|
332
332
|
SPICE_TOOLS: list[Tool] = []
|
|
333
333
|
|
|
334
|
-
# Phase 4: Simulation & Advanced Tools
|
|
335
|
-
ADVANCED_TOOLS: list[Tool] = [
|
|
334
|
+
# Phase 4: Simulation & Advanced Tools
|
|
335
|
+
ADVANCED_TOOLS: list[Tool] = [
|
|
336
|
+
Tool(
|
|
337
|
+
name="simulate_component",
|
|
338
|
+
description=(
|
|
339
|
+
"Run a SAX circuit simulation on a photonic component by name. "
|
|
340
|
+
"This simulates the optical behavior of the component using its "
|
|
341
|
+
"SAX model. Returns S-parameters showing how light propagates "
|
|
342
|
+
"through the component's ports. Use this to analyze component "
|
|
343
|
+
"performance before fabrication."
|
|
344
|
+
),
|
|
345
|
+
inputSchema=_add_project_param(
|
|
346
|
+
{
|
|
347
|
+
"type": "object",
|
|
348
|
+
"properties": {
|
|
349
|
+
"name": {
|
|
350
|
+
"type": "string",
|
|
351
|
+
"description": (
|
|
352
|
+
"Name of the component/cell to simulate. The component "
|
|
353
|
+
"must have a SAX model defined."
|
|
354
|
+
),
|
|
355
|
+
},
|
|
356
|
+
},
|
|
357
|
+
"required": ["name"],
|
|
358
|
+
}
|
|
359
|
+
),
|
|
360
|
+
),
|
|
361
|
+
Tool(
|
|
362
|
+
name="get_port_center",
|
|
363
|
+
description=(
|
|
364
|
+
"Get the center coordinates (x, y) of a specific port in a component "
|
|
365
|
+
"instance. This is useful for positioning components, routing waveguides, "
|
|
366
|
+
"or analyzing layout geometry. Returns the physical coordinates in "
|
|
367
|
+
"microns."
|
|
368
|
+
),
|
|
369
|
+
inputSchema=_add_project_param(
|
|
370
|
+
{
|
|
371
|
+
"type": "object",
|
|
372
|
+
"properties": {
|
|
373
|
+
"netlist": {
|
|
374
|
+
"type": "string",
|
|
375
|
+
"description": (
|
|
376
|
+
"Name of the component/netlist containing the instance"
|
|
377
|
+
),
|
|
378
|
+
},
|
|
379
|
+
"instance": {
|
|
380
|
+
"type": "string",
|
|
381
|
+
"description": "Name of the instance within the netlist",
|
|
382
|
+
},
|
|
383
|
+
"port": {
|
|
384
|
+
"type": "string",
|
|
385
|
+
"description": "Name of the port to get coordinates for",
|
|
386
|
+
},
|
|
387
|
+
},
|
|
388
|
+
"required": ["netlist", "instance", "port"],
|
|
389
|
+
}
|
|
390
|
+
),
|
|
391
|
+
),
|
|
392
|
+
Tool(
|
|
393
|
+
name="generate_bbox",
|
|
394
|
+
description=(
|
|
395
|
+
"Generate a bounding box GDS file from an input GDS. This creates "
|
|
396
|
+
"a simplified version of the layout with only a bounding box on "
|
|
397
|
+
"specified layers. Useful for creating abstract views, floorplanning, "
|
|
398
|
+
"or hierarchical design. Can optionally preserve specific layers and "
|
|
399
|
+
"ports."
|
|
400
|
+
),
|
|
401
|
+
inputSchema=_add_project_param(
|
|
402
|
+
{
|
|
403
|
+
"type": "object",
|
|
404
|
+
"properties": {
|
|
405
|
+
"path": {
|
|
406
|
+
"type": "string",
|
|
407
|
+
"description": (
|
|
408
|
+
"Path to the input GDS file. Can be absolute or relative "
|
|
409
|
+
"to the project directory."
|
|
410
|
+
),
|
|
411
|
+
},
|
|
412
|
+
"outpath": {
|
|
413
|
+
"type": "string",
|
|
414
|
+
"description": (
|
|
415
|
+
"Output path for the bounding box GDS. If not specified, "
|
|
416
|
+
"uses the input filename with '-bbox' suffix."
|
|
417
|
+
),
|
|
418
|
+
"default": "",
|
|
419
|
+
},
|
|
420
|
+
"layers_to_keep": {
|
|
421
|
+
"type": "array",
|
|
422
|
+
"items": {"type": "string"},
|
|
423
|
+
"description": (
|
|
424
|
+
"List of layer names to preserve in the output. "
|
|
425
|
+
"Other layers will be replaced by the bounding box."
|
|
426
|
+
),
|
|
427
|
+
"default": [],
|
|
428
|
+
},
|
|
429
|
+
"bbox_layer": {
|
|
430
|
+
"type": "array",
|
|
431
|
+
"items": {"type": "integer"},
|
|
432
|
+
"description": (
|
|
433
|
+
"Layer (as [layer, datatype]) to use for the bounding box. "
|
|
434
|
+
"Default is [99, 0]."
|
|
435
|
+
),
|
|
436
|
+
"default": [99, 0],
|
|
437
|
+
},
|
|
438
|
+
"ignore_ports": {
|
|
439
|
+
"type": "boolean",
|
|
440
|
+
"description": (
|
|
441
|
+
"If true, do not include ports in the output. "
|
|
442
|
+
"Default is false."
|
|
443
|
+
),
|
|
444
|
+
"default": False,
|
|
445
|
+
},
|
|
446
|
+
},
|
|
447
|
+
"required": ["path"],
|
|
448
|
+
}
|
|
449
|
+
),
|
|
450
|
+
),
|
|
451
|
+
Tool(
|
|
452
|
+
name="freeze_cell",
|
|
453
|
+
description=(
|
|
454
|
+
"Freeze a parametric Python cell as a static schematic netlist. "
|
|
455
|
+
"This converts a gdsfactory component with specific parameters into "
|
|
456
|
+
"a fixed netlist representation in YAML format. Useful for creating "
|
|
457
|
+
"versioned snapshots of parametric designs or preparing components "
|
|
458
|
+
"for simulation workflows."
|
|
459
|
+
),
|
|
460
|
+
inputSchema=_add_project_param(
|
|
461
|
+
{
|
|
462
|
+
"type": "object",
|
|
463
|
+
"properties": {
|
|
464
|
+
"cell_name": {
|
|
465
|
+
"type": "string",
|
|
466
|
+
"description": "Name of the cell/component to freeze",
|
|
467
|
+
},
|
|
468
|
+
"kwargs": {
|
|
469
|
+
"type": "object",
|
|
470
|
+
"description": (
|
|
471
|
+
"Optional keyword arguments to pass to the component "
|
|
472
|
+
"factory. Use this to specify parameter values when "
|
|
473
|
+
"freezing the cell. Default is empty (use default params)."
|
|
474
|
+
),
|
|
475
|
+
"default": {},
|
|
476
|
+
},
|
|
477
|
+
},
|
|
478
|
+
"required": ["cell_name"],
|
|
479
|
+
}
|
|
480
|
+
),
|
|
481
|
+
),
|
|
482
|
+
Tool(
|
|
483
|
+
name="get_pdk_info",
|
|
484
|
+
description=(
|
|
485
|
+
"Get information about the current PDK (Process Design Kit) in use. "
|
|
486
|
+
"Returns metadata including PDK name, project name, project path, "
|
|
487
|
+
"server port, and version. Use this to verify which PDK is active "
|
|
488
|
+
"and get project configuration details."
|
|
489
|
+
),
|
|
490
|
+
inputSchema=_add_project_param(
|
|
491
|
+
{
|
|
492
|
+
"type": "object",
|
|
493
|
+
"properties": {},
|
|
494
|
+
}
|
|
495
|
+
),
|
|
496
|
+
),
|
|
497
|
+
]
|
|
336
498
|
|
|
337
499
|
# All tools (Phase 1 + Project tools)
|
|
338
500
|
TOOLS: list[Tool] = [
|
gfp_mcp-0.1.0.dist-info/METADATA
DELETED
|
@@ -1,360 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: gfp-mcp
|
|
3
|
-
Version: 0.1.0
|
|
4
|
-
Summary: Model Context Protocol (MCP) server for GDSFactory+ photonic IC design
|
|
5
|
-
Author: GDSFactory+ Team
|
|
6
|
-
License: MIT
|
|
7
|
-
Project-URL: Homepage, https://github.com/doplaydo/gfp-mcp
|
|
8
|
-
Project-URL: Repository, https://github.com/doplaydo/gfp-mcp
|
|
9
|
-
Project-URL: Documentation, https://github.com/doplaydo/gfp-mcp#readme
|
|
10
|
-
Project-URL: Changelog, https://github.com/doplaydo/gfp-mcp/blob/main/CHANGELOG.md
|
|
11
|
-
Project-URL: Issue Tracker, https://github.com/doplaydo/gfp-mcp/issues
|
|
12
|
-
Keywords: mcp,gdsfactory,photonics,ic-design,eda,model-context-protocol,photonic-ic,gds
|
|
13
|
-
Classifier: Development Status :: 4 - Beta
|
|
14
|
-
Classifier: Intended Audience :: Developers
|
|
15
|
-
Classifier: Intended Audience :: Science/Research
|
|
16
|
-
Classifier: Topic :: Scientific/Engineering :: Electronic Design Automation (EDA)
|
|
17
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
19
|
-
Classifier: Programming Language :: Python :: 3
|
|
20
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
-
Classifier: Programming Language :: Python :: 3 :: Only
|
|
24
|
-
Requires-Python: >=3.10
|
|
25
|
-
Description-Content-Type: text/markdown
|
|
26
|
-
Requires-Dist: mcp>=1.7.1
|
|
27
|
-
Requires-Dist: httpx>=0.25.0
|
|
28
|
-
Requires-Dist: typing-extensions>=4.0.0; python_version < "3.11"
|
|
29
|
-
Requires-Dist: psutil>=5.9.0
|
|
30
|
-
Provides-Extra: dev
|
|
31
|
-
Requires-Dist: pytest>=7.0.0; extra == "dev"
|
|
32
|
-
Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
|
|
33
|
-
Requires-Dist: pytest-asyncio>=0.21.0; extra == "dev"
|
|
34
|
-
Requires-Dist: ruff>=0.1.0; extra == "dev"
|
|
35
|
-
|
|
36
|
-
# GDSFactory+ MCP Server
|
|
37
|
-
|
|
38
|
-
[](https://pypi.org/project/gfp-mcp/)
|
|
39
|
-
[](https://pypi.org/project/gfp-mcp/)
|
|
40
|
-
[](https://github.com/doplaydo/gfp-mcp/actions)
|
|
41
|
-
[](https://opensource.org/licenses/MIT)
|
|
42
|
-
|
|
43
|
-
Model Context Protocol (MCP) server for GDSFactory+ that exposes photonic IC design operations as tools for AI assistants like Claude Code and Claude Desktop.
|
|
44
|
-
|
|
45
|
-
## Overview
|
|
46
|
-
|
|
47
|
-
This project implements a standalone MCP server that bridges AI assistants with GDSFactory+ photonic IC design capabilities. The server acts as a lightweight proxy that exposes GDSFactory+ operations through standardized MCP tools while maintaining zero modifications to the existing FastAPI backend.
|
|
48
|
-
|
|
49
|
-
## Features
|
|
50
|
-
|
|
51
|
-
### Phase 1: Core Building Tools (Complete)
|
|
52
|
-
|
|
53
|
-
- **build_cell** - Build a single GDS cell by name
|
|
54
|
-
- **build_cells** - Build multiple GDS cells in batch
|
|
55
|
-
- **list_cells** - List all available photonic components
|
|
56
|
-
- **get_cell_info** - Get detailed component metadata
|
|
57
|
-
- **download_gds** - Download built GDS files
|
|
58
|
-
- **list_projects** - List all running GDSFactory+ server instances
|
|
59
|
-
- **get_project_info** - Get detailed information about a specific project
|
|
60
|
-
|
|
61
|
-
### Multi-Project Support
|
|
62
|
-
|
|
63
|
-
The MCP server integrates with the GDSFactory+ server registry to support working with multiple projects simultaneously. The registry is stored at `~/.gdsfactory/server-registry.json` and is automatically managed by GDSFactory+ servers.
|
|
64
|
-
|
|
65
|
-
#### How It Works
|
|
66
|
-
|
|
67
|
-
1. When you start a GDSFactory+ server with `gfp serve`, it registers itself in the shared registry
|
|
68
|
-
2. The MCP server reads from this registry to discover available projects
|
|
69
|
-
3. Tools accept an optional `project` parameter to route requests to specific servers
|
|
70
|
-
4. The MCP server automatically resolves project names to the correct port
|
|
71
|
-
|
|
72
|
-
#### Example Usage
|
|
73
|
-
|
|
74
|
-
```
|
|
75
|
-
User: "List all running GDSFactory+ projects"
|
|
76
|
-
Claude: [Uses list_projects tool to show all registered servers]
|
|
77
|
-
|
|
78
|
-
User: "Build the mzi component in the my_photonics_project"
|
|
79
|
-
Claude: [Uses build_cell tool with project="my_photonics_project"]
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
**Note**: The MCP has read-only access to the registry. Only GDSFactory+ servers can register/unregister themselves.
|
|
83
|
-
|
|
84
|
-
### Architecture
|
|
85
|
-
|
|
86
|
-
```
|
|
87
|
-
AI Assistant (Claude) <-> MCP Server (STDIO) <-> HTTP Client <-> FastAPI Server
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
**Key Benefits:**
|
|
91
|
-
- Universal MCP client compatibility via STDIO transport
|
|
92
|
-
- Zero modifications to existing FastAPI server
|
|
93
|
-
- Clean separation of concerns
|
|
94
|
-
- No database conflicts (only FastAPI touches SQLite)
|
|
95
|
-
- Scalable architecture ready for 20+ tools
|
|
96
|
-
|
|
97
|
-
## Installation
|
|
98
|
-
|
|
99
|
-
### From PyPI (Recommended)
|
|
100
|
-
|
|
101
|
-
Install the package from PyPI:
|
|
102
|
-
|
|
103
|
-
```bash
|
|
104
|
-
pip install gfp-mcp
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
Or with uv:
|
|
108
|
-
|
|
109
|
-
```bash
|
|
110
|
-
uv pip install gfp-mcp
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
### From Source (Development)
|
|
114
|
-
|
|
115
|
-
For development or if you want the latest unreleased changes:
|
|
116
|
-
|
|
117
|
-
```bash
|
|
118
|
-
git clone https://github.com/doplaydo/gfp-mcp.git
|
|
119
|
-
cd gfp-mcp
|
|
120
|
-
pip install -e ".[dev]"
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
### Prerequisites
|
|
124
|
-
|
|
125
|
-
- Python 3.10 or higher
|
|
126
|
-
- GDSFactory+ with FastAPI server running
|
|
127
|
-
|
|
128
|
-
### Verify Installation
|
|
129
|
-
|
|
130
|
-
```bash
|
|
131
|
-
gfp-mcp-serve --help
|
|
132
|
-
```
|
|
133
|
-
|
|
134
|
-
## Quick Start
|
|
135
|
-
|
|
136
|
-
### 1. Start the FastAPI Server
|
|
137
|
-
|
|
138
|
-
In one terminal:
|
|
139
|
-
|
|
140
|
-
```bash
|
|
141
|
-
gfp serve --port 8787
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
### 2. Configure Your AI Assistant
|
|
145
|
-
|
|
146
|
-
#### Claude Code
|
|
147
|
-
|
|
148
|
-
Add to `.claude/settings.json`:
|
|
149
|
-
|
|
150
|
-
```json
|
|
151
|
-
{
|
|
152
|
-
"mcpServers": {
|
|
153
|
-
"gdsfactoryplus": {
|
|
154
|
-
"command": "gfp-mcp-serve",
|
|
155
|
-
"args": [],
|
|
156
|
-
"env": {
|
|
157
|
-
"GFP_API_URL": "http://localhost:8787"
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
```
|
|
163
|
-
|
|
164
|
-
Or use the command line:
|
|
165
|
-
|
|
166
|
-
```bash
|
|
167
|
-
claude mcp add gdsfactoryplus -- gfp-mcp-serve
|
|
168
|
-
```
|
|
169
|
-
|
|
170
|
-
#### Claude Desktop
|
|
171
|
-
|
|
172
|
-
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS):
|
|
173
|
-
|
|
174
|
-
```json
|
|
175
|
-
{
|
|
176
|
-
"mcpServers": {
|
|
177
|
-
"gdsfactoryplus": {
|
|
178
|
-
"command": "gfp-mcp-serve",
|
|
179
|
-
"args": []
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
For Windows: `%APPDATA%\Claude\claude_desktop_config.json`
|
|
186
|
-
|
|
187
|
-
For Linux: `~/.config/Claude/claude_desktop_config.json`
|
|
188
|
-
|
|
189
|
-
### 3. Use the Tools
|
|
190
|
-
|
|
191
|
-
Ask your AI assistant to:
|
|
192
|
-
|
|
193
|
-
- "List all available photonic components"
|
|
194
|
-
- "Build the mzi component"
|
|
195
|
-
- "Show me details about the coupler component"
|
|
196
|
-
- "Build multiple components: mzi, coupler, and bend_euler"
|
|
197
|
-
|
|
198
|
-
## Environment Variables
|
|
199
|
-
|
|
200
|
-
Configure the MCP server using environment variables:
|
|
201
|
-
|
|
202
|
-
```bash
|
|
203
|
-
# FastAPI server URL (default: http://localhost:8787)
|
|
204
|
-
export GFP_API_URL="http://localhost:8787"
|
|
205
|
-
|
|
206
|
-
# Request timeout in seconds (default: 300)
|
|
207
|
-
export GFP_MCP_TIMEOUT=300
|
|
208
|
-
|
|
209
|
-
# Enable debug logging (default: false)
|
|
210
|
-
export GFP_MCP_DEBUG=true
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
## Project Structure
|
|
214
|
-
|
|
215
|
-
```
|
|
216
|
-
gfp-mcp/
|
|
217
|
-
├── mcp_standalone/ # MCP server implementation
|
|
218
|
-
│ ├── __init__.py # Package exports
|
|
219
|
-
│ ├── config.py # Configuration management
|
|
220
|
-
│ ├── client.py # HTTP client for FastAPI
|
|
221
|
-
│ ├── registry.py # Server registry (multi-project support)
|
|
222
|
-
│ ├── tools.py # MCP tool definitions
|
|
223
|
-
│ ├── mappings.py # Tool → Endpoint mappings
|
|
224
|
-
│ ├── server.py # MCP server core
|
|
225
|
-
│ └── README.md # Detailed documentation
|
|
226
|
-
├── tests/ # Test suite
|
|
227
|
-
│ ├── test_mcp_tools.py
|
|
228
|
-
│ ├── test_mcp_mappings.py
|
|
229
|
-
│ ├── test_mcp_integration.py
|
|
230
|
-
│ └── test_registry.py
|
|
231
|
-
├── mcp_serve.py # CLI entry point
|
|
232
|
-
├── MCP_QUICKSTART.md # Quick start guide
|
|
233
|
-
├── MCP_IMPLEMENTATION_STATUS.md # Implementation details
|
|
234
|
-
└── README.md # This file
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
## Testing
|
|
238
|
-
|
|
239
|
-
Run the test suite:
|
|
240
|
-
|
|
241
|
-
```bash
|
|
242
|
-
# Run all MCP tests
|
|
243
|
-
pytest tests/test_mcp_*.py -v
|
|
244
|
-
|
|
245
|
-
# Run with coverage
|
|
246
|
-
pytest tests/test_mcp_*.py --cov=mcp_standalone --cov-report=term-missing
|
|
247
|
-
|
|
248
|
-
# Run specific test file
|
|
249
|
-
pytest tests/test_mcp_tools.py -v
|
|
250
|
-
```
|
|
251
|
-
|
|
252
|
-
All tests are passing (46/46 tests):
|
|
253
|
-
- Tool definitions: 15 tests
|
|
254
|
-
- Endpoint mappings: 13 tests
|
|
255
|
-
- Integration & client: 9 tests
|
|
256
|
-
- Registry integration: 9 tests
|
|
257
|
-
|
|
258
|
-
## Example Workflows
|
|
259
|
-
|
|
260
|
-
### Build and Verify a Component
|
|
261
|
-
|
|
262
|
-
```
|
|
263
|
-
User: "List all available photonic components"
|
|
264
|
-
Claude: [Uses list_cells tool]
|
|
265
|
-
|
|
266
|
-
User: "Build the mzi component"
|
|
267
|
-
Claude: [Uses build_cell tool with name="mzi"]
|
|
268
|
-
|
|
269
|
-
User: "Show me the details of the mzi component"
|
|
270
|
-
Claude: [Uses get_cell_info tool with name="mzi"]
|
|
271
|
-
```
|
|
272
|
-
|
|
273
|
-
### Batch Build Multiple Components
|
|
274
|
-
|
|
275
|
-
```
|
|
276
|
-
User: "Build the following components: mzi, coupler, and bend_euler"
|
|
277
|
-
Claude: [Uses build_cells tool with names=["mzi", "coupler", "bend_euler"]]
|
|
278
|
-
```
|
|
279
|
-
|
|
280
|
-
## Troubleshooting
|
|
281
|
-
|
|
282
|
-
### Error: "Connection refused to localhost:8787"
|
|
283
|
-
|
|
284
|
-
**Cause**: FastAPI server is not running
|
|
285
|
-
|
|
286
|
-
**Solution**: Start the FastAPI server:
|
|
287
|
-
|
|
288
|
-
```bash
|
|
289
|
-
gfp serve --port 8787
|
|
290
|
-
```
|
|
291
|
-
|
|
292
|
-
### Error: "MCP server not responding"
|
|
293
|
-
|
|
294
|
-
**Cause**: STDIO transport issue or MCP client misconfiguration
|
|
295
|
-
|
|
296
|
-
**Solution**:
|
|
297
|
-
1. Check Claude Code/Desktop logs with `claude --debug`
|
|
298
|
-
2. Restart the MCP server
|
|
299
|
-
3. Verify the configuration in settings.json
|
|
300
|
-
|
|
301
|
-
### Error: "Tool execution timeout"
|
|
302
|
-
|
|
303
|
-
**Cause**: Long-running operation exceeded timeout
|
|
304
|
-
|
|
305
|
-
**Solution**: Increase the timeout:
|
|
306
|
-
|
|
307
|
-
```bash
|
|
308
|
-
export GFP_MCP_TIMEOUT=600 # 10 minutes
|
|
309
|
-
gfp mcp-serve
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
## Roadmap
|
|
313
|
-
|
|
314
|
-
### Future Phases
|
|
315
|
-
|
|
316
|
-
- **Phase 2**: Verification tools (DRC, LVS)
|
|
317
|
-
- **Phase 3**: SPICE workflow tools
|
|
318
|
-
- **Phase 4**: Simulation & advanced tools
|
|
319
|
-
- **Phase 5**: Comprehensive testing & documentation
|
|
320
|
-
|
|
321
|
-
## Documentation
|
|
322
|
-
|
|
323
|
-
- [Quick Start Guide](MCP_QUICKSTART.md) - Step-by-step setup instructions
|
|
324
|
-
- [Implementation Status](MCP_IMPLEMENTATION_STATUS.md) - Detailed implementation notes
|
|
325
|
-
- [MCP Standalone README](mcp_standalone/README.md) - Architecture details
|
|
326
|
-
- [Contributing Guide](CONTRIBUTING.md) - Development and release guidelines
|
|
327
|
-
- [Changelog](CHANGELOG.md) - Version history and release notes
|
|
328
|
-
|
|
329
|
-
## Contributing
|
|
330
|
-
|
|
331
|
-
Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for detailed guidelines on:
|
|
332
|
-
|
|
333
|
-
- Development setup
|
|
334
|
-
- Running tests and code quality checks
|
|
335
|
-
- Making changes and submitting PRs
|
|
336
|
-
- Release process (for maintainers)
|
|
337
|
-
|
|
338
|
-
Quick checklist:
|
|
339
|
-
|
|
340
|
-
1. All tests pass: `pytest tests/test_mcp_*.py -v`
|
|
341
|
-
2. Code quality: `ruff check . && ruff format --check .`
|
|
342
|
-
3. Documentation is updated
|
|
343
|
-
4. Changes are backward compatible
|
|
344
|
-
|
|
345
|
-
## License
|
|
346
|
-
|
|
347
|
-
See the main GDSFactory+ project for license information.
|
|
348
|
-
|
|
349
|
-
## Support
|
|
350
|
-
|
|
351
|
-
For issues or questions:
|
|
352
|
-
|
|
353
|
-
1. Check the [Quick Start Guide](MCP_QUICKSTART.md) troubleshooting section
|
|
354
|
-
2. Review the [Implementation Status](MCP_IMPLEMENTATION_STATUS.md) document
|
|
355
|
-
3. Enable debug mode with `GFP_MCP_DEBUG=true` and check server logs
|
|
356
|
-
4. Open an issue on GitHub
|
|
357
|
-
|
|
358
|
-
## Acknowledgments
|
|
359
|
-
|
|
360
|
-
Built on the Model Context Protocol by Anthropic, enabling seamless AI assistant integration with photonic IC design workflows.
|
gfp_mcp-0.1.0.dist-info/RECORD
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
mcp_standalone/__init__.py,sha256=7PhYozHyiRK_oFui0RkF5GJWxA2OZoWVcU_-ESfHIR4,953
|
|
2
|
-
mcp_standalone/client.py,sha256=gUs9m2M27OP-GYmJ9fkojyxv212ETVJFqp0v2uN8Q2c,8205
|
|
3
|
-
mcp_standalone/config.py,sha256=zr2LnI_wNEcMWrnB_WLscR-skkXjE33ZPBtK08XjaX0,1386
|
|
4
|
-
mcp_standalone/mappings.py,sha256=jXEHwSrSYNDuVeMRM2dsSUsr38CzrHBLoe6exkJhqvc,7695
|
|
5
|
-
mcp_standalone/registry.py,sha256=1E61UalVot8HUS3cALjM7ejYB0qR6tI5QbQSZZeQe7Y,6401
|
|
6
|
-
mcp_standalone/server.py,sha256=Celd9j0KY1Fl_Qw09b9Px03vGhtaTUac2ozlYdGJ23A,7100
|
|
7
|
-
mcp_standalone/tools.py,sha256=__j9N396-cJj9CKi6EAdP5_J-xESrbRZG35KNzdszXM,12349
|
|
8
|
-
gfp_mcp-0.1.0.dist-info/METADATA,sha256=dVk1r3JfmlEY3RcqVSDqMLYm2fPAqwYjM4cTUD6sVQE,10442
|
|
9
|
-
gfp_mcp-0.1.0.dist-info/WHEEL,sha256=qELbo2s1Yzl39ZmrAibXA2jjPLUYfnVhUNTlyF1rq0Y,92
|
|
10
|
-
gfp_mcp-0.1.0.dist-info/entry_points.txt,sha256=mgyus9dsB_8mjgnztuHNPqzPi-7HcPg1iYzfM5NMIjk,61
|
|
11
|
-
gfp_mcp-0.1.0.dist-info/top_level.txt,sha256=g2hRJHoDDPNtrNdXR70T7FR9Ev6DTRJiGW7ZvlvnXMc,15
|
|
12
|
-
gfp_mcp-0.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|