epitaxy-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,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 epitaxy
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,90 @@
1
+ Metadata-Version: 2.4
2
+ Name: epitaxy-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server for federal drug shortages and recalls joined to federal drug contracts
5
+ Author: epitaxy
6
+ License: MIT
7
+ Project-URL: Homepage, https://docs.crossgrain.xyz
8
+ Project-URL: Source, https://github.com/vor-bot/epitaxy
9
+ Project-URL: API, https://drugs.crossgrain.xyz/openapi.json
10
+ Keywords: mcp,model-context-protocol,fda,drug-shortage,recall,usaspending,federal-contracts,procurement,open-data
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Dynamic: license-file
20
+
21
+ # epitaxy
22
+
23
+ mcp-name: xyz.crossgrain/epitaxy
24
+
25
+ Federal drug shortages and recalls, joined to the federal contracts that
26
+ buy those drugs. One call, no signup.
27
+
28
+ **What it claims:** this government supplier has an active FDA shortage
29
+ or recall. **What it does not claim:** that a specific contract supplies
30
+ a specific drug. Federal contract descriptions average 47 characters and
31
+ almost never name the drug, so we say so instead of pretending otherwise.
32
+
33
+ ## Try it now, no key
34
+
35
+ ```bash
36
+ curl https://drugs.crossgrain.xyz/v1/exposure?limit=5
37
+ ```
38
+
39
+ ## MCP
40
+
41
+ Remote, nothing to install:
42
+
43
+ ```json
44
+ { "mcpServers": { "epitaxy": { "url": "https://drugs.crossgrain.xyz/v1/mcp" } } }
45
+ ```
46
+
47
+ Local, stdio:
48
+
49
+ ```json
50
+ { "mcpServers": { "epitaxy": { "command": "uvx", "args": ["epitaxy-mcp"] } } }
51
+ ```
52
+
53
+ Tools: `get_data_freshness`, `list_drug_shortages`, `list_drug_recalls`,
54
+ `list_federal_drug_contracts`, `get_supplier_exposure`.
55
+
56
+ ## Read the confidence field, always
57
+
58
+ | value | meaning |
59
+ | --- | --- |
60
+ | `exact` | match on a shared identifier, here an NDC inside FDA data |
61
+ | `probable` | normalized company name, or a drug name token in the contract text |
62
+ | `weak` | anything softer, an indication only |
63
+
64
+ Matching on both company and drug at once is **not** promoted to
65
+ `exact`. Cross source joins are never `exact`, because FDA and
66
+ USAspending share no identifier. Anyone claiming otherwise has a
67
+ different source or is guessing.
68
+
69
+ ## Free tier
70
+
71
+ Works forever, no key, no signup. Returns at most 20 rows, without the
72
+ `evidence` field, without `weak` matches, and with data delayed by 24
73
+ hours. Nothing is stored: no counters, no IP addresses.
74
+
75
+ ## Paid
76
+
77
+ | plan | price | contents |
78
+ | --- | --- | --- |
79
+ | Starter | 29 USD/mo | 10 000 calls |
80
+ | Pro | 99 USD/mo | 100 000 calls plus daily delta feed |
81
+ | x402 | 0.004 USD/call | USDC on Base, no signup |
82
+ | Bulk dump | 199 USD | one off, Stripe only |
83
+
84
+ ## Sources and licence
85
+
86
+ - openFDA, public domain, CC0 1.0 Universal
87
+ - USAspending, public domain, code under CC0
88
+
89
+ Data is unvalidated and must not be used for medical decisions.
90
+ This project is MIT licensed. Docs: https://docs.crossgrain.xyz
@@ -0,0 +1,70 @@
1
+ # epitaxy
2
+
3
+ mcp-name: xyz.crossgrain/epitaxy
4
+
5
+ Federal drug shortages and recalls, joined to the federal contracts that
6
+ buy those drugs. One call, no signup.
7
+
8
+ **What it claims:** this government supplier has an active FDA shortage
9
+ or recall. **What it does not claim:** that a specific contract supplies
10
+ a specific drug. Federal contract descriptions average 47 characters and
11
+ almost never name the drug, so we say so instead of pretending otherwise.
12
+
13
+ ## Try it now, no key
14
+
15
+ ```bash
16
+ curl https://drugs.crossgrain.xyz/v1/exposure?limit=5
17
+ ```
18
+
19
+ ## MCP
20
+
21
+ Remote, nothing to install:
22
+
23
+ ```json
24
+ { "mcpServers": { "epitaxy": { "url": "https://drugs.crossgrain.xyz/v1/mcp" } } }
25
+ ```
26
+
27
+ Local, stdio:
28
+
29
+ ```json
30
+ { "mcpServers": { "epitaxy": { "command": "uvx", "args": ["epitaxy-mcp"] } } }
31
+ ```
32
+
33
+ Tools: `get_data_freshness`, `list_drug_shortages`, `list_drug_recalls`,
34
+ `list_federal_drug_contracts`, `get_supplier_exposure`.
35
+
36
+ ## Read the confidence field, always
37
+
38
+ | value | meaning |
39
+ | --- | --- |
40
+ | `exact` | match on a shared identifier, here an NDC inside FDA data |
41
+ | `probable` | normalized company name, or a drug name token in the contract text |
42
+ | `weak` | anything softer, an indication only |
43
+
44
+ Matching on both company and drug at once is **not** promoted to
45
+ `exact`. Cross source joins are never `exact`, because FDA and
46
+ USAspending share no identifier. Anyone claiming otherwise has a
47
+ different source or is guessing.
48
+
49
+ ## Free tier
50
+
51
+ Works forever, no key, no signup. Returns at most 20 rows, without the
52
+ `evidence` field, without `weak` matches, and with data delayed by 24
53
+ hours. Nothing is stored: no counters, no IP addresses.
54
+
55
+ ## Paid
56
+
57
+ | plan | price | contents |
58
+ | --- | --- | --- |
59
+ | Starter | 29 USD/mo | 10 000 calls |
60
+ | Pro | 99 USD/mo | 100 000 calls plus daily delta feed |
61
+ | x402 | 0.004 USD/call | USDC on Base, no signup |
62
+ | Bulk dump | 199 USD | one off, Stripe only |
63
+
64
+ ## Sources and licence
65
+
66
+ - openFDA, public domain, CC0 1.0 Universal
67
+ - USAspending, public domain, code under CC0
68
+
69
+ Data is unvalidated and must not be used for medical decisions.
70
+ This project is MIT licensed. Docs: https://docs.crossgrain.xyz
@@ -0,0 +1,90 @@
1
+ Metadata-Version: 2.4
2
+ Name: epitaxy-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server for federal drug shortages and recalls joined to federal drug contracts
5
+ Author: epitaxy
6
+ License: MIT
7
+ Project-URL: Homepage, https://docs.crossgrain.xyz
8
+ Project-URL: Source, https://github.com/vor-bot/epitaxy
9
+ Project-URL: API, https://drugs.crossgrain.xyz/openapi.json
10
+ Keywords: mcp,model-context-protocol,fda,drug-shortage,recall,usaspending,federal-contracts,procurement,open-data
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
16
+ Requires-Python: >=3.9
17
+ Description-Content-Type: text/markdown
18
+ License-File: LICENSE
19
+ Dynamic: license-file
20
+
21
+ # epitaxy
22
+
23
+ mcp-name: xyz.crossgrain/epitaxy
24
+
25
+ Federal drug shortages and recalls, joined to the federal contracts that
26
+ buy those drugs. One call, no signup.
27
+
28
+ **What it claims:** this government supplier has an active FDA shortage
29
+ or recall. **What it does not claim:** that a specific contract supplies
30
+ a specific drug. Federal contract descriptions average 47 characters and
31
+ almost never name the drug, so we say so instead of pretending otherwise.
32
+
33
+ ## Try it now, no key
34
+
35
+ ```bash
36
+ curl https://drugs.crossgrain.xyz/v1/exposure?limit=5
37
+ ```
38
+
39
+ ## MCP
40
+
41
+ Remote, nothing to install:
42
+
43
+ ```json
44
+ { "mcpServers": { "epitaxy": { "url": "https://drugs.crossgrain.xyz/v1/mcp" } } }
45
+ ```
46
+
47
+ Local, stdio:
48
+
49
+ ```json
50
+ { "mcpServers": { "epitaxy": { "command": "uvx", "args": ["epitaxy-mcp"] } } }
51
+ ```
52
+
53
+ Tools: `get_data_freshness`, `list_drug_shortages`, `list_drug_recalls`,
54
+ `list_federal_drug_contracts`, `get_supplier_exposure`.
55
+
56
+ ## Read the confidence field, always
57
+
58
+ | value | meaning |
59
+ | --- | --- |
60
+ | `exact` | match on a shared identifier, here an NDC inside FDA data |
61
+ | `probable` | normalized company name, or a drug name token in the contract text |
62
+ | `weak` | anything softer, an indication only |
63
+
64
+ Matching on both company and drug at once is **not** promoted to
65
+ `exact`. Cross source joins are never `exact`, because FDA and
66
+ USAspending share no identifier. Anyone claiming otherwise has a
67
+ different source or is guessing.
68
+
69
+ ## Free tier
70
+
71
+ Works forever, no key, no signup. Returns at most 20 rows, without the
72
+ `evidence` field, without `weak` matches, and with data delayed by 24
73
+ hours. Nothing is stored: no counters, no IP addresses.
74
+
75
+ ## Paid
76
+
77
+ | plan | price | contents |
78
+ | --- | --- | --- |
79
+ | Starter | 29 USD/mo | 10 000 calls |
80
+ | Pro | 99 USD/mo | 100 000 calls plus daily delta feed |
81
+ | x402 | 0.004 USD/call | USDC on Base, no signup |
82
+ | Bulk dump | 199 USD | one off, Stripe only |
83
+
84
+ ## Sources and licence
85
+
86
+ - openFDA, public domain, CC0 1.0 Universal
87
+ - USAspending, public domain, code under CC0
88
+
89
+ Data is unvalidated and must not be used for medical decisions.
90
+ This project is MIT licensed. Docs: https://docs.crossgrain.xyz
@@ -0,0 +1,10 @@
1
+ LICENSE
2
+ README.md
3
+ pyproject.toml
4
+ epitaxy_mcp.egg-info/PKG-INFO
5
+ epitaxy_mcp.egg-info/SOURCES.txt
6
+ epitaxy_mcp.egg-info/dependency_links.txt
7
+ epitaxy_mcp.egg-info/entry_points.txt
8
+ epitaxy_mcp.egg-info/top_level.txt
9
+ mcp_server/__init__.py
10
+ mcp_server/server.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ epitaxy-mcp = mcp_server.server:main
@@ -0,0 +1 @@
1
+ mcp_server
File without changes
@@ -0,0 +1,186 @@
1
+ """MCP server nad epitaxy API. Stdio transport, len stdlib.
2
+
3
+ Toto je zároveň distribučný kanál číslo 1 aj 2 z research/distribution.md:
4
+ zápis do MCP registrov a vlastný open source klient. Balík sa spúšťa
5
+ jedným príkazom a funguje bez kľúča, lebo bezplatná vrstva nepotrebuje
6
+ registráciu.
7
+
8
+ Spustenie:
9
+ python3 -m mcp_server.server
10
+
11
+ Premenné:
12
+ EPITAXY_API_URL základ API, predvolene https://api.crossgrain.xyz
13
+ EPITAXY_API_KEY nepovinný, bez neho beží bezplatná vrstva
14
+ """
15
+
16
+ import json
17
+ import os
18
+ import sys
19
+ import urllib.error
20
+ import urllib.parse
21
+ import urllib.request
22
+
23
+ API_URL = os.environ.get("EPITAXY_API_URL", "https://api.crossgrain.xyz")
24
+ API_KEY = os.environ.get("EPITAXY_API_KEY")
25
+ USER_AGENT = "epitaxy-mcp/0.1"
26
+ PROTOCOL_VERSION = "2025-06-18"
27
+
28
+ TOOLS = [
29
+ {
30
+ "name": "get_data_freshness",
31
+ "description": ("Vrati cas poslednej aktivacie dat, pocet zivych "
32
+ "segmentov a stav posledneho behu. Volaj to prve, "
33
+ "ked chces vediet, ci su data cerstve."),
34
+ "inputSchema": {"type": "object", "properties": {}},
35
+ },
36
+ {
37
+ "name": "list_drug_shortages",
38
+ "description": ("Vypadky liekov podla FDA. Filtre: status, "
39
+ "generic_name, company_id, limit."),
40
+ "inputSchema": {
41
+ "type": "object",
42
+ "properties": {
43
+ "status": {"type": "string"},
44
+ "generic_name": {"type": "string"},
45
+ "company_id": {"type": "string"},
46
+ "limit": {"type": "integer"},
47
+ },
48
+ },
49
+ },
50
+ {
51
+ "name": "list_drug_recalls",
52
+ "description": "Stiahnutia liekov podla FDA. Filtre: classification, company_id, limit.",
53
+ "inputSchema": {
54
+ "type": "object",
55
+ "properties": {
56
+ "classification": {"type": "string"},
57
+ "company_id": {"type": "string"},
58
+ "limit": {"type": "integer"},
59
+ },
60
+ },
61
+ },
62
+ {
63
+ "name": "list_federal_drug_contracts",
64
+ "description": ("Federalne kontrakty na lieky, PSC 6505. "
65
+ "Filtre: agency, company_id, limit."),
66
+ "inputSchema": {
67
+ "type": "object",
68
+ "properties": {
69
+ "agency": {"type": "string"},
70
+ "company_id": {"type": "string"},
71
+ "limit": {"type": "integer"},
72
+ },
73
+ },
74
+ },
75
+ {
76
+ "name": "get_supplier_exposure",
77
+ "description": (
78
+ "Spojenie kontraktu s vypadkom alebo stiahnutim. KAZDY riadok "
79
+ "nesie confidence exact, probable alebo weak a match_method. "
80
+ "Cross source spojenie NIKDY nie je exact, lebo medzi FDA a "
81
+ "USAspending neexistuje spolocny identifikator. Tvrdenie znie: "
82
+ "tento dodavatel vlady ma u FDA aktivny vypadok alebo "
83
+ "stiahnutie. NETVRDI, ze konkretny kontrakt dodava konkretny "
84
+ "liek. Bez kluca sa vracaju len exact a probable zhody, "
85
+ "najviac 20 riadkov, bez evidence."),
86
+ "inputSchema": {
87
+ "type": "object",
88
+ "properties": {
89
+ "award_id": {"type": "string"},
90
+ "company_id": {"type": "string"},
91
+ "min_confidence": {"type": "string",
92
+ "enum": ["probable", "weak"]},
93
+ "limit": {"type": "integer"},
94
+ },
95
+ },
96
+ },
97
+ ]
98
+
99
+ TOOL_PATHS = {
100
+ "get_data_freshness": "/v1/meta",
101
+ "list_drug_shortages": "/v1/shortages",
102
+ "list_drug_recalls": "/v1/recalls",
103
+ "list_federal_drug_contracts": "/v1/contracts",
104
+ "get_supplier_exposure": "/v1/exposure",
105
+ }
106
+
107
+
108
+ def call_api(path, params):
109
+ query = urllib.parse.urlencode(
110
+ dict((k, v) for k, v in params.items() if v not in (None, "")))
111
+ url = "%s%s%s" % (API_URL, path, ("?" + query) if query else "")
112
+ headers = {"User-Agent": USER_AGENT, "Accept": "application/json"}
113
+ if API_KEY:
114
+ headers["X-API-Key"] = API_KEY
115
+ request = urllib.request.Request(url, headers=headers)
116
+ try:
117
+ with urllib.request.urlopen(request, timeout=30) as response:
118
+ return json.loads(response.read().decode("utf-8"))
119
+ except urllib.error.HTTPError as exc:
120
+ body = exc.read().decode("utf-8", "replace")
121
+ try:
122
+ return json.loads(body)
123
+ except ValueError:
124
+ return {"error": "http_%d" % exc.code, "body": body[:500]}
125
+ except Exception as exc:
126
+ return {"error": "network", "message": str(exc)[:200]}
127
+
128
+
129
+ def handle(message):
130
+ method = message.get("method")
131
+ request_id = message.get("id")
132
+
133
+ if method == "initialize":
134
+ return {
135
+ "jsonrpc": "2.0", "id": request_id,
136
+ "result": {
137
+ "protocolVersion": PROTOCOL_VERSION,
138
+ "capabilities": {"tools": {}},
139
+ "serverInfo": {"name": "epitaxy", "version": "0.1.0"},
140
+ "instructions": (
141
+ "Data o vypadkoch a stiahnutiach liekov spojene s "
142
+ "federalnymi kontraktmi. Vzdy citaj pole confidence."),
143
+ },
144
+ }
145
+ if method in ("notifications/initialized", "notifications/cancelled"):
146
+ return None
147
+ if method == "tools/list":
148
+ return {"jsonrpc": "2.0", "id": request_id, "result": {"tools": TOOLS}}
149
+ if method == "tools/call":
150
+ params = message.get("params", {})
151
+ name = params.get("name")
152
+ path = TOOL_PATHS.get(name)
153
+ if not path:
154
+ return {"jsonrpc": "2.0", "id": request_id,
155
+ "error": {"code": -32601, "message": "neznamy nastroj"}}
156
+ result = call_api(path, params.get("arguments") or {})
157
+ return {
158
+ "jsonrpc": "2.0", "id": request_id,
159
+ "result": {
160
+ "content": [{"type": "text",
161
+ "text": json.dumps(result, ensure_ascii=False)}],
162
+ "isError": bool(result.get("error")),
163
+ },
164
+ }
165
+ return {"jsonrpc": "2.0", "id": request_id,
166
+ "error": {"code": -32601, "message": "neznama metoda %s" % method}}
167
+
168
+
169
+ def main(argv=None):
170
+ for line in sys.stdin:
171
+ line = line.strip()
172
+ if not line:
173
+ continue
174
+ try:
175
+ message = json.loads(line)
176
+ except ValueError:
177
+ continue
178
+ response = handle(message)
179
+ if response is not None:
180
+ sys.stdout.write(json.dumps(response, ensure_ascii=False) + "\n")
181
+ sys.stdout.flush()
182
+ return 0
183
+
184
+
185
+ if __name__ == "__main__":
186
+ sys.exit(main())
@@ -0,0 +1,35 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "epitaxy-mcp"
7
+ version = "0.1.0"
8
+ description = "MCP server for federal drug shortages and recalls joined to federal drug contracts"
9
+ readme = "README.md"
10
+ requires-python = ">=3.9"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "epitaxy" }]
13
+ keywords = [
14
+ "mcp", "model-context-protocol", "fda", "drug-shortage", "recall",
15
+ "usaspending", "federal-contracts", "procurement", "open-data",
16
+ ]
17
+ classifiers = [
18
+ "Development Status :: 4 - Beta",
19
+ "Intended Audience :: Developers",
20
+ "License :: OSI Approved :: MIT License",
21
+ "Programming Language :: Python :: 3",
22
+ "Topic :: Scientific/Engineering :: Information Analysis",
23
+ ]
24
+ dependencies = []
25
+
26
+ [project.urls]
27
+ Homepage = "https://docs.crossgrain.xyz"
28
+ Source = "https://github.com/vor-bot/epitaxy"
29
+ API = "https://drugs.crossgrain.xyz/openapi.json"
30
+
31
+ [project.scripts]
32
+ epitaxy-mcp = "mcp_server.server:main"
33
+
34
+ [tool.setuptools]
35
+ packages = ["mcp_server"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+