web-algebra 2.0.0__tar.gz → 2.0.2__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 (94) hide show
  1. {web_algebra-2.0.0 → web_algebra-2.0.2}/PKG-INFO +6 -2
  2. {web_algebra-2.0.0 → web_algebra-2.0.2}/README.md +5 -1
  3. {web_algebra-2.0.0 → web_algebra-2.0.2}/pyproject.toml +1 -1
  4. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/main.py +12 -0
  5. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/add_result_set_chart.py +4 -3
  6. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/add_view.py +22 -17
  7. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra.egg-info/PKG-INFO +6 -2
  8. {web_algebra-2.0.0 → web_algebra-2.0.2}/tests/test_mcp_server.py +12 -2
  9. {web_algebra-2.0.0 → web_algebra-2.0.2}/tests/test_packaging.py +5 -0
  10. {web_algebra-2.0.0 → web_algebra-2.0.2}/LICENSE +0 -0
  11. {web_algebra-2.0.0 → web_algebra-2.0.2}/setup.cfg +0 -0
  12. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/__init__.py +0 -0
  13. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/__main__.py +0 -0
  14. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/client.py +0 -0
  15. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/client_operation.py +0 -0
  16. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/exceptions.py +0 -0
  17. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/focus.py +0 -0
  18. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/json_result.py +0 -0
  19. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/mcp_tool.py +0 -0
  20. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operation.py +0 -0
  21. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/__init__.py +0 -0
  22. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/bindings.py +0 -0
  23. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/current.py +0 -0
  24. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/filter.py +0 -0
  25. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/for_each.py +0 -0
  26. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/iterate.py +0 -0
  27. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/last.py +0 -0
  28. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linked_data/__init__.py +0 -0
  29. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linked_data/get.py +0 -0
  30. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linked_data/patch.py +0 -0
  31. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linked_data/post.py +0 -0
  32. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linked_data/put.py +0 -0
  33. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/__init__.py +0 -0
  34. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/add_construct.py +0 -0
  35. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/add_file.py +0 -0
  36. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/add_generic_service.py +0 -0
  37. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/add_select.py +0 -0
  38. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/content/__init__.py +0 -0
  39. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/content/add_object_block.py +0 -0
  40. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/content/add_xhtml_block.py +0 -0
  41. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/content/generate_class_containers.py +0 -0
  42. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/content/generate_ontology_views.py +0 -0
  43. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/content/generate_portal.py +0 -0
  44. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/content/remove_block.py +0 -0
  45. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/create_container.py +0 -0
  46. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/create_item.py +0 -0
  47. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/fragments.py +0 -0
  48. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/linkeddatahub/list.py +0 -0
  49. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/merge.py +0 -0
  50. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/now.py +0 -0
  51. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/position.py +0 -0
  52. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/resolve_uri.py +0 -0
  53. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/schema/__init__.py +0 -0
  54. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/schema/extract_classes.py +0 -0
  55. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/schema/extract_datatype_properties.py +0 -0
  56. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/schema/extract_object_properties.py +0 -0
  57. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/schema/extract_ontology.py +0 -0
  58. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/sparql/__init__.py +0 -0
  59. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/sparql/construct.py +0 -0
  60. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/sparql/describe.py +0 -0
  61. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/sparql/select.py +0 -0
  62. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/sparql/substitute.py +0 -0
  63. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/sparql/values.py +0 -0
  64. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/sparql_string.py +0 -0
  65. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/str.py +0 -0
  66. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/string/__init__.py +0 -0
  67. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/string/concat.py +0 -0
  68. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/string/encode_for_uri.py +0 -0
  69. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/string/replace.py +0 -0
  70. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/struuid.py +0 -0
  71. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/uri.py +0 -0
  72. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/value.py +0 -0
  73. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/operations/variable.py +0 -0
  74. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/prompts/system.md +0 -0
  75. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/prompts/user.template.txt +0 -0
  76. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/py.typed +0 -0
  77. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/query_source.py +0 -0
  78. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/rfc3986.py +0 -0
  79. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/schema_extraction.py +0 -0
  80. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/server.py +0 -0
  81. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra/sparql_restrict.py +0 -0
  82. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra.egg-info/SOURCES.txt +0 -0
  83. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra.egg-info/dependency_links.txt +0 -0
  84. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra.egg-info/entry_points.txt +0 -0
  85. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra.egg-info/requires.txt +0 -0
  86. {web_algebra-2.0.0 → web_algebra-2.0.2}/src/web_algebra.egg-info/top_level.txt +0 -0
  87. {web_algebra-2.0.0 → web_algebra-2.0.2}/tests/test_client_writes.py +0 -0
  88. {web_algebra-2.0.0 → web_algebra-2.0.2}/tests/test_examples.py +0 -0
  89. {web_algebra-2.0.0 → web_algebra-2.0.2}/tests/test_ldh_cli_parity.py +0 -0
  90. {web_algebra-2.0.0 → web_algebra-2.0.2}/tests/test_operation_kind.py +0 -0
  91. {web_algebra-2.0.0 → web_algebra-2.0.2}/tests/test_operation_names.py +0 -0
  92. {web_algebra-2.0.0 → web_algebra-2.0.2}/tests/test_planner.py +0 -0
  93. {web_algebra-2.0.0 → web_algebra-2.0.2}/tests/test_sparql_string_ask.py +0 -0
  94. {web_algebra-2.0.0 → web_algebra-2.0.2}/tests/test_system_prompt.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: web-algebra
3
- Version: 2.0.0
3
+ Version: 2.0.2
4
4
  Summary: Composable RDF operations in JSON
5
5
  Author-email: Martynas Jusevicius <martynas@atomgraph.com>
6
6
  License-Expression: Apache-2.0
@@ -33,6 +33,8 @@ Dynamic: license-file
33
33
 
34
34
  # Web-Algebra
35
35
 
36
+ [![Web-Algebra - Listed on Claude AI Directory](https://www.claudeai.directory/badge/web-algebra?theme=dark)](https://www.claudeai.directory/launches/web-algebra)
37
+
36
38
  <!-- mcp-name: io.github.AtomGraph/web-algebra -->
37
39
 
38
40
  A composable RDF operations system that translates natural language instructions into JSON-formatted domain-specific language operations for loading, querying, and writing RDF Linked Data.
@@ -48,7 +50,7 @@ Instead of agents executing semantic workflows step-by-step through individual M
48
50
 
49
51
  ## Demo
50
52
 
51
- [![ Agentic Content Management with Web-Algebra MCP](https://img.youtube.com/vi/eRMrSqKc9_E/0.jpg)](https://www.youtube.com/watch?v=eRMrSqKc9_E)
53
+ [![Web-Algebra in action: an AI agent builds Linked Data pages over MCP](https://img.youtube.com/vi/zSbvl5kmKic/maxresdefault.jpg)](https://www.youtube.com/watch?v=zSbvl5kmKic)
52
54
 
53
55
  *See WebAlgebra in action - translating natural language into RDF operations.*
54
56
 
@@ -202,6 +204,8 @@ or with Claude Code:
202
204
  claude mcp add web-algebra -e CERT_PEM_PATH=/path/to/LinkedDataHub/ssl/owner/cert.pem -e CERT_PASSWORD=******** -- uvx --from web-algebra web-algebra-mcp
203
205
  ```
204
206
 
207
+ `uvx web-algebra mcp` runs the same server.
208
+
205
209
  Environment variables:
206
210
 
207
211
  | Name | Required | Description |
@@ -1,5 +1,7 @@
1
1
  # Web-Algebra
2
2
 
3
+ [![Web-Algebra - Listed on Claude AI Directory](https://www.claudeai.directory/badge/web-algebra?theme=dark)](https://www.claudeai.directory/launches/web-algebra)
4
+
3
5
  <!-- mcp-name: io.github.AtomGraph/web-algebra -->
4
6
 
5
7
  A composable RDF operations system that translates natural language instructions into JSON-formatted domain-specific language operations for loading, querying, and writing RDF Linked Data.
@@ -15,7 +17,7 @@ Instead of agents executing semantic workflows step-by-step through individual M
15
17
 
16
18
  ## Demo
17
19
 
18
- [![ Agentic Content Management with Web-Algebra MCP](https://img.youtube.com/vi/eRMrSqKc9_E/0.jpg)](https://www.youtube.com/watch?v=eRMrSqKc9_E)
20
+ [![Web-Algebra in action: an AI agent builds Linked Data pages over MCP](https://img.youtube.com/vi/zSbvl5kmKic/maxresdefault.jpg)](https://www.youtube.com/watch?v=zSbvl5kmKic)
19
21
 
20
22
  *See WebAlgebra in action - translating natural language into RDF operations.*
21
23
 
@@ -169,6 +171,8 @@ or with Claude Code:
169
171
  claude mcp add web-algebra -e CERT_PEM_PATH=/path/to/LinkedDataHub/ssl/owner/cert.pem -e CERT_PASSWORD=******** -- uvx --from web-algebra web-algebra-mcp
170
172
  ```
171
173
 
174
+ `uvx web-algebra mcp` runs the same server.
175
+
172
176
  Environment variables:
173
177
 
174
178
  | Name | Required | Description |
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "web-algebra"
3
- version = "2.0.0"
3
+ version = "2.0.2"
4
4
  description = "Composable RDF operations in JSON"
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -135,6 +135,12 @@ def main(settings: BaseSettings, json_data: Optional[str]):
135
135
 
136
136
  def cli() -> None:
137
137
  parser = argparse.ArgumentParser(description="Run the AI-powered DSL interpreter.")
138
+ parser.add_argument(
139
+ "command",
140
+ nargs="?",
141
+ choices=["mcp"],
142
+ help="mcp: run the MCP server on stdio, as web-algebra-mcp does",
143
+ )
138
144
  parser.add_argument(
139
145
  "--from-json",
140
146
  type=str,
@@ -152,6 +158,12 @@ def cli() -> None:
152
158
  )
153
159
  args = parser.parse_args()
154
160
 
161
+ if args.command == "mcp":
162
+ from web_algebra.__main__ import main as serve
163
+
164
+ serve()
165
+ return
166
+
155
167
  # the flags override CERT_PEM_PATH / CERT_PASSWORD, which the settings
156
168
  # read from the environment, as the MCP server and the tests do
157
169
  overrides = {
@@ -18,9 +18,10 @@ class AddResultSetChart(POST):
18
18
  The chart is a resource the document holds, not one of its content blocks: to show it in the content mode,
19
19
  place it with ldh-AddObjectBlock, the chart's URI as its value - so give the chart a fragment identifier.
20
20
 
21
- This tool creates a ResultSetChart that visualizes data from SPARQL SELECT query resources.
22
- The chart references an existing sp:Select resource (not a query string) and can display
23
- results using different chart types (bar, line, pie, etc.) with variable mappings.
21
+ A chart shows values: the query's bindings themselves, as a table or a plot, the way a spreadsheet would.
22
+ It is the fit for aggregates and measurements - totals, counts, sums per shop or per month. A resource in
23
+ a chart is a bare cell, with no image, label or links of its own: to show resources themselves (things,
24
+ people, places), use ldh-AddView, whose modes render each one as itself.
24
25
 
25
26
  This tool:
26
27
  - Creates an ldh:ResultSetChart resource linked to an existing sp:Select query resource
@@ -18,27 +18,32 @@ class AddView(POST):
18
18
  The view is a resource the document holds, not one of its content blocks: to show it in the content mode,
19
19
  place it with ldh-AddObjectBlock, the view's URI as its value - so give the view a fragment identifier.
20
20
 
21
- This tool creates a View that displays data from SPARQL SELECT query resources.
22
- The view references an existing sp:Select resource (not a query string) and can display
23
- results using different display modes (list, grid, etc.).
24
-
21
+ A view shows resources - things, people, places, documents - each as itself: its label, its image,
22
+ its links. LinkedDataHub DESCRIBEs the resources the query's first projected variable binds and renders
23
+ those descriptions in the view's mode, so that variable must bind resources (SELECT ?thing WHERE { ... }).
24
+ One that binds values - a name, a price, a computed total - describes nothing. To show values or
25
+ aggregates (totals, counts, sums by month), use ldh-AddResultSetChart instead.
26
+
25
27
  This tool:
26
28
  - Creates an ldh:View resource linked to an existing sp:Select query resource
27
29
  - Configures optional display mode for the view
28
30
  - Posts the new view resource to the target document
29
31
  - Supports optional title, description, fragment identifier, and display mode
30
-
31
- Possible display modes include:
32
- - https://w3id.org/atomgraph/client#ReadMode: Default read mode for displaying resources
33
- - https://w3id.org/atomgraph/client#ListMode: List display of results
34
- - https://w3id.org/atomgraph/client#GridMode: Grid display of results
35
- - https://w3id.org/atomgraph/client#GraphMode: Graph visualization of resources
36
- - https://w3id.org/atomgraph/client#MapMode: Map display for geographic data
37
-
38
- IMPORTANT: All variables projected by the SELECT query will be DESCRIBE'd by LinkedDataHub,
39
- meaning that the view will fetch complete RDF descriptions for each result resource. This can
40
- result in very large graph results and may not be suitable for all SELECT queries, especially
41
- those returning many resources or aggregate/computed values.
32
+
33
+ Pick the mode by what the resources carry:
34
+ - https://w3id.org/atomgraph/client#GridMode: a card per resource, led by its image. The fit for resources
35
+ that have one (foaf:img, foaf:depiction, foaf:logo, schema:image, schema:logo, schema:thumbnailUrl):
36
+ products, possessions, people, organizations
37
+ - https://w3id.org/atomgraph/client#MapMode: a pin per resource that has geo:lat and geo:long. The fit for
38
+ places, addresses, venues, shops
39
+ - https://w3id.org/atomgraph/client#GraphMode: the resources and the links between them, as a network. The
40
+ fit for showing how things connect (who owns what, what came from where)
41
+ - https://w3id.org/atomgraph/client#ListMode: a labelled list; the default, for resources with no image or
42
+ coordinates
43
+ - https://w3id.org/atomgraph/client#TableMode: a row per resource, a column per property, for comparing
44
+ many resources property by property
45
+ - https://w3id.org/atomgraph/client#ReadMode: each resource's full description, for a few resources
46
+ - https://w3id.org/atomgraph/client#ChartMode: the resources' properties charted
42
47
 
43
48
  Note: The query parameter must be a URI of an existing sp:Select resource, not a SPARQL query string."""
44
49
 
@@ -66,7 +71,7 @@ class AddView(POST):
66
71
  },
67
72
  "mode": {
68
73
  "type": "string",
69
- "description": "Optional URI of the layout the view shows its results in (a view mode, not an object block's mode). Defaults to ListMode.",
74
+ "description": "Optional URI of the layout the view shows its results in (a view mode, not an object block's mode). Defaults to ListMode. Pick it by what the resources carry: GridMode for resources with an image, MapMode for ones with coordinates, GraphMode for how they link (see the tool description).",
70
75
  "enum": [
71
76
  "https://w3id.org/atomgraph/client#ListMode",
72
77
  "https://w3id.org/atomgraph/client#TableMode",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: web-algebra
3
- Version: 2.0.0
3
+ Version: 2.0.2
4
4
  Summary: Composable RDF operations in JSON
5
5
  Author-email: Martynas Jusevicius <martynas@atomgraph.com>
6
6
  License-Expression: Apache-2.0
@@ -33,6 +33,8 @@ Dynamic: license-file
33
33
 
34
34
  # Web-Algebra
35
35
 
36
+ [![Web-Algebra - Listed on Claude AI Directory](https://www.claudeai.directory/badge/web-algebra?theme=dark)](https://www.claudeai.directory/launches/web-algebra)
37
+
36
38
  <!-- mcp-name: io.github.AtomGraph/web-algebra -->
37
39
 
38
40
  A composable RDF operations system that translates natural language instructions into JSON-formatted domain-specific language operations for loading, querying, and writing RDF Linked Data.
@@ -48,7 +50,7 @@ Instead of agents executing semantic workflows step-by-step through individual M
48
50
 
49
51
  ## Demo
50
52
 
51
- [![ Agentic Content Management with Web-Algebra MCP](https://img.youtube.com/vi/eRMrSqKc9_E/0.jpg)](https://www.youtube.com/watch?v=eRMrSqKc9_E)
53
+ [![Web-Algebra in action: an AI agent builds Linked Data pages over MCP](https://img.youtube.com/vi/zSbvl5kmKic/maxresdefault.jpg)](https://www.youtube.com/watch?v=zSbvl5kmKic)
52
54
 
53
55
  *See WebAlgebra in action - translating natural language into RDF operations.*
54
56
 
@@ -202,6 +204,8 @@ or with Claude Code:
202
204
  claude mcp add web-algebra -e CERT_PEM_PATH=/path/to/LinkedDataHub/ssl/owner/cert.pem -e CERT_PASSWORD=******** -- uvx --from web-algebra web-algebra-mcp
203
205
  ```
204
206
 
207
+ `uvx web-algebra mcp` runs the same server.
208
+
205
209
  Environment variables:
206
210
 
207
211
  | Name | Required | Description |
@@ -48,9 +48,9 @@ def mcp_tools():
48
48
 
49
49
 
50
50
  class Stdio:
51
- def __init__(self):
51
+ def __init__(self, command=("-m", "web_algebra")):
52
52
  self.proc = subprocess.Popen(
53
- [sys.executable, "-m", "web_algebra"],
53
+ [sys.executable, *command],
54
54
  stdin=subprocess.PIPE,
55
55
  stdout=subprocess.PIPE,
56
56
  stderr=subprocess.DEVNULL,
@@ -106,6 +106,16 @@ def test_initialize_names_the_server_and_its_version(stdio):
106
106
  assert info["version"] == version("web-algebra")
107
107
 
108
108
 
109
+ def test_the_cli_mcp_command_is_the_stdio_server():
110
+ # `web-algebra mcp` is what an MCP Registry client runs (server.json)
111
+ server = Stdio(("-m", "web_algebra.main", "mcp"))
112
+ try:
113
+ answer = server.request("initialize", INITIALIZE, timeout=60)
114
+ finally:
115
+ server.close()
116
+ assert answer["result"]["serverInfo"]["name"] == "web-algebra"
117
+
118
+
109
119
  def test_initialize_offers_tools(stdio):
110
120
  assert "tools" in stdio.initialized["result"]["capabilities"]
111
121
 
@@ -39,6 +39,11 @@ def test_server_json_names_the_pypi_package():
39
39
  assert [p["identifier"] for p in SERVER["packages"] if p["registryType"] == "pypi"] == ["web-algebra"]
40
40
 
41
41
 
42
+ def test_server_json_runs_the_mcp_command():
43
+ # `uvx web-algebra` alone would start the planner, not the server
44
+ assert [p.get("packageArguments") for p in SERVER["packages"]] == [[{"type": "positional", "value": "mcp"}]]
45
+
46
+
42
47
  def test_readme_carries_the_server_name():
43
48
  assert f"mcp-name: {SERVER['name']} " in (ROOT / "README.md").read_text().replace("-->", " -->")
44
49
 
File without changes
File without changes