Skip to content

Commit 22566ea

Browse files
committed
feat: add x402_fetch tool
1 parent 747441e commit 22566ea

3 files changed

Lines changed: 62 additions & 0 deletions

File tree

package-lock.json

Lines changed: 22 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"@injectivelabs/networks": "^1.14.27",
2323
"@injectivelabs/sdk-ts": "^1.14.27",
2424
"@injectivelabs/utils": "^1.14.27",
25+
"@injectivelabs/x402": "^0.0.1",
2526
"@modelcontextprotocol/sdk": "^1.0.4",
2627
"decimal.js": "^10.4.3",
2728
"zod": "^3.22.0"

src/mcp/server.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import { debridge } from '../bridges/debridge.js'
2525
import { evm } from '../evm/index.js'
2626
import { eip712 } from '../evm/eip712.js'
2727
import { authz, TRADING_MSG_TYPES } from '../authz/index.js'
28+
import { createInjectiveClient } from '@injectivelabs/x402/client'
2829

2930
const injAddress = z.string().regex(/^inj1[a-z0-9]{38}$/, 'Must be a valid inj1... address (42 chars)')
3031
const numericString = z.string().regex(/^\d+(\.\d+)?$/, 'Must be a positive numeric string')
@@ -809,6 +810,44 @@ server.tool(
809810
},
810811
)
811812

813+
// ─── x402 Payment Tools ────────────────────────────────────────────────────────
814+
815+
server.tool(
816+
'x402_fetch',
817+
'Fetch data from an x402-gated API endpoint. Automatically handles 402 Payment Required ' +
818+
'responses by signing a USDC payment using the Injective EVM wallet, submitting it to the facilitator, ' +
819+
'and retrying the request. IMPORTANT: Real on-chain payment with real funds.',
820+
{
821+
address: injAddress.describe('The inj1... address of your trading wallet.'),
822+
password: z.string().describe('Keystore password to decrypt the private key for signing.'),
823+
url: z.string().url().describe('The URL of the x402-gated API endpoint.'),
824+
},
825+
async ({ address, password, url }) => {
826+
const privateKeyHex = wallets.unlock(address, password)
827+
const client = createInjectiveClient({ privateKey: privateKeyHex as `0x${string}` })
828+
const response = await client.fetch(url)
829+
830+
const text = await response.text()
831+
let data;
832+
try {
833+
data = JSON.parse(text)
834+
} catch {
835+
data = text
836+
}
837+
838+
return {
839+
content: [{
840+
type: 'text',
841+
text: JSON.stringify({
842+
status: response.status,
843+
url: response.url,
844+
data
845+
}, null, 2),
846+
}],
847+
}
848+
},
849+
)
850+
812851
// ─── Start ───────────────────────────────────────────────────────────────────
813852

814853
const transport = new StdioServerTransport()

0 commit comments

Comments
 (0)