k402-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,4 @@
1
+ .venv/
2
+ __pycache__/
3
+ dist/
4
+ *.egg-info/
k402_mcp-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Kaspa Lab
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,79 @@
1
+ Metadata-Version: 2.4
2
+ Name: k402-mcp
3
+ Version: 0.1.0
4
+ Summary: MCP server for the k402 agent-payable API catalog on Kaspa — text tools, chain data, and GPU inference, paid per call in KAS with no account or API key
5
+ Project-URL: Homepage, https://github.com/Kali123411/k402-mcp
6
+ Project-URL: Repository, https://github.com/Kali123411/k402-mcp
7
+ Author: Kaspa Lab
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: agent-payments,k402,kaspa,mcp,micropayments,x402
11
+ Classifier: License :: OSI Approved :: MIT License
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Topic :: Software Development :: Libraries
14
+ Requires-Python: >=3.10
15
+ Requires-Dist: httpx>=0.27
16
+ Requires-Dist: mcp>=1.2
17
+ Description-Content-Type: text/markdown
18
+
19
+ # k402-mcp — pay-per-call APIs for AI agents, settled in Kaspa
20
+
21
+ An MCP server that gives any agent (Claude Code, Claude Desktop, agent SDKs) a catalog of
22
+ **agent-payable APIs**: text tools (summarize, schema-guaranteed extraction, classify, rewrite),
23
+ web reading, embeddings + semantic search, live Kaspa mainnet chain data, and GPU model tiers.
24
+ **No account, no card, no API key** — the agent opens a session, gets a personal KAS deposit
25
+ address, and every call meters against the prepaid balance. Prices are USD-pegged, fractions of a
26
+ cent per call, settled on Kaspa L1 (sub-second, ~zero fees).
27
+
28
+ The payment loop is agent-native: an unfunded call returns *instructions* ("send KAS to this
29
+ address, this call costs X"), so an agent can discover the service, learn how to pay, and use it
30
+ autonomously — the [x402](https://www.x402.org/) idea, on Kaspa.
31
+
32
+ ## Install
33
+
34
+ ```bash
35
+ pip install k402-mcp
36
+ ```
37
+
38
+ Claude Code:
39
+ ```bash
40
+ claude mcp add k402 -- k402-mcp
41
+ ```
42
+
43
+ Claude Desktop / generic MCP config:
44
+ ```json
45
+ { "mcpServers": { "k402": { "command": "k402-mcp" } } }
46
+ ```
47
+
48
+ Env (all optional): `K402_GATEWAY` (defaults to the public gateway), `K402_SESSION` (pin a funded
49
+ session key), `K402_STATE` (where the auto-opened session persists, default `~/.k402/session.json`).
50
+
51
+ ## Use
52
+
53
+ 1. `catalog` — see every service and its live KAS/USD price (free)
54
+ 2. `open_session` — get a session + personal Kaspa mainnet deposit address (free); fund it from
55
+ any wallet (min 0.25 KAS — confirmed in seconds)
56
+ 3. Call anything: `summarize`, `extract`, `classify`, `rewrite`, `read_url`, `embed_text`,
57
+ `search_index`/`search_query`, `kaspa_balance`, `kaspa_utxos`, `kaspa_tx_status`,
58
+ `kaspa_fee_estimate`, `kaspa_network`, `generate` (tiers: chat / reason / code / kaspa-expert)
59
+ 4. `session_status` — watch the balance draw down (free)
60
+
61
+ Example, in Claude Code after `claude mcp add`:
62
+
63
+ > "Use the k402 tools to check the current Kaspa network status and summarize https://kaspa.org"
64
+
65
+ The first call returns how-to-pay instructions; fund the deposit address it gives you and retry.
66
+
67
+ ## Notes & honest caveats
68
+
69
+ - **Prototype.** The payment rail is custodial-prepaid today (a trustless covenant-based
70
+ settlement layer — the k402 protocol on Kaspa L1 — is in the works). Keep balances small:
71
+ a few KAS covers thousands of calls.
72
+ - Paid tools return `payment_required` + instructions instead of failing opaquely.
73
+ - The gateway rate-limits per IP; prices float with KAS/USD, so `catalog` shows current numbers.
74
+ - Need KAS? Any exchange or wallet works — deposits are plain mainnet transfers.
75
+
76
+ ---
77
+ `mcpName: io.github.kali123411/k402`
78
+
79
+ MIT © Kaspa Lab
@@ -0,0 +1,61 @@
1
+ # k402-mcp — pay-per-call APIs for AI agents, settled in Kaspa
2
+
3
+ An MCP server that gives any agent (Claude Code, Claude Desktop, agent SDKs) a catalog of
4
+ **agent-payable APIs**: text tools (summarize, schema-guaranteed extraction, classify, rewrite),
5
+ web reading, embeddings + semantic search, live Kaspa mainnet chain data, and GPU model tiers.
6
+ **No account, no card, no API key** — the agent opens a session, gets a personal KAS deposit
7
+ address, and every call meters against the prepaid balance. Prices are USD-pegged, fractions of a
8
+ cent per call, settled on Kaspa L1 (sub-second, ~zero fees).
9
+
10
+ The payment loop is agent-native: an unfunded call returns *instructions* ("send KAS to this
11
+ address, this call costs X"), so an agent can discover the service, learn how to pay, and use it
12
+ autonomously — the [x402](https://www.x402.org/) idea, on Kaspa.
13
+
14
+ ## Install
15
+
16
+ ```bash
17
+ pip install k402-mcp
18
+ ```
19
+
20
+ Claude Code:
21
+ ```bash
22
+ claude mcp add k402 -- k402-mcp
23
+ ```
24
+
25
+ Claude Desktop / generic MCP config:
26
+ ```json
27
+ { "mcpServers": { "k402": { "command": "k402-mcp" } } }
28
+ ```
29
+
30
+ Env (all optional): `K402_GATEWAY` (defaults to the public gateway), `K402_SESSION` (pin a funded
31
+ session key), `K402_STATE` (where the auto-opened session persists, default `~/.k402/session.json`).
32
+
33
+ ## Use
34
+
35
+ 1. `catalog` — see every service and its live KAS/USD price (free)
36
+ 2. `open_session` — get a session + personal Kaspa mainnet deposit address (free); fund it from
37
+ any wallet (min 0.25 KAS — confirmed in seconds)
38
+ 3. Call anything: `summarize`, `extract`, `classify`, `rewrite`, `read_url`, `embed_text`,
39
+ `search_index`/`search_query`, `kaspa_balance`, `kaspa_utxos`, `kaspa_tx_status`,
40
+ `kaspa_fee_estimate`, `kaspa_network`, `generate` (tiers: chat / reason / code / kaspa-expert)
41
+ 4. `session_status` — watch the balance draw down (free)
42
+
43
+ Example, in Claude Code after `claude mcp add`:
44
+
45
+ > "Use the k402 tools to check the current Kaspa network status and summarize https://kaspa.org"
46
+
47
+ The first call returns how-to-pay instructions; fund the deposit address it gives you and retry.
48
+
49
+ ## Notes & honest caveats
50
+
51
+ - **Prototype.** The payment rail is custodial-prepaid today (a trustless covenant-based
52
+ settlement layer — the k402 protocol on Kaspa L1 — is in the works). Keep balances small:
53
+ a few KAS covers thousands of calls.
54
+ - Paid tools return `payment_required` + instructions instead of failing opaquely.
55
+ - The gateway rate-limits per IP; prices float with KAS/USD, so `catalog` shows current numbers.
56
+ - Need KAS? Any exchange or wallet works — deposits are plain mainnet transfers.
57
+
58
+ ---
59
+ `mcpName: io.github.kali123411/k402`
60
+
61
+ MIT © Kaspa Lab
@@ -0,0 +1,181 @@
1
+ #!/usr/bin/env python3
2
+ # k402-mcp — MCP server exposing the k402 agent-payable API catalog as tools.
3
+ #
4
+ # Any MCP-capable agent (Claude Code, Claude Desktop, agent SDKs) gets the whole paid catalog —
5
+ # text tools, Kaspa chain data, GPU inference — as ordinary tools. Payment is a prepaid KAS
6
+ # balance: open_session() mints a personal mainnet deposit address; fund it from any wallet and
7
+ # every paid tool call meters against it. A 402 comes back as readable "how to pay" instructions,
8
+ # so an agent can discover the service, learn how to fund it, and (once funded) use it — the whole
9
+ # loop without a human account, card, or API key.
10
+ #
11
+ # Env: K402_GATEWAY (default: the public gateway), K402_SESSION (optional fixed session key),
12
+ # K402_STATE (session persistence, default ~/.k402/session.json)
13
+ import json, os, pathlib
14
+ import httpx
15
+ from mcp.server.fastmcp import FastMCP
16
+
17
+ GATEWAY = os.environ.get("K402_GATEWAY", "https://x402-compute.68cxgfyr0.workers.dev").rstrip("/")
18
+ STATE = pathlib.Path(os.environ.get("K402_STATE", os.path.expanduser("~/.k402/session.json")))
19
+
20
+ mcp = FastMCP("k402")
21
+ http = httpx.Client(timeout=180)
22
+
23
+ def _session():
24
+ if os.environ.get("K402_SESSION"):
25
+ return os.environ["K402_SESSION"]
26
+ try:
27
+ return json.loads(STATE.read_text())["session"]
28
+ except Exception:
29
+ return None
30
+
31
+ def _paid(path, body):
32
+ """POST a paid endpoint with the session; turn 402s into actionable payment instructions."""
33
+ sid = _session()
34
+ headers = {"X-Session": sid} if sid else {}
35
+ r = http.post(f"{GATEWAY}{path}", json=body, headers=headers)
36
+ try:
37
+ out = r.json()
38
+ except Exception:
39
+ return {"error": f"gateway returned non-JSON (HTTP {r.status_code})"}
40
+ if r.status_code == 402:
41
+ if not sid:
42
+ return {"payment_required": True,
43
+ "how_to_pay": "No session yet. Call the open_session tool to get a personal "
44
+ "Kaspa deposit address, fund it with KAS from any wallet, then retry."}
45
+ return {"payment_required": True, "how_to_pay":
46
+ f"Session balance is too low. Send KAS to your deposit address "
47
+ f"{out.get('depositAddress', '(see session_status)')} — this call costs "
48
+ f"~{out.get('neededKas', '?')} KAS. Balance updates within seconds of confirmation.",
49
+ **out}
50
+ return out
51
+
52
+ # ------------------------------------------------------------------ free: discovery + payment
53
+ @mcp.tool()
54
+ def catalog() -> dict:
55
+ """List every service this gateway sells (text tools, Kaspa chain data, LLM tiers) with live
56
+ prices in KAS and USD. Free. Start here to see what's available and what calls cost."""
57
+ return http.get(f"{GATEWAY}/").json()
58
+
59
+ @mcp.tool()
60
+ def open_session() -> dict:
61
+ """Open a prepaid payment session: returns a session key and a personal Kaspa MAINNET deposit
62
+ address. Send KAS to the address from any wallet (min 0.25 KAS); confirmed deposits become
63
+ spendable balance within seconds and every paid tool call meters against it. Free. The session
64
+ is saved locally so subsequent calls use it automatically."""
65
+ r = http.post(f"{GATEWAY}/onboard/request", json={}).json()
66
+ if "session" in r:
67
+ STATE.parent.mkdir(parents=True, exist_ok=True)
68
+ STATE.write_text(json.dumps({"session": r["session"], "depositAddress": r["depositAddress"],
69
+ "gateway": GATEWAY}))
70
+ STATE.chmod(0o600)
71
+ r["note"] = f"session saved to {STATE} — fund the deposit address, then call any paid tool"
72
+ return r
73
+
74
+ @mcp.tool()
75
+ def session_status() -> dict:
76
+ """Check the current payment session: deposit address, deposited / spent / remaining KAS.
77
+ Free."""
78
+ sid = _session()
79
+ if not sid:
80
+ return {"session": None, "note": "no session yet — call open_session first"}
81
+ return http.get(f"{GATEWAY}/session/{sid}").json()
82
+
83
+ # ------------------------------------------------------------------ paid: text tools
84
+ @mcp.tool()
85
+ def summarize(text: str = "", url: str = "", max_words: int = 150) -> dict:
86
+ """Summarize text or a public URL in at most max_words. Paid (~$0.001 in KAS)."""
87
+ body = {"max_words": max_words, **({"url": url} if url else {"text": text})}
88
+ return _paid("/summarize", body)
89
+
90
+ @mcp.tool()
91
+ def extract(text: str, schema: dict, instruction: str = "") -> dict:
92
+ """Extract structured data from text as JSON guaranteed to match your JSON schema
93
+ (schema-constrained decoding, not best-effort). Paid (~$0.0015 in KAS)."""
94
+ body = {"text": text, "schema": schema}
95
+ if instruction:
96
+ body["instruction"] = instruction
97
+ return _paid("/extract", body)
98
+
99
+ @mcp.tool()
100
+ def rewrite(text: str, instruction: str) -> dict:
101
+ """Rewrite text per an instruction (tone, format, length...). Paid (~$0.001 in KAS)."""
102
+ return _paid("/rewrite", {"text": text, "instruction": instruction})
103
+
104
+ @mcp.tool()
105
+ def classify(text: str, labels: list[str], multi: bool = False) -> dict:
106
+ """Classify text into one (or multiple, if multi=true) of 2-32 labels; the result is
107
+ constrained to your label set. Paid (~$0.0003 in KAS)."""
108
+ return _paid("/classify", {"text": text, "labels": labels, "multi": multi})
109
+
110
+ @mcp.tool()
111
+ def read_url(url: str, distill: bool = False) -> dict:
112
+ """Fetch a public web page and return its title + clean markdown; distill=true adds key-fact
113
+ bullets. Useful when you have no web access of your own. Paid (~$0.0012 in KAS)."""
114
+ return _paid("/read", {"url": url, "distill": distill})
115
+
116
+ @mcp.tool()
117
+ def embed_text(texts: list[str]) -> dict:
118
+ """Embed up to 64 texts (768-dim vectors, nomic-embed-text). Paid (~$0.0003 in KAS)."""
119
+ return _paid("/embed", {"input": texts})
120
+
121
+ @mcp.tool()
122
+ def search_index(collection: str, documents: list[dict], replace: bool = False) -> dict:
123
+ """Store documents [{id, text, meta?}] in a named server-side collection for semantic search.
124
+ Use an unguessable collection name and keep it secret. Paid (~$0.0015 in KAS)."""
125
+ return _paid("/search/index", {"collection": collection, "documents": documents, "replace": replace})
126
+
127
+ @mcp.tool()
128
+ def search_query(collection: str, q: str, top_k: int = 5) -> dict:
129
+ """Semantic-search a collection you indexed earlier; returns top-k matches with scores.
130
+ Paid (~$0.0003 in KAS)."""
131
+ return _paid("/search/query", {"collection": collection, "q": q, "top_k": top_k})
132
+
133
+ # ------------------------------------------------------------------ paid: Kaspa chain data
134
+ @mcp.tool()
135
+ def kaspa_balance(address: str) -> dict:
136
+ """Balance of any Kaspa MAINNET address, straight from a node (no indexer, no API key).
137
+ Paid (~$0.00015 in KAS)."""
138
+ return _paid("/kaspa/balance", {"address": address})
139
+
140
+ @mcp.tool()
141
+ def kaspa_utxos(address: str) -> dict:
142
+ """UTXO set of a Kaspa mainnet address, including scriptPublicKey and covenant_id where set.
143
+ Paid (~$0.0003 in KAS)."""
144
+ return _paid("/kaspa/utxos", {"address": address})
145
+
146
+ @mcp.tool()
147
+ def kaspa_tx_status(txid: str) -> dict:
148
+ """Mempool status of a Kaspa transaction. Absent from mempool means accepted-or-unknown —
149
+ confirm acceptance by checking one of its outputs with kaspa_utxos. Paid (~$0.00015)."""
150
+ return _paid("/kaspa/tx", {"txid": txid})
151
+
152
+ @mcp.tool()
153
+ def kaspa_fee_estimate() -> dict:
154
+ """Current Kaspa mainnet feerate buckets (sompi per gram of tx mass). Paid (~$0.00015)."""
155
+ return _paid("/kaspa/fee-estimate", {})
156
+
157
+ @mcp.tool()
158
+ def kaspa_network() -> dict:
159
+ """Kaspa mainnet status: DAA score, block count, difficulty, node sync state.
160
+ Paid (~$0.00015 in KAS)."""
161
+ return _paid("/kaspa/network", {})
162
+
163
+ # ------------------------------------------------------------------ paid: LLM tiers
164
+ @mcp.tool()
165
+ def generate(prompt: str, tier: str = "chat", system: str = "", max_tokens: int = 512) -> dict:
166
+ """Run a prompt on a GPU model tier: 'chat' (fast 7B, ~$0.0015), 'reason' (35B, ~$0.004),
167
+ 'code' (coder model, ~$0.0025), or 'kaspa-expert' (RAG-grounded, current Kaspa knowledge,
168
+ ~$0.0015). Returns the completion text."""
169
+ msgs = ([{"role": "system", "content": system}] if system else []) + \
170
+ [{"role": "user", "content": prompt}]
171
+ out = _paid("/v1/chat/completions", {"model": tier, "messages": msgs, "max_tokens": max_tokens})
172
+ if isinstance(out, dict) and out.get("choices"):
173
+ return {"tier": tier, "text": out["choices"][0]["message"]["content"],
174
+ "usage": out.get("usage")}
175
+ return out
176
+
177
+ def main():
178
+ mcp.run()
179
+
180
+ if __name__ == "__main__":
181
+ main()
@@ -0,0 +1,29 @@
1
+ [project]
2
+ name = "k402-mcp"
3
+ version = "0.1.0"
4
+ description = "MCP server for the k402 agent-payable API catalog on Kaspa — text tools, chain data, and GPU inference, paid per call in KAS with no account or API key"
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ license = { text = "MIT" }
8
+ authors = [{ name = "Kaspa Lab" }]
9
+ keywords = ["mcp", "kaspa", "k402", "x402", "agent-payments", "micropayments"]
10
+ classifiers = [
11
+ "License :: OSI Approved :: MIT License",
12
+ "Programming Language :: Python :: 3",
13
+ "Topic :: Software Development :: Libraries",
14
+ ]
15
+ dependencies = ["mcp>=1.2", "httpx>=0.27"]
16
+
17
+ [project.urls]
18
+ Homepage = "https://github.com/Kali123411/k402-mcp"
19
+ Repository = "https://github.com/Kali123411/k402-mcp"
20
+
21
+ [project.scripts]
22
+ k402-mcp = "k402_mcp:main"
23
+
24
+ [build-system]
25
+ requires = ["hatchling"]
26
+ build-backend = "hatchling.build"
27
+
28
+ [tool.hatch.build.targets.wheel]
29
+ include = ["k402_mcp.py"]
@@ -0,0 +1,18 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-09-29/server.schema.json",
3
+ "name": "io.github.kali123411/k402",
4
+ "description": "Agent-payable APIs on Kaspa: text tools, chain data, GPU inference — pay per call in KAS, no account or API key",
5
+ "version": "0.1.0",
6
+ "packages": [
7
+ {
8
+ "registryType": "pypi",
9
+ "identifier": "k402-mcp",
10
+ "version": "0.1.0",
11
+ "transport": { "type": "stdio" },
12
+ "environmentVariables": [
13
+ { "name": "K402_GATEWAY", "description": "Gateway URL (defaults to the public k402 gateway)", "isRequired": false },
14
+ { "name": "K402_SESSION", "description": "Pin a funded session key (otherwise open_session mints one)", "isRequired": false }
15
+ ]
16
+ }
17
+ ]
18
+ }