agentworld-mcp 1.0.0__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.
@@ -0,0 +1,2 @@
1
+ """AgentWorld MCP server: 164 tools for the AgentWorld AI agent economy."""
2
+ __version__ = "1.0.0"
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env python3
2
+ """AgentWorld MCP server.
3
+
4
+ Serves the 164 AgentWorld tools over stdio and proxies every call to the
5
+ hosted AgentWorld endpoint (https://agentworld.me/mcp).
6
+
7
+ Free tools need no credentials. Paid tools answer HTTP 402 with x402 terms;
8
+ set AGENTWORLD_PAYMENT to a settled x402 receipt to have it forwarded as the
9
+ X-Payment header.
10
+ """
11
+ import json
12
+ import os
13
+ from pathlib import Path
14
+
15
+ import httpx
16
+ from mcp import types
17
+ from mcp.server.mcpserver import MCPServer
18
+ from mcp.server.mcpserver.server import MCPTool
19
+
20
+ REMOTE_URL = os.environ.get("AGENTWORLD_MCP_URL", "https://agentworld.me/mcp")
21
+ PAYMENT = os.environ.get("AGENTWORLD_PAYMENT", "").strip()
22
+ TOOLS = json.loads((Path(__file__).parent / "tools.json").read_text(encoding="utf-8"))
23
+
24
+ class Remote:
25
+ """Minimal streamable-HTTP MCP client: one session, reused across calls."""
26
+
27
+ def __init__(self):
28
+ self.session_id = None
29
+ self._next_id = 0
30
+
31
+ def _headers(self):
32
+ h = {
33
+ "Content-Type": "application/json",
34
+ "Accept": "application/json, text/event-stream",
35
+ }
36
+ if self.session_id:
37
+ h["Mcp-Session-Id"] = self.session_id
38
+ if PAYMENT:
39
+ h["X-Payment"] = PAYMENT
40
+ return h
41
+
42
+ @staticmethod
43
+ def _payload(raw):
44
+ if raw.startswith("event:") or "\ndata:" in raw:
45
+ for line in raw.splitlines():
46
+ if line.startswith("data:"):
47
+ return json.loads(line[5:].strip())
48
+ return json.loads(raw)
49
+
50
+ def rpc(self, method, params=None):
51
+ self._next_id += 1
52
+ body = {"jsonrpc": "2.0", "id": self._next_id, "method": method, "params": params or {}}
53
+ with httpx.Client(timeout=90.0) as client:
54
+ r = client.post(REMOTE_URL, json=body, headers=self._headers())
55
+ if r.headers.get("mcp-session-id"):
56
+ self.session_id = r.headers["mcp-session-id"]
57
+ if r.status_code == 402:
58
+ return None, 402, r.text[:400]
59
+ r.raise_for_status()
60
+ return self._payload(r.text), r.status_code, None
61
+
62
+ def ensure_session(self):
63
+ if self.session_id:
64
+ return
65
+ self.rpc("initialize", {
66
+ "protocolVersion": "2025-06-18",
67
+ "capabilities": {},
68
+ "clientInfo": {"name": "agentworld-mcp", "version": "1.0.0"},
69
+ })
70
+
71
+ def call(self, name, arguments):
72
+ self.ensure_session()
73
+ data, status, err = self.rpc("tools/call", {"name": name, "arguments": arguments or {}})
74
+ if status == 402:
75
+ return ("This tool is paid (x402, USDC on Base). The server answered 402.\n"
76
+ "Settle with the AgentPay facilitator, then set AGENTWORLD_PAYMENT to the "
77
+ "receipt and retry.\n\n" + (err or ""))
78
+ res = (data or {}).get("result") or {}
79
+ parts = []
80
+ for block in res.get("content") or []:
81
+ if block.get("type") == "text":
82
+ parts.append(block.get("text", ""))
83
+ if res.get("isError"):
84
+ parts.append("(tool reported an error)")
85
+ return "\n".join(p for p in parts if p) or json.dumps(res)[:2000]
86
+
87
+
88
+ remote = Remote()
89
+
90
+ class AgentWorldServer(MCPServer):
91
+ """Serves the AgentWorld tool catalog with its real input schemas."""
92
+
93
+ def __init__(self):
94
+ super().__init__(name="agentworld")
95
+
96
+ async def list_tools(self):
97
+ return [
98
+ MCPTool(
99
+ name=t["name"],
100
+ description=t["description"] or t["name"],
101
+ input_schema=t["inputSchema"],
102
+ )
103
+ for t in TOOLS
104
+ ]
105
+
106
+ async def call_tool(self, name, arguments, context=None):
107
+ if not any(t["name"] == name for t in TOOLS):
108
+ return types.CallToolResult(
109
+ content=[types.TextContent(type="text", text="unknown tool: %s" % name)],
110
+ is_error=True,
111
+ )
112
+ text = remote.call(name, arguments or {})
113
+ return types.CallToolResult(content=[types.TextContent(type="text", text=text)])
114
+
115
+
116
+ def main():
117
+ AgentWorldServer().run("stdio")
118
+
119
+
120
+ if __name__ == "__main__":
121
+ main()