m2m-sentinel-sdk 1.2.3 → 1.2.7
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.
- package/LICENSE +21 -0
- package/README.md +106 -112
- package/agent_adapter.js +11 -23
- package/base_account_paymaster_guard.js +921 -0
- package/eliza_plugin.js +1 -1
- package/index.d.ts +244 -1
- package/index.js +3 -1
- package/langchain_tool.js +93 -0
- package/mcp_server.js +176 -84
- package/package.json +19 -3
- package/smithery.yaml +2 -2
- package/typescript/base_account_paymaster_guard.ts +284 -0
- package/typescript/index.ts +2 -0
- package/typescript/package-lock.json +50 -0
- package/typescript/package.json +6 -2
- package/typescript/tsconfig.json +13 -0
- package/typescript/x402.ts +1 -1
- package/x402_signer.js +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 M2M Sentinel
|
|
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.
|
package/README.md
CHANGED
|
@@ -1,158 +1,152 @@
|
|
|
1
|
-
# M2M Sentinel
|
|
1
|
+
# M2M Sentinel SDK & MCP Server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Official multi-language client library, **Model Context Protocol (MCP) server**, and **Coinbase AgentKit ActionProvider** for M2M Sentinel — deterministic EVM bytecode capability observations and common-proxy resolution for autonomous applications operating on Base. Callers own transaction policy.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/m2m-sentinel-sdk)
|
|
6
|
+
[](https://pypi.org/project/m2m-sentinel/)
|
|
7
|
+
[](LICENSE)
|
|
8
|
+
[](https://smithery.ai/server/m2m-sentinel-sdk)
|
|
6
9
|
|
|
7
10
|
---
|
|
8
11
|
|
|
9
|
-
##
|
|
10
|
-
|
|
11
|
-
Autonomous agents handling value must never rely on a single oracle or heuristic. M2M Sentinel can supply static observations as Layer 1 of a caller-owned pipeline:
|
|
12
|
-
|
|
13
|
-
```text
|
|
14
|
-
[Agent Intent]
|
|
15
|
-
│
|
|
16
|
-
▼
|
|
17
|
-
[Transaction Builder]
|
|
18
|
-
│
|
|
19
|
-
▼
|
|
20
|
-
[Stage 1: M2M Sentinel Observation] ── (Bytecode hash, proxy target, selected opcode/selector evidence)
|
|
21
|
-
│
|
|
22
|
-
▼
|
|
23
|
-
[Stage 2: Local Policy Engine] ── (Caller-defined rules: Check spending bounds, reject DELEGATECALL, verify allowlist)
|
|
24
|
-
│
|
|
25
|
-
▼
|
|
26
|
-
[Stage 3: Execution Simulation] ── (eth_call / Tenderly / Trace state simulation)
|
|
27
|
-
│
|
|
28
|
-
▼
|
|
29
|
-
[Stage 4: Sub-Wallet Signing] ── (Scoped ephemeral wallet signs & broadcasts on Base)
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## Installation
|
|
12
|
+
## ⚡ 1. Model Context Protocol (MCP) Server
|
|
35
13
|
|
|
36
|
-
|
|
14
|
+
Connect M2M Sentinel directly to **Claude Desktop**, **Cursor**, **Windsurf**, or any MCP-compliant LLM agent.
|
|
37
15
|
|
|
16
|
+
### Option A: 1-Click via Smithery
|
|
38
17
|
```bash
|
|
39
|
-
|
|
40
|
-
|
|
18
|
+
npx -y @smithery/cli mcp add M2M-Sentinel/m2m-sentinel-sdk --client claude
|
|
19
|
+
```
|
|
41
20
|
|
|
42
|
-
|
|
43
|
-
|
|
21
|
+
### Option B: Local Stdio (`claude_desktop_config.json`)
|
|
22
|
+
```json
|
|
23
|
+
{
|
|
24
|
+
"mcpServers": {
|
|
25
|
+
"m2m-sentinel": {
|
|
26
|
+
"command": "npx",
|
|
27
|
+
"args": ["-y", "m2m-sentinel-sdk"],
|
|
28
|
+
"env": {
|
|
29
|
+
"M2M_SENTINEL_API_KEY": ""
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
44
34
|
```
|
|
45
35
|
|
|
46
|
-
###
|
|
36
|
+
### Option C: Remote Streamable HTTP
|
|
37
|
+
* **Current MCP endpoint**: `https://api.m2msentinel.com/mcp`
|
|
38
|
+
* **Legacy HTTP+SSE compatibility**: `https://api.m2msentinel.com/sse` with messages at `https://api.m2msentinel.com/messages`
|
|
47
39
|
|
|
48
|
-
|
|
49
|
-
pip install m2m-sentinel==1.2.3
|
|
50
|
-
```
|
|
40
|
+
---
|
|
51
41
|
|
|
52
|
-
|
|
42
|
+
## 🤖 2. Coinbase AgentKit Integration
|
|
53
43
|
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
44
|
+
```typescript
|
|
45
|
+
import { AgentKit } from "@coinbase/agentkit";
|
|
46
|
+
import { m2mSentinelActionProvider } from "m2m-sentinel-sdk";
|
|
47
|
+
|
|
48
|
+
const agentKit = await AgentKit.from({
|
|
49
|
+
walletProvider,
|
|
50
|
+
actionProviders: [
|
|
51
|
+
m2mSentinelActionProvider({
|
|
52
|
+
apiKey: process.env.M2M_SENTINEL_API_KEY
|
|
53
|
+
})
|
|
54
|
+
]
|
|
55
|
+
});
|
|
58
56
|
```
|
|
59
57
|
|
|
60
58
|
---
|
|
61
59
|
|
|
62
|
-
##
|
|
60
|
+
## 📦 3. JavaScript / TypeScript Client
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm install m2m-sentinel-sdk
|
|
64
|
+
```
|
|
63
65
|
|
|
64
66
|
```javascript
|
|
65
|
-
const { M2MSentinelClient
|
|
67
|
+
const { M2MSentinelClient } = require('m2m-sentinel-sdk');
|
|
66
68
|
|
|
67
|
-
|
|
68
|
-
const client = new M2MSentinelClient({
|
|
69
|
-
apiKey: process.env.M2M_SENTINEL_API_KEY,
|
|
70
|
-
baseUrl: 'https://api.m2msentinel.com'
|
|
71
|
-
});
|
|
69
|
+
const client = new M2MSentinelClient();
|
|
72
70
|
|
|
73
|
-
|
|
74
|
-
const audit = await client.auditContract('0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913');
|
|
75
|
-
console.log('
|
|
76
|
-
console.log('
|
|
77
|
-
console.log('
|
|
78
|
-
console.log('
|
|
79
|
-
|
|
80
|
-
// Transaction-specific observation before a caller-owned signing decision.
|
|
81
|
-
const preflight = await client.preflightTransaction({
|
|
82
|
-
chainId: 8453,
|
|
83
|
-
to: '0x1111111111111111111111111111111111111111',
|
|
84
|
-
data: '0x40c10f19'
|
|
85
|
-
});
|
|
86
|
-
console.log('Selector:', preflight.selectorHex);
|
|
87
|
-
console.log('Executing target:', preflight.resolvedExecutionTarget);
|
|
88
|
-
console.log('Observation block:', preflight.observationBlock.blockNumber);
|
|
89
|
-
// The caller must apply its own policy; M2M Sentinel does not return a safety verdict.
|
|
90
|
-
|
|
91
|
-
// 2. Autonomous Headless x402 Micropayments (EIP-3009 Local Signing)
|
|
92
|
-
const x402Client = new X402SignerClient({
|
|
93
|
-
walletSigner: myAgentWallet, // ethers / viem signer
|
|
94
|
-
baseUrl: 'https://api.m2msentinel.com',
|
|
95
|
-
maxPriceUsd: 0.01 // Optional: strict spending limit (default $0.05)
|
|
96
|
-
});
|
|
71
|
+
async function main() {
|
|
72
|
+
const audit = await client.auditContract('0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913');
|
|
73
|
+
console.log('Proxy Detected:', audit.audit.proxyResolution.isProxy);
|
|
74
|
+
console.log('Proxy Target:', audit.audit.proxyResolution.targetAddress);
|
|
75
|
+
console.log('Capabilities:', audit.audit.verdict.executableCapabilities);
|
|
76
|
+
console.log('Evidence:', audit.audit.dissection.capabilities);
|
|
77
|
+
}
|
|
97
78
|
|
|
98
|
-
|
|
99
|
-
console.log('Paid analysis result:', res.json);
|
|
79
|
+
main().catch(console.error);
|
|
100
80
|
```
|
|
101
81
|
|
|
102
82
|
---
|
|
103
83
|
|
|
104
|
-
## 🛡️
|
|
84
|
+
## 🛡️ Base Account `wallet_sendCalls` Guard
|
|
105
85
|
|
|
106
|
-
|
|
86
|
+
The public SDK includes `guardWalletSendCalls`, a customer-side execution-identity
|
|
87
|
+
boundary for Base Account / EIP-5792 batches. It preflights the anchor call and
|
|
88
|
+
evaluates its caller policy before scheduling any remaining call, then pins
|
|
89
|
+
remaining calls to the first trusted block identity in waves of at most four.
|
|
90
|
+
Each settled wave is validated and policy-checked in ascending request-index
|
|
91
|
+
order before a later wave starts; a failure or rejection stops later scheduling.
|
|
92
|
+
The original detached request is forwarded only after all checks pass. It does
|
|
93
|
+
not sign, broadcast, custody funds, infer inner UserOperation semantics, or
|
|
94
|
+
make a safety claim. See `examples/base_account_paymaster_guard.js` for a no-network fixture.
|
|
107
95
|
|
|
108
|
-
|
|
109
|
-
| :--- | :--- | :--- |
|
|
110
|
-
| **Chain ID** | `8453` (Base Mainnet) | Rejects signing on any unapproved EVM chain. |
|
|
111
|
-
| **Asset Contract** | `0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913` | Rejects signing for unapproved tokens (Base USDC only). |
|
|
112
|
-
| **Payout Recipient** | `0x6d6c398390cfb88f1cd42715b84906a0bd6652aa` | Rejects signing payments to unexpected recipient addresses. |
|
|
113
|
-
| **Price Ceiling** | `maxPriceUsd` (Default: `$0.05`) | Throws if remote challenge requests funds exceeding caller's authorized ceiling. |
|
|
96
|
+
---
|
|
114
97
|
|
|
115
|
-
|
|
116
|
-
import { X402SignerClient } from '@m2msentinel/sdk';
|
|
98
|
+
## 🐍 4. Python Client
|
|
117
99
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
100
|
+
```bash
|
|
101
|
+
pip install m2m-sentinel
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
from m2m_sentinel import M2MSentinelClient
|
|
106
|
+
|
|
107
|
+
client = M2MSentinelClient()
|
|
108
|
+
audit = client.audit_contract("0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913")
|
|
109
|
+
print("Proxy detected:", audit["audit"]["proxyResolution"]["isProxy"])
|
|
110
|
+
print("Proxy target:", audit["audit"]["proxyResolution"].get("targetAddress"))
|
|
111
|
+
print("Capabilities:", audit["audit"]["verdict"]["executableCapabilities"])
|
|
112
|
+
print("Evidence:", audit["audit"]["dissection"]["capabilities"])
|
|
123
113
|
```
|
|
124
114
|
|
|
125
115
|
---
|
|
126
116
|
|
|
127
|
-
##
|
|
117
|
+
## Transaction-specific preflight example
|
|
128
118
|
|
|
129
|
-
|
|
119
|
+
The public repository includes a standalone, mock-only transaction boundary
|
|
120
|
+
example at [`examples/transaction_preflight.js`](examples/transaction_preflight.js).
|
|
121
|
+
From this repository root, run:
|
|
130
122
|
|
|
131
|
-
|
|
123
|
+
```bash
|
|
124
|
+
node examples/transaction_preflight.js
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
It observes one caller-supplied Base transaction, passes the observation to a
|
|
128
|
+
caller-owned policy, and reaches only a mock signing/send callback. It refuses
|
|
129
|
+
to continue on unverified evidence, unresolved execution, an observation
|
|
130
|
+
mismatch, or a missing Diamond selector mapping. It never signs or sends a
|
|
131
|
+
transaction; optional live mode uses only a caller-supplied API-key header and
|
|
132
|
+
remains the caller's responsibility.
|
|
132
133
|
|
|
133
|
-
|
|
134
|
+
---
|
|
134
135
|
|
|
135
|
-
|
|
136
|
-
- `GET /v1/stats` (public privacy envelope; exact aggregate commercial counters are operator-only)
|
|
137
|
-
- `GET /v1/plans`
|
|
138
|
-
- `GET /v1/demo/audit/:address` for the published sample allowlist
|
|
139
|
-
- `GET /v1/audit/:address` (requires API key or x402 payment)
|
|
140
|
-
- `POST /v1/transaction/preflight` (requires an API key or verified RapidAPI proxy authentication; not x402-payable)
|
|
136
|
+
## 💳 5. Autonomous x402 Micropayments (Headless M2M)
|
|
141
137
|
|
|
142
|
-
|
|
138
|
+
```typescript
|
|
139
|
+
import { x402SignerClient } from "m2m-sentinel-sdk";
|
|
143
140
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
renewExistingKey: true,
|
|
148
|
-
apiKey: existingPaidKey
|
|
141
|
+
const client = new x402SignerClient({
|
|
142
|
+
walletSigner: myAgentWallet,
|
|
143
|
+
baseUrl: "https://api.m2msentinel.com"
|
|
149
144
|
});
|
|
150
|
-
|
|
151
|
-
await client.
|
|
145
|
+
|
|
146
|
+
const result = await client.request("/v1/audit/0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913");
|
|
152
147
|
```
|
|
153
148
|
|
|
154
149
|
---
|
|
155
150
|
|
|
156
|
-
##
|
|
157
|
-
|
|
158
|
-
Deterministic EVM bytecode and proxy capability intelligence on Base. Factual static capability observation — not a formal reachability audit, safety guarantee, or transaction advice. Live latency depends on RPC availability and deployment geography.
|
|
151
|
+
## 📜 License
|
|
152
|
+
MIT License. Copyright (c) 2026 M2M Sentinel.
|
package/agent_adapter.js
CHANGED
|
@@ -67,7 +67,7 @@ class M2MSentinelActionProvider {
|
|
|
67
67
|
|
|
68
68
|
const headers = {
|
|
69
69
|
Accept: 'application/json',
|
|
70
|
-
'User-Agent': 'M2MSentinel-AgentKit/1.2.
|
|
70
|
+
'User-Agent': 'M2MSentinel-AgentKit/1.2.7',
|
|
71
71
|
...options.headers
|
|
72
72
|
};
|
|
73
73
|
if (this.apiKey && !headers['x-api-key']) {
|
|
@@ -161,18 +161,16 @@ class M2MSentinelActionProvider {
|
|
|
161
161
|
return JSON.stringify(res.body);
|
|
162
162
|
}
|
|
163
163
|
|
|
164
|
-
async getDexLiquidity(
|
|
165
|
-
const
|
|
166
|
-
const res = await this._queryApi(`/v1/dex/metrics?pair=${encodeURIComponent(pair)}`);
|
|
164
|
+
async getDexLiquidity(_args = {}) {
|
|
165
|
+
const res = await this._queryApi('/v1/dex/metrics');
|
|
167
166
|
if (!res.ok) {
|
|
168
167
|
return JSON.stringify({ status: 'ERROR', statusCode: res.statusCode, message: 'Failed to retrieve DEX liquidity' });
|
|
169
168
|
}
|
|
170
169
|
return JSON.stringify(res.body);
|
|
171
170
|
}
|
|
172
171
|
|
|
173
|
-
async getWhaleSignals(
|
|
174
|
-
const
|
|
175
|
-
const res = await this._queryApi(`/v1/whales/signals?limit=${encodeURIComponent(limit)}`);
|
|
172
|
+
async getWhaleSignals(_args = {}) {
|
|
173
|
+
const res = await this._queryApi('/v1/whales/signals');
|
|
176
174
|
if (!res.ok) {
|
|
177
175
|
return JSON.stringify({ status: 'ERROR', statusCode: res.statusCode, message: 'Failed to retrieve whale signals' });
|
|
178
176
|
}
|
|
@@ -198,7 +196,7 @@ class M2MSentinelActionProvider {
|
|
|
198
196
|
},
|
|
199
197
|
{
|
|
200
198
|
name: 'm2m_get_gas_metrics',
|
|
201
|
-
description: '
|
|
199
|
+
description: 'Fetch current Base gas price in wei/gwei with RPC provenance. Read-only telemetry; does not authorize or submit transactions.',
|
|
202
200
|
schema: {
|
|
203
201
|
type: 'object',
|
|
204
202
|
properties: {}
|
|
@@ -207,7 +205,7 @@ class M2MSentinelActionProvider {
|
|
|
207
205
|
},
|
|
208
206
|
{
|
|
209
207
|
name: 'm2m_get_token_price',
|
|
210
|
-
description: '
|
|
208
|
+
description: 'Fetch the median Base DEX spot price in USD across up to five deepest indexed pools for one allowlisted token symbol. No historical price series.',
|
|
211
209
|
schema: {
|
|
212
210
|
type: 'object',
|
|
213
211
|
properties: {
|
|
@@ -222,29 +220,19 @@ class M2MSentinelActionProvider {
|
|
|
222
220
|
},
|
|
223
221
|
{
|
|
224
222
|
name: 'm2m_get_dex_liquidity',
|
|
225
|
-
description: '
|
|
223
|
+
description: 'Fetch aggregate reserve, depth, and volume metrics across tracked Base DEX liquidity pools; no individual pair filtering.',
|
|
226
224
|
schema: {
|
|
227
225
|
type: 'object',
|
|
228
|
-
properties: {
|
|
229
|
-
pair: {
|
|
230
|
-
type: 'string',
|
|
231
|
-
description: 'DEX pair identifier (e.g. WETH-USDC)'
|
|
232
|
-
}
|
|
233
|
-
}
|
|
226
|
+
properties: {}
|
|
234
227
|
},
|
|
235
228
|
invoke: (args) => this.getDexLiquidity(args)
|
|
236
229
|
},
|
|
237
230
|
{
|
|
238
231
|
name: 'm2m_get_whale_signals',
|
|
239
|
-
description: '
|
|
232
|
+
description: 'Fetch up to 50 tracked recent high-value ERC-20 transfer signals on Base; no query parameter limit filtering.',
|
|
240
233
|
schema: {
|
|
241
234
|
type: 'object',
|
|
242
|
-
properties: {
|
|
243
|
-
limit: {
|
|
244
|
-
type: 'number',
|
|
245
|
-
description: 'Maximum signals to retrieve (1-50)'
|
|
246
|
-
}
|
|
247
|
-
}
|
|
235
|
+
properties: {}
|
|
248
236
|
},
|
|
249
237
|
invoke: (args) => this.getWhaleSignals(args)
|
|
250
238
|
},
|