fid-mcp 0.1.0__py3-none-any.whl → 0.1.2__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.

Potentially problematic release.


This version of fid-mcp might be problematic. Click here for more details.

fid_mcp/server.py CHANGED
@@ -204,14 +204,38 @@ class DynamicToolServer:
204
204
  }
205
205
  self.tools: Dict[str, Dict[str, Any]] = {}
206
206
 
207
+ # Fid knowledge base configuration
208
+ self.fid_config = None
209
+ self.fid_pat = os.environ.get("FID_PAT")
210
+
207
211
  # Setup handlers
208
212
  self.setup_handlers()
209
213
 
210
214
  def setup_handlers(self):
211
215
  @self.server.list_tools()
212
216
  async def handle_list_tools() -> list[types.Tool]:
213
- """Return all dynamically loaded tools"""
217
+ """Return all dynamically loaded tools plus Fid search"""
214
218
  tools = []
219
+
220
+ # Always add Fid search tool (will show error if not configured when called)
221
+ tools.append(
222
+ types.Tool(
223
+ name="search",
224
+ description="Search the user's Fid knowledge base, which typically contains datasheets, integration manuals, API references, and other technical documentation, particularly for hardware components. ALWAYS try searching Fid first if the user asks about a hardware component, datasheet, manual, or API spec.",
225
+ inputSchema={
226
+ "type": "object",
227
+ "properties": {
228
+ "query": {
229
+ "type": "string",
230
+ "description": "The search query string",
231
+ }
232
+ },
233
+ "required": ["query"],
234
+ },
235
+ )
236
+ )
237
+
238
+ # Add dynamically loaded tools
215
239
  for tool_name, tool_def in self.tools.items():
216
240
  # Build input schema from parameters
217
241
  properties = {}
@@ -249,7 +273,33 @@ class DynamicToolServer:
249
273
  async def handle_call_tool(
250
274
  name: str, arguments: Dict[str, Any] | None
251
275
  ) -> list[types.TextContent | types.ImageContent | types.EmbeddedResource]:
252
- """Execute a dynamically loaded tool"""
276
+ """Execute a dynamically loaded tool or Fid search"""
277
+
278
+ # Handle Fid search tool
279
+ if name == "search":
280
+ if not self.fid_pat:
281
+ error_msg = "Personal Access Token (PAT) missing. Please install the Fid MCP server according to these instructions: https://docs.fidlabs.ai/en/latest/connecting-agents.html"
282
+ return [types.TextContent(type="text", text=f"Error: {error_msg}")]
283
+
284
+ if not self.fid_config:
285
+ error_msg = "No Fid toolkit found in current directory. Download an existing toolkit from your Fid project, or create a new one with these instructions: https://docs.fidlabs.ai/en/latest/toolkits.html"
286
+ return [types.TextContent(type="text", text=f"Error: {error_msg}")]
287
+
288
+ if not arguments or "query" not in arguments:
289
+ raise ValueError("Query parameter is required")
290
+
291
+ try:
292
+ results = await self._search_fid_knowledge(arguments["query"])
293
+ return [
294
+ types.TextContent(
295
+ type="text", text=json.dumps(results, indent=2)
296
+ )
297
+ ]
298
+ except Exception as e:
299
+ error_msg = f"Search failed: {str(e)}"
300
+ return [types.TextContent(type="text", text=f"Error: {error_msg}")]
301
+
302
+ # Handle dynamic tools
253
303
  if name not in self.tools:
254
304
  raise ValueError(f"Unknown tool: {name}")
255
305
 
@@ -324,8 +374,57 @@ class DynamicToolServer:
324
374
  output = self._build_output(tool_def.get("output"), exec_context)
325
375
  return [types.TextContent(type="text", text=json.dumps(output, indent=2))]
326
376
 
377
+ async def _search_fid_knowledge(self, query: str) -> Dict[str, Any]:
378
+ """Search the Fid knowledge base"""
379
+ import aiohttp
380
+ import time
381
+
382
+ start_time = time.time()
383
+ default_k = 6
384
+
385
+ # Use the correct projects/{projectId}/search endpoint
386
+ url = f"{self.fid_config['apiBaseUrl']}/projects/{self.fid_config['projectId']}/search"
387
+ headers = {
388
+ "X-API-Key": self.fid_pat,
389
+ "X-Client-Source": "mcp_client",
390
+ }
391
+
392
+ payload = {
393
+ "query": query,
394
+ "k": default_k,
395
+ "userId": "", # Required field, can be empty
396
+ "search_method": "multi_stage",
397
+ "multi_stage_methods": ["full_text", "vector"],
398
+ }
399
+
400
+ async with aiohttp.ClientSession() as session:
401
+ async with session.post(url, json=payload, headers=headers) as response:
402
+ if response.status != 200:
403
+ error_text = await response.text()
404
+ raise ValueError(
405
+ f"API request failed with status {response.status}: {error_text}"
406
+ )
407
+
408
+ data = await response.json()
409
+
410
+ # Log search time
411
+ duration = time.time() - start_time
412
+
413
+ if not data.get("results"):
414
+ return {
415
+ "results": [],
416
+ "message": "No search results found",
417
+ "duration": duration,
418
+ }
419
+
420
+ return {
421
+ "results": data.get("results", []),
422
+ "totalCount": data.get("totalCount"),
423
+ "duration": duration,
424
+ }
425
+
327
426
  def load_toolset(self, filepath: Path):
328
- """Load and register tools from a .fidtools file"""
427
+ """Load and register tools from a .fidtools or fidtools.json file"""
329
428
  with open(filepath, "r") as f:
330
429
  toolset = json.load(f)
331
430
 
@@ -335,6 +434,13 @@ class DynamicToolServer:
335
434
  except ValueError as e:
336
435
  raise ValueError(f"Failed to validate toolset '{filepath}': {e}")
337
436
 
437
+ # Extract Fid configuration if present
438
+ if "projectId" in toolset and "apiBaseUrl" in toolset:
439
+ self.fid_config = {
440
+ "projectId": toolset["projectId"],
441
+ "apiBaseUrl": toolset["apiBaseUrl"],
442
+ }
443
+
338
444
  # Register each tool
339
445
  for tool_def in toolset["tools"]:
340
446
  self.tools[tool_def["name"]] = tool_def
@@ -425,17 +531,29 @@ class DynamicToolServer:
425
531
  f.write(f"os.getcwd(): {os.getcwd()}\n")
426
532
  f.write(f"Using working_dir: {working_dir}\n")
427
533
 
428
- # Look for .fidtools file in actual working directory
429
- fidtools_file = working_dir / ".fidtools"
534
+ # Look for .fidtools or fidtools.json file in actual working directory
535
+ config_files = [working_dir / ".fidtools", working_dir / "fidtools.json"]
536
+
537
+ config_file = None
538
+ for file_path in config_files:
539
+ if file_path.exists() and file_path.is_file():
540
+ config_file = file_path
541
+ break
542
+
430
543
  with open(debug_log, "a") as f:
431
- f.write(f"Looking for .fidtools at: {fidtools_file}\n")
432
- f.write(f"File exists: {fidtools_file.exists()}\n")
544
+ f.write(
545
+ f"Looking for config files: {', '.join(str(f) for f in config_files)}\n"
546
+ )
547
+ if config_file:
548
+ f.write(f"Found config file: {config_file}\n")
549
+ else:
550
+ f.write("No config file found\n")
433
551
 
434
- if fidtools_file.exists() and fidtools_file.is_file():
552
+ if config_file:
435
553
  try:
436
- self.load_toolset(fidtools_file)
554
+ self.load_toolset(config_file)
437
555
  with open(debug_log, "a") as f:
438
- f.write(f"Successfully loaded toolset from {fidtools_file}\n")
556
+ f.write(f"Successfully loaded toolset from {config_file}\n")
439
557
  f.write(f"Loaded {len(self.tools)} tools\n")
440
558
  except Exception as e:
441
559
  with open(debug_log, "a") as f:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fid-mcp
3
- Version: 0.1.0
3
+ Version: 0.1.2
4
4
  Summary: MCP Server for serving configurable Fid toolkits
5
5
  Project-URL: Homepage, https://fidlabs.ai
6
6
  Author-email: Fid Labs <contact@fidlabs.ai>
@@ -10,6 +10,7 @@ Keywords: mcp,model-context-protocol,server,tools
10
10
  Classifier: Operating System :: OS Independent
11
11
  Classifier: Programming Language :: Python :: 3
12
12
  Requires-Python: >=3.8
13
+ Requires-Dist: aiohttp
13
14
  Requires-Dist: mcp
14
15
  Requires-Dist: pexpect
15
16
  Requires-Dist: pydantic
@@ -17,12 +18,12 @@ Description-Content-Type: text/markdown
17
18
 
18
19
  # Fid MCP Server
19
20
 
20
- MCP server that dynamically serves tools according to `.fidtools` configs present in the working directory. `.fidtools` are generated by the Fid web application and intended to allow developers to quickly onboard coding agents to their unique development environments.
21
+ MCP server that dynamically serves tools according to `fidtools.json` or `.fidtools` configs present in the working directory. Toolkits are generated by the Fid web application and intended to allow developers to quickly onboard coding agents to their unique development environments.
21
22
 
22
23
  To install:
23
24
  ```bash
24
- claude mcp add fid --scope user --env FID_PAT=YOUR_FID_PAT -- uvx fid-mcp
25
+ claude mcp add Fid --scope user --env FID_PAT=YOUR_FID_PAT -- uvx fid-mcp
25
26
  ```
26
27
  Note: retrieve your PAT from the user menu in your Fid project, or just use the pre-constructed install command provided by the "Connect to your Agent" button.
27
28
 
28
- See [fidlabs.ai](https://fidlabs.ai) for more information or reach out to us at [contact@fidlabs.ai](mailto:contact@fidlabs.ai).
29
+ See [docs.fidlabs.ai](https://docs.fidlabs.ai) for more information or reach out to us at [contact@fidlabs.ai](mailto:contact@fidlabs.ai).
@@ -0,0 +1,9 @@
1
+ fid_mcp/__init__.py,sha256=cv_5UWE6kUBeTfAY6JZq9o47hEfzaLhcoKW0rw8GKq8,17
2
+ fid_mcp/config.py,sha256=YEH9BD4UWU9Hp3ifc3PGg4nk3FvFadfRt52-_fhCaqk,7365
3
+ fid_mcp/server.py,sha256=LctNUIjsBzvza6-NGNOxcByHjyFG83ojfxUdoELX8ak,22501
4
+ fid_mcp/shell.py,sha256=mLbGIVuk4LGCT37tS8deDOyTSY2zPG57WE9KBGsKSHg,26459
5
+ fid_mcp-0.1.2.dist-info/METADATA,sha256=VCqD3CDKW5tUkwe-HCtQGLFKFn_trrjxL0m4hBiArrM,1259
6
+ fid_mcp-0.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
+ fid_mcp-0.1.2.dist-info/entry_points.txt,sha256=Xdh2RDDC7r5rIXe1kM3smsA1rgNxd1tafL_JuuTJf2o,48
8
+ fid_mcp-0.1.2.dist-info/licenses/LICENSE,sha256=5SkiXC7s2RbMDCdmq4N6MCWNKw151sFmkGbWS9BLSJE,177
9
+ fid_mcp-0.1.2.dist-info/RECORD,,
@@ -1,9 +0,0 @@
1
- fid_mcp/__init__.py,sha256=cv_5UWE6kUBeTfAY6JZq9o47hEfzaLhcoKW0rw8GKq8,17
2
- fid_mcp/config.py,sha256=YEH9BD4UWU9Hp3ifc3PGg4nk3FvFadfRt52-_fhCaqk,7365
3
- fid_mcp/server.py,sha256=c3RYpLvUKJcMC4W26YfQ2lBWQwWRNOODESUsn-UDH6s,17633
4
- fid_mcp/shell.py,sha256=mLbGIVuk4LGCT37tS8deDOyTSY2zPG57WE9KBGsKSHg,26459
5
- fid_mcp-0.1.0.dist-info/METADATA,sha256=QaenjwxRoRNpK46yGi-S9UdSex05q-Ma9ftD0m52DEs,1210
6
- fid_mcp-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
- fid_mcp-0.1.0.dist-info/entry_points.txt,sha256=Xdh2RDDC7r5rIXe1kM3smsA1rgNxd1tafL_JuuTJf2o,48
8
- fid_mcp-0.1.0.dist-info/licenses/LICENSE,sha256=5SkiXC7s2RbMDCdmq4N6MCWNKw151sFmkGbWS9BLSJE,177
9
- fid_mcp-0.1.0.dist-info/RECORD,,