meddata-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,41 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ *.egg-info/
7
+ *.egg
8
+ dist/
9
+ build/
10
+ eggs/
11
+ *.whl
12
+
13
+ # Virtual environments
14
+ .venv/
15
+ venv/
16
+ env/
17
+ ENV/
18
+
19
+ # Environment variables
20
+ .env
21
+
22
+ # IDE
23
+ .vscode/
24
+ .idea/
25
+ *.swp
26
+ *.swo
27
+ *~
28
+
29
+ # OS
30
+ .DS_Store
31
+ Thumbs.db
32
+
33
+ # Testing
34
+ .pytest_cache/
35
+ .coverage
36
+ htmlcov/
37
+ .mypy_cache/
38
+
39
+ # Distribution
40
+ *.tar.gz
41
+ *.zip
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Anthesia
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,123 @@
1
+ Metadata-Version: 2.4
2
+ Name: meddata-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server for the MedData API: drug and supplement lookup and interaction checks from free U.S. government health databases.
5
+ Project-URL: Homepage, https://meddata.anthesia.io
6
+ Project-URL: Documentation, https://meddata.anthesia.io/docs
7
+ Project-URL: Repository, https://github.com/anthesiallc/meddata-api
8
+ Author-email: Anthesia <support@anthesia.io>
9
+ License: MIT
10
+ License-File: LICENSE
11
+ Keywords: drug,fda,healthcare,interactions,mcp,model-context-protocol,openfda,pharmacy,rxnorm,supplement
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
17
+ Requires-Python: >=3.10
18
+ Requires-Dist: httpx>=0.27.0
19
+ Requires-Dist: mcp>=1.2.0
20
+ Description-Content-Type: text/markdown
21
+
22
+ # MedData MCP Server
23
+
24
+ mcp-name: io.github.anthesiallc/meddata
25
+
26
+ A [Model Context Protocol](https://modelcontextprotocol.io) server that exposes the
27
+ [MedData API](https://meddata.anthesia.io) as tools, so any MCP client (Claude
28
+ Desktop, Cursor, ChatGPT connectors, or an agent framework) can look up drug and
29
+ supplement data and check interactions conversationally.
30
+
31
+ It's a thin wrapper: each tool maps to one MedData REST endpoint. All the data
32
+ work happens in the API.
33
+
34
+ ## Tools
35
+
36
+ | Tool | What it does |
37
+ |------|--------------|
38
+ | `search_drugs` | Search drugs by brand or generic name; returns RxCUI + details |
39
+ | `get_drug` | Full drug profile by RxCUI |
40
+ | `get_drug_by_ndc` | Drug profile by NDC package code |
41
+ | `search_supplements` | Search supplements by name; returns supplement IDs |
42
+ | `get_supplement` | Full supplement fact sheet by ID |
43
+ | `check_interactions` | Interactions across a mixed list of 2-10 drugs/supplements |
44
+ | `get_usage` | Current billing period usage and plan limit |
45
+
46
+ ## Get an API key
47
+
48
+ Free tier is 250 calls/month, no credit card:
49
+
50
+ ```bash
51
+ curl -X POST https://meddata.anthesia.io/api/v1/signup \
52
+ -H 'Content-Type: application/json' \
53
+ -d '{"email":"you@example.com"}'
54
+ ```
55
+
56
+ The key comes back in the `api_key` field of the response.
57
+
58
+ ## Install and run
59
+
60
+ The easiest way is with [uv](https://docs.astral.sh/uv/) (no manual venv needed):
61
+
62
+ ```bash
63
+ # stdio transport (default — for Claude Desktop, Cursor, most local clients)
64
+ MEDDATA_API_KEY=md_your_key uvx meddata-mcp
65
+
66
+ # streamable-HTTP transport (for remote / web clients)
67
+ MEDDATA_API_KEY=md_your_key uvx meddata-mcp --http
68
+ ```
69
+
70
+ Or install with pip into its own environment:
71
+
72
+ ```bash
73
+ pip install meddata-mcp
74
+ MEDDATA_API_KEY=md_your_key meddata-mcp
75
+ ```
76
+
77
+ > Note: install into a dedicated environment. The `mcp` SDK requires a newer
78
+ > `starlette` than the MedData API app pins, so the two will conflict if installed
79
+ > together.
80
+
81
+ Environment variables:
82
+
83
+ - `MEDDATA_API_KEY` (required) — your MedData API key.
84
+ - `MEDDATA_BASE_URL` (optional) — defaults to `https://meddata.anthesia.io`.
85
+ - `MEDDATA_TIMEOUT` (optional) — request timeout in seconds, default `30`.
86
+
87
+ ## Client configuration
88
+
89
+ ### Claude Desktop
90
+
91
+ Add to `claude_desktop_config.json` (Settings → Developer → Edit Config):
92
+
93
+ ```json
94
+ {
95
+ "mcpServers": {
96
+ "meddata": {
97
+ "command": "uvx",
98
+ "args": ["meddata-mcp"],
99
+ "env": { "MEDDATA_API_KEY": "md_your_key" }
100
+ }
101
+ }
102
+ }
103
+ ```
104
+
105
+ ### Cursor
106
+
107
+ Add the same block to `~/.cursor/mcp.json` (or the project `.cursor/mcp.json`).
108
+
109
+ ## Develop from source
110
+
111
+ ```bash
112
+ cd mcp_server
113
+ python -m venv .venv
114
+ .venv/Scripts/python -m pip install -e . # Windows
115
+ # .venv/bin/pip install -e . # macOS/Linux
116
+ MEDDATA_API_KEY=md_your_key .venv/Scripts/python -m meddata_mcp.server
117
+ ```
118
+
119
+ ## Notes
120
+
121
+ - Data is for informational purposes only and is not medical advice.
122
+ - Interaction data comes from established medical databases; an empty result
123
+ means none were found in those sources, not that a combination is proven safe.
@@ -0,0 +1,102 @@
1
+ # MedData MCP Server
2
+
3
+ mcp-name: io.github.anthesiallc/meddata
4
+
5
+ A [Model Context Protocol](https://modelcontextprotocol.io) server that exposes the
6
+ [MedData API](https://meddata.anthesia.io) as tools, so any MCP client (Claude
7
+ Desktop, Cursor, ChatGPT connectors, or an agent framework) can look up drug and
8
+ supplement data and check interactions conversationally.
9
+
10
+ It's a thin wrapper: each tool maps to one MedData REST endpoint. All the data
11
+ work happens in the API.
12
+
13
+ ## Tools
14
+
15
+ | Tool | What it does |
16
+ |------|--------------|
17
+ | `search_drugs` | Search drugs by brand or generic name; returns RxCUI + details |
18
+ | `get_drug` | Full drug profile by RxCUI |
19
+ | `get_drug_by_ndc` | Drug profile by NDC package code |
20
+ | `search_supplements` | Search supplements by name; returns supplement IDs |
21
+ | `get_supplement` | Full supplement fact sheet by ID |
22
+ | `check_interactions` | Interactions across a mixed list of 2-10 drugs/supplements |
23
+ | `get_usage` | Current billing period usage and plan limit |
24
+
25
+ ## Get an API key
26
+
27
+ Free tier is 250 calls/month, no credit card:
28
+
29
+ ```bash
30
+ curl -X POST https://meddata.anthesia.io/api/v1/signup \
31
+ -H 'Content-Type: application/json' \
32
+ -d '{"email":"you@example.com"}'
33
+ ```
34
+
35
+ The key comes back in the `api_key` field of the response.
36
+
37
+ ## Install and run
38
+
39
+ The easiest way is with [uv](https://docs.astral.sh/uv/) (no manual venv needed):
40
+
41
+ ```bash
42
+ # stdio transport (default — for Claude Desktop, Cursor, most local clients)
43
+ MEDDATA_API_KEY=md_your_key uvx meddata-mcp
44
+
45
+ # streamable-HTTP transport (for remote / web clients)
46
+ MEDDATA_API_KEY=md_your_key uvx meddata-mcp --http
47
+ ```
48
+
49
+ Or install with pip into its own environment:
50
+
51
+ ```bash
52
+ pip install meddata-mcp
53
+ MEDDATA_API_KEY=md_your_key meddata-mcp
54
+ ```
55
+
56
+ > Note: install into a dedicated environment. The `mcp` SDK requires a newer
57
+ > `starlette` than the MedData API app pins, so the two will conflict if installed
58
+ > together.
59
+
60
+ Environment variables:
61
+
62
+ - `MEDDATA_API_KEY` (required) — your MedData API key.
63
+ - `MEDDATA_BASE_URL` (optional) — defaults to `https://meddata.anthesia.io`.
64
+ - `MEDDATA_TIMEOUT` (optional) — request timeout in seconds, default `30`.
65
+
66
+ ## Client configuration
67
+
68
+ ### Claude Desktop
69
+
70
+ Add to `claude_desktop_config.json` (Settings → Developer → Edit Config):
71
+
72
+ ```json
73
+ {
74
+ "mcpServers": {
75
+ "meddata": {
76
+ "command": "uvx",
77
+ "args": ["meddata-mcp"],
78
+ "env": { "MEDDATA_API_KEY": "md_your_key" }
79
+ }
80
+ }
81
+ }
82
+ ```
83
+
84
+ ### Cursor
85
+
86
+ Add the same block to `~/.cursor/mcp.json` (or the project `.cursor/mcp.json`).
87
+
88
+ ## Develop from source
89
+
90
+ ```bash
91
+ cd mcp_server
92
+ python -m venv .venv
93
+ .venv/Scripts/python -m pip install -e . # Windows
94
+ # .venv/bin/pip install -e . # macOS/Linux
95
+ MEDDATA_API_KEY=md_your_key .venv/Scripts/python -m meddata_mcp.server
96
+ ```
97
+
98
+ ## Notes
99
+
100
+ - Data is for informational purposes only and is not medical advice.
101
+ - Interaction data comes from established medical databases; an empty result
102
+ means none were found in those sources, not that a combination is proven safe.
@@ -0,0 +1,3 @@
1
+ """MedData MCP server package."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,187 @@
1
+ """MedData MCP server.
2
+
3
+ Exposes the MedData REST API (https://meddata.anthesia.io) as Model Context
4
+ Protocol tools so that agents and MCP-capable clients (Claude Desktop, Cursor,
5
+ ChatGPT connectors, agent frameworks) can look up drug and supplement data and
6
+ check interactions conversationally.
7
+
8
+ This is a thin wrapper: every tool maps to one REST endpoint. The API key is
9
+ read from the MEDDATA_API_KEY environment variable. Get a free key (250
10
+ calls/month, no card) from https://meddata.anthesia.io or by POSTing your email
11
+ to /api/v1/signup -- the key comes back in the response.
12
+
13
+ Run it:
14
+ MEDDATA_API_KEY=md_... meddata-mcp # stdio (default)
15
+ MEDDATA_API_KEY=md_... meddata-mcp --http # streamable-http
16
+ MEDDATA_API_KEY=md_... python -m meddata_mcp.server # equivalent
17
+
18
+ Drug and supplement data is for informational purposes only and is not medical
19
+ advice. Interaction data comes from established medical databases; it is never
20
+ generated or inferred.
21
+ """
22
+
23
+ import os
24
+ import sys
25
+ from typing import Any
26
+
27
+ import httpx
28
+ from mcp.server.fastmcp import FastMCP
29
+
30
+ BASE_URL = os.environ.get("MEDDATA_BASE_URL", "https://meddata.anthesia.io").rstrip("/")
31
+ API_KEY = os.environ.get("MEDDATA_API_KEY", "")
32
+ TIMEOUT = float(os.environ.get("MEDDATA_TIMEOUT", "30"))
33
+
34
+ mcp = FastMCP(
35
+ "meddata",
36
+ instructions=(
37
+ "Tools for looking up drug and supplement information and checking "
38
+ "interactions, backed by free U.S. government health databases (openFDA, "
39
+ "RxNorm, DailyMed, FDA Orange Book, NADAC, NIH ODS). Use search_drugs / "
40
+ "search_supplements to find an item, then get_drug / get_supplement for "
41
+ "the full profile, and check_interactions to screen a list of drugs and "
42
+ "supplements together. Results are informational only, not medical advice."
43
+ ),
44
+ )
45
+
46
+
47
+ async def _get(path: str, params: dict[str, Any] | None = None) -> dict[str, Any]:
48
+ """Call a MedData GET endpoint and return parsed JSON (or an error dict)."""
49
+ if not API_KEY:
50
+ return {
51
+ "error": "missing_api_key",
52
+ "detail": (
53
+ "Set the MEDDATA_API_KEY environment variable. Get a free key at "
54
+ "https://meddata.anthesia.io (no credit card)."
55
+ ),
56
+ }
57
+ headers = {"X-API-Key": API_KEY, "Accept": "application/json"}
58
+ try:
59
+ async with httpx.AsyncClient(timeout=TIMEOUT) as client:
60
+ resp = await client.get(f"{BASE_URL}{path}", params=params, headers=headers)
61
+ except httpx.RequestError as exc:
62
+ return {"error": "network_error", "detail": str(exc)}
63
+
64
+ if resp.status_code >= 400:
65
+ # The API returns a structured ErrorResponse; pass its detail through.
66
+ try:
67
+ body = resp.json()
68
+ except ValueError:
69
+ body = {"detail": resp.text[:500]}
70
+ return {
71
+ "error": f"http_{resp.status_code}",
72
+ "detail": body.get("detail") or body.get("error") or "Request failed.",
73
+ "status_code": resp.status_code,
74
+ }
75
+ try:
76
+ return resp.json()
77
+ except ValueError:
78
+ return {"error": "bad_response", "detail": "API returned non-JSON content."}
79
+
80
+
81
+ def _join(items: list[str]) -> str:
82
+ """Join a list of names into the comma-separated form the API expects."""
83
+ return ",".join(i.strip() for i in items if i and i.strip())
84
+
85
+
86
+ @mcp.tool()
87
+ async def search_drugs(name: str, limit: int = 10) -> dict[str, Any]:
88
+ """Search for drugs by brand or generic name.
89
+
90
+ Returns matching drugs with their RxCUI (the identifier you pass to
91
+ get_drug), generic and brand names, and dosage form/strength when known.
92
+ Use this first when you have a drug name but need its details or RxCUI.
93
+
94
+ Args:
95
+ name: Brand or generic drug name, e.g. "aspirin" or "Lipitor".
96
+ limit: Max results to return (1-50).
97
+ """
98
+ return await _get("/api/v1/drugs/search", {"name": name, "limit": limit})
99
+
100
+
101
+ @mcp.tool()
102
+ async def get_drug(rxcui: str) -> dict[str, Any]:
103
+ """Get the full profile for a drug by its RxCUI.
104
+
105
+ Returns names, dosage forms, NDC codes, label sections, and related data.
106
+ Get the RxCUI from search_drugs first if you only have a name.
107
+
108
+ Args:
109
+ rxcui: RxNorm Concept Unique Identifier, e.g. "1191" for aspirin.
110
+ """
111
+ return await _get(f"/api/v1/drugs/{rxcui}")
112
+
113
+
114
+ @mcp.tool()
115
+ async def get_drug_by_ndc(ndc_code: str) -> dict[str, Any]:
116
+ """Get a drug profile by its NDC (National Drug Code) package code.
117
+
118
+ Use when you have an NDC from a label or packaging rather than a name.
119
+
120
+ Args:
121
+ ndc_code: NDC code, e.g. "0363-0160".
122
+ """
123
+ return await _get(f"/api/v1/drugs/ndc/{ndc_code}")
124
+
125
+
126
+ @mcp.tool()
127
+ async def search_supplements(name: str, limit: int = 10) -> dict[str, Any]:
128
+ """Search for dietary supplements by name.
129
+
130
+ Returns matching supplements with their IDs (pass to get_supplement) and
131
+ summary info. Use first when you have a supplement name like "Vitamin D"
132
+ or "Fish Oil".
133
+
134
+ Args:
135
+ name: Supplement name, e.g. "Vitamin D" or "magnesium".
136
+ limit: Max results to return (1-50).
137
+ """
138
+ return await _get("/api/v1/supplements/search", {"name": name, "limit": limit})
139
+
140
+
141
+ @mcp.tool()
142
+ async def get_supplement(supplement_id: int) -> dict[str, Any]:
143
+ """Get the full fact sheet for a supplement by its ID.
144
+
145
+ Returns ingredients, recommended intake, and NIH reference data. Get the ID
146
+ from search_supplements first.
147
+
148
+ Args:
149
+ supplement_id: Numeric supplement ID from search_supplements.
150
+ """
151
+ return await _get(f"/api/v1/supplements/{supplement_id}")
152
+
153
+
154
+ @mcp.tool()
155
+ async def check_interactions(items: list[str]) -> dict[str, Any]:
156
+ """Check interactions across a mixed list of drugs and supplements.
157
+
158
+ Accepts 2-10 items (drug names, supplement names, or both) and returns known
159
+ interactions among them. Interaction data comes from established medical
160
+ databases; it is never generated or inferred, so an empty result means none
161
+ were found in those sources, not that the combination is proven safe.
162
+
163
+ Args:
164
+ items: 2-10 drug and/or supplement names,
165
+ e.g. ["warfarin", "aspirin", "Fish Oil"].
166
+ """
167
+ if len(items) < 2:
168
+ return {"error": "too_few_items", "detail": "Provide at least 2 items to compare."}
169
+ if len(items) > 10:
170
+ return {"error": "too_many_items", "detail": "Provide at most 10 items."}
171
+ return await _get("/api/v1/interactions/check", {"items": _join(items)})
172
+
173
+
174
+ @mcp.tool()
175
+ async def get_usage() -> dict[str, Any]:
176
+ """Show this API key's current billing period usage and plan limits."""
177
+ return await _get("/api/v1/billing/usage")
178
+
179
+
180
+ def main() -> None:
181
+ """Run the MCP server. Use --http for streamable-HTTP, otherwise stdio."""
182
+ transport = "streamable-http" if "--http" in sys.argv else "stdio"
183
+ mcp.run(transport=transport)
184
+
185
+
186
+ if __name__ == "__main__":
187
+ main()
@@ -0,0 +1,46 @@
1
+ [build-system]
2
+ requires = ["hatchling"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "meddata-mcp"
7
+ version = "0.1.0"
8
+ description = "MCP server for the MedData API: drug and supplement lookup and interaction checks from free U.S. government health databases."
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "MIT" }
12
+ authors = [{ name = "Anthesia", email = "support@anthesia.io" }]
13
+ keywords = [
14
+ "mcp",
15
+ "model-context-protocol",
16
+ "drug",
17
+ "supplement",
18
+ "interactions",
19
+ "fda",
20
+ "openfda",
21
+ "rxnorm",
22
+ "healthcare",
23
+ "pharmacy",
24
+ ]
25
+ classifiers = [
26
+ "Programming Language :: Python :: 3",
27
+ "License :: OSI Approved :: MIT License",
28
+ "Operating System :: OS Independent",
29
+ "Intended Audience :: Developers",
30
+ "Topic :: Scientific/Engineering :: Medical Science Apps.",
31
+ ]
32
+ dependencies = [
33
+ "mcp>=1.2.0",
34
+ "httpx>=0.27.0",
35
+ ]
36
+
37
+ [project.urls]
38
+ Homepage = "https://meddata.anthesia.io"
39
+ Documentation = "https://meddata.anthesia.io/docs"
40
+ Repository = "https://github.com/anthesiallc/meddata-api"
41
+
42
+ [project.scripts]
43
+ meddata-mcp = "meddata_mcp.server:main"
44
+
45
+ [tool.hatch.build.targets.wheel]
46
+ packages = ["meddata_mcp"]
@@ -0,0 +1,29 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-07-09/server.json",
3
+ "name": "io.github.anthesiallc/meddata",
4
+ "description": "Look up U.S. drug and supplement data and check interactions, from free government health databases (openFDA, RxNorm, NIH ODS).",
5
+ "status": "active",
6
+ "version": "0.1.0",
7
+ "repository": {
8
+ "url": "https://github.com/anthesiallc/meddata-api",
9
+ "source": "github"
10
+ },
11
+ "packages": [
12
+ {
13
+ "registryType": "pypi",
14
+ "identifier": "meddata-mcp",
15
+ "version": "0.1.0",
16
+ "transport": {
17
+ "type": "stdio"
18
+ },
19
+ "environmentVariables": [
20
+ {
21
+ "name": "MEDDATA_API_KEY",
22
+ "description": "MedData API key. Get a free one (250 calls/month, no card) at https://meddata.anthesia.io",
23
+ "isRequired": true,
24
+ "isSecret": true
25
+ }
26
+ ]
27
+ }
28
+ ]
29
+ }