nutriref-mcp 0.2.2__py3-none-any.whl

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.
mcp_server/__init__.py ADDED
@@ -0,0 +1,13 @@
1
+ """MCP server that exposes NutriRef's endpoints as tools for AI agents.
2
+
3
+ Run with:
4
+ python -m mcp_server
5
+
6
+ Required env vars:
7
+ PAYER_PRIVATE_KEY -- a funded Base mainnet wallet's private key (the agent operator pays from this wallet)
8
+ NUTRIREF_BASE_URL -- defaults to https://nutriref.xyz
9
+ """
10
+
11
+ from .server import main
12
+
13
+ __all__ = ["main"]
mcp_server/__main__.py ADDED
@@ -0,0 +1,4 @@
1
+ from .server import main
2
+
3
+ if __name__ == "__main__":
4
+ main()
mcp_server/server.py ADDED
@@ -0,0 +1,107 @@
1
+ """FastMCP server exposing NutriRef as four tools.
2
+
3
+ Each tool call makes a real x402 micropayment against NUTRIREF_BASE_URL using
4
+ PAYER_PRIVATE_KEY. The agent operator funds that wallet with USDC on Base.
5
+ """
6
+
7
+ import os
8
+ from typing import Any
9
+
10
+ import httpx
11
+ from eth_account import Account
12
+ from mcp.server.fastmcp import FastMCP
13
+ from x402.client import x402Client
14
+ from x402.http.clients.httpx import wrapHttpxWithPayment
15
+ from x402.mechanisms.evm.exact import register_exact_evm_client
16
+
17
+
18
+ NUTRIREF_BASE_URL = os.environ.get("NUTRIREF_BASE_URL", "https://nutriref.xyz")
19
+
20
+ _http: httpx.AsyncClient | None = None
21
+
22
+
23
+ def _client() -> httpx.AsyncClient:
24
+ global _http
25
+ if _http is not None:
26
+ return _http
27
+ key = os.environ.get("PAYER_PRIVATE_KEY")
28
+ if not key:
29
+ raise RuntimeError(
30
+ "PAYER_PRIVATE_KEY env var is required to make a paid NutriRef call. "
31
+ "Set it to a Base mainnet wallet private key with USDC balance "
32
+ "(each call costs $0.001-$0.005)."
33
+ )
34
+ account = Account.from_key(key)
35
+ x402 = x402Client()
36
+ register_exact_evm_client(x402, account)
37
+ _http = wrapHttpxWithPayment(x402, base_url=NUTRIREF_BASE_URL, timeout=30.0)
38
+ return _http
39
+
40
+
41
+ mcp = FastMCP(
42
+ "nutriref",
43
+ instructions=(
44
+ "NutriRef: structured USDA FoodData Central nutrition data. Each call charges "
45
+ "USDC from the configured PAYER_PRIVATE_KEY wallet on Base mainnet via x402. "
46
+ "Use nutrition_search first to get an fdc_id, then nutrition_detail for the "
47
+ "full breakdown. nutrition_compare and nutrition_recipe compose from cached "
48
+ "detail data."
49
+ ),
50
+ )
51
+
52
+
53
+ @mcp.tool()
54
+ async def nutrition_search(q: str, limit: int = 10) -> dict[str, Any]:
55
+ """Find foods in the USDA FoodData Central database by free-text name. Use this FIRST when the user mentions a food by name and you need its `fdc_id` for any of the other nutrition_* tools. Returns ranked matches with fdc_id, description, brand_owner, and a quick macro summary (calories/protein/carbs/fat per 100g). Charges $0.001 USDC per call.
56
+
57
+ Args:
58
+ q: Free-text food name (e.g. "banana", "greek yogurt", "chicken breast").
59
+ limit: Max results to return, 1-50. Default 10. Use a small limit unless you need to browse.
60
+ """
61
+ r = await _client().get("/v1/nutrition/search", params={"q": q, "limit": limit})
62
+ r.raise_for_status()
63
+ return r.json()
64
+
65
+
66
+ @mcp.tool()
67
+ async def nutrition_detail(fdc_id: int) -> dict[str, Any]:
68
+ """Get the full per-100g nutrition profile for one specific food. Use this when you have an `fdc_id` (from nutrition_search) and the user needs micronutrients beyond just calories/protein/carbs/fat. Returns all 13 tracked nutrients: calories, protein, fat, carbs, fiber, sugar, sodium, cholesterol, saturated_fat, vitamin_c, calcium, iron, potassium. Missing nutrients are `null`, not 0. Charges $0.002 USDC per call.
69
+
70
+ Args:
71
+ fdc_id: USDA FoodData Central ID, obtained from nutrition_search.
72
+ """
73
+ r = await _client().get(f"/v1/nutrition/detail/{fdc_id}")
74
+ r.raise_for_status()
75
+ return r.json()
76
+
77
+
78
+ @mcp.tool()
79
+ async def nutrition_compare(fdc_ids: list[int]) -> dict[str, Any]:
80
+ """Compare 2 to 5 foods side by side. Use this when the user asks "which is healthier," "which has more protein," or any cross-food comparison — it's cheaper and clearer than calling nutrition_detail multiple times. Returns each food's full nutrition plus per-nutrient winners (highest protein, lowest sodium, etc.). Charges $0.003 USDC per call.
81
+
82
+ Args:
83
+ fdc_ids: 2 to 5 USDA FDC IDs to compare.
84
+ """
85
+ r = await _client().post("/v1/nutrition/compare", json={"fdc_ids": fdc_ids})
86
+ r.raise_for_status()
87
+ return r.json()
88
+
89
+
90
+ @mcp.tool()
91
+ async def nutrition_recipe(ingredients: list[dict[str, Any]]) -> dict[str, Any]:
92
+ """Sum nutrition across a recipe of weighted ingredients. Use this for meal planning, recipe analysis, or any "what are the totals if I combine X grams of A with Y grams of B" task. Each food's per-100g nutrition is scaled by grams/100 then summed. Charges $0.005 USDC per call.
93
+
94
+ Args:
95
+ ingredients: List of {"fdc_id": int, "grams": float} pairs. At least one; weights in grams.
96
+ """
97
+ r = await _client().post("/v1/nutrition/recipe", json={"ingredients": ingredients})
98
+ r.raise_for_status()
99
+ return r.json()
100
+
101
+
102
+ def main() -> None:
103
+ mcp.run()
104
+
105
+
106
+ if __name__ == "__main__":
107
+ main()
@@ -0,0 +1,72 @@
1
+ Metadata-Version: 2.4
2
+ Name: nutriref-mcp
3
+ Version: 0.2.2
4
+ Summary: MCP server for NutriRef — pay-per-call USDA nutrition for AI agents (x402 + USDC on Base).
5
+ Author: Derek Hefley
6
+ License: MIT
7
+ Project-URL: Homepage, https://nutriref.xyz
8
+ Project-URL: Repository, https://github.com/Younghef/nutriref-api
9
+ Project-URL: Issues, https://github.com/Younghef/nutriref-api/issues
10
+ Keywords: mcp,nutrition,usda,x402,agents,food,fooddata-central
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Intended Audience :: Developers
17
+ Classifier: Topic :: Scientific/Engineering
18
+ Requires-Python: >=3.11
19
+ Description-Content-Type: text/markdown
20
+ Requires-Dist: mcp>=1.0.0
21
+ Requires-Dist: httpx>=0.27.0
22
+ Requires-Dist: eth-account>=0.13.0
23
+ Requires-Dist: x402[evm]>=2.10.0
24
+
25
+ # nutriref-mcp
26
+
27
+ MCP server for **[NutriRef](https://nutriref.xyz)** — pay-per-call USDA FoodData Central nutrition for AI agents, gated by [x402](https://www.x402.org/) micropayments in USDC on Base. No signup, no API keys.
28
+
29
+ It exposes four tools:
30
+
31
+ | Tool | What it does | Price |
32
+ |---|---|---|
33
+ | `nutrition_search` | Find foods by name, get `fdc_id` + macros | $0.001 |
34
+ | `nutrition_detail` | Full per-100g profile (13 nutrients) for one food | $0.002 |
35
+ | `nutrition_compare` | Compare 2–5 foods with per-nutrient winners | $0.003 |
36
+ | `nutrition_recipe` | Scale and sum nutrition across weighted ingredients | $0.005 |
37
+
38
+ ## Install
39
+
40
+ ```bash
41
+ pip install nutriref-mcp
42
+ ```
43
+
44
+ Or run without installing:
45
+
46
+ ```bash
47
+ uvx nutriref-mcp
48
+ ```
49
+
50
+ ## Configure your MCP client
51
+
52
+ Add this to your client config (Claude Desktop's `claude_desktop_config.json`, Claude Code's MCP settings, etc.):
53
+
54
+ ```json
55
+ {
56
+ "mcpServers": {
57
+ "nutriref": {
58
+ "command": "nutriref-mcp",
59
+ "env": {
60
+ "PAYER_PRIVATE_KEY": "0x...your-funded-wallet-key...",
61
+ "NUTRIREF_BASE_URL": "https://nutriref.xyz"
62
+ }
63
+ }
64
+ }
65
+ }
66
+ ```
67
+
68
+ `PAYER_PRIVATE_KEY` is the private key of a Base mainnet wallet holding USDC — the wallet pays for each tool call. Use a dedicated wallet funded only with what you're willing to spend. `NUTRIREF_BASE_URL` is optional and defaults to `https://nutriref.xyz`.
69
+
70
+ ## License
71
+
72
+ MIT
@@ -0,0 +1,8 @@
1
+ mcp_server/__init__.py,sha256=WsV7TMPncqJZoQwM-q4cytxkBf9woxn_Dld4gIgJ4dw,349
2
+ mcp_server/__main__.py,sha256=9it1my_mM7xBpDh79QSi7FAvZD3Vki3GQFPJIDZw_zs,64
3
+ mcp_server/server.py,sha256=7n9brAv_gB7dxm8msRNZxY074MuytWwZ1X3fQ6Dj79c,4446
4
+ nutriref_mcp-0.2.2.dist-info/METADATA,sha256=8d14X77yUzhDmQu9YPMoLBvmpPEAmNHu6mbe1SnAri8,2418
5
+ nutriref_mcp-0.2.2.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
6
+ nutriref_mcp-0.2.2.dist-info/entry_points.txt,sha256=7sk1JF2nsBdpE0aBnERR4XvHzprUVCLrxv4Q9g50nQw,49
7
+ nutriref_mcp-0.2.2.dist-info/top_level.txt,sha256=R49ZBwHkJvJ-AJ8o9wy6MuCs0rvZpyCEuvdwhI4PpHs,11
8
+ nutriref_mcp-0.2.2.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ nutriref-mcp = mcp_server:main
@@ -0,0 +1 @@
1
+ mcp_server