fix(mcp): use semantica.__version__ as authoritative MCP version source

The previous implementation used importlib.metadata.version('semantica') as
the primary version source with a PackageNotFoundError fallback to
semantica.__version__. This caused two of the three new regression tests to
fail in editable/development installs, where dist-info (egg-info) is written
at install time and is not automatically updated on subsequent version bumps.

In this repo, pyproject.toml declares version as a static field (not dynamic),
and semantica/__init__.py maintains __version__ in sync with it by convention.
semantica.__version__ is therefore the authoritative source of truth and is
always present whenever semantica.mcp_server is importable -- the importlib
.metadata indirection adds no value and can return a stale value.

Changes:
- semantica/mcp_server/__init__.py: replace the importlib.metadata try/except
  block with a direct 'from semantica import __version__ as _SEMANTICA_VERSION'
- tests/test_mcp_server_version.py: rewrite tests to assert both MCP version
  surfaces (SERVER_INFO['version'] and semantica://schema/info) against
  semantica.__version__ as the single ground truth; add 0.4.0 regression
  canaries and a cross-surface consistency assertion; remove the mirrored
  importlib.metadata resolution that masked the staleness problem

The root-level mcp/ directory (a separate unpublished companion implementation
not included in the built package) is intentionally left unchanged -- it is
outside the scope of issue #863 which targets the semantica-mcp entry point.
This commit is contained in:
Sameer6305
2026-08-12 13:56:02 +05:30
parent f821fa7e2e
commit b8e8b2f227
2 changed files with 80 additions and 20 deletions
+8 -6
View File
@@ -45,14 +45,16 @@ import json
import logging
import os
import sys
from importlib.metadata import PackageNotFoundError, version
from typing import Any
try:
_SEMANTICA_VERSION = version("semantica")
except PackageNotFoundError:
# Preserve direct source-tree execution when distribution metadata is absent.
from semantica import __version__ as _SEMANTICA_VERSION
# `semantica.__version__` is the authoritative package version — it is kept in
# sync with pyproject.toml's static `version` field by the release process and
# is always present whenever this submodule is importable. Using it directly
# is simpler and more reliable than `importlib.metadata.version("semantica")`,
# which reads dist-info written at install time and can lag the source in
# editable installs (egg-info / dist-info is not regenerated on every version
# bump, so it can reflect a stale value).
from semantica import __version__ as _SEMANTICA_VERSION
# ── logging ────────────────────────────────────────────────────────────────
_log_level = getattr(logging, os.environ.get("SEMANTICA_LOG_LEVEL", "WARNING").upper(), logging.WARNING)
+72 -14
View File
@@ -1,35 +1,93 @@
"""Regression tests for MCP server version reporting."""
"""Regression tests for MCP server version reporting (issue #863).
Both public MCP version surfaces must derive from the same authoritative
package version rather than a hardcoded stale literal:
1. MCP ``initialize`` → ``serverInfo.version``
2. ``semantica://schema/info`` → ``version``
The authoritative source of truth is ``semantica.__version__``, which is
maintained in sync with ``pyproject.toml``'s static ``version`` field by
the release process. We assert equality against that value rather than
duplicating the version-resolution logic here, so the tests remain valid
through future version bumps without modification.
The ``assertNotEqual(..., "0.4.0")`` canaries guard against regression to
the original stale literal that triggered issue #863.
"""
import unittest
from importlib.metadata import PackageNotFoundError, version
import semantica
from semantica import mcp_server
_EXPECTED = semantica.__version__
class TestMCPServerVersion(unittest.TestCase):
def test_server_info_uses_distribution_version(self):
try:
expected = version("semantica")
except PackageNotFoundError:
expected = semantica.__version__
self.assertEqual(mcp_server.SERVER_INFO["version"], expected)
# ------------------------------------------------------------------ #
# SERVER_INFO (used directly in the initialize response)
# ------------------------------------------------------------------ #
def test_initialize_reports_package_version(self):
def test_server_info_version_matches_package(self):
"""SERVER_INFO['version'] must equal the authoritative package version."""
self.assertEqual(mcp_server.SERVER_INFO["version"], _EXPECTED)
def test_server_info_version_is_not_stale_literal(self):
"""Guard: SERVER_INFO must not report the original hardcoded 0.4.0."""
self.assertNotEqual(mcp_server.SERVER_INFO["version"], "0.4.0")
# ------------------------------------------------------------------ #
# MCP initialize → serverInfo.version
# ------------------------------------------------------------------ #
def test_initialize_server_info_version_matches_package(self):
"""The MCP initialize response must report the authoritative package version."""
response = mcp_server._handle(
{"jsonrpc": "2.0", "id": 1, "method": "initialize"}
)
self.assertIsNotNone(response)
self.assertEqual(
response["result"]["serverInfo"]["version"], semantica.__version__
response["result"]["serverInfo"]["version"],
_EXPECTED,
)
def test_schema_info_resource_reports_package_version(self):
resource = mcp_server._read_resource("semantica://schema/info")
def test_initialize_server_info_version_is_not_stale_literal(self):
"""Guard: initialize must not report the original hardcoded 0.4.0."""
response = mcp_server._handle(
{"jsonrpc": "2.0", "id": 1, "method": "initialize"}
)
self.assertNotEqual(response["result"]["serverInfo"]["version"], "0.4.0")
self.assertEqual(resource["version"], semantica.__version__)
# ------------------------------------------------------------------ #
# semantica://schema/info → version
# ------------------------------------------------------------------ #
def test_schema_info_resource_version_matches_package(self):
"""The semantica://schema/info resource must report the authoritative package version."""
resource = mcp_server._read_resource("semantica://schema/info")
self.assertEqual(resource["version"], _EXPECTED)
def test_schema_info_resource_version_is_not_stale_literal(self):
"""Guard: schema/info must not report the original hardcoded 0.4.0."""
resource = mcp_server._read_resource("semantica://schema/info")
self.assertNotEqual(resource["version"], "0.4.0")
# ------------------------------------------------------------------ #
# Both surfaces must agree
# ------------------------------------------------------------------ #
def test_both_version_surfaces_are_identical(self):
"""SERVER_INFO and schema/info must report the exact same version string,
confirming both surfaces derive from a single authoritative value."""
init_response = mcp_server._handle(
{"jsonrpc": "2.0", "id": 1, "method": "initialize"}
)
schema_resource = mcp_server._read_resource("semantica://schema/info")
self.assertEqual(
init_response["result"]["serverInfo"]["version"],
schema_resource["version"],
)
if __name__ == "__main__":