zetesis 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.
zetesis-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Reut Avidan
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.
zetesis-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,84 @@
1
+ Metadata-Version: 2.4
2
+ Name: zetesis
3
+ Version: 0.1.0
4
+ Summary: MCP client for Zetesis: scientific due diligence on a claim, evaluated by a hosted engine and sealed in a verifiable attestation.
5
+ Project-URL: Homepage, https://api.zetesis.science
6
+ Project-URL: Signup, https://api.zetesis.science/signup
7
+ Author-email: Reut Avidan <reutavidan@gmail.com>
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: biotech,claim-verification,due-diligence,evaluation,mcp,research,science
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Scientific/Engineering
19
+ Requires-Python: >=3.10
20
+ Requires-Dist: mcp>=1.2.0
21
+ Description-Content-Type: text/markdown
22
+
23
+ # Zetesis
24
+
25
+ Scientific due diligence on a claim, from inside Claude, Copilot, or any MCP host.
26
+
27
+ Zetesis takes a high-dimensional scientific or technical claim and grades it
28
+ dimension by dimension against public literature, clinical trials, and filings.
29
+ It returns an overall reading, cites every source by id, and, for a full
30
+ evaluation, translates the science into what a commitment to the claim turns on
31
+ and seals the result in an attestation anyone can re-check.
32
+
33
+ This package is a thin MCP client. It holds no keys and runs no model. Every call
34
+ is proxied to the hosted engine at <https://api.zetesis.science> with your token.
35
+
36
+ ## Get a token
37
+
38
+ Free, no card, at <https://api.zetesis.science/signup>. The free plan gives you a
39
+ handful of screening evaluations each month.
40
+
41
+ ## Connect it
42
+
43
+ Claude Code:
44
+
45
+ ```bash
46
+ claude mcp add zetesis --env ZETESIS_TOKEN=zk_... -- uvx --from zetesis zetesis-client
47
+ ```
48
+
49
+ Claude Desktop (`claude_desktop_config.json`):
50
+
51
+ ```json
52
+ {
53
+ "mcpServers": {
54
+ "zetesis": {
55
+ "command": "uvx",
56
+ "args": ["--from", "zetesis", "zetesis-client"],
57
+ "env": { "ZETESIS_TOKEN": "zk_..." }
58
+ }
59
+ }
60
+ }
61
+ ```
62
+
63
+ ## Tools
64
+
65
+ - **evaluate_claim** — grade a claim. `depth="screen"` returns the verdict directly
66
+ (free tier); `depth="deep"` runs the full signed dossier in the background.
67
+ `mode="research"` is science only; `mode="diligence"` adds the capital reading.
68
+ - **check_evaluation** — get the verdict and the rendered dossier link for a deep run.
69
+ - **verify_attestation** — re-check any Zetesis attestation. No account needed.
70
+ - **account_status** — your plan and remaining evaluations or credits.
71
+
72
+ ## How it grades
73
+
74
+ It grades only what the evidence supports, cites sources by hard id (PMID, DOI,
75
+ NCT, NIH grant, SEC filing), and flags gaps rather than filling them. It never
76
+ invents citations. Claim text is not logged; only metadata (the routed domain,
77
+ depth, counts) is kept.
78
+
79
+ ## Configuration
80
+
81
+ - `ZETESIS_TOKEN` — your token (required for evaluations; verify works without one)
82
+ - `ZETESIS_API` — override the API base (default `https://api.zetesis.science`)
83
+
84
+ MIT licensed. The hosted engine is a separate service.
@@ -0,0 +1,53 @@
1
+ # Publish `zetesis` to PyPI
2
+
3
+ The package is built and validated in `dist/`. Publishing is your action because
4
+ it needs your PyPI account, and it is permanent (a version number can never be
5
+ reused or reclaimed).
6
+
7
+ ## 1. One-time: PyPI account + token
8
+
9
+ - Create an account at <https://pypi.org> (verify the email).
10
+ - Account settings → API tokens → **Add API token**. Scope it to "Entire account"
11
+ for the first upload (you can narrow it to the `zetesis` project afterward).
12
+ - Copy the token (starts with `pypi-`). It is shown once.
13
+
14
+ ## 2. Publish
15
+
16
+ From this folder:
17
+
18
+ ```bash
19
+ cd /Users/reutavidan/zetesis/01-current/zetesis-pypi
20
+ UV_PUBLISH_TOKEN=pypi-XXXX uv publish
21
+ ```
22
+
23
+ (Equivalent with twine: `uvx twine upload -u __token__ -p pypi-XXXX dist/*`.)
24
+
25
+ ## 3. Verify it is live
26
+
27
+ ```bash
28
+ uvx --from zetesis zetesis-client # should start (Ctrl+C to stop); confirms install works
29
+ ```
30
+
31
+ Then the marketplace / user config just uses the published name:
32
+
33
+ ```bash
34
+ claude mcp add zetesis --env ZETESIS_TOKEN=zk_... -- uvx --from zetesis zetesis-client
35
+ ```
36
+
37
+ ## Optional: dry run on TestPyPI first
38
+
39
+ ```bash
40
+ UV_PUBLISH_TOKEN=pypi-TESTTOKEN uv publish --publish-url https://test.pypi.org/legacy/
41
+ ```
42
+
43
+ ## Future releases
44
+
45
+ Bump `version` in `pyproject.toml`, then `uv build` and `uv publish` again. You
46
+ cannot overwrite 0.1.0; the next upload must be 0.1.1 or higher.
47
+
48
+ ## After publishing: list on the marketplaces
49
+
50
+ - **Anthropic MCP directory**: submit the server (name, description, the `uvx --from
51
+ zetesis zetesis-client` command, the tool list). Goes through a review.
52
+ - **Microsoft Copilot store**: submit as a connector.
53
+ Two named reference users help both, since neither store features a zero-usage server.
@@ -0,0 +1,62 @@
1
+ # Zetesis
2
+
3
+ Scientific due diligence on a claim, from inside Claude, Copilot, or any MCP host.
4
+
5
+ Zetesis takes a high-dimensional scientific or technical claim and grades it
6
+ dimension by dimension against public literature, clinical trials, and filings.
7
+ It returns an overall reading, cites every source by id, and, for a full
8
+ evaluation, translates the science into what a commitment to the claim turns on
9
+ and seals the result in an attestation anyone can re-check.
10
+
11
+ This package is a thin MCP client. It holds no keys and runs no model. Every call
12
+ is proxied to the hosted engine at <https://api.zetesis.science> with your token.
13
+
14
+ ## Get a token
15
+
16
+ Free, no card, at <https://api.zetesis.science/signup>. The free plan gives you a
17
+ handful of screening evaluations each month.
18
+
19
+ ## Connect it
20
+
21
+ Claude Code:
22
+
23
+ ```bash
24
+ claude mcp add zetesis --env ZETESIS_TOKEN=zk_... -- uvx --from zetesis zetesis-client
25
+ ```
26
+
27
+ Claude Desktop (`claude_desktop_config.json`):
28
+
29
+ ```json
30
+ {
31
+ "mcpServers": {
32
+ "zetesis": {
33
+ "command": "uvx",
34
+ "args": ["--from", "zetesis", "zetesis-client"],
35
+ "env": { "ZETESIS_TOKEN": "zk_..." }
36
+ }
37
+ }
38
+ }
39
+ ```
40
+
41
+ ## Tools
42
+
43
+ - **evaluate_claim** — grade a claim. `depth="screen"` returns the verdict directly
44
+ (free tier); `depth="deep"` runs the full signed dossier in the background.
45
+ `mode="research"` is science only; `mode="diligence"` adds the capital reading.
46
+ - **check_evaluation** — get the verdict and the rendered dossier link for a deep run.
47
+ - **verify_attestation** — re-check any Zetesis attestation. No account needed.
48
+ - **account_status** — your plan and remaining evaluations or credits.
49
+
50
+ ## How it grades
51
+
52
+ It grades only what the evidence supports, cites sources by hard id (PMID, DOI,
53
+ NCT, NIH grant, SEC filing), and flags gaps rather than filling them. It never
54
+ invents citations. Claim text is not logged; only metadata (the routed domain,
55
+ depth, counts) is kept.
56
+
57
+ ## Configuration
58
+
59
+ - `ZETESIS_TOKEN` — your token (required for evaluations; verify works without one)
60
+ - `ZETESIS_API` — override the API base (default `https://api.zetesis.science`)
61
+
62
+ MIT licensed. The hosted engine is a separate service.
@@ -0,0 +1,43 @@
1
+ # Listing Zetesis on the MCP registry and the Claude Connectors Directory
2
+
3
+ Do this after publishing `zetesis` to PyPI (see PUBLISH.md).
4
+
5
+ ## 1. Official MCP Registry (the canonical feed)
6
+
7
+ The registry is the hub; downstream directories (Smithery, Glama, MCP.so, PulseMCP)
8
+ pull from it. `server.json` is ready in this folder.
9
+
10
+ - **Namespace + verification.** `server.json` uses `science.zetesis/zetesis`, which
11
+ requires proving you control zetesis.science (a DNS TXT record or a file the
12
+ registry publisher tells you to serve). Alternatively switch the name to
13
+ `io.github.reutavidan/zetesis` and verify with your GitHub account, which is
14
+ quicker.
15
+ - **Publish.** Install the registry publisher CLI (`mcp-publisher`), authenticate
16
+ for your namespace, and run it against `server.json`. It validates the file
17
+ against the current schema and pushes the listing. Follow the current steps at
18
+ <https://modelcontextprotocol.io/registry/about> (the schema and CLI evolve, so
19
+ validate against the live schema when you submit).
20
+
21
+ ## 2. Claude Connectors Directory (to be inside Claude)
22
+
23
+ Separate from the registry, and reviewed by Anthropic. This listing is the credential
24
+ and is what lets Claude surface Zetesis to users automatically.
25
+
26
+ Two things the review checks, both already handled:
27
+ - **Read-only tool annotations.** All four tools are annotated `readOnlyHint: true`
28
+ in the client, so nothing looks destructive.
29
+ - **A public privacy policy.** Live at <https://api.zetesis.science/privacy>. A missing
30
+ or incomplete policy is an automatic rejection.
31
+
32
+ Submit through the Anthropic connectors submission flow with: the name, the discovery
33
+ description, the `uvx --from zetesis zetesis-client` command (env `ZETESIS_TOKEN`
34
+ optional, only for the full dossier), the privacy policy URL, and the tool list.
35
+
36
+ ## 3. Discovery is earned, not bought
37
+
38
+ Ranking in the Connectors Directory is by adoption (active users, tool calls), shown
39
+ in a developer dashboard, with no paid placement. Claude surfaces a connector by
40
+ matching the user's intent against tool **names, descriptions, and parameter names**,
41
+ so the descriptions in `client.py` are the discovery surface. Own the phrasings you
42
+ want to win ("evaluate a scientific claim", "how rigorous is this study", "audit this
43
+ biotech or AI claim") and the free screen becomes your spontaneous top-of-funnel.
@@ -0,0 +1,35 @@
1
+ [project]
2
+ name = "zetesis"
3
+ version = "0.1.0"
4
+ description = "MCP client for Zetesis: scientific due diligence on a claim, evaluated by a hosted engine and sealed in a verifiable attestation."
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ license = { text = "MIT" }
8
+ authors = [{ name = "Reut Avidan", email = "reutavidan@gmail.com" }]
9
+ keywords = ["mcp", "science", "due-diligence", "evaluation", "claim-verification", "biotech", "research"]
10
+ classifiers = [
11
+ "Development Status :: 4 - Beta",
12
+ "Intended Audience :: Science/Research",
13
+ "License :: OSI Approved :: MIT License",
14
+ "Programming Language :: Python :: 3",
15
+ "Programming Language :: Python :: 3.10",
16
+ "Programming Language :: Python :: 3.11",
17
+ "Programming Language :: Python :: 3.12",
18
+ "Topic :: Scientific/Engineering",
19
+ ]
20
+ dependencies = ["mcp>=1.2.0"]
21
+
22
+ [project.urls]
23
+ Homepage = "https://api.zetesis.science"
24
+ Signup = "https://api.zetesis.science/signup"
25
+
26
+ [project.scripts]
27
+ zetesis-client = "zetesis.client:main"
28
+ zetesis = "zetesis.client:main"
29
+
30
+ [build-system]
31
+ requires = ["hatchling"]
32
+ build-backend = "hatchling.build"
33
+
34
+ [tool.hatch.build.targets.wheel]
35
+ packages = ["src/zetesis"]
@@ -0,0 +1,26 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.schema.json",
3
+ "name": "science.zetesis/zetesis",
4
+ "description": "Scientific due diligence on a claim. Evaluate how rigorously a scientific, biomedical, clinical, or AI claim was derived, and how well public literature, clinical trials, and filings support it, with a signed, independently re-checkable attestation. Free screen; gated full dossier.",
5
+ "status": "active",
6
+ "version": "0.1.0",
7
+ "websiteUrl": "https://api.zetesis.science",
8
+ "packages": [
9
+ {
10
+ "registryType": "pypi",
11
+ "registryBaseUrl": "https://pypi.org",
12
+ "identifier": "zetesis",
13
+ "version": "0.1.0",
14
+ "transport": { "type": "stdio" },
15
+ "runtimeHint": "uvx",
16
+ "environmentVariables": [
17
+ {
18
+ "name": "ZETESIS_TOKEN",
19
+ "description": "Zetesis access token. Only needed for a full attested dossier; the free screen needs none. Request access at https://api.zetesis.science/request-access.",
20
+ "isRequired": false,
21
+ "isSecret": true
22
+ }
23
+ ]
24
+ }
25
+ ]
26
+ }
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
@@ -0,0 +1,167 @@
1
+ """Thin-client MCP server. Proxies to the hosted Zetesis API.
2
+
3
+ This is the server that lists on the Official MCP Registry and the Claude
4
+ Connectors Directory. It holds no engine, no Anthropic key, and no signing key:
5
+ the user sets ZETESIS_TOKEN (only for the full dossier) and every call goes to
6
+ https://api.zetesis.science. If MCP is superseded, this file is rewritten and the
7
+ hosted engine is untouched.
8
+
9
+ Tool descriptions are written for discovery: the model reads them to decide when
10
+ to reach for Zetesis, so they name the intents this tool should win.
11
+
12
+ Config:
13
+ ZETESIS_TOKEN the user's token (only for a full dossier; the free screen needs none)
14
+ ZETESIS_API override the API base (default https://api.zetesis.science)
15
+ """
16
+ import json
17
+ import os
18
+ import urllib.error
19
+ import urllib.request
20
+
21
+ from mcp.server.fastmcp import FastMCP
22
+
23
+ API = os.environ.get("ZETESIS_API", "https://api.zetesis.science").rstrip("/")
24
+ TOKEN = os.environ.get("ZETESIS_TOKEN", "")
25
+
26
+ mcp = FastMCP("zetesis")
27
+
28
+ # every tool here only reads / requests an evaluation; nothing mutates the user's
29
+ # environment. openWorld because each call reaches an external service.
30
+ _READ = {"readOnlyHint": True, "destructiveHint": False, "openWorldHint": True}
31
+
32
+
33
+ @mcp.tool(annotations={**_READ, "title": "Evaluate a scientific or AI claim"})
34
+ def evaluate_claim(claim: str, context: str = "", documents: str = "", depth: str = "screen", mode: str = "research") -> str:
35
+ """Evaluate how rigorously a scientific, biomedical, clinical, or AI/ML claim was derived, and how well the evidence supports it.
36
+
37
+ Use this whenever someone wants to assess, screen, sanity-check, or do due
38
+ diligence on a research claim, a study, a paper, an abstract, a preprint, a
39
+ grant or a pitch: whether the methodology is sound, whether the data was
40
+ harmonized and controlled properly, whether the statistics hold, whether the
41
+ result reproduces, and how well the public literature, clinical trials, and
42
+ filings back it. It grades each evidence dimension and returns an overall
43
+ reading with sources cited by hard id (PMID, DOI, NCT, NIH grant, SEC filing).
44
+ Works for drug, omics, target-validation, diagnostic, and AI-model claims.
45
+
46
+ A screen is free and needs no token. A full attested dossier (deep) is the
47
+ signed, independently re-checkable audit and needs access.
48
+
49
+ Args:
50
+ claim: the claim to evaluate, in one or two sentences.
51
+ context: optional background (stage, field, the decision at hand).
52
+ documents: optional source text (a deck, abstract, or paper).
53
+ depth: "screen" for a fast, free pass (no token needed), "deep" for the full
54
+ attested dossier (needs access).
55
+ mode: "research" (science only) or "diligence" (adds the capital reading); deep only.
56
+ """
57
+ if depth == "screen":
58
+ status, d = _call("POST", "/screen",
59
+ {"claim": claim, "context": context, "documents": documents}, auth=False)
60
+ if status == 429:
61
+ return d.get("detail", "Free screens are used up for now.")
62
+ if status == 0:
63
+ return d.get("detail", "network error")
64
+ if status >= 400:
65
+ return f"Error: {d.get('detail', status)}"
66
+ return d.get("summary", "(no summary returned)")
67
+
68
+ if not TOKEN:
69
+ return f"A full attested dossier needs access. Request it at {API}/request-access."
70
+ status, d = _call("POST", "/evaluate",
71
+ {"claim": claim, "context": context, "documents": documents, "depth": "deep", "mode": mode})
72
+ if status == 401:
73
+ return "Your token was rejected. Check ZETESIS_TOKEN."
74
+ if status == 402:
75
+ return f"{d.get('detail', 'This needs a paid plan.')} Manage your plan at {API}."
76
+ if status == 0:
77
+ return d.get("detail", "network error")
78
+ if status >= 400:
79
+ return f"Error: {d.get('detail', status)}"
80
+ jid = d.get("job_id")
81
+ return (f"Full evaluation started (job {jid}). It runs in the background.\n"
82
+ f"Call check_evaluation with job_id \"{jid}\" for the result, "
83
+ f"or open the dossier at {API}/d/{jid} once it is ready.")
84
+
85
+
86
+ @mcp.tool(annotations={**_READ, "title": "Get a full dossier result"})
87
+ def check_evaluation(job_id: str) -> str:
88
+ """Get the result of a full (deep) Zetesis dossier started earlier. Returns the
89
+ reading and the rendered dossier link once it is ready.
90
+
91
+ Args:
92
+ job_id: the id returned by evaluate_claim for a deep evaluation.
93
+ """
94
+ status, d = _call("GET", f"/jobs/{job_id}")
95
+ if status >= 400:
96
+ return f"Error: {d.get('detail', status)}"
97
+ st = d.get("status")
98
+ if st == "pending":
99
+ return "Still running. Check again in a moment."
100
+ if st == "error":
101
+ return f"The evaluation failed: {d.get('error')}"
102
+ return d.get("summary", "(no summary)") + f"\n\nRendered dossier: {API}{d.get('dossier_url', '')}"
103
+
104
+
105
+ @mcp.tool(annotations={**_READ, "title": "Verify a Zetesis attestation"})
106
+ def verify_attestation(attestation_json: str) -> str:
107
+ """Verify a Zetesis attestation, confirming an evaluation's claim, evidence, and
108
+ conclusion have not been altered since it was signed. Use when someone has a
109
+ Zetesis dossier or attestation and wants to independently re-check it. No
110
+ account needed.
111
+
112
+ Args:
113
+ attestation_json: the full attestation object as JSON text.
114
+ """
115
+ try:
116
+ att = json.loads(attestation_json)
117
+ except json.JSONDecodeError as e:
118
+ return f"Not valid JSON: {e}"
119
+ status, d = _call("POST", "/verify", att, auth=False)
120
+ if status >= 400:
121
+ return f"Error: {d.get('detail', status)}"
122
+ if not d.get("valid"):
123
+ return f"INVALID: {d.get('reason', 'verification failed')}"
124
+ v = d.get("verdict", {})
125
+ return (f"VALID. Attestation {str(d.get('id', ''))[:16]} signed at {d.get('created')} "
126
+ f"using {d.get('model')}. Overall reading: {v.get('overall')}. "
127
+ f"{d.get('evidence_count')} public sources pinned.")
128
+
129
+
130
+ @mcp.tool(annotations={**_READ, "title": "Zetesis account status"})
131
+ def account_status() -> str:
132
+ """Show the caller's Zetesis plan and remaining free evaluations or dossier credits."""
133
+ if not TOKEN:
134
+ return f"No ZETESIS_TOKEN set. Request access at {API}/request-access."
135
+ status, d = _call("GET", "/me")
136
+ if status >= 400:
137
+ return f"Error: {d.get('detail', status)}"
138
+ cap = d.get("screen_cap")
139
+ cap = "unlimited" if cap is None else cap
140
+ return (f"Plan: {d.get('plan')}. Screens this month: {d.get('screens_used')}/{cap}. "
141
+ f"Dossier credits: {d.get('dossier_balance')}.")
142
+
143
+
144
+ def _call(method, path, body=None, auth=True):
145
+ headers = {"Content-Type": "application/json"}
146
+ if auth and TOKEN:
147
+ headers["Authorization"] = f"Bearer {TOKEN}"
148
+ data = json.dumps(body).encode() if body is not None else None
149
+ req = urllib.request.Request(API + path, data=data, headers=headers, method=method)
150
+ try:
151
+ with urllib.request.urlopen(req, timeout=175) as r:
152
+ return r.status, json.load(r)
153
+ except urllib.error.HTTPError as e:
154
+ try:
155
+ return e.code, json.load(e)
156
+ except Exception:
157
+ return e.code, {"detail": e.reason}
158
+ except Exception as e: # network / timeout
159
+ return 0, {"detail": f"could not reach Zetesis ({type(e).__name__})"}
160
+
161
+
162
+ def main():
163
+ mcp.run()
164
+
165
+
166
+ if __name__ == "__main__":
167
+ main()