ctxprotocol 0.5.5__tar.gz → 0.5.7__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.
Files changed (22) hide show
  1. ctxprotocol-0.5.7/.gitignore +51 -0
  2. {ctxprotocol-0.5.5 → ctxprotocol-0.5.7}/PKG-INFO +46 -7
  3. {ctxprotocol-0.5.5 → ctxprotocol-0.5.7}/README.md +45 -6
  4. {ctxprotocol-0.5.5 → ctxprotocol-0.5.7}/ctxprotocol/__init__.py +45 -0
  5. {ctxprotocol-0.5.5 → ctxprotocol-0.5.7}/ctxprotocol/auth/__init__.py +34 -7
  6. ctxprotocol-0.5.7/ctxprotocol/handshake/__init__.py +418 -0
  7. ctxprotocol-0.5.7/examples/server/hummingbot-contributor/README.md +249 -0
  8. ctxprotocol-0.5.7/examples/server/hummingbot-contributor/env.example +16 -0
  9. ctxprotocol-0.5.7/examples/server/hummingbot-contributor/requirements.txt +23 -0
  10. ctxprotocol-0.5.7/examples/server/hummingbot-contributor/server.py +769 -0
  11. {ctxprotocol-0.5.5 → ctxprotocol-0.5.7}/pyproject.toml +1 -1
  12. {ctxprotocol-0.5.5 → ctxprotocol-0.5.7}/ctxprotocol/client/__init__.py +0 -0
  13. {ctxprotocol-0.5.5 → ctxprotocol-0.5.7}/ctxprotocol/client/client.py +0 -0
  14. {ctxprotocol-0.5.5 → ctxprotocol-0.5.7}/ctxprotocol/client/resources/__init__.py +0 -0
  15. {ctxprotocol-0.5.5 → ctxprotocol-0.5.7}/ctxprotocol/client/resources/discovery.py +0 -0
  16. {ctxprotocol-0.5.5 → ctxprotocol-0.5.7}/ctxprotocol/client/resources/tools.py +0 -0
  17. {ctxprotocol-0.5.5 → ctxprotocol-0.5.7}/ctxprotocol/client/types.py +0 -0
  18. {ctxprotocol-0.5.5 → ctxprotocol-0.5.7}/ctxprotocol/context/__init__.py +0 -0
  19. {ctxprotocol-0.5.5 → ctxprotocol-0.5.7}/ctxprotocol/context/hyperliquid.py +0 -0
  20. {ctxprotocol-0.5.5 → ctxprotocol-0.5.7}/ctxprotocol/context/polymarket.py +0 -0
  21. {ctxprotocol-0.5.5 → ctxprotocol-0.5.7}/ctxprotocol/context/wallet.py +0 -0
  22. {ctxprotocol-0.5.5 → ctxprotocol-0.5.7}/ctxprotocol/py.typed +0 -0
@@ -0,0 +1,51 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ *.egg-info/
20
+ .installed.cfg
21
+ *.egg
22
+
23
+ # Virtual environments
24
+ .env
25
+ .venv
26
+ env/
27
+ venv/
28
+ ENV/
29
+
30
+ # IDE
31
+ .idea/
32
+ .vscode/
33
+ *.swp
34
+ *.swo
35
+
36
+ # Testing
37
+ .tox/
38
+ .coverage
39
+ .coverage.*
40
+ htmlcov/
41
+ .pytest_cache/
42
+
43
+ # md files
44
+ *.md
45
+ !README.md
46
+ !docs/mcp-builder-template.md
47
+
48
+ # Shell scripts (deployment)
49
+ *.sh
50
+
51
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ctxprotocol
3
- Version: 0.5.5
3
+ Version: 0.5.7
4
4
  Summary: Official Python SDK for the Context Protocol - Discover and execute AI tools programmatically
5
5
  Project-URL: Homepage, https://ctxprotocol.com
6
6
  Project-URL: Documentation, https://docs.ctxprotocol.com
@@ -48,12 +48,26 @@ Context Protocol is **pip for AI capabilities**. Just as you install packages to
48
48
  [![Python versions](https://img.shields.io/pypi/pyversions/ctxprotocol.svg)](https://pypi.org/project/ctxprotocol/)
49
49
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
50
50
 
51
+ ---
52
+
53
+ ### 💰 $10,000 Developer Grant Program
54
+
55
+ We're funding the initial supply of MCP Tools for the Context Marketplace. **Become a Data Broker.**
56
+
57
+ - **🛠️ Build:** Create an MCP Server using this SDK (Solana data, Trading tools, Scrapers, etc.)
58
+ - **📦 List:** Publish it to the Context Registry
59
+ - **💵 Earn:** Get a **$250–$1,000 Grant** + earn USDC every time an agent queries your tool
60
+
61
+ 👉 [**View Open Bounties & Apply Here**](https://docs.ctxprotocol.com/grants)
62
+
63
+ ---
64
+
51
65
  ## Why use Context?
52
66
 
53
67
  - **🔌 One Interface, Everything:** Stop integrating APIs one by one. Use a single SDK to access any tool in the marketplace.
54
68
  - **🧠 Zero-Ops:** We're a gateway to the best MCP tools. Just send the JSON and get the result.
55
69
  - **⚡️ Agentic Discovery:** Your Agent can search the marketplace at runtime to find tools it didn't know it needed.
56
- - **💸 Micro-Billing:** Pay only for what you use (e.g., $0.001/query). No monthly subscriptions for tools you rarely use.
70
+ - **💸 Pay-Per-Response:** The $500/year subscription? Now $0.01/response. No monthly fees, just results.
57
71
 
58
72
  ## Who Is This SDK For?
59
73
 
@@ -263,15 +277,40 @@ if is_protected_mcp_method(body["method"]):
263
277
  raise HTTPException(status_code=401, detail="Unauthorized")
264
278
  ```
265
279
 
266
- ### Security Model
280
+ ### MCP Security Model
281
+
282
+ The SDK implements a **selective authentication** model — discovery is open, execution is protected:
267
283
 
268
- | MCP Method | Auth Required | Reason |
269
- |------------|---------------|--------|
270
- | `tools/list` | ❌ No | Discovery - just returns tool schemas |
271
- | `tools/call` | ✅ Yes | Execution - runs code, may cost money |
284
+ | MCP Method | Auth Required | Why |
285
+ |------------|---------------|-----|
272
286
  | `initialize` | ❌ No | Session setup |
287
+ | `tools/list` | ❌ No | Discovery - agents need to see your schemas |
273
288
  | `resources/list` | ❌ No | Discovery |
274
289
  | `prompts/list` | ❌ No | Discovery |
290
+ | `tools/call` | ✅ **Yes** | **Execution - costs money, runs your code** |
291
+
292
+ **What this means in practice:**
293
+ - ✅ `https://your-mcp.com/mcp` + `initialize` → Works without auth
294
+ - ✅ `https://your-mcp.com/mcp` + `tools/list` → Works without auth
295
+ - ❌ `https://your-mcp.com/mcp` + `tools/call` → **Requires Context Protocol JWT**
296
+
297
+ This matches standard API patterns (OpenAPI schemas are public, GraphQL introspection is open).
298
+
299
+ ## Execution Timeout & Product Design
300
+
301
+ ⚠️ **Important**: MCP tool execution has a **~60 second timeout** (enforced at the platform/client level, not by MCP itself). This is intentional—it encourages building pre-computed insight products rather than raw data access.
302
+
303
+ **Best practice**: Run heavy queries offline (via cron jobs), store results in your database, and serve instant results via MCP. This is how Bloomberg, Nansen, and Arkham work.
304
+
305
+ ```python
306
+ # ❌ BAD: Raw access (timeout-prone, no moat)
307
+ {"name": "run_sql", "description": "Run any SQL against blockchain data"}
308
+
309
+ # ✅ GOOD: Pre-computed product (instant, defensible)
310
+ {"name": "get_smart_money_wallets", "description": "Top 100 wallets that timed market tops"}
311
+ ```
312
+
313
+ See the [full documentation](https://docs.ctxprotocol.com/guides/build-tools#execution-limits--product-design) for detailed guidance.
275
314
 
276
315
  ## Context Injection (Personalized Tools)
277
316
 
@@ -10,12 +10,26 @@ Context Protocol is **pip for AI capabilities**. Just as you install packages to
10
10
  [![Python versions](https://img.shields.io/pypi/pyversions/ctxprotocol.svg)](https://pypi.org/project/ctxprotocol/)
11
11
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
12
12
 
13
+ ---
14
+
15
+ ### 💰 $10,000 Developer Grant Program
16
+
17
+ We're funding the initial supply of MCP Tools for the Context Marketplace. **Become a Data Broker.**
18
+
19
+ - **🛠️ Build:** Create an MCP Server using this SDK (Solana data, Trading tools, Scrapers, etc.)
20
+ - **📦 List:** Publish it to the Context Registry
21
+ - **💵 Earn:** Get a **$250–$1,000 Grant** + earn USDC every time an agent queries your tool
22
+
23
+ 👉 [**View Open Bounties & Apply Here**](https://docs.ctxprotocol.com/grants)
24
+
25
+ ---
26
+
13
27
  ## Why use Context?
14
28
 
15
29
  - **🔌 One Interface, Everything:** Stop integrating APIs one by one. Use a single SDK to access any tool in the marketplace.
16
30
  - **🧠 Zero-Ops:** We're a gateway to the best MCP tools. Just send the JSON and get the result.
17
31
  - **⚡️ Agentic Discovery:** Your Agent can search the marketplace at runtime to find tools it didn't know it needed.
18
- - **💸 Micro-Billing:** Pay only for what you use (e.g., $0.001/query). No monthly subscriptions for tools you rarely use.
32
+ - **💸 Pay-Per-Response:** The $500/year subscription? Now $0.01/response. No monthly fees, just results.
19
33
 
20
34
  ## Who Is This SDK For?
21
35
 
@@ -225,15 +239,40 @@ if is_protected_mcp_method(body["method"]):
225
239
  raise HTTPException(status_code=401, detail="Unauthorized")
226
240
  ```
227
241
 
228
- ### Security Model
242
+ ### MCP Security Model
243
+
244
+ The SDK implements a **selective authentication** model — discovery is open, execution is protected:
229
245
 
230
- | MCP Method | Auth Required | Reason |
231
- |------------|---------------|--------|
232
- | `tools/list` | ❌ No | Discovery - just returns tool schemas |
233
- | `tools/call` | ✅ Yes | Execution - runs code, may cost money |
246
+ | MCP Method | Auth Required | Why |
247
+ |------------|---------------|-----|
234
248
  | `initialize` | ❌ No | Session setup |
249
+ | `tools/list` | ❌ No | Discovery - agents need to see your schemas |
235
250
  | `resources/list` | ❌ No | Discovery |
236
251
  | `prompts/list` | ❌ No | Discovery |
252
+ | `tools/call` | ✅ **Yes** | **Execution - costs money, runs your code** |
253
+
254
+ **What this means in practice:**
255
+ - ✅ `https://your-mcp.com/mcp` + `initialize` → Works without auth
256
+ - ✅ `https://your-mcp.com/mcp` + `tools/list` → Works without auth
257
+ - ❌ `https://your-mcp.com/mcp` + `tools/call` → **Requires Context Protocol JWT**
258
+
259
+ This matches standard API patterns (OpenAPI schemas are public, GraphQL introspection is open).
260
+
261
+ ## Execution Timeout & Product Design
262
+
263
+ ⚠️ **Important**: MCP tool execution has a **~60 second timeout** (enforced at the platform/client level, not by MCP itself). This is intentional—it encourages building pre-computed insight products rather than raw data access.
264
+
265
+ **Best practice**: Run heavy queries offline (via cron jobs), store results in your database, and serve instant results via MCP. This is how Bloomberg, Nansen, and Arkham work.
266
+
267
+ ```python
268
+ # ❌ BAD: Raw access (timeout-prone, no moat)
269
+ {"name": "run_sql", "description": "Run any SQL against blockchain data"}
270
+
271
+ # ✅ GOOD: Pre-computed product (instant, defensible)
272
+ {"name": "get_smart_money_wallets", "description": "Top 100 wallets that timed market tops"}
273
+ ```
274
+
275
+ See the [full documentation](https://docs.ctxprotocol.com/guides/build-tools#execution-limits--product-design) for detailed guidance.
237
276
 
238
277
  ## Context Injection (Personalized Tools)
239
278
 
@@ -91,6 +91,31 @@ from ctxprotocol.auth import (
91
91
  CreateContextMiddlewareOptions,
92
92
  )
93
93
 
94
+ # Handshake types and helpers for tools that need user interaction
95
+ # (signatures, transactions, OAuth)
96
+ from ctxprotocol.handshake import (
97
+ # Types
98
+ HandshakeMeta,
99
+ EIP712Domain,
100
+ EIP712TypeField,
101
+ SignatureRequest,
102
+ TransactionProposalMeta,
103
+ TransactionProposal,
104
+ AuthRequiredMeta,
105
+ AuthRequired,
106
+ HandshakeAction,
107
+ # Type guards
108
+ is_handshake_action,
109
+ is_signature_request,
110
+ is_transaction_proposal,
111
+ is_auth_required,
112
+ # Helper functions
113
+ create_signature_request,
114
+ create_transaction_proposal,
115
+ create_auth_required,
116
+ wrap_handshake_response,
117
+ )
118
+
94
119
  __all__ = [
95
120
  # Version
96
121
  "__version__",
@@ -144,5 +169,25 @@ __all__ = [
144
169
  "ContextMiddleware",
145
170
  "VerifyRequestOptions",
146
171
  "CreateContextMiddlewareOptions",
172
+ # Handshake types
173
+ "HandshakeMeta",
174
+ "EIP712Domain",
175
+ "EIP712TypeField",
176
+ "SignatureRequest",
177
+ "TransactionProposalMeta",
178
+ "TransactionProposal",
179
+ "AuthRequiredMeta",
180
+ "AuthRequired",
181
+ "HandshakeAction",
182
+ # Handshake type guards
183
+ "is_handshake_action",
184
+ "is_signature_request",
185
+ "is_transaction_proposal",
186
+ "is_auth_required",
187
+ # Handshake helper functions
188
+ "create_signature_request",
189
+ "create_transaction_proposal",
190
+ "create_auth_required",
191
+ "wrap_handshake_response",
147
192
  ]
148
193
 
@@ -160,17 +160,32 @@ async def verify_context_request(
160
160
  CONTEXT_PLATFORM_PUBLIC_KEY_PEM.encode()
161
161
  )
162
162
 
163
+ # Build decode options - match TypeScript SDK behavior
164
+ decode_options: dict[str, Any] = {
165
+ "verify_signature": True,
166
+ "verify_exp": True,
167
+ "verify_iat": True,
168
+ "require": ["exp", "iat"],
169
+ }
170
+
171
+ # Only verify issuer if we expect it (TypeScript SDK does this)
172
+ # But don't require it in case the platform doesn't always include it
173
+ decode_options["verify_iss"] = True
174
+
175
+ # Only verify audience if explicitly provided
176
+ if audience:
177
+ decode_options["verify_aud"] = True
178
+ else:
179
+ decode_options["verify_aud"] = False
180
+
163
181
  # Verify the JWT
164
182
  payload = jwt.decode(
165
183
  token,
166
184
  public_key,
167
185
  algorithms=["RS256"],
168
186
  issuer="https://ctxprotocol.com",
169
- audience=audience,
170
- options={
171
- "require": ["iss", "sub", "exp", "iat"],
172
- "verify_aud": audience is not None,
173
- },
187
+ audience=audience if audience else None,
188
+ options=decode_options,
174
189
  )
175
190
 
176
191
  return payload
@@ -193,9 +208,21 @@ async def verify_context_request(
193
208
  code="unauthorized",
194
209
  status_code=401,
195
210
  )
196
- except jwt.PyJWTError:
211
+ except jwt.DecodeError as e:
212
+ raise ContextError(
213
+ message=f"JWT decode error: {e}",
214
+ code="unauthorized",
215
+ status_code=401,
216
+ )
217
+ except jwt.InvalidSignatureError:
218
+ raise ContextError(
219
+ message="Invalid JWT signature",
220
+ code="unauthorized",
221
+ status_code=401,
222
+ )
223
+ except jwt.PyJWTError as e:
197
224
  raise ContextError(
198
- message="Invalid Context Protocol signature",
225
+ message=f"JWT verification failed: {e}",
199
226
  code="unauthorized",
200
227
  status_code=401,
201
228
  )