66 行
2.6 KiB
Python
66 行
2.6 KiB
Python
"""Check the installed server over stdio without modifying design files."""
|
|
|
|
import asyncio
|
|
import json
|
|
import os
|
|
from pathlib import Path
|
|
|
|
import pcbnew
|
|
from mcp import ClientSession, StdioServerParameters
|
|
from mcp.client.stdio import stdio_client
|
|
|
|
ROOT = Path(__file__).resolve().parents[1]
|
|
PYTHON = Path('D:/kicad-mcp/.venv/Scripts/python.exe')
|
|
|
|
|
|
async def verify():
|
|
env = dict(os.environ)
|
|
env.update(
|
|
KICAD_CLI='D:/KiCad/bin/kicad-cli.exe',
|
|
KICAD_PROJECT_PATHS=str(ROOT),
|
|
PYTHONIOENCODING='utf-8',
|
|
PYTHONDONTWRITEBYTECODE='1',
|
|
)
|
|
parameters = StdioServerParameters(
|
|
command=str(PYTHON), args=['-B', '-m', 'kicad_mcp_server'],
|
|
cwd=str(ROOT), env=env,
|
|
)
|
|
async with stdio_client(parameters) as (read, write):
|
|
async with ClientSession(read, write) as session:
|
|
info = await session.initialize()
|
|
available = []
|
|
cursor = None
|
|
while True:
|
|
page = await session.list_tools(cursor=cursor)
|
|
available.extend(tool.name for tool in page.tools)
|
|
cursor = page.nextCursor
|
|
if not cursor:
|
|
break
|
|
required = {'list_schematic_components', 'run_erc', 'run_drc'}
|
|
if not required.issubset(available):
|
|
raise RuntimeError(f'Missing tools: {required - set(available)}')
|
|
resource = await session.read_resource('kicad://config')
|
|
configuration = json.loads(resource.contents[0].text)
|
|
if configuration['project_paths'] != [str(ROOT)]:
|
|
raise RuntimeError('Project search path was not applied')
|
|
schematic = ROOT / 'PhoneRail-Board1' / 'P1-INPUT.kicad_sch'
|
|
result = await session.call_tool(
|
|
'list_schematic_components', {'file_path': str(schematic)}
|
|
)
|
|
output = '\n'.join(getattr(part, 'text', '') for part in result.content)
|
|
if result.isError or 'Total:' not in output:
|
|
raise RuntimeError(f'Schematic read failed: {output}')
|
|
print(json.dumps({
|
|
'server': info.serverInfo.name,
|
|
'pcbnew': pcbnew.Version(),
|
|
'tool_count': len(available),
|
|
'project_paths': configuration['project_paths'],
|
|
'schematic': str(schematic),
|
|
'components': next(line for line in output.splitlines() if line.startswith('Total:')),
|
|
'status': 'PASS',
|
|
}, indent=2))
|
|
|
|
|
|
if __name__ == '__main__':
|
|
asyncio.run(asyncio.wait_for(verify(), timeout=60))
|