mcpsmith 0.2.0__tar.gz → 0.2.1__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 (67) hide show
  1. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/.claude-plugin/plugin.json +2 -2
  2. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/PKG-INFO +2 -1
  3. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/pyproject.toml +2 -1
  4. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/server.json +2 -2
  5. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/__init__.py +1 -1
  6. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/importers/__init__.py +2 -1
  7. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/runtime/http.py +11 -1
  8. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/test_runtime.py +9 -0
  9. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/uv.lock +3 -1
  10. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/.claude-plugin/marketplace.json +0 -0
  11. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/.github/workflows/ci.yml +0 -0
  12. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/.github/workflows/publish.yml +0 -0
  13. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/.gitignore +0 -0
  14. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/AGENTS.md +0 -0
  15. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/LICENSE +0 -0
  16. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/README.md +0 -0
  17. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/docs/design.md +0 -0
  18. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/docs/superpowers/plans/2026-10-21-hub-core.md +0 -0
  19. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/docs/superpowers/specs/2026-10-20-mcp-everything-design.md +0 -0
  20. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/skills/build-mcp-server/SKILL.md +0 -0
  21. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/skills/design-mcp-tools/SKILL.md +0 -0
  22. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/skills/extract-api/SKILL.md +0 -0
  23. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/browser.py +0 -0
  24. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/capture.py +0 -0
  25. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/check.py +0 -0
  26. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/cli.py +0 -0
  27. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/codegen.py +0 -0
  28. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/design/__init__.py +0 -0
  29. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/design/_digest.py +0 -0
  30. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/design/_draft.py +0 -0
  31. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/design/_validate.py +0 -0
  32. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/design/guide.md +0 -0
  33. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/design/llm.py +0 -0
  34. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/hub.py +0 -0
  35. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/importers/har.py +0 -0
  36. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/importers/openapi.py +0 -0
  37. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/importers/rea.py +0 -0
  38. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/model.py +0 -0
  39. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/record.py +0 -0
  40. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/runtime/__init__.py +0 -0
  41. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/runtime/interpret.py +0 -0
  42. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/runtime/server.py +0 -0
  43. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/runtime/shape.py +0 -0
  44. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/runtime/transforms.py +0 -0
  45. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/secrets.py +0 -0
  46. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/server.py +0 -0
  47. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/templates/ci.yml +0 -0
  48. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/templates/conftest.py.tmpl +0 -0
  49. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/templates/gitignore +0 -0
  50. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/src/mcpsmith/templates/publish.yml +0 -0
  51. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/conftest.py +0 -0
  52. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/fake_cdp.py +0 -0
  53. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/fixtures/har/shop.har +0 -0
  54. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/fixtures/openapi/petstore2.yaml +0 -0
  55. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/fixtures/openapi/petstore3.json +0 -0
  56. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/fixtures/openapi/tasks31.json +0 -0
  57. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/fixtures/rea/scenario.json +0 -0
  58. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/test_browser.py +0 -0
  59. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/test_cli.py +0 -0
  60. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/test_codegen.py +0 -0
  61. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/test_design.py +0 -0
  62. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/test_hub.py +0 -0
  63. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/test_importers.py +0 -0
  64. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/test_interpret.py +0 -0
  65. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/test_record.py +0 -0
  66. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/test_secrets.py +0 -0
  67. {mcpsmith-0.2.0 → mcpsmith-0.2.1}/tests/test_transforms.py +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mcpsmith",
3
3
  "displayName": "mcpsmith",
4
- "version": "0.2.0",
4
+ "version": "0.2.1",
5
5
  "description": "Turn an OpenAPI file or a recorded website session into a curated, tested MCP server. Skills and an MCP server for your coding agent.",
6
6
  "author": {
7
7
  "name": "Sepehr Radmard",
@@ -23,7 +23,7 @@
23
23
  "mcpsmith": {
24
24
  "command": "uvx",
25
25
  "args": [
26
- "mcpsmith@0.2.0",
26
+ "mcpsmith@0.2.1",
27
27
  "mcp"
28
28
  ]
29
29
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: mcpsmith
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Turn an OpenAPI file or a recorded website session into a curated, tested MCP server, with an LLM designing the tools.
5
5
  Project-URL: Homepage, https://github.com/sepehr071/mcpsmith
6
6
  Project-URL: Issues, https://github.com/sepehr071/mcpsmith/issues
@@ -22,6 +22,7 @@ Requires-Dist: httpx>=0.27
22
22
  Requires-Dist: keyring>=25
23
23
  Requires-Dist: mcp<3,>=2.2
24
24
  Requires-Dist: pyyaml>=6
25
+ Requires-Dist: truststore>=0.9
25
26
  Requires-Dist: tzdata>=2024.1; sys_platform == 'win32'
26
27
  Requires-Dist: websockets>=12
27
28
  Provides-Extra: capture
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "mcpsmith"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  description = "Turn an OpenAPI file or a recorded website session into a curated, tested MCP server, with an LLM designing the tools."
5
5
  readme = "README.md"
6
6
  license = "MIT"
@@ -22,6 +22,7 @@ classifiers = [
22
22
  dependencies = [
23
23
  "mcp>=2.2,<3",
24
24
  "httpx>=0.27",
25
+ "truststore>=0.9",
25
26
  "pyyaml>=6",
26
27
  "websockets>=12",
27
28
  "keyring>=25",
@@ -8,13 +8,13 @@
8
8
  "source": "github"
9
9
  },
10
10
  "websiteUrl": "https://github.com/sepehr071/mcpsmith",
11
- "version": "0.2.0",
11
+ "version": "0.2.1",
12
12
  "packages": [
13
13
  {
14
14
  "registryType": "pypi",
15
15
  "registryBaseUrl": "https://pypi.org",
16
16
  "identifier": "mcpsmith",
17
- "version": "0.2.0",
17
+ "version": "0.2.1",
18
18
  "runtimeHint": "uvx",
19
19
  "transport": {
20
20
  "type": "stdio"
@@ -1,3 +1,3 @@
1
1
  """mcpsmith: turn an OpenAPI file or a recorded website session into a curated, tested MCP server."""
2
2
 
3
- __version__ = "0.2.0"
3
+ __version__ = "0.2.1"
@@ -10,13 +10,14 @@ import yaml
10
10
 
11
11
  from mcpsmith.importers import har, openapi, rea
12
12
  from mcpsmith.model import Source
13
+ from mcpsmith.runtime.http import tls_context
13
14
 
14
15
 
15
16
  def load(path_or_url: str, hosts: list[str] | None = None) -> Source:
16
17
  """`hosts` filters HAR traffic to those hosts (exact or subdomain); ignored for OpenAPI."""
17
18
  origin = None
18
19
  if path_or_url.startswith(("http://", "https://")):
19
- resp = httpx.get(path_or_url, follow_redirects=True, timeout=60)
20
+ resp = httpx.get(path_or_url, follow_redirects=True, timeout=60, verify=tls_context())
20
21
  resp.raise_for_status()
21
22
  text, origin = resp.text, str(resp.url)
22
23
  else:
@@ -16,12 +16,14 @@ import logging
16
16
  import os
17
17
  import random
18
18
  import re
19
+ import ssl
19
20
  import time
20
21
  from collections.abc import Awaitable, Callable
21
22
  from typing import Any
22
23
  from urllib.parse import quote
23
24
 
24
25
  import httpx
26
+ import truststore
25
27
  from mcp.server.mcpserver.exceptions import ToolError
26
28
 
27
29
  log = logging.getLogger("mcpsmith")
@@ -38,6 +40,12 @@ class ApiError(ToolError):
38
40
  self.status = status
39
41
 
40
42
 
43
+ @functools.cache
44
+ def tls_context() -> ssl.SSLContext:
45
+ """Verify with the OS trust store (fixes incomplete chains, honors corporate CAs); verification stays on."""
46
+ return truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
47
+
48
+
41
49
  @functools.cache
42
50
  def _curl() -> tuple[type, Any] | None:
43
51
  """The curl_cffi transport class (Chrome TLS/HTTP2 fingerprint) and CurlOpt, or None without the extra."""
@@ -283,7 +291,9 @@ class Api:
283
291
  proxy=proxy,
284
292
  max_connections=2 * self.concurrency,
285
293
  )
286
- return httpx.AsyncHTTPTransport(proxy=proxy, limits=httpx.Limits(max_connections=2 * self.concurrency))
294
+ return httpx.AsyncHTTPTransport(
295
+ verify=tls_context(), proxy=proxy, limits=httpx.Limits(max_connections=2 * self.concurrency)
296
+ )
287
297
 
288
298
  async def _request(self, method, url, query, headers, payload, host) -> tuple[httpx.Response, bytes]:
289
299
  client, limit = self._get_client()
@@ -1,8 +1,10 @@
1
1
  import json
2
+ import ssl
2
3
  from typing import Annotated
3
4
 
4
5
  import httpx
5
6
  import pytest
7
+ import truststore
6
8
  from mcp import Client
7
9
  from pydantic import Field
8
10
 
@@ -351,3 +353,10 @@ async def test_browser_auth_cookie_errors_map_to_not_running(exc):
351
353
  api = make_api(lambda r: httpx.Response(200, json={}), auth={"type": "browser"}, cookie_provider=down)
352
354
  with pytest.raises(ApiError, match="The mcpsmith Chrome is not running"):
353
355
  await api.call("GET", "/x")
356
+
357
+
358
+ def test_plain_transport_verifies_with_os_trust_store():
359
+ transport = Api(base_url="https://api.example.com", env_prefix="EX_MCP")._make_transport(None)
360
+ ctx = transport._pool._ssl_context
361
+ assert isinstance(ctx, truststore.SSLContext) and ctx is http.tls_context()
362
+ assert ctx.verify_mode == ssl.CERT_REQUIRED
@@ -689,13 +689,14 @@ wheels = [
689
689
 
690
690
  [[package]]
691
691
  name = "mcpsmith"
692
- version = "0.2.0"
692
+ version = "0.2.1"
693
693
  source = { editable = "." }
694
694
  dependencies = [
695
695
  { name = "httpx" },
696
696
  { name = "keyring" },
697
697
  { name = "mcp" },
698
698
  { name = "pyyaml" },
699
+ { name = "truststore" },
699
700
  { name = "tzdata", marker = "sys_platform == 'win32'" },
700
701
  { name = "websockets", version = "16.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" },
701
702
  { name = "websockets", version = "17.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" },
@@ -726,6 +727,7 @@ requires-dist = [
726
727
  { name = "mcp", specifier = ">=2.2,<3" },
727
728
  { name = "playwright", marker = "extra == 'capture'", specifier = ">=1.45" },
728
729
  { name = "pyyaml", specifier = ">=6" },
730
+ { name = "truststore", specifier = ">=0.9" },
729
731
  { name = "tzdata", marker = "sys_platform == 'win32'", specifier = ">=2024.1" },
730
732
  { name = "websockets", specifier = ">=12" },
731
733
  ]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes