eclipse-bazaar 0.1.0__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.
- eclipse_bazaar-0.1.0/LICENSE +21 -0
- eclipse_bazaar-0.1.0/PKG-INFO +109 -0
- eclipse_bazaar-0.1.0/PYPI_README.md +85 -0
- eclipse_bazaar-0.1.0/README.md +172 -0
- eclipse_bazaar-0.1.0/VERSION +1 -0
- eclipse_bazaar-0.1.0/pyproject.toml +51 -0
- eclipse_bazaar-0.1.0/setup.cfg +4 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar/__init__.py +15 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar/_version.py +2 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar/catalog.py +166 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar/check.py +233 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar/cli.py +178 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar/client.py +53 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar/configparse.py +314 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar/data/catalog.json +1 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar/data/corpus.jsonl +101 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar/data/corpus.manifest.json +8 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar/data/verdict_snapshot.json +1825 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar/integrations/__init__.py +3 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar/integrations/crewai_tools.py +44 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar/integrations/langchain_tools.py +43 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar/mcp_server.py +314 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar.egg-info/PKG-INFO +109 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar.egg-info/SOURCES.txt +32 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar.egg-info/dependency_links.txt +1 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar.egg-info/entry_points.txt +3 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar.egg-info/requires.txt +6 -0
- eclipse_bazaar-0.1.0/src/eclipse_bazaar.egg-info/top_level.txt +1 -0
- eclipse_bazaar-0.1.0/tests/test_check_m1.py +432 -0
- eclipse_bazaar-0.1.0/tests/test_sdk_cli.py +131 -0
- eclipse_bazaar-0.1.0/tests/test_snapshot_parity.py +98 -0
- eclipse_bazaar-0.1.0/tests/test_sync_verdicts_dateless.py +115 -0
- eclipse_bazaar-0.1.0/tests/test_sync_verdicts_invalid_filename_date.py +129 -0
- eclipse_bazaar-0.1.0/tests/test_version_drift.py +49 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Cyan Eclipse Technologies LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: eclipse-bazaar
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Eclipse Bazaar — Cyan Eclipse Technologies' catalog of tested MCP products: MCP server, CLI, and Python SDK in one distribution.
|
|
5
|
+
Author: Cyan Eclipse Technologies LLC
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://eclipsebazaar.com
|
|
8
|
+
Project-URL: Repository, https://github.com/CYAN-ECLIPSE-TECHNOLOGIES-LLC/bazaar-mcp
|
|
9
|
+
Project-URL: Vendor, https://cetech.ai
|
|
10
|
+
Keywords: mcp,model-context-protocol,marketplace,catalog,agent-tools
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: Software Development :: Libraries
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Description-Content-Type: text/markdown
|
|
18
|
+
License-File: LICENSE
|
|
19
|
+
Provides-Extra: langchain
|
|
20
|
+
Requires-Dist: langchain-core>=0.3; extra == "langchain"
|
|
21
|
+
Provides-Extra: crewai
|
|
22
|
+
Requires-Dist: crewai>=0.80; extra == "crewai"
|
|
23
|
+
Dynamic: license-file
|
|
24
|
+
|
|
25
|
+
# eclipse-bazaar
|
|
26
|
+
|
|
27
|
+
**Eclipse Bazaar is Cyan Eclipse Technologies' own catalog** of tested
|
|
28
|
+
MCP products — at v0.1.0 it lists Cyan Eclipse Technologies products
|
|
29
|
+
only (86 listings). It is not a general index of every MCP server, and
|
|
30
|
+
this package does not claim to be one. Third-party listings are future
|
|
31
|
+
work (P2 on the server's own roadmap).
|
|
32
|
+
|
|
33
|
+
One distribution, three surfaces:
|
|
34
|
+
|
|
35
|
+
## 1. The Bazaar MCP server
|
|
36
|
+
|
|
37
|
+
```json
|
|
38
|
+
{ "mcpServers": { "eclipse-bazaar": { "command": "uvx", "args": ["eclipse-bazaar"] } } }
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Six tools — `search_products`, `find_solutions`, `get_product`,
|
|
42
|
+
`compare_products`, `get_certification`, `list_categories` — that let an
|
|
43
|
+
agent shop by *problem*, with transparent match reasons. Every listing
|
|
44
|
+
carries its Test Bench verdict and scope, or states plainly that it has
|
|
45
|
+
none; every entry carries a `not_tested` list. A product labelled
|
|
46
|
+
spec-stage is a spec, not a product; an uncertified product says so.
|
|
47
|
+
|
|
48
|
+
Catalog data ships as a stamped snapshot bundled in the wheel, and
|
|
49
|
+
verdict summaries ship as a hash-pinned verdict snapshot generated from
|
|
50
|
+
the Test Bench cards — an installed run never reads files outside the
|
|
51
|
+
package.
|
|
52
|
+
|
|
53
|
+
## 2. The `bazaar` CLI
|
|
54
|
+
|
|
55
|
+
```console
|
|
56
|
+
$ bazaar search "certificate renewal"
|
|
57
|
+
$ bazaar product certbridge-mcp
|
|
58
|
+
$ bazaar categories
|
|
59
|
+
$ bazaar check # classify your configured MCP servers
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`bazaar check` reads your MCP client configs, extracts each configured
|
|
63
|
+
server's *identity* (package / image / URL / local path), and joins it
|
|
64
|
+
locally against the published Bazaar corpus — downloaded whole and
|
|
65
|
+
verified against its sha256 manifest first. Each entry is classified
|
|
66
|
+
`CERTIFIED` (listed, Tier-2 verdict on record), `LISTED` (in the
|
|
67
|
+
catalog, no verdict yet), `NOT LISTED` (no record — a neutral fact), or
|
|
68
|
+
`UNRESOLVABLE` (no identity could be extracted, with the reason).
|
|
69
|
+
Version pins that differ from the listed version are flagged as drift.
|
|
70
|
+
|
|
71
|
+
Privacy, by construction: config `env` **values are never read, copied,
|
|
72
|
+
hashed, logged, or transmitted** — the parser redacts them structurally
|
|
73
|
+
before anything else runs. There is no telemetry. The check never
|
|
74
|
+
executes a configured server and never contacts one.
|
|
75
|
+
|
|
76
|
+
## 3. The Python SDK
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
from eclipse_bazaar import Bazaar
|
|
80
|
+
|
|
81
|
+
bz = Bazaar() # bundled snapshot, works offline
|
|
82
|
+
bz.search("ssl certificate") # same ranking/reasons as the MCP tool
|
|
83
|
+
bz.get_listing("certbridge-mcp")
|
|
84
|
+
bz.check() # the Phase-1 standing check, as a dict
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Optional framework adapters (standard adapter pattern):
|
|
88
|
+
|
|
89
|
+
```console
|
|
90
|
+
$ pip install "eclipse-bazaar[langchain]" # or [crewai]
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
from eclipse_bazaar.integrations.langchain_tools import make_langchain_tools
|
|
95
|
+
tools = make_langchain_tools()
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Scope and honesty
|
|
99
|
+
|
|
100
|
+
- Statuses and verdicts are as of the catalog build date stamped in
|
|
101
|
+
every response (`data_freshness`).
|
|
102
|
+
- Spec-stage listings are labelled spec; in-development listings say
|
|
103
|
+
so; absence of a verdict is stated, never implied.
|
|
104
|
+
- `bazaar check` v0.1 is Phase 1: it speaks only about listing and
|
|
105
|
+
Tier-2 verdict records. Further record classes join the vocabulary
|
|
106
|
+
only when the underlying records themselves are public.
|
|
107
|
+
|
|
108
|
+
Powered by Cyan Eclipse Technologies LLC (cetech.ai) — a Veteran-Owned
|
|
109
|
+
Small Business. MIT licensed.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# eclipse-bazaar
|
|
2
|
+
|
|
3
|
+
**Eclipse Bazaar is Cyan Eclipse Technologies' own catalog** of tested
|
|
4
|
+
MCP products — at v0.1.0 it lists Cyan Eclipse Technologies products
|
|
5
|
+
only (86 listings). It is not a general index of every MCP server, and
|
|
6
|
+
this package does not claim to be one. Third-party listings are future
|
|
7
|
+
work (P2 on the server's own roadmap).
|
|
8
|
+
|
|
9
|
+
One distribution, three surfaces:
|
|
10
|
+
|
|
11
|
+
## 1. The Bazaar MCP server
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{ "mcpServers": { "eclipse-bazaar": { "command": "uvx", "args": ["eclipse-bazaar"] } } }
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Six tools — `search_products`, `find_solutions`, `get_product`,
|
|
18
|
+
`compare_products`, `get_certification`, `list_categories` — that let an
|
|
19
|
+
agent shop by *problem*, with transparent match reasons. Every listing
|
|
20
|
+
carries its Test Bench verdict and scope, or states plainly that it has
|
|
21
|
+
none; every entry carries a `not_tested` list. A product labelled
|
|
22
|
+
spec-stage is a spec, not a product; an uncertified product says so.
|
|
23
|
+
|
|
24
|
+
Catalog data ships as a stamped snapshot bundled in the wheel, and
|
|
25
|
+
verdict summaries ship as a hash-pinned verdict snapshot generated from
|
|
26
|
+
the Test Bench cards — an installed run never reads files outside the
|
|
27
|
+
package.
|
|
28
|
+
|
|
29
|
+
## 2. The `bazaar` CLI
|
|
30
|
+
|
|
31
|
+
```console
|
|
32
|
+
$ bazaar search "certificate renewal"
|
|
33
|
+
$ bazaar product certbridge-mcp
|
|
34
|
+
$ bazaar categories
|
|
35
|
+
$ bazaar check # classify your configured MCP servers
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`bazaar check` reads your MCP client configs, extracts each configured
|
|
39
|
+
server's *identity* (package / image / URL / local path), and joins it
|
|
40
|
+
locally against the published Bazaar corpus — downloaded whole and
|
|
41
|
+
verified against its sha256 manifest first. Each entry is classified
|
|
42
|
+
`CERTIFIED` (listed, Tier-2 verdict on record), `LISTED` (in the
|
|
43
|
+
catalog, no verdict yet), `NOT LISTED` (no record — a neutral fact), or
|
|
44
|
+
`UNRESOLVABLE` (no identity could be extracted, with the reason).
|
|
45
|
+
Version pins that differ from the listed version are flagged as drift.
|
|
46
|
+
|
|
47
|
+
Privacy, by construction: config `env` **values are never read, copied,
|
|
48
|
+
hashed, logged, or transmitted** — the parser redacts them structurally
|
|
49
|
+
before anything else runs. There is no telemetry. The check never
|
|
50
|
+
executes a configured server and never contacts one.
|
|
51
|
+
|
|
52
|
+
## 3. The Python SDK
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
from eclipse_bazaar import Bazaar
|
|
56
|
+
|
|
57
|
+
bz = Bazaar() # bundled snapshot, works offline
|
|
58
|
+
bz.search("ssl certificate") # same ranking/reasons as the MCP tool
|
|
59
|
+
bz.get_listing("certbridge-mcp")
|
|
60
|
+
bz.check() # the Phase-1 standing check, as a dict
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Optional framework adapters (standard adapter pattern):
|
|
64
|
+
|
|
65
|
+
```console
|
|
66
|
+
$ pip install "eclipse-bazaar[langchain]" # or [crewai]
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
from eclipse_bazaar.integrations.langchain_tools import make_langchain_tools
|
|
71
|
+
tools = make_langchain_tools()
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Scope and honesty
|
|
75
|
+
|
|
76
|
+
- Statuses and verdicts are as of the catalog build date stamped in
|
|
77
|
+
every response (`data_freshness`).
|
|
78
|
+
- Spec-stage listings are labelled spec; in-development listings say
|
|
79
|
+
so; absence of a verdict is stated, never implied.
|
|
80
|
+
- `bazaar check` v0.1 is Phase 1: it speaks only about listing and
|
|
81
|
+
Tier-2 verdict records. Further record classes join the vocabulary
|
|
82
|
+
only when the underlying records themselves are public.
|
|
83
|
+
|
|
84
|
+
Powered by Cyan Eclipse Technologies LLC (cetech.ai) — a Veteran-Owned
|
|
85
|
+
Small Business. MIT licensed.
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Eclipse Bazaar MCP
|
|
2
|
+
|
|
3
|
+
**Powered by Cyan Eclipse Technologies** — https://cetech.ai
|
|
4
|
+
The agent-facing discovery layer for **Eclipse Bazaar** (eclipsebazaar.com) — CETech's tested MCP marketplace.
|
|
5
|
+
|
|
6
|
+
## Why this exists
|
|
7
|
+
|
|
8
|
+
Agents shop by problem, not by product name. A registry listing tells an agent that a server *exists*; it does not say what problem the tool solves, whether anyone tested it, or what was **not** tested. Eclipse Bazaar's differentiator is exactly that honesty layer — every listing carries its Test Bench verdict, its certified scope, and its not-tested list, or states plainly that no verdict exists yet.
|
|
9
|
+
|
|
10
|
+
This MCP server is how agents query that catalog:
|
|
11
|
+
|
|
12
|
+
- **By problem** — `find_solutions` matches a plain-language problem against problem statements + capabilities and explains the fit, with status and certification badges inline.
|
|
13
|
+
- **By keyword** — `search_products` ranks across names, capabilities, and categories, and every hit carries `match_reasons[]`: the ranking is never a black box.
|
|
14
|
+
- **With receipts** — `get_certification` returns the latest Test Bench verdict plus a live summary of the underlying scorecard (check counts, environment, date), the certified scope, and the `not_tested` list.
|
|
15
|
+
- **Honestly labelled** — spec-stage products are `status: spec` and `certified: false`; products whose bench run is pending say "not yet certified"; The White Report MCP's verdict is CERTIFIED(live) — the 2026-10-25 live-host bench (card -11) superseded its earlier logic-level PARTIAL, and every surface is kept in sync from the newest scorecard by `sync_verdicts.py`.
|
|
16
|
+
|
|
17
|
+
## Tools (6)
|
|
18
|
+
|
|
19
|
+
| Tool | What it does |
|
|
20
|
+
|---|---|
|
|
21
|
+
| `search_products(query, category?)` | Ranked keyword search; every hit carries `match_reasons[]`. |
|
|
22
|
+
| `find_solutions(problem)` | Problem-first matching with fit explanation + status/certification badges. |
|
|
23
|
+
| `get_product(id)` | Full entry incl. certification block and what was NOT tested. |
|
|
24
|
+
| `compare_products(ids[])` | Side-by-side: status, pricing model, certification, platforms. |
|
|
25
|
+
| `get_certification(id)` | Latest bench verdict + scorecard summary + scope + not_tested; explicit "NOT YET CERTIFIED" when none exists. |
|
|
26
|
+
| `list_categories()` | Categories with counts by status. |
|
|
27
|
+
|
|
28
|
+
Every response includes a `data_freshness` note (catalog build date + source references). Scorecard summaries are read live from `../test-bench/results/` at call time.
|
|
29
|
+
|
|
30
|
+
## Catalog (v0.1.0 — 101 products, CETech only)
|
|
31
|
+
|
|
32
|
+
Seeded only from real sources — each product's `bazaar-manifest.json`, the latest Test Bench scorecard, the MCP product slate, and the Eclipse Mail spec. No invented products, no invented verdicts.
|
|
33
|
+
|
|
34
|
+
| Product | Status | Bench verdict |
|
|
35
|
+
|---|---|---|
|
|
36
|
+
| Eclipse Agent Wallet MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(sandbox) |
|
|
37
|
+
| CertBridge MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(staging) |
|
|
38
|
+
| HostBridge MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local-real) |
|
|
39
|
+
| Eclipse Connect | dogfood | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(dogfood) |
|
|
40
|
+
| The White Report MCP | live | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(live) |
|
|
41
|
+
| Eclipse Apply MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(sandbox) |
|
|
42
|
+
| Eclipse Herald MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
43
|
+
| Eclipse Beacon MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
44
|
+
| Eclipse Cluster MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(simulator) |
|
|
45
|
+
| Eclipse Thread MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(simulator) |
|
|
46
|
+
| Eclipse Constellation MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
47
|
+
| Eclipse Deep Field MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
48
|
+
| Eclipse Pantry MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(simulator) |
|
|
49
|
+
| Eclipse Marquee MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(simulator) |
|
|
50
|
+
| Eclipse Dispatch MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
51
|
+
| Eclipse Social Core MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
52
|
+
| Eclipse Aperture MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
53
|
+
| Eclipse Zephyr MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(live-read) |
|
|
54
|
+
| Eclipse Environment MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(simulator) |
|
|
55
|
+
| Eclipse Procure MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(simulator) |
|
|
56
|
+
| Eclipse Gig Core MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
57
|
+
| Eclipse Compass MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(simulator) |
|
|
58
|
+
| Eclipse Stage MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(simulator) |
|
|
59
|
+
| Eclipse Zenith MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(simulator) |
|
|
60
|
+
| Eclipse Muster MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
61
|
+
| Eclipse Haven MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(simulator) |
|
|
62
|
+
| Eclipse Orbit MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(simulator) |
|
|
63
|
+
| Eclipse Voice Core MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
64
|
+
| Eclipse Trunk MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(simulator) |
|
|
65
|
+
| Eclipse Connect MCP | dogfood | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(dogfood-facade) |
|
|
66
|
+
| Eclipse Connect · Beyond Compare MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(simulated) |
|
|
67
|
+
| AgentReady MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
68
|
+
| Florida Bid Intel MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
69
|
+
| Eclipse Bazaar MCP (this server) | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
70
|
+
| Eclipse Envoy MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
71
|
+
| Eclipse Fathom MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
72
|
+
| Eclipse Codex MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
73
|
+
| Eclipse Ledger MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
74
|
+
| Eclipse Till MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) · Ads Rail P1 extension CERTIFIED(local/simulator), Stripe test mode only — NOT PROVEN IN STRIPE |
|
|
75
|
+
| Eclipse Book MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
76
|
+
| Eclipse Forecast MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
77
|
+
| Eclipse Strike MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
78
|
+
| Eclipse Meter MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
79
|
+
| Eclipse Tripwire MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
80
|
+
| Eclipse Umbra MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
81
|
+
| Eclipse Blackbox MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
82
|
+
| Eclipse Docket MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
83
|
+
| Eclipse Countermark MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
84
|
+
| Eclipse Census MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
85
|
+
| Eclipse Crosswalk MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
86
|
+
| Eclipse Redteam MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
87
|
+
| Eclipse Span MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
88
|
+
| Eclipse Airtime MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local/simulator) |
|
|
89
|
+
| Eclipse Friction MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
90
|
+
| Eclipse Test Bench | in-development | not certified — in-house artifact, productization in progress (slate T1) |
|
|
91
|
+
| Eclipse Stocktake | in-development | not certified — in-house artifact, productization in progress (slate T4) |
|
|
92
|
+
| Eclipse Press | in-development | not certified — in-house artifact, productization in progress (slate T3) |
|
|
93
|
+
| Herald Card Kit | in-development | not certified — in-house artifact, productization in progress (slate T7) |
|
|
94
|
+
| Eclipse BidMatrix MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
95
|
+
| Section 508 Evidence MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
96
|
+
| FedScope MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
97
|
+
| Eclipse Health Check MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
98
|
+
| Eclipse Legacy Recon MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) — at the NARROWED OBSERVED SCOPE (CLAIM-SCOPE.md), scoped re-bench card -11 (30/30 checks); cards -1..-10 retained append-only (card -10 FAILED at the former universal claim) |
|
|
99
|
+
| Eclipse Steward MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
100
|
+
| Eclipse Mail MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local / fixture-only) |
|
|
101
|
+
| Eclipse Proof MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
102
|
+
| Eclipse Charter MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
103
|
+
| Eclipse Colophon MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local/simulator) |
|
|
104
|
+
| Eclipse Tether MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(simulator) |
|
|
105
|
+
| Eclipse Proving MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(simulator) |
|
|
106
|
+
| Eclipse Wageward MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
107
|
+
| Eclipse Covenant MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local/simulator) |
|
|
108
|
+
| Eclipse Meridian MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local, synthetic scope) |
|
|
109
|
+
| Eclipse Consent MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
110
|
+
| Eclipse Lineage MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
111
|
+
| Eclipse Attest MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
112
|
+
| Eclipse Revoke MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
113
|
+
| Eclipse Keyhold MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
114
|
+
| Eclipse Loft MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(simulator) |
|
|
115
|
+
| Eclipse Corona MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
116
|
+
| Eclipse Crosslist MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(split per facet) |
|
|
117
|
+
| Eclipse Verbatim MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
118
|
+
| Eclipse Roll MCP | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
119
|
+
| Eclipse Verbatim — Executive Orders | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
120
|
+
| Eclipse Flood Witness | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
121
|
+
| Eclipse Recall Witness | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
122
|
+
| Eclipse Sunset | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED (local, fixture) |
|
|
123
|
+
| Eclipse Nexus Witness | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED (local, fixture-vintage) |
|
|
124
|
+
| Eclipse Warranty | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED (local, fixture) |
|
|
125
|
+
| Eclipse Toolprint | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED (local) |
|
|
126
|
+
| Eclipse Boomerang | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED (local, fixture) |
|
|
127
|
+
| Eclipse Rebuttal | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED (local, fixture) |
|
|
128
|
+
| Eclipse Crawlway | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED (local, fixture) |
|
|
129
|
+
| Eclipse Outwatch | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED (LOCAL) |
|
|
130
|
+
| Eclipse Feedforge | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED (local, fixture) |
|
|
131
|
+
|
|
132
|
+
| Eclipse Permits | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local) |
|
|
133
|
+
| Eclipse Scholarly Witness | in-development | <img src="seal-certified.svg" width="20" alt="Cyan Eclipse Certified"> CERTIFIED(local, fixture scope) |
|
|
134
|
+
| Eclipse Patent Witness | in-development | PARTIAL (local, FIXTURE scope) — certification withheld on three MED defects (PW-D1, PW-D2, PW-D4); not certified |
|
|
135
|
+
| Eclipse SEC Figure Witness | in-development | not certified — no Test Bench verdict on record yet (listed only) |
|
|
136
|
+
| Eclipse Trademark Witness | in-development | not certified — no Test Bench verdict on record yet (listed only) |
|
|
137
|
+
|
|
138
|
+
## The `bazaar` CLI — including `bazaar check`
|
|
139
|
+
|
|
140
|
+
```console
|
|
141
|
+
$ bazaar search "certificate renewal"
|
|
142
|
+
$ bazaar product certbridge-mcp
|
|
143
|
+
$ bazaar categories
|
|
144
|
+
$ bazaar check # classify your configured MCP servers
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
`bazaar check` reads your MCP client configs, extracts each configured server's *identity* (package / image / URL / local path), and joins it locally against the published Bazaar corpus — downloaded whole and verified against its sha256 manifest first. Each entry is classified `CERTIFIED` (listed, Tier-2 verdict on record), `LISTED` (in the catalog, no verdict yet), `NOT LISTED` (no record — a neutral fact), or `UNRESOLVABLE` (no identity could be extracted, with the reason). Version pins that differ from the listed version are flagged as drift.
|
|
148
|
+
|
|
149
|
+
Privacy, by construction: config `env` **values are never read, copied, hashed, logged, or transmitted** — the parser redacts them structurally before anything else runs. There is no telemetry. The check never executes a configured server and never contacts one. (The CLI ships in the `eclipse-bazaar` PyPI distribution alongside the MCP server above.)
|
|
150
|
+
|
|
151
|
+
## Run it
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
python3 server.py # MCP over stdio, stdlib only, no dependencies
|
|
155
|
+
python3 smoke_test.py # protocol + routing + honesty assertions (9 checks)
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Catalog lives in `catalog.json` beside the server (override with `$BAZAAR_CATALOG`).
|
|
159
|
+
|
|
160
|
+
## Verdict sync (EB-09)
|
|
161
|
+
|
|
162
|
+
Bench verdicts have ONE source of truth: the newest scorecard per tool in `../test-bench/results/` (run-sequence suffix decides — a `-11` card supersedes `-2`). `python3 sync_verdicts.py` rebuilds `verdict-ledger.json` and checks catalog.json, product `bazaar-manifest.json` files, this README's table, and the storefront bench lines against it (exit 1 on drift); `--apply` fixes the machine-safe fields. Dogfood logs annotate live state only — they never change a bench verdict. Run it after every bench run.
|
|
163
|
+
|
|
164
|
+
## Scope & roadmap
|
|
165
|
+
|
|
166
|
+
- **v0.1.0 (this):** CETech catalog only, discovery only. **No purchasing.**
|
|
167
|
+
- **P2:** third-party listings (the vendor catalog opens; listings pass the Test Bench gate before they can carry a badge).
|
|
168
|
+
- **Future purchase hooks (noted, not built):** x402 pay-per-call for paid tools, and an **Agent Wallet policy check before any charge** — an agent's granted spending scope governs Bazaar purchases the same way it governs everything else.
|
|
169
|
+
|
|
170
|
+
## License / attribution
|
|
171
|
+
|
|
172
|
+
A Cyan Eclipse Technologies product. The "Powered by Cyan Eclipse Technologies" attribution travels with it.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.1.0
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "eclipse-bazaar"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Eclipse Bazaar — Cyan Eclipse Technologies' catalog of tested MCP products: MCP server, CLI, and Python SDK in one distribution."
|
|
9
|
+
readme = "PYPI_README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Cyan Eclipse Technologies LLC" },
|
|
14
|
+
]
|
|
15
|
+
keywords = ["mcp", "model-context-protocol", "marketplace", "catalog", "agent-tools"]
|
|
16
|
+
classifiers = [
|
|
17
|
+
"Development Status :: 3 - Alpha",
|
|
18
|
+
"Intended Audience :: Developers",
|
|
19
|
+
"License :: OSI Approved :: MIT License",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Topic :: Software Development :: Libraries",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.urls]
|
|
25
|
+
Homepage = "https://eclipsebazaar.com"
|
|
26
|
+
Repository = "https://github.com/CYAN-ECLIPSE-TECHNOLOGIES-LLC/bazaar-mcp"
|
|
27
|
+
Vendor = "https://cetech.ai"
|
|
28
|
+
|
|
29
|
+
[project.optional-dependencies]
|
|
30
|
+
langchain = ["langchain-core>=0.3"]
|
|
31
|
+
crewai = ["crewai>=0.80"]
|
|
32
|
+
|
|
33
|
+
[project.scripts]
|
|
34
|
+
eclipse-bazaar = "eclipse_bazaar.mcp_server:main"
|
|
35
|
+
bazaar = "eclipse_bazaar.cli:main"
|
|
36
|
+
|
|
37
|
+
# Version is dynamic: server.json is the single source of truth;
|
|
38
|
+
# tools/sync_version.py stamps it into VERSION (gate A3 version law).
|
|
39
|
+
[tool.setuptools.dynamic]
|
|
40
|
+
version = { file = "VERSION" }
|
|
41
|
+
|
|
42
|
+
[tool.setuptools.packages.find]
|
|
43
|
+
where = ["src"]
|
|
44
|
+
|
|
45
|
+
[tool.setuptools.package-data]
|
|
46
|
+
eclipse_bazaar = [
|
|
47
|
+
"data/catalog.json",
|
|
48
|
+
"data/verdict_snapshot.json",
|
|
49
|
+
"data/corpus.jsonl",
|
|
50
|
+
"data/corpus.manifest.json",
|
|
51
|
+
]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Eclipse Bazaar · © 2026 Cyan Eclipse Technologies LLC · cetech.ai
|
|
2
|
+
"""eclipse-bazaar — one distribution, three surfaces (gate A5):
|
|
3
|
+
|
|
4
|
+
* the Eclipse Bazaar MCP server (console script: eclipse-bazaar)
|
|
5
|
+
* the `bazaar` CLI (search / product / categories / check)
|
|
6
|
+
* the Python SDK (from eclipse_bazaar import Bazaar)
|
|
7
|
+
|
|
8
|
+
Catalog data ships as a stamped bundled snapshot; verdict summaries
|
|
9
|
+
ship as a hash-pinned verdict snapshot (gate A1). Powered by Cyan
|
|
10
|
+
Eclipse Technologies (cetech.ai).
|
|
11
|
+
"""
|
|
12
|
+
from ._version import __version__
|
|
13
|
+
from .client import Bazaar
|
|
14
|
+
|
|
15
|
+
__all__ = ["__version__", "Bazaar"]
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Eclipse Bazaar · © 2026 Cyan Eclipse Technologies LLC · cetech.ai
|
|
2
|
+
"""Data access for the eclipse-bazaar distribution.
|
|
3
|
+
|
|
4
|
+
Resolution order (first hit wins):
|
|
5
|
+
catalog $BAZAAR_CATALOG -> repo-root catalog.json (repo mode only,
|
|
6
|
+
kept canonical by sync_verdicts.py) -> bundled
|
|
7
|
+
data/catalog.json
|
|
8
|
+
corpus see eclipse_bazaar.check (bulk file, sha256-verified)
|
|
9
|
+
scorecard bundled verdict snapshot first (stamped + hash-pinned by
|
|
10
|
+
tools/make_verdict_snapshot.py); repo mode falls back to the
|
|
11
|
+
live Test Bench card when the snapshot lacks the ref.
|
|
12
|
+
|
|
13
|
+
Gate A1: packaged mode never reaches for ../test-bench/results/ — the
|
|
14
|
+
snapshot is the only verdict source an installed wheel needs.
|
|
15
|
+
|
|
16
|
+
Repo mode is a proven state, not a path-existence guess (PY-D1): it
|
|
17
|
+
holds only inside the bazaar-mcp checkout itself (its own markers —
|
|
18
|
+
.git and server.json at the repo root) or when BAZAAR_REPO_MODE=1 is
|
|
19
|
+
set explicitly. An installed wheel is snapshot-only by construction:
|
|
20
|
+
files planted at the computed install-tree levels are never served.
|
|
21
|
+
"""
|
|
22
|
+
import json
|
|
23
|
+
import os
|
|
24
|
+
import urllib.request
|
|
25
|
+
from pathlib import Path
|
|
26
|
+
|
|
27
|
+
PKG_DIR = Path(__file__).resolve().parent
|
|
28
|
+
DATA_DIR = PKG_DIR / "data"
|
|
29
|
+
REPO_ROOT = PKG_DIR.parents[1] # dev layout: bazaar-mcp/ (site-packages when installed)
|
|
30
|
+
CETECH_DIR = PKG_DIR.parents[2] # dev layout: cyan-eclipse/ (meaningless when installed)
|
|
31
|
+
|
|
32
|
+
REFRESH_URLS = [
|
|
33
|
+
"https://raw.githubusercontent.com/CYAN-ECLIPSE-TECHNOLOGIES-LLC/bazaar-mcp/main/catalog.json",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
_LAST_SOURCE = "bundled snapshot"
|
|
37
|
+
_SNAPSHOT = None
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def _repo_mode() -> bool:
|
|
41
|
+
"""True only in the bazaar-mcp checkout itself (proven by its own
|
|
42
|
+
markers) or under an explicit BAZAAR_REPO_MODE=1 opt-in. This gates
|
|
43
|
+
both repo-mode fallbacks below; an installed wheel never satisfies
|
|
44
|
+
it by accident of the install layout (PY-D1)."""
|
|
45
|
+
if os.environ.get("BAZAAR_REPO_MODE") == "1":
|
|
46
|
+
return True
|
|
47
|
+
return (REPO_ROOT / ".git").exists() and \
|
|
48
|
+
(REPO_ROOT / "server.json").exists()
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def catalog_path() -> Path:
|
|
52
|
+
env = os.environ.get("BAZAAR_CATALOG")
|
|
53
|
+
if env:
|
|
54
|
+
return Path(env)
|
|
55
|
+
repo_cat = REPO_ROOT / "catalog.json"
|
|
56
|
+
if _repo_mode() and repo_cat.exists():
|
|
57
|
+
return repo_cat
|
|
58
|
+
return DATA_DIR / "catalog.json"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def fetch_catalog(url: str, timeout: int = 15) -> dict:
|
|
62
|
+
req = urllib.request.Request(url, headers={"Accept": "application/json"})
|
|
63
|
+
with urllib.request.urlopen(req, timeout=timeout) as resp:
|
|
64
|
+
return json.loads(resp.read().decode("utf-8"))
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def catalog_dict(refresh: bool = False) -> dict:
|
|
68
|
+
"""The catalog as a dict. refresh=True tries the public HTTPS JSON
|
|
69
|
+
source first (one bulk document — never per-product queries) and
|
|
70
|
+
falls back to the local snapshot on any failure."""
|
|
71
|
+
global _LAST_SOURCE
|
|
72
|
+
if refresh:
|
|
73
|
+
for url in REFRESH_URLS:
|
|
74
|
+
try:
|
|
75
|
+
cat = fetch_catalog(url)
|
|
76
|
+
if isinstance(cat, dict) and "products" in cat:
|
|
77
|
+
_LAST_SOURCE = f"refreshed from {url}"
|
|
78
|
+
return cat
|
|
79
|
+
except Exception:
|
|
80
|
+
continue
|
|
81
|
+
path = catalog_path()
|
|
82
|
+
cat = json.loads(path.read_text())
|
|
83
|
+
_LAST_SOURCE = ("repo catalog.json" if path == REPO_ROOT / "catalog.json"
|
|
84
|
+
else "bundled snapshot")
|
|
85
|
+
return cat
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def freshness(cat: dict) -> dict:
|
|
89
|
+
return {"catalog_built": cat.get("built"),
|
|
90
|
+
"sources": cat.get("sources", []),
|
|
91
|
+
"served_from": _LAST_SOURCE,
|
|
92
|
+
"note": "Statuses and verdicts are as of the catalog build date; "
|
|
93
|
+
"scorecard summaries come from the stamped verdict "
|
|
94
|
+
"snapshot bundled with this package (hash-pinned to the "
|
|
95
|
+
"Test Bench cards), or the referenced card in repo mode."}
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
# ------------------------------------------------------------ scorecards
|
|
99
|
+
def _check_rows(sc: dict):
|
|
100
|
+
"""Normalise the three Test Bench card shapes to (name, verdict):
|
|
101
|
+
list-of-dicts (original), dict-of-results (later cards), and
|
|
102
|
+
checks-absent (scoped re-bench cards -> no rows)."""
|
|
103
|
+
checks = sc.get("checks")
|
|
104
|
+
if isinstance(checks, list):
|
|
105
|
+
for ch in checks:
|
|
106
|
+
if isinstance(ch, dict):
|
|
107
|
+
yield ch.get("name"), ch.get("verdict", "other")
|
|
108
|
+
elif isinstance(checks, dict):
|
|
109
|
+
for name, res in checks.items():
|
|
110
|
+
if isinstance(res, dict):
|
|
111
|
+
if "verdict" in res:
|
|
112
|
+
yield name, res["verdict"]
|
|
113
|
+
elif "pass" in res:
|
|
114
|
+
yield name, "pass" if res["pass"] else "fail"
|
|
115
|
+
else:
|
|
116
|
+
yield name, "other"
|
|
117
|
+
else:
|
|
118
|
+
yield name, "other"
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def summarize_card(sc: dict) -> dict:
|
|
122
|
+
"""Scorecard file -> the summary the server returns. Pure function —
|
|
123
|
+
tools/make_verdict_snapshot.py builds the snapshot with this exact
|
|
124
|
+
code, which is what makes packaged/repo parity testable. (The
|
|
125
|
+
pre-packaging server crashed on dict-shaped and checks-absent cards;
|
|
126
|
+
the summary for list-shaped cards is unchanged.)"""
|
|
127
|
+
counts = {"pass": 0, "fail": 0, "na": 0, "other": 0}
|
|
128
|
+
na_names, fail_names = [], []
|
|
129
|
+
total = 0
|
|
130
|
+
for name, v in _check_rows(sc):
|
|
131
|
+
total += 1
|
|
132
|
+
counts[v if v in counts else "other"] += 1
|
|
133
|
+
if v == "na":
|
|
134
|
+
na_names.append(name)
|
|
135
|
+
if v == "fail":
|
|
136
|
+
fail_names.append(name)
|
|
137
|
+
return {"tool": sc.get("tool") or sc.get("product"),
|
|
138
|
+
"version": sc.get("version"),
|
|
139
|
+
"bench_date": sc.get("bench_date") or sc.get("date"),
|
|
140
|
+
"bench_version": sc.get("bench_version"),
|
|
141
|
+
"environment": sc.get("environment"),
|
|
142
|
+
"verdict": sc.get("verdict"),
|
|
143
|
+
"checks_total": total, "counts": counts,
|
|
144
|
+
"not_tested_checks": na_names,
|
|
145
|
+
"failed_checks": fail_names}
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def load_snapshot():
|
|
149
|
+
global _SNAPSHOT
|
|
150
|
+
if _SNAPSHOT is None:
|
|
151
|
+
path = DATA_DIR / "verdict_snapshot.json"
|
|
152
|
+
_SNAPSHOT = json.loads(path.read_text()) if path.exists() else {}
|
|
153
|
+
return _SNAPSHOT
|
|
154
|
+
|
|
155
|
+
|
|
156
|
+
def scorecard_summary(ref: str):
|
|
157
|
+
"""Summary for a catalog scorecard_ref, or None if unavailable."""
|
|
158
|
+
snap = load_snapshot()
|
|
159
|
+
rec = (snap.get("cards") or {}).get(ref)
|
|
160
|
+
if rec is not None:
|
|
161
|
+
return rec["summary"]
|
|
162
|
+
if _repo_mode():
|
|
163
|
+
path = CETECH_DIR / ref # the live Test Bench card, checkout only
|
|
164
|
+
if path.exists():
|
|
165
|
+
return summarize_card(json.loads(path.read_text()))
|
|
166
|
+
return None
|