Rename mcp-ltspice -> mcltspice, remove stdout banner
Rename package from mcp-ltspice/mcp_ltspice to mcltspice throughout: source directory, imports, pyproject.toml, tests, and README. Remove startup banner prints from main() since FastMCP handles its own banner and stdout is the MCP JSON-RPC transport. Point repo URL at git.supported.systems/MCP/mcltspice.
This commit is contained in:
parent
0c545800f7
commit
cf8394fa6f
12
README.md
12
README.md
@ -1,4 +1,4 @@
|
|||||||
# mcp-ltspice
|
# mcltspice
|
||||||
|
|
||||||
MCP server for LTspice circuit simulation automation on Linux.
|
MCP server for LTspice circuit simulation automation on Linux.
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ MCP server for LTspice circuit simulation automation on Linux.
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# From PyPI (once published)
|
# From PyPI (once published)
|
||||||
uvx mcp-ltspice
|
uvx mcltspice
|
||||||
|
|
||||||
# From source
|
# From source
|
||||||
uv pip install -e .
|
uv pip install -e .
|
||||||
@ -67,15 +67,19 @@ Set the `LTSPICE_DIR` environment variable or use the default `~/claude/ltspice/
|
|||||||
## Usage with Claude Code
|
## Usage with Claude Code
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
claude mcp add mcp-ltspice -- uvx mcp-ltspice
|
claude mcp add mcltspice -- uvx mcltspice
|
||||||
```
|
```
|
||||||
|
|
||||||
Or for local development:
|
Or for local development:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
claude mcp add mcp-ltspice -- uv run --directory /path/to/mcp-ltspice mcp-ltspice
|
claude mcp add mcltspice -- uv run --directory /path/to/mcltspice mcltspice
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Repository
|
||||||
|
|
||||||
|
[git.supported.systems/MCP/mcltspice](https://git.supported.systems/MCP/mcltspice)
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT
|
MIT
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "mcp-ltspice"
|
name = "mcltspice"
|
||||||
version = "2026.02.10"
|
version = "2026.02.10"
|
||||||
description = "MCP server for LTspice circuit simulation automation"
|
description = "MCP server for LTspice circuit simulation automation"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
@ -35,17 +35,17 @@ plot = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[project.scripts]
|
[project.scripts]
|
||||||
mcp-ltspice = "mcp_ltspice.server:main"
|
mcltspice = "mcltspice.server:main"
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
Repository = "https://github.com/ryanmalloy/mcp-ltspice"
|
Repository = "https://git.supported.systems/MCP/mcltspice"
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["hatchling"]
|
requires = ["hatchling"]
|
||||||
build-backend = "hatchling.build"
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
[tool.hatch.build.targets.wheel]
|
[tool.hatch.build.targets.wheel]
|
||||||
packages = ["src/mcp_ltspice"]
|
packages = ["src/mcltspice"]
|
||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
testpaths = ["tests"]
|
testpaths = ["tests"]
|
||||||
|
|||||||
@ -3,6 +3,6 @@
|
|||||||
from importlib.metadata import version
|
from importlib.metadata import version
|
||||||
|
|
||||||
try:
|
try:
|
||||||
__version__ = version("mcp-ltspice")
|
__version__ = version("mcltspice")
|
||||||
except Exception:
|
except Exception:
|
||||||
__version__ = "0.0.0"
|
__version__ = "0.0.0"
|
||||||
@ -1,4 +1,4 @@
|
|||||||
"""Configuration for mcp-ltspice."""
|
"""Configuration for mcltspice."""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -20,7 +20,6 @@ import numpy as np
|
|||||||
from fastmcp import FastMCP
|
from fastmcp import FastMCP
|
||||||
from fastmcp.prompts import Message
|
from fastmcp.prompts import Message
|
||||||
|
|
||||||
from . import __version__
|
|
||||||
from .asc_generator import (
|
from .asc_generator import (
|
||||||
generate_boost_converter as generate_boost_converter_asc,
|
generate_boost_converter as generate_boost_converter_asc,
|
||||||
)
|
)
|
||||||
@ -129,7 +128,7 @@ from .waveform_math import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
mcp = FastMCP(
|
mcp = FastMCP(
|
||||||
name="mcp-ltspice",
|
name="mcltspice",
|
||||||
instructions="""
|
instructions="""
|
||||||
LTspice MCP Server - Circuit simulation automation.
|
LTspice MCP Server - Circuit simulation automation.
|
||||||
|
|
||||||
@ -2751,15 +2750,6 @@ Common failure modes:
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Run the MCP server."""
|
"""Run the MCP server."""
|
||||||
print(f"\U0001f50c mcp-ltspice v{__version__}")
|
|
||||||
print(" LTspice circuit simulation automation")
|
|
||||||
|
|
||||||
ok, msg = validate_installation()
|
|
||||||
if ok:
|
|
||||||
print(f" \u2713 {msg}")
|
|
||||||
else:
|
|
||||||
print(f" \u26a0 {msg}")
|
|
||||||
|
|
||||||
mcp.run()
|
mcp.run()
|
||||||
|
|
||||||
|
|
||||||
@ -1,4 +1,4 @@
|
|||||||
"""Shared fixtures for mcp-ltspice test suite.
|
"""Shared fixtures for mcltspice test suite.
|
||||||
|
|
||||||
All fixtures produce synthetic data -- no LTspice or Wine required.
|
All fixtures produce synthetic data -- no LTspice or Wine required.
|
||||||
"""
|
"""
|
||||||
@ -8,8 +8,8 @@ from pathlib import Path
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from mcp_ltspice.raw_parser import RawFile, Variable
|
from mcltspice.raw_parser import RawFile, Variable
|
||||||
from mcp_ltspice.schematic import Component, Flag, Schematic, Text, Wire
|
from mcltspice.schematic import Component, Flag, Schematic, Text, Wire
|
||||||
|
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Time-domain fixtures
|
# Time-domain fixtures
|
||||||
@ -329,7 +329,7 @@ def schematic_duplicate_names() -> Schematic:
|
|||||||
@pytest.fixture
|
@pytest.fixture
|
||||||
def ltspice_available():
|
def ltspice_available():
|
||||||
"""Skip test if LTspice is not available."""
|
"""Skip test if LTspice is not available."""
|
||||||
from mcp_ltspice.config import validate_installation
|
from mcltspice.config import validate_installation
|
||||||
ok, msg = validate_installation()
|
ok, msg = validate_installation()
|
||||||
if not ok:
|
if not ok:
|
||||||
pytest.skip(f"LTspice not available: {msg}")
|
pytest.skip(f"LTspice not available: {msg}")
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from mcp_ltspice.asc_generator import (
|
from mcltspice.asc_generator import (
|
||||||
_PIN_OFFSETS,
|
_PIN_OFFSETS,
|
||||||
AscSchematic,
|
AscSchematic,
|
||||||
_rotate,
|
_rotate,
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
from mcp_ltspice.diff import (
|
from mcltspice.diff import (
|
||||||
ComponentChange,
|
ComponentChange,
|
||||||
SchematicDiff,
|
SchematicDiff,
|
||||||
_diff_components,
|
_diff_components,
|
||||||
@ -11,7 +11,7 @@ from mcp_ltspice.diff import (
|
|||||||
_diff_wires,
|
_diff_wires,
|
||||||
diff_schematics,
|
diff_schematics,
|
||||||
)
|
)
|
||||||
from mcp_ltspice.schematic import Component, Flag, Schematic, Text, Wire, write_schematic
|
from mcltspice.schematic import Component, Flag, Schematic, Text, Wire, write_schematic
|
||||||
|
|
||||||
|
|
||||||
def _make_schematic(**kwargs) -> Schematic:
|
def _make_schematic(**kwargs) -> Schematic:
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
from mcp_ltspice.drc import (
|
from mcltspice.drc import (
|
||||||
DRCResult,
|
DRCResult,
|
||||||
DRCViolation,
|
DRCViolation,
|
||||||
Severity,
|
Severity,
|
||||||
@ -10,7 +10,7 @@ from mcp_ltspice.drc import (
|
|||||||
_check_ground,
|
_check_ground,
|
||||||
_check_simulation_directive,
|
_check_simulation_directive,
|
||||||
)
|
)
|
||||||
from mcp_ltspice.schematic import Schematic, write_schematic
|
from mcltspice.schematic import Schematic, write_schematic
|
||||||
|
|
||||||
|
|
||||||
def _run_single_check(check_fn, schematic: Schematic) -> DRCResult:
|
def _run_single_check(check_fn, schematic: Schematic) -> DRCResult:
|
||||||
@ -110,7 +110,7 @@ class TestFullDRC:
|
|||||||
|
|
||||||
def test_valid_schematic_passes(self, valid_schematic, tmp_path):
|
def test_valid_schematic_passes(self, valid_schematic, tmp_path):
|
||||||
"""A valid schematic should pass DRC with no errors."""
|
"""A valid schematic should pass DRC with no errors."""
|
||||||
from mcp_ltspice.drc import run_drc
|
from mcltspice.drc import run_drc
|
||||||
|
|
||||||
path = tmp_path / "valid.asc"
|
path = tmp_path / "valid.asc"
|
||||||
write_schematic(valid_schematic, path)
|
write_schematic(valid_schematic, path)
|
||||||
@ -119,7 +119,7 @@ class TestFullDRC:
|
|||||||
assert len(result.errors) == 0
|
assert len(result.errors) == 0
|
||||||
|
|
||||||
def test_no_ground_fails(self, schematic_no_ground, tmp_path):
|
def test_no_ground_fails(self, schematic_no_ground, tmp_path):
|
||||||
from mcp_ltspice.drc import run_drc
|
from mcltspice.drc import run_drc
|
||||||
|
|
||||||
path = tmp_path / "no_ground.asc"
|
path = tmp_path / "no_ground.asc"
|
||||||
write_schematic(schematic_no_ground, path)
|
write_schematic(schematic_no_ground, path)
|
||||||
|
|||||||
@ -10,20 +10,20 @@ from pathlib import Path
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from mcp_ltspice.asc_generator import (
|
from mcltspice.asc_generator import (
|
||||||
generate_colpitts_oscillator as generate_colpitts_asc,
|
generate_colpitts_oscillator as generate_colpitts_asc,
|
||||||
)
|
)
|
||||||
from mcp_ltspice.asc_generator import (
|
from mcltspice.asc_generator import (
|
||||||
generate_common_emitter_amp as generate_ce_amp_asc,
|
generate_common_emitter_amp as generate_ce_amp_asc,
|
||||||
)
|
)
|
||||||
from mcp_ltspice.asc_generator import (
|
from mcltspice.asc_generator import (
|
||||||
generate_non_inverting_amp as generate_noninv_amp_asc,
|
generate_non_inverting_amp as generate_noninv_amp_asc,
|
||||||
)
|
)
|
||||||
from mcp_ltspice.asc_generator import (
|
from mcltspice.asc_generator import (
|
||||||
generate_rc_lowpass as generate_rc_lowpass_asc,
|
generate_rc_lowpass as generate_rc_lowpass_asc,
|
||||||
)
|
)
|
||||||
from mcp_ltspice.runner import run_simulation
|
from mcltspice.runner import run_simulation
|
||||||
from mcp_ltspice.waveform_math import compute_bandwidth, compute_rms
|
from mcltspice.waveform_math import compute_bandwidth, compute_rms
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.integration
|
@pytest.mark.integration
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from mcp_ltspice.netlist import (
|
from mcltspice.netlist import (
|
||||||
Netlist,
|
Netlist,
|
||||||
buck_converter,
|
buck_converter,
|
||||||
colpitts_oscillator,
|
colpitts_oscillator,
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from mcp_ltspice.asc_generator import (
|
from mcltspice.asc_generator import (
|
||||||
AscSchematic,
|
AscSchematic,
|
||||||
generate_boost_converter,
|
generate_boost_converter,
|
||||||
generate_current_mirror,
|
generate_current_mirror,
|
||||||
@ -10,7 +10,7 @@ from mcp_ltspice.asc_generator import (
|
|||||||
generate_sallen_key_lowpass,
|
generate_sallen_key_lowpass,
|
||||||
generate_transimpedance_amp,
|
generate_transimpedance_amp,
|
||||||
)
|
)
|
||||||
from mcp_ltspice.netlist import (
|
from mcltspice.netlist import (
|
||||||
Netlist,
|
Netlist,
|
||||||
boost_converter,
|
boost_converter,
|
||||||
current_mirror,
|
current_mirror,
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from mcp_ltspice.optimizer import format_engineering, snap_to_preferred
|
from mcltspice.optimizer import format_engineering, snap_to_preferred
|
||||||
|
|
||||||
|
|
||||||
class TestSnapToPreferred:
|
class TestSnapToPreferred:
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from mcp_ltspice.power_analysis import (
|
from mcltspice.power_analysis import (
|
||||||
compute_average_power,
|
compute_average_power,
|
||||||
compute_efficiency,
|
compute_efficiency,
|
||||||
compute_instantaneous_power,
|
compute_instantaneous_power,
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from mcp_ltspice.raw_parser import _detect_run_boundaries
|
from mcltspice.raw_parser import _detect_run_boundaries
|
||||||
|
|
||||||
|
|
||||||
class TestDetectRunBoundaries:
|
class TestDetectRunBoundaries:
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from mcp_ltspice.stability import (
|
from mcltspice.stability import (
|
||||||
compute_gain_margin,
|
compute_gain_margin,
|
||||||
compute_phase_margin,
|
compute_phase_margin,
|
||||||
compute_stability_metrics,
|
compute_stability_metrics,
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from mcp_ltspice.svg_plot import (
|
from mcltspice.svg_plot import (
|
||||||
_format_freq,
|
_format_freq,
|
||||||
_nice_ticks,
|
_nice_ticks,
|
||||||
plot_bode,
|
plot_bode,
|
||||||
|
|||||||
@ -5,7 +5,7 @@ from pathlib import Path
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from mcp_ltspice.touchstone import (
|
from mcltspice.touchstone import (
|
||||||
_detect_ports,
|
_detect_ports,
|
||||||
_to_complex,
|
_to_complex,
|
||||||
get_s_parameter,
|
get_s_parameter,
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from mcp_ltspice.waveform_expr import (
|
from mcltspice.waveform_expr import (
|
||||||
WaveformCalculator,
|
WaveformCalculator,
|
||||||
_tokenize,
|
_tokenize,
|
||||||
_TokenType,
|
_TokenType,
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from mcp_ltspice.waveform_math import (
|
from mcltspice.waveform_math import (
|
||||||
compute_bandwidth,
|
compute_bandwidth,
|
||||||
compute_fft,
|
compute_fft,
|
||||||
compute_peak_to_peak,
|
compute_peak_to_peak,
|
||||||
|
|||||||
52
uv.lock
generated
52
uv.lock
generated
@ -1027,32 +1027,7 @@ wheels = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mcp"
|
name = "mcltspice"
|
||||||
version = "1.26.0"
|
|
||||||
source = { registry = "https://pypi.org/simple" }
|
|
||||||
dependencies = [
|
|
||||||
{ name = "anyio" },
|
|
||||||
{ name = "httpx" },
|
|
||||||
{ name = "httpx-sse" },
|
|
||||||
{ name = "jsonschema" },
|
|
||||||
{ name = "pydantic" },
|
|
||||||
{ name = "pydantic-settings" },
|
|
||||||
{ name = "pyjwt", extra = ["crypto"] },
|
|
||||||
{ name = "python-multipart" },
|
|
||||||
{ name = "pywin32", marker = "sys_platform == 'win32'" },
|
|
||||||
{ name = "sse-starlette" },
|
|
||||||
{ name = "starlette" },
|
|
||||||
{ name = "typing-extensions" },
|
|
||||||
{ name = "typing-inspection" },
|
|
||||||
{ name = "uvicorn", marker = "sys_platform != 'emscripten'" },
|
|
||||||
]
|
|
||||||
sdist = { url = "https://files.pythonhosted.org/packages/fc/6d/62e76bbb8144d6ed86e202b5edd8a4cb631e7c8130f3f4893c3f90262b10/mcp-1.26.0.tar.gz", hash = "sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66", size = 608005, upload-time = "2026-01-24T19:40:32.468Z" }
|
|
||||||
wheels = [
|
|
||||||
{ url = "https://files.pythonhosted.org/packages/fd/d9/eaa1f80170d2b7c5ba23f3b59f766f3a0bb41155fbc32a69adfa1adaaef9/mcp-1.26.0-py3-none-any.whl", hash = "sha256:904a21c33c25aa98ddbeb47273033c435e595bbacfdb177f4bd87f6dceebe1ca", size = 233615, upload-time = "2026-01-24T19:40:30.652Z" },
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "mcp-ltspice"
|
|
||||||
version = "2026.2.10"
|
version = "2026.2.10"
|
||||||
source = { editable = "." }
|
source = { editable = "." }
|
||||||
dependencies = [
|
dependencies = [
|
||||||
@ -1081,6 +1056,31 @@ requires-dist = [
|
|||||||
]
|
]
|
||||||
provides-extras = ["dev", "plot"]
|
provides-extras = ["dev", "plot"]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mcp"
|
||||||
|
version = "1.26.0"
|
||||||
|
source = { registry = "https://pypi.org/simple" }
|
||||||
|
dependencies = [
|
||||||
|
{ name = "anyio" },
|
||||||
|
{ name = "httpx" },
|
||||||
|
{ name = "httpx-sse" },
|
||||||
|
{ name = "jsonschema" },
|
||||||
|
{ name = "pydantic" },
|
||||||
|
{ name = "pydantic-settings" },
|
||||||
|
{ name = "pyjwt", extra = ["crypto"] },
|
||||||
|
{ name = "python-multipart" },
|
||||||
|
{ name = "pywin32", marker = "sys_platform == 'win32'" },
|
||||||
|
{ name = "sse-starlette" },
|
||||||
|
{ name = "starlette" },
|
||||||
|
{ name = "typing-extensions" },
|
||||||
|
{ name = "typing-inspection" },
|
||||||
|
{ name = "uvicorn", marker = "sys_platform != 'emscripten'" },
|
||||||
|
]
|
||||||
|
sdist = { url = "https://files.pythonhosted.org/packages/fc/6d/62e76bbb8144d6ed86e202b5edd8a4cb631e7c8130f3f4893c3f90262b10/mcp-1.26.0.tar.gz", hash = "sha256:db6e2ef491eecc1a0d93711a76f28dec2e05999f93afd48795da1c1137142c66", size = 608005, upload-time = "2026-01-24T19:40:32.468Z" }
|
||||||
|
wheels = [
|
||||||
|
{ url = "https://files.pythonhosted.org/packages/fd/d9/eaa1f80170d2b7c5ba23f3b59f766f3a0bb41155fbc32a69adfa1adaaef9/mcp-1.26.0-py3-none-any.whl", hash = "sha256:904a21c33c25aa98ddbeb47273033c435e595bbacfdb177f4bd87f6dceebe1ca", size = 233615, upload-time = "2026-01-24T19:40:30.652Z" },
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mdurl"
|
name = "mdurl"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user