verify-api-mcp 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.
@@ -0,0 +1,8 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.egg-info/
4
+ .venv/
5
+ venv/
6
+ build/
7
+ dist/
8
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Mick Goodson
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,74 @@
1
+ Metadata-Version: 2.5
2
+ Name: verify-api-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server for Verify API -- evidence-backed citation and URL verification for agents.
5
+ Project-URL: Homepage, https://goodsong.dev
6
+ Project-URL: Repository, https://github.com/mgdsn/verify-api-mcp
7
+ Author: Mick Goodson
8
+ License-Expression: MIT
9
+ License-File: LICENSE
10
+ Requires-Python: >=3.10
11
+ Requires-Dist: httpx>=0.27
12
+ Requires-Dist: mcp>=1.2
13
+ Description-Content-Type: text/markdown
14
+
15
+ # Verify API MCP Server
16
+
17
+ MCP server for [Verify API](https://goodsong.dev): a pay-per-call verification
18
+ service that gives agents a fast, structured, evidence-backed yes/no/unknown on
19
+ claims they'd otherwise guess at.
20
+
21
+ Stop your agent from citing things that don't exist. Two tools, one answer each,
22
+ evidence attached.
23
+
24
+ ## Tools
25
+
26
+ - **`verify_citation`** -- does a citation exist, is it retracted, and does the
27
+ given title/authors/year/journal match the canonical record? Checked against
28
+ Crossref (includes Retraction Watch data) with OpenAlex as a fallback.
29
+ - **`verify_url`** -- does a URL resolve, what's the final status and redirect
30
+ chain, is it archived on the Wayback Machine, and (optionally) does expected
31
+ text appear on the page?
32
+
33
+ Every response includes a `verdict` (`confirmed` / `contradicted` / `unknown`),
34
+ the individual `checks` that were run, and `evidence` with source URLs so a
35
+ human can verify the answer themselves. `unknown` is a valid, honest answer --
36
+ this server never guesses to avoid it.
37
+
38
+ ## Install
39
+
40
+ ```bash
41
+ pip install verify-api-mcp
42
+ ```
43
+
44
+ ## Configure
45
+
46
+ Get a free API key (100 calls, no card required):
47
+
48
+ ```bash
49
+ curl -X POST https://goodsong.dev/signup
50
+ ```
51
+
52
+ Then add to your MCP client's config (e.g. `mcp.json`):
53
+
54
+ ```json
55
+ {
56
+ "mcpServers": {
57
+ "verify-api": {
58
+ "command": "verify-api-mcp",
59
+ "env": {
60
+ "VERIFY_API_KEY": "vk_..."
61
+ }
62
+ }
63
+ }
64
+ }
65
+ ```
66
+
67
+ `VERIFY_API_URL` defaults to `https://goodsong.dev` and only needs to be set if
68
+ you're pointing at a different deployment.
69
+
70
+ ## License
71
+
72
+ MIT
73
+
74
+ <!-- mcp-name: io.github.mgdsn/verify-api-mcp -->
@@ -0,0 +1,60 @@
1
+ # Verify API MCP Server
2
+
3
+ MCP server for [Verify API](https://goodsong.dev): a pay-per-call verification
4
+ service that gives agents a fast, structured, evidence-backed yes/no/unknown on
5
+ claims they'd otherwise guess at.
6
+
7
+ Stop your agent from citing things that don't exist. Two tools, one answer each,
8
+ evidence attached.
9
+
10
+ ## Tools
11
+
12
+ - **`verify_citation`** -- does a citation exist, is it retracted, and does the
13
+ given title/authors/year/journal match the canonical record? Checked against
14
+ Crossref (includes Retraction Watch data) with OpenAlex as a fallback.
15
+ - **`verify_url`** -- does a URL resolve, what's the final status and redirect
16
+ chain, is it archived on the Wayback Machine, and (optionally) does expected
17
+ text appear on the page?
18
+
19
+ Every response includes a `verdict` (`confirmed` / `contradicted` / `unknown`),
20
+ the individual `checks` that were run, and `evidence` with source URLs so a
21
+ human can verify the answer themselves. `unknown` is a valid, honest answer --
22
+ this server never guesses to avoid it.
23
+
24
+ ## Install
25
+
26
+ ```bash
27
+ pip install verify-api-mcp
28
+ ```
29
+
30
+ ## Configure
31
+
32
+ Get a free API key (100 calls, no card required):
33
+
34
+ ```bash
35
+ curl -X POST https://goodsong.dev/signup
36
+ ```
37
+
38
+ Then add to your MCP client's config (e.g. `mcp.json`):
39
+
40
+ ```json
41
+ {
42
+ "mcpServers": {
43
+ "verify-api": {
44
+ "command": "verify-api-mcp",
45
+ "env": {
46
+ "VERIFY_API_KEY": "vk_..."
47
+ }
48
+ }
49
+ }
50
+ }
51
+ ```
52
+
53
+ `VERIFY_API_URL` defaults to `https://goodsong.dev` and only needs to be set if
54
+ you're pointing at a different deployment.
55
+
56
+ ## License
57
+
58
+ MIT
59
+
60
+ <!-- mcp-name: io.github.mgdsn/verify-api-mcp -->
@@ -0,0 +1,23 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "verify-api-mcp"
7
+ version = "0.1.0"
8
+ description = "MCP server for Verify API -- evidence-backed citation and URL verification for agents."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ requires-python = ">=3.10"
12
+ authors = [{ name = "Mick Goodson" }]
13
+ dependencies = ["httpx>=0.27", "mcp>=1.2"]
14
+
15
+ [project.urls]
16
+ Homepage = "https://goodsong.dev"
17
+ Repository = "https://github.com/mgdsn/verify-api-mcp"
18
+
19
+ [project.scripts]
20
+ verify-api-mcp = "verify_api_mcp.server:main"
21
+
22
+ [tool.hatch.build.targets.wheel]
23
+ packages = ["src/verify_api_mcp"]
@@ -0,0 +1,25 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.mgdsn/verify-api-mcp",
4
+ "title": "Verify API",
5
+ "description": "Deterministic, evidence-backed verification for citations and URLs -- catches fabricated or retracted citations and dead/altered links before an agent repeats them.",
6
+ "repository": { "url": "https://github.com/mgdsn/verify-api-mcp", "source": "github" },
7
+ "version": "0.1.0",
8
+ "packages": [
9
+ {
10
+ "registryType": "pypi",
11
+ "identifier": "verify-api-mcp",
12
+ "version": "0.1.0",
13
+ "transport": { "type": "stdio" },
14
+ "environmentVariables": [
15
+ {
16
+ "name": "VERIFY_API_KEY",
17
+ "description": "API key from POST /signup at https://goodsong.dev/signup",
18
+ "isRequired": true,
19
+ "isSecret": true,
20
+ "format": "string"
21
+ }
22
+ ]
23
+ }
24
+ ]
25
+ }
File without changes
@@ -0,0 +1,11 @@
1
+ import os
2
+
3
+ # The API key this server instance authenticates as -- issued via
4
+ # https://goodsong.dev/signup (free tier) or a paid key. Set per MCP client
5
+ # config, e.g. `"env": {"VERIFY_API_KEY": "vk_..."}` in the client's mcp.json.
6
+ VERIFY_API_KEY = os.environ.get("VERIFY_API_KEY", "")
7
+
8
+ # This server runs on the END USER's machine (installed from PyPI/an MCP
9
+ # registry), not ours -- it has no access to our database or core code, so
10
+ # it must call the hosted API over HTTP like any other API-key client would.
11
+ VERIFY_API_URL = os.environ.get("VERIFY_API_URL", "https://goodsong.dev")
@@ -0,0 +1,97 @@
1
+ """MCP server: exposes verify_citation and verify_url as tools.
2
+
3
+ A thin HTTP client against the hosted Verify API at https://goodsong.dev,
4
+ authenticated the same way any other API-key caller is
5
+ (Authorization: Bearer <key>). Has no access to the API's database or core
6
+ verification code -- it just calls the public endpoints.
7
+ """
8
+
9
+ import httpx
10
+ from mcp.server.mcpserver import MCPServer
11
+ from mcp.server.mcpserver.exceptions import ToolError
12
+
13
+ from verify_api_mcp.config import VERIFY_API_KEY, VERIFY_API_URL
14
+
15
+ server = MCPServer(
16
+ name="verify-api",
17
+ title="Verify API",
18
+ description=(
19
+ "Deterministic, evidence-backed verification for citations and URLs -- "
20
+ "catches fabricated or retracted citations and dead/altered links before "
21
+ "an agent repeats them."
22
+ ),
23
+ )
24
+
25
+
26
+ async def _call_api(path: str, payload: dict) -> dict:
27
+ if not VERIFY_API_KEY:
28
+ raise ToolError(
29
+ "No API key configured for this MCP server. Set VERIFY_API_KEY in the "
30
+ "client's MCP config to a key from POST /signup at https://goodsong.dev/signup."
31
+ )
32
+ body = {k: v for k, v in payload.items() if v is not None}
33
+ try:
34
+ async with httpx.AsyncClient(timeout=20.0) as client:
35
+ resp = await client.post(
36
+ f"{VERIFY_API_URL}{path}",
37
+ json=body,
38
+ headers={"Authorization": f"Bearer {VERIFY_API_KEY}"},
39
+ )
40
+ except httpx.RequestError as e:
41
+ raise ToolError(f"Could not reach the Verify API at {VERIFY_API_URL}: {e}") from e
42
+
43
+ if resp.status_code == 401:
44
+ raise ToolError("VERIFY_API_KEY is invalid or revoked.")
45
+ if resp.status_code == 402:
46
+ detail = resp.json().get("error", {}).get("message", "Monthly call quota exceeded.")
47
+ raise ToolError(detail)
48
+ if resp.status_code >= 400:
49
+ raise ToolError(f"Verify API returned {resp.status_code}: {resp.text[:200]}")
50
+ return resp.json()
51
+
52
+
53
+ @server.tool(
54
+ description=(
55
+ "Verify a citation: does it exist, is it retracted, and do the given title/"
56
+ "authors/year/journal match the canonical record? Checked against Crossref "
57
+ "(includes Retraction Watch data) with OpenAlex as a fallback when no DOI "
58
+ "is given. Provide a doi and/or a title."
59
+ )
60
+ )
61
+ async def verify_citation(
62
+ doi: str | None = None,
63
+ title: str | None = None,
64
+ authors: list[str] | None = None,
65
+ year: int | None = None,
66
+ journal: str | None = None,
67
+ ) -> dict:
68
+ return await _call_api(
69
+ "/verify/citation",
70
+ {"doi": doi, "title": title, "authors": authors, "year": year, "journal": journal},
71
+ )
72
+
73
+
74
+ @server.tool(
75
+ description=(
76
+ "Verify a URL: does it resolve, what's the final status and redirect chain, "
77
+ "is it archived on the Wayback Machine, and (optionally) does expected text "
78
+ "appear on the page. Checked via direct fetch and the Internet Archive."
79
+ )
80
+ )
81
+ async def verify_url(
82
+ url: str,
83
+ expected_content: str | None = None,
84
+ expected_date: str | None = None,
85
+ ) -> dict:
86
+ return await _call_api(
87
+ "/verify/url",
88
+ {"url": url, "expected_content": expected_content, "expected_date": expected_date},
89
+ )
90
+
91
+
92
+ def main() -> None:
93
+ server.run()
94
+
95
+
96
+ if __name__ == "__main__":
97
+ main()