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.
Files changed (24) hide show
  1. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/PKG-INFO +25 -8
  2. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/README.md +22 -7
  3. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/gfp_mcp.egg-info/PKG-INFO +25 -8
  4. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/gfp_mcp.egg-info/requires.txt +2 -0
  5. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/mcp_standalone/__init__.py +1 -1
  6. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/mcp_standalone/client.py +57 -19
  7. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/mcp_standalone/config.py +3 -9
  8. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/mcp_standalone/mappings.py +246 -67
  9. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/mcp_standalone/registry.py +0 -4
  10. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/mcp_standalone/resources.py +0 -3
  11. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/mcp_standalone/server.py +9 -21
  12. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/mcp_standalone/tools.py +6 -70
  13. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/pyproject.toml +3 -1
  14. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/tests/test_mcp_integration.py +71 -27
  15. gfp_mcp-0.2.4/tests/test_mcp_mappings.py +571 -0
  16. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/tests/test_mcp_tools.py +3 -34
  17. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/tests/test_registry.py +0 -12
  18. gfp_mcp-0.2.1/tests/test_mcp_mappings.py +0 -320
  19. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/LICENSE +0 -0
  20. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/gfp_mcp.egg-info/SOURCES.txt +0 -0
  21. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/gfp_mcp.egg-info/dependency_links.txt +0 -0
  22. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/gfp_mcp.egg-info/entry_points.txt +0 -0
  23. {gfp_mcp-0.2.1 → gfp_mcp-0.2.4}/gfp_mcp.egg-info/top_level.txt +0 -0
  24. {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.1
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
  [![PyPI version](https://img.shields.io/pypi/v/gfp-mcp.svg)](https://pypi.org/project/gfp-mcp/)
41
43
  [![Python versions](https://img.shields.io/pypi/pyversions/gfp-mcp.svg)](https://pypi.org/project/gfp-mcp/)
42
- [![Tests](https://github.com/doplaydo/gfp-mcp/workflows/Tests/badge.svg)](https://github.com/doplaydo/gfp-mcp/actions)
44
+ [![Tests](https://github.com/doplaydo/gfp-mcp/actions/workflows/test.yml/badge.svg)](https://github.com/doplaydo/gfp-mcp/actions)
43
45
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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
- pip install gfp-mcp
67
+ uv tool install gfp-mcp
62
68
  ```
63
69
 
64
- Or with uv:
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
- - **build_cell** - Build a single GDS cell by name
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
  [![PyPI version](https://img.shields.io/pypi/v/gfp-mcp.svg)](https://pypi.org/project/gfp-mcp/)
4
4
  [![Python versions](https://img.shields.io/pypi/pyversions/gfp-mcp.svg)](https://pypi.org/project/gfp-mcp/)
5
- [![Tests](https://github.com/doplaydo/gfp-mcp/workflows/Tests/badge.svg)](https://github.com/doplaydo/gfp-mcp/actions)
5
+ [![Tests](https://github.com/doplaydo/gfp-mcp/actions/workflows/test.yml/badge.svg)](https://github.com/doplaydo/gfp-mcp/actions)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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
- pip install gfp-mcp
28
+ uv tool install gfp-mcp
25
29
  ```
26
30
 
27
- Or with uv:
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
- - **build_cell** - Build a single GDS cell by name
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.1
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
  [![PyPI version](https://img.shields.io/pypi/v/gfp-mcp.svg)](https://pypi.org/project/gfp-mcp/)
41
43
  [![Python versions](https://img.shields.io/pypi/pyversions/gfp-mcp.svg)](https://pypi.org/project/gfp-mcp/)
42
- [![Tests](https://github.com/doplaydo/gfp-mcp/workflows/Tests/badge.svg)](https://github.com/doplaydo/gfp-mcp/actions)
44
+ [![Tests](https://github.com/doplaydo/gfp-mcp/actions/workflows/test.yml/badge.svg)](https://github.com/doplaydo/gfp-mcp/actions)
43
45
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](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
- pip install gfp-mcp
67
+ uv tool install gfp-mcp
62
68
  ```
63
69
 
64
- Or with uv:
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
- - **build_cell** - Build a single GDS cell by name
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
 
@@ -10,3 +10,5 @@ pytest>=7.0.0
10
10
  pytest-cov>=4.0.0
11
11
  pytest-asyncio>=0.21.0
12
12
  ruff>=0.1.0
13
+ bump-my-version>=0.26.0
14
+ build>=1.4.0
@@ -39,4 +39,4 @@ __all__ = [
39
39
  "get_resource_content",
40
40
  ]
41
41
 
42
- __version__ = "0.2.1"
42
+ __version__ = "0.2.4"
@@ -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=self.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("HTTP client started with base URL: %s", self.base_url)
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 project not found in registry
102
+ ValueError: If base URL cannot be resolved
83
103
  """
84
- # If no project specified, use default base_url
85
- if project is None:
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
- # Look up project in registry
89
- server_info = self._registry.get_server_by_project(project)
90
- if server_info is None:
91
- msg = (
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
- raise ValueError(msg)
134
+ return default_url
96
135
 
97
- return f"http://localhost:{server_info.port}"
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
- # 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.
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