@obolos_tech/mcp-server 0.1.0

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/README.md ADDED
@@ -0,0 +1,111 @@
1
+ # Obolos MCP Server
2
+
3
+ **Let AI agents discover and pay for APIs on the Obolos x402 marketplace.**
4
+
5
+ Every API on the Obolos marketplace becomes a tool your AI agent can call — with automatic USDC micropayments on Base.
6
+
7
+ ## Quick Setup
8
+
9
+ ### Claude Code
10
+
11
+ ```bash
12
+ claude mcp add obolos -- node /path/to/mcp-server/dist/index.js
13
+ ```
14
+
15
+ Or with a payment wallet:
16
+
17
+ ```bash
18
+ claude mcp add obolos -e OBOLOS_PRIVATE_KEY=0xyour_private_key -- node /path/to/mcp-server/dist/index.js
19
+ ```
20
+
21
+ ### Claude Desktop
22
+
23
+ Add to `~/.claude/claude_desktop_config.json`:
24
+
25
+ ```json
26
+ {
27
+ "mcpServers": {
28
+ "obolos": {
29
+ "command": "node",
30
+ "args": ["/path/to/mcp-server/dist/index.js"],
31
+ "env": {
32
+ "OBOLOS_PRIVATE_KEY": "0xyour_private_key"
33
+ }
34
+ }
35
+ }
36
+ }
37
+ ```
38
+
39
+ ### Cursor / Windsurf / Other MCP Clients
40
+
41
+ Add to your MCP config:
42
+
43
+ ```json
44
+ {
45
+ "obolos": {
46
+ "command": "node",
47
+ "args": ["/path/to/mcp-server/dist/index.js"],
48
+ "env": {
49
+ "OBOLOS_PRIVATE_KEY": "0xyour_private_key"
50
+ }
51
+ }
52
+ }
53
+ ```
54
+
55
+ ## Tools
56
+
57
+ | Tool | Description |
58
+ |------|-------------|
59
+ | `search_apis` | Search the marketplace by query, category, or sort order |
60
+ | `list_categories` | Browse available API categories |
61
+ | `get_api_details` | Get full details, input fields, and pricing for an API |
62
+ | `call_api` | Execute an API with automatic x402 USDC payment |
63
+ | `get_balance` | Check your wallet's USDC balance on Base |
64
+
65
+ ## Environment Variables
66
+
67
+ | Variable | Required | Description |
68
+ |----------|----------|-------------|
69
+ | `OBOLOS_PRIVATE_KEY` | For payments | Private key of a Base wallet with USDC |
70
+ | `OBOLOS_API_URL` | No | Marketplace URL (default: `https://obolos.tech`) |
71
+
72
+ ## Example Usage
73
+
74
+ Once configured, your AI agent can:
75
+
76
+ ```
77
+ "Search for token price APIs on Obolos"
78
+ → search_apis(query: "token price")
79
+
80
+ "How much does the DeFi portfolio API cost?"
81
+ → get_api_details(api_id: "ext-abc123")
82
+
83
+ "Get the current ETH price using Obolos"
84
+ → call_api(api_id: "ext-abc123", method: "GET", query_params: {"symbol": "ETH"})
85
+
86
+ "What's my Obolos wallet balance?"
87
+ → get_balance()
88
+ ```
89
+
90
+ ## How Payments Work
91
+
92
+ 1. Agent calls `call_api` with an API id and parameters
93
+ 2. MCP server sends request to Obolos proxy
94
+ 3. Proxy returns HTTP 402 with payment requirements
95
+ 4. Server signs an EIP-712 payment with your private key
96
+ 5. Retries request with payment header
97
+ 6. API response is returned to the agent
98
+
99
+ Payments are USDC micropayments on Base ($0.001–$0.10 per call). Only 1% platform fee — 99% goes directly to the API creator.
100
+
101
+ ## Build from Source
102
+
103
+ ```bash
104
+ cd mcp-server
105
+ npm install
106
+ npm run build
107
+ ```
108
+
109
+ ## License
110
+
111
+ MIT
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Obolos MCP Server
4
+ *
5
+ * Exposes the Obolos x402 API marketplace as MCP tools.
6
+ * Any AI agent (Claude Code, Cursor, Windsurf, etc.) can discover,
7
+ * browse, and pay for APIs through this server.
8
+ *
9
+ * Configuration (env vars):
10
+ * OBOLOS_API_URL — Marketplace URL (default: https://obolos.tech)
11
+ * OBOLOS_PRIVATE_KEY — Wallet private key for x402 payments (optional)
12
+ */
13
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,301 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Obolos MCP Server
4
+ *
5
+ * Exposes the Obolos x402 API marketplace as MCP tools.
6
+ * Any AI agent (Claude Code, Cursor, Windsurf, etc.) can discover,
7
+ * browse, and pay for APIs through this server.
8
+ *
9
+ * Configuration (env vars):
10
+ * OBOLOS_API_URL — Marketplace URL (default: https://obolos.tech)
11
+ * OBOLOS_PRIVATE_KEY — Wallet private key for x402 payments (optional)
12
+ */
13
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
14
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
15
+ import { z } from 'zod';
16
+ import { MarketplaceClient } from './marketplace.js';
17
+ import { PaymentSigner } from './payment.js';
18
+ const OBOLOS_API_URL = process.env.OBOLOS_API_URL || 'https://obolos.tech';
19
+ const OBOLOS_PRIVATE_KEY = process.env.OBOLOS_PRIVATE_KEY || '';
20
+ const marketplace = new MarketplaceClient(OBOLOS_API_URL);
21
+ const signer = OBOLOS_PRIVATE_KEY ? new PaymentSigner(OBOLOS_PRIVATE_KEY) : null;
22
+ const server = new McpServer({
23
+ name: 'obolos',
24
+ version: '0.1.0',
25
+ });
26
+ // ─── Tool: search_apis ──────────────────────────────────────────────────────
27
+ server.tool('search_apis', 'Search the Obolos x402 marketplace for pay-per-call APIs. ' +
28
+ 'Returns APIs that AI agents can call with automatic USDC micropayments. ' +
29
+ 'Use this to find data services, AI endpoints, blockchain tools, and more.', {
30
+ query: z.string().optional().describe('Search query (e.g. "weather", "token price", "web scraping")'),
31
+ category: z.string().optional().describe('Filter by category'),
32
+ sort: z.enum(['popular', 'newest', 'price_asc', 'price_desc']).optional()
33
+ .describe('Sort order. Default: popular'),
34
+ limit: z.number().min(1).max(50).optional().describe('Max results (default 20)'),
35
+ }, async ({ query, category, sort, limit }) => {
36
+ try {
37
+ const result = await marketplace.searchApis({
38
+ query,
39
+ category,
40
+ sort,
41
+ limit: limit || 20,
42
+ });
43
+ const summary = result.apis.map((api) => ({
44
+ id: api.id,
45
+ name: api.name,
46
+ description: api.description?.slice(0, 200),
47
+ category: api.category,
48
+ price: `$${api.price_per_call.toFixed(4)} USDC`,
49
+ method: api.http_method,
50
+ type: api.api_type,
51
+ rating: api.average_rating ? `${api.average_rating.toFixed(1)}/5` : 'unrated',
52
+ calls: api.total_calls,
53
+ }));
54
+ return {
55
+ content: [
56
+ {
57
+ type: 'text',
58
+ text: JSON.stringify({
59
+ total: result.pagination.total,
60
+ showing: summary.length,
61
+ apis: summary,
62
+ tip: 'Use get_api_details with an API id to see full details including input fields. Use call_api to execute.',
63
+ }, null, 2),
64
+ },
65
+ ],
66
+ };
67
+ }
68
+ catch (err) {
69
+ return {
70
+ content: [{ type: 'text', text: `Error searching APIs: ${err.message}` }],
71
+ isError: true,
72
+ };
73
+ }
74
+ });
75
+ // ─── Tool: list_categories ──────────────────────────────────────────────────
76
+ server.tool('list_categories', 'List all API categories available on the Obolos marketplace. ' +
77
+ 'Useful for browsing what types of APIs are available.', {}, async () => {
78
+ try {
79
+ const result = await marketplace.getCategories();
80
+ return {
81
+ content: [
82
+ {
83
+ type: 'text',
84
+ text: JSON.stringify({
85
+ categories: result.categories,
86
+ total_native_apis: result.nativeCount,
87
+ total_external_apis: result.externalCount,
88
+ }, null, 2),
89
+ },
90
+ ],
91
+ };
92
+ }
93
+ catch (err) {
94
+ return {
95
+ content: [{ type: 'text', text: `Error: ${err.message}` }],
96
+ isError: true,
97
+ };
98
+ }
99
+ });
100
+ // ─── Tool: get_api_details ──────────────────────────────────────────────────
101
+ server.tool('get_api_details', 'Get full details for a specific API including input fields, pricing, ' +
102
+ 'example request/response, and how to call it. Use an API id from search_apis.', {
103
+ api_id: z.string().describe('The API id (e.g. "ext-a1b2c3d4" for external, or a UUID for native)'),
104
+ }, async ({ api_id }) => {
105
+ try {
106
+ const api = await marketplace.getApiDetails(api_id);
107
+ const details = {
108
+ id: api.id,
109
+ name: api.name,
110
+ description: api.description,
111
+ category: api.category,
112
+ price: `$${api.price_per_call.toFixed(4)} USDC per call`,
113
+ method: api.http_method,
114
+ type: api.api_type,
115
+ rating: api.average_rating ? `${api.average_rating.toFixed(1)}/5 (${api.review_count} reviews)` : 'unrated',
116
+ total_calls: api.total_calls,
117
+ seller: api.seller_name,
118
+ };
119
+ if (api.input_schema) {
120
+ details.input_fields = api.input_schema;
121
+ }
122
+ if (api.example_request) {
123
+ try {
124
+ details.example_request = JSON.parse(api.example_request);
125
+ }
126
+ catch {
127
+ details.example_request = api.example_request;
128
+ }
129
+ }
130
+ if (api.example_response) {
131
+ try {
132
+ details.example_response = JSON.parse(api.example_response);
133
+ }
134
+ catch {
135
+ details.example_response = api.example_response;
136
+ }
137
+ }
138
+ details.how_to_call = {
139
+ tool: 'call_api',
140
+ params: {
141
+ api_id: api.id,
142
+ method: api.http_method,
143
+ body: api.input_schema?.fields
144
+ ? Object.fromEntries(Object.entries(api.input_schema.fields).map(([k, v]) => [
145
+ k,
146
+ v.example ?? `<${v.type}>`,
147
+ ]))
148
+ : undefined,
149
+ },
150
+ note: signer
151
+ ? `Payment will be signed automatically with wallet ${signer.address}`
152
+ : 'Set OBOLOS_PRIVATE_KEY env var to enable automatic payments',
153
+ };
154
+ return {
155
+ content: [{ type: 'text', text: JSON.stringify(details, null, 2) }],
156
+ };
157
+ }
158
+ catch (err) {
159
+ return {
160
+ content: [{ type: 'text', text: `Error: ${err.message}` }],
161
+ isError: true,
162
+ };
163
+ }
164
+ });
165
+ // ─── Tool: call_api ─────────────────────────────────────────────────────────
166
+ server.tool('call_api', 'Execute an API call on the Obolos marketplace with automatic x402 USDC payment. ' +
167
+ 'Requires OBOLOS_PRIVATE_KEY env var to be set. ' +
168
+ 'The payment is a micropayment (typically $0.001–$0.01 USDC per call).', {
169
+ api_id: z.string().describe('The API id to call'),
170
+ method: z.enum(['GET', 'POST', 'PUT', 'PATCH']).optional().describe('HTTP method (default: GET)'),
171
+ body: z.record(z.unknown()).optional().describe('Request body (for POST/PUT/PATCH)'),
172
+ query_params: z.record(z.string()).optional().describe('Query parameters (for GET)'),
173
+ }, async ({ api_id, method, body, query_params }) => {
174
+ if (!signer) {
175
+ return {
176
+ content: [
177
+ {
178
+ type: 'text',
179
+ text: 'Payment not configured. Set the OBOLOS_PRIVATE_KEY environment variable ' +
180
+ 'with a Base wallet private key that has USDC balance.\n\n' +
181
+ 'Example: OBOLOS_PRIVATE_KEY=0xabc123... in your MCP server config.',
182
+ },
183
+ ],
184
+ isError: true,
185
+ };
186
+ }
187
+ try {
188
+ const result = await marketplace.callApi(api_id, {
189
+ method,
190
+ body,
191
+ queryParams: query_params,
192
+ signPayment: async (paymentRequired) => {
193
+ return signer.signPayment(paymentRequired);
194
+ },
195
+ });
196
+ if (result.status >= 400) {
197
+ return {
198
+ content: [
199
+ {
200
+ type: 'text',
201
+ text: JSON.stringify({
202
+ error: true,
203
+ status: result.status,
204
+ body: result.body,
205
+ }, null, 2),
206
+ },
207
+ ],
208
+ isError: true,
209
+ };
210
+ }
211
+ return {
212
+ content: [
213
+ {
214
+ type: 'text',
215
+ text: JSON.stringify({
216
+ status: result.status,
217
+ data: result.body,
218
+ }, null, 2),
219
+ },
220
+ ],
221
+ };
222
+ }
223
+ catch (err) {
224
+ return {
225
+ content: [{ type: 'text', text: `API call failed: ${err.message}` }],
226
+ isError: true,
227
+ };
228
+ }
229
+ });
230
+ // ─── Tool: get_balance ──────────────────────────────────────────────────────
231
+ server.tool('get_balance', 'Check the USDC balance of the configured payment wallet on Base.', {}, async () => {
232
+ if (!signer) {
233
+ return {
234
+ content: [
235
+ {
236
+ type: 'text',
237
+ text: 'No wallet configured. Set OBOLOS_PRIVATE_KEY env var.',
238
+ },
239
+ ],
240
+ isError: true,
241
+ };
242
+ }
243
+ try {
244
+ const balance = await signer.getUsdcBalance();
245
+ return {
246
+ content: [
247
+ {
248
+ type: 'text',
249
+ text: JSON.stringify({
250
+ address: signer.address,
251
+ usdc_balance: `${balance.formatted} USDC`,
252
+ network: 'Base (Chain ID: 8453)',
253
+ }, null, 2),
254
+ },
255
+ ],
256
+ };
257
+ }
258
+ catch (err) {
259
+ return {
260
+ content: [{ type: 'text', text: `Balance check failed: ${err.message}` }],
261
+ isError: true,
262
+ };
263
+ }
264
+ });
265
+ // ─── Resources ──────────────────────────────────────────────────────────────
266
+ server.resource('marketplace-info', 'obolos://marketplace/info', async () => ({
267
+ contents: [
268
+ {
269
+ uri: 'obolos://marketplace/info',
270
+ mimeType: 'application/json',
271
+ text: JSON.stringify({
272
+ name: 'Obolos x402 Marketplace',
273
+ url: OBOLOS_API_URL,
274
+ description: 'Pay-per-call API marketplace powered by x402 micropayments. ' +
275
+ 'Browse and call hundreds of APIs with automatic USDC payments on Base. ' +
276
+ 'Only 1% platform fee — 99% goes directly to API creators.',
277
+ wallet: signer
278
+ ? { address: signer.address, configured: true }
279
+ : { configured: false, note: 'Set OBOLOS_PRIVATE_KEY to enable payments' },
280
+ documentation: 'https://obolos.tech/app/marketplace',
281
+ }, null, 2),
282
+ },
283
+ ],
284
+ }));
285
+ // ─── Start ──────────────────────────────────────────────────────────────────
286
+ async function main() {
287
+ const transport = new StdioServerTransport();
288
+ await server.connect(transport);
289
+ console.error(`[obolos-mcp] Connected to ${OBOLOS_API_URL}`);
290
+ if (signer) {
291
+ console.error(`[obolos-mcp] Wallet: ${signer.address}`);
292
+ }
293
+ else {
294
+ console.error('[obolos-mcp] No wallet configured (set OBOLOS_PRIVATE_KEY for payments)');
295
+ }
296
+ }
297
+ main().catch((err) => {
298
+ console.error('[obolos-mcp] Fatal:', err);
299
+ process.exit(1);
300
+ });
301
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Obolos Marketplace API Client
3
+ * Fetches API catalog from the Obolos marketplace backend
4
+ */
5
+ import type { MarketplaceApi, MarketplaceListResponse, MarketplaceSearchResponse, CategoryResponse } from './types.js';
6
+ export declare class MarketplaceClient {
7
+ private baseUrl;
8
+ constructor(baseUrl: string);
9
+ /**
10
+ * List all marketplace APIs with optional category filter
11
+ */
12
+ listApis(options?: {
13
+ category?: string;
14
+ page?: number;
15
+ limit?: number;
16
+ }): Promise<MarketplaceListResponse>;
17
+ /**
18
+ * Search APIs by query, category, and sort order
19
+ */
20
+ searchApis(options: {
21
+ query?: string;
22
+ category?: string;
23
+ sort?: 'popular' | 'newest' | 'price_asc' | 'price_desc';
24
+ page?: number;
25
+ limit?: number;
26
+ }): Promise<MarketplaceSearchResponse>;
27
+ /**
28
+ * Get full details for a single API
29
+ */
30
+ getApiDetails(id: string): Promise<MarketplaceApi>;
31
+ /**
32
+ * List all available categories
33
+ */
34
+ getCategories(): Promise<CategoryResponse>;
35
+ /**
36
+ * Call an API via the Obolos proxy.
37
+ * Handles the x402 payment flow: initial request → 402 → sign → retry.
38
+ */
39
+ callApi(apiId: string, options: {
40
+ method?: string;
41
+ body?: Record<string, unknown>;
42
+ queryParams?: Record<string, string>;
43
+ signPayment: (paymentRequired: any) => Promise<Record<string, string>>;
44
+ }): Promise<{
45
+ status: number;
46
+ headers: Record<string, string>;
47
+ body: unknown;
48
+ }>;
49
+ }
@@ -0,0 +1,138 @@
1
+ /**
2
+ * Obolos Marketplace API Client
3
+ * Fetches API catalog from the Obolos marketplace backend
4
+ */
5
+ export class MarketplaceClient {
6
+ baseUrl;
7
+ constructor(baseUrl) {
8
+ // Strip trailing slash
9
+ this.baseUrl = baseUrl.replace(/\/+$/, '');
10
+ }
11
+ /**
12
+ * List all marketplace APIs with optional category filter
13
+ */
14
+ async listApis(options) {
15
+ const params = new URLSearchParams();
16
+ if (options?.category)
17
+ params.set('category', options.category);
18
+ if (options?.page)
19
+ params.set('page', String(options.page));
20
+ if (options?.limit)
21
+ params.set('limit', String(options.limit));
22
+ params.set('type', 'native');
23
+ const url = `${this.baseUrl}/api/marketplace/apis?${params}`;
24
+ const res = await fetch(url);
25
+ if (!res.ok)
26
+ throw new Error(`Marketplace list failed: ${res.status} ${res.statusText}`);
27
+ return res.json();
28
+ }
29
+ /**
30
+ * Search APIs by query, category, and sort order
31
+ */
32
+ async searchApis(options) {
33
+ const params = new URLSearchParams();
34
+ if (options.query)
35
+ params.set('q', options.query);
36
+ if (options.category)
37
+ params.set('category', options.category);
38
+ if (options.sort)
39
+ params.set('sort', options.sort);
40
+ if (options.page)
41
+ params.set('page', String(options.page));
42
+ if (options.limit)
43
+ params.set('limit', String(options.limit));
44
+ params.set('type', 'native');
45
+ const url = `${this.baseUrl}/api/marketplace/apis/search?${params}`;
46
+ const res = await fetch(url);
47
+ if (!res.ok)
48
+ throw new Error(`Marketplace search failed: ${res.status} ${res.statusText}`);
49
+ return res.json();
50
+ }
51
+ /**
52
+ * Get full details for a single API
53
+ */
54
+ async getApiDetails(id) {
55
+ const url = `${this.baseUrl}/api/marketplace/apis/${encodeURIComponent(id)}`;
56
+ const res = await fetch(url);
57
+ if (!res.ok)
58
+ throw new Error(`API detail fetch failed: ${res.status} ${res.statusText}`);
59
+ return res.json();
60
+ }
61
+ /**
62
+ * List all available categories
63
+ */
64
+ async getCategories() {
65
+ const url = `${this.baseUrl}/api/marketplace/categories`;
66
+ const res = await fetch(url);
67
+ if (!res.ok)
68
+ throw new Error(`Categories fetch failed: ${res.status} ${res.statusText}`);
69
+ return res.json();
70
+ }
71
+ /**
72
+ * Call an API via the Obolos proxy.
73
+ * Handles the x402 payment flow: initial request → 402 → sign → retry.
74
+ */
75
+ async callApi(apiId, options) {
76
+ const method = (options.method || 'GET').toUpperCase();
77
+ const proxyUrl = new URL(`${this.baseUrl}/api/proxy/${encodeURIComponent(apiId)}`);
78
+ if (options.queryParams) {
79
+ for (const [k, v] of Object.entries(options.queryParams)) {
80
+ proxyUrl.searchParams.set(k, v);
81
+ }
82
+ }
83
+ const fetchOptions = { method };
84
+ if (method !== 'GET' && options.body) {
85
+ fetchOptions.headers = { 'Content-Type': 'application/json' };
86
+ fetchOptions.body = JSON.stringify(options.body);
87
+ }
88
+ // First request — expect 402
89
+ let response = await fetch(proxyUrl.toString(), fetchOptions);
90
+ if (response.status === 402) {
91
+ // Parse payment requirements from body (v1 format) or header (v2)
92
+ let paymentInfo;
93
+ try {
94
+ paymentInfo = await response.json();
95
+ }
96
+ catch {
97
+ throw new Error('Got 402 but could not parse payment requirements');
98
+ }
99
+ // Ask caller to sign the payment
100
+ const paymentHeaders = await options.signPayment(paymentInfo);
101
+ // Retry with payment
102
+ const paidFetchOptions = {
103
+ ...fetchOptions,
104
+ headers: {
105
+ ...(fetchOptions.headers || {}),
106
+ ...paymentHeaders,
107
+ },
108
+ };
109
+ response = await fetch(proxyUrl.toString(), paidFetchOptions);
110
+ }
111
+ // Collect response headers
112
+ const responseHeaders = {};
113
+ response.headers.forEach((v, k) => {
114
+ responseHeaders[k] = v;
115
+ });
116
+ // Parse response body
117
+ const contentType = response.headers.get('content-type') || '';
118
+ let body;
119
+ if (contentType.includes('application/json')) {
120
+ body = await response.json();
121
+ }
122
+ else if (contentType.includes('text/')) {
123
+ body = await response.text();
124
+ }
125
+ else {
126
+ // Binary — return base64
127
+ const buffer = await response.arrayBuffer();
128
+ body = {
129
+ _binary: true,
130
+ contentType,
131
+ base64: Buffer.from(buffer).toString('base64'),
132
+ size: buffer.byteLength,
133
+ };
134
+ }
135
+ return { status: response.status, headers: responseHeaders, body };
136
+ }
137
+ }
138
+ //# sourceMappingURL=marketplace.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"marketplace.js","sourceRoot":"","sources":["../src/marketplace.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * x402 Payment Signing for MCP Server
3
+ *
4
+ * Signs x402 payment requests using a private key (no browser wallet needed).
5
+ * Supports both v1 (exact) and v2 (x402x-router-settlement) payment schemes.
6
+ */
7
+ export declare class PaymentSigner {
8
+ private account;
9
+ private client;
10
+ constructor(privateKey: string);
11
+ get address(): string;
12
+ /**
13
+ * Get USDC balance for the signing wallet
14
+ */
15
+ getUsdcBalance(): Promise<{
16
+ raw: bigint;
17
+ formatted: string;
18
+ }>;
19
+ /**
20
+ * Sign an x402 payment request and return the payment headers.
21
+ *
22
+ * This handles the EIP-712 typed data signing that the x402 protocol requires.
23
+ * Works with both v1 (exact scheme) and v2 format 402 responses.
24
+ */
25
+ signPayment(paymentRequired: any): Promise<Record<string, string>>;
26
+ }
@@ -0,0 +1,137 @@
1
+ /**
2
+ * x402 Payment Signing for MCP Server
3
+ *
4
+ * Signs x402 payment requests using a private key (no browser wallet needed).
5
+ * Supports both v1 (exact) and v2 (x402x-router-settlement) payment schemes.
6
+ */
7
+ import { createWalletClient, http, publicActions, formatUnits, } from 'viem';
8
+ import { privateKeyToAccount } from 'viem/accounts';
9
+ import { base } from 'viem/chains';
10
+ const USDC_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
11
+ const USDC_ABI = [
12
+ {
13
+ inputs: [{ name: 'account', type: 'address' }],
14
+ name: 'balanceOf',
15
+ outputs: [{ name: '', type: 'uint256' }],
16
+ stateMutability: 'view',
17
+ type: 'function',
18
+ },
19
+ ];
20
+ export class PaymentSigner {
21
+ account;
22
+ client;
23
+ constructor(privateKey) {
24
+ if (!privateKey.startsWith('0x')) {
25
+ privateKey = `0x${privateKey}`;
26
+ }
27
+ this.account = privateKeyToAccount(privateKey);
28
+ this.client = createWalletClient({
29
+ account: this.account,
30
+ chain: base,
31
+ transport: http(),
32
+ }).extend(publicActions);
33
+ }
34
+ get address() {
35
+ return this.account.address;
36
+ }
37
+ /**
38
+ * Get USDC balance for the signing wallet
39
+ */
40
+ async getUsdcBalance() {
41
+ const balance = await this.client.readContract({
42
+ address: USDC_ADDRESS,
43
+ abi: USDC_ABI,
44
+ functionName: 'balanceOf',
45
+ args: [this.account.address],
46
+ });
47
+ return {
48
+ raw: balance,
49
+ formatted: formatUnits(balance, 6),
50
+ };
51
+ }
52
+ /**
53
+ * Sign an x402 payment request and return the payment headers.
54
+ *
55
+ * This handles the EIP-712 typed data signing that the x402 protocol requires.
56
+ * Works with both v1 (exact scheme) and v2 format 402 responses.
57
+ */
58
+ async signPayment(paymentRequired) {
59
+ // Extract payment details from the 402 response
60
+ const accepts = paymentRequired.accepts;
61
+ if (!accepts || accepts.length === 0) {
62
+ throw new Error('No payment options in 402 response');
63
+ }
64
+ const requirement = accepts[0];
65
+ const scheme = requirement.scheme || 'exact';
66
+ const network = requirement.network || 'base';
67
+ const amount = requirement.maxAmountRequired || requirement.amount;
68
+ const payTo = requirement.payTo;
69
+ const asset = requirement.asset || USDC_ADDRESS;
70
+ if (!amount || !payTo) {
71
+ throw new Error('Missing amount or payTo in payment requirement');
72
+ }
73
+ // Build EIP-712 typed data for the exact scheme
74
+ const deadline = BigInt(Math.floor(Date.now() / 1000) + 300); // 5 min
75
+ const amountBigInt = BigInt(amount);
76
+ const domain = {
77
+ name: 'x402',
78
+ version: '1',
79
+ chainId: 8453n,
80
+ verifyingContract: asset,
81
+ };
82
+ const types = {
83
+ TransferWithAuthorization: [
84
+ { name: 'from', type: 'address' },
85
+ { name: 'to', type: 'address' },
86
+ { name: 'value', type: 'uint256' },
87
+ { name: 'validAfter', type: 'uint256' },
88
+ { name: 'validBefore', type: 'uint256' },
89
+ { name: 'nonce', type: 'bytes32' },
90
+ ],
91
+ };
92
+ // Generate a random nonce
93
+ const nonceBytes = new Uint8Array(32);
94
+ crypto.getRandomValues(nonceBytes);
95
+ const nonce = `0x${Array.from(nonceBytes).map(b => b.toString(16).padStart(2, '0')).join('')}`;
96
+ const message = {
97
+ from: this.account.address,
98
+ to: payTo,
99
+ value: amountBigInt,
100
+ validAfter: 0n,
101
+ validBefore: deadline,
102
+ nonce,
103
+ };
104
+ const signature = await this.client.signTypedData({
105
+ account: this.account,
106
+ domain,
107
+ types,
108
+ primaryType: 'TransferWithAuthorization',
109
+ message,
110
+ });
111
+ // Build the payment payload
112
+ const paymentPayload = {
113
+ x402Version: paymentRequired.x402Version || 1,
114
+ scheme,
115
+ network,
116
+ payload: {
117
+ signature,
118
+ authorization: {
119
+ from: this.account.address,
120
+ to: payTo,
121
+ value: amount.toString(),
122
+ validAfter: '0',
123
+ validBefore: deadline.toString(),
124
+ nonce,
125
+ },
126
+ },
127
+ };
128
+ // Encode as base64 for the payment header
129
+ const encoded = Buffer.from(JSON.stringify(paymentPayload)).toString('base64');
130
+ // Return appropriate headers based on version
131
+ if (paymentRequired.x402Version === 2) {
132
+ return { 'payment-signature': encoded };
133
+ }
134
+ return { 'x-payment': encoded };
135
+ }
136
+ }
137
+ //# sourceMappingURL=payment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payment.js","sourceRoot":"","sources":["../src/payment.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,kBAAkB,EAClB,IAAI,EACJ,aAAa,EACb,WAAW,GAGZ,MAAM,MAAM,CAAC;AACd,OAAO,EAAE,mBAAmB,EAA0B,MAAM,eAAe,CAAC;AAC5E,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEnC,MAAM,YAAY,GAAG,4CAAqD,CAAC;AAC3E,MAAM,QAAQ,GAAG;IACf;QACE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAC9C,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QACxC,eAAe,EAAE,MAAM;QACvB,IAAI,EAAE,UAAU;KACjB;CACO,CAAC;AAEX,MAAM,OAAO,aAAa;IAChB,OAAO,CAAoB;IAC3B,MAAM,CAA8B;IAE5C,YAAY,UAAkB;QAC5B,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACjC,UAAU,GAAG,KAAK,UAAU,EAAE,CAAC;QACjC,CAAC;QACD,IAAI,CAAC,OAAO,GAAG,mBAAmB,CAAC,UAA2B,CAAC,CAAC;QAChE,IAAI,CAAC,MAAM,GAAG,kBAAkB,CAAC;YAC/B,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,KAAK,EAAE,IAAI;YACX,SAAS,EAAE,IAAI,EAAE;SAClB,CAAC,CAAC,MAAM,CAAC,aAAa,CAAQ,CAAC;IAClC,CAAC;IAED,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc;QAClB,MAAM,OAAO,GAAG,MAAO,IAAI,CAAC,MAAc,CAAC,YAAY,CAAC;YACtD,OAAO,EAAE,YAAY;YACrB,GAAG,EAAE,QAAQ;YACb,YAAY,EAAE,WAAW;YACzB,IAAI,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;SAC7B,CAAC,CAAC;QACH,OAAO;YACL,GAAG,EAAE,OAAiB;YACtB,SAAS,EAAE,WAAW,CAAC,OAAiB,EAAE,CAAC,CAAC;SAC7C,CAAC;IACJ,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,WAAW,CAAC,eAAoB;QACpC,gDAAgD;QAChD,MAAM,OAAO,GAAG,eAAe,CAAC,OAAO,CAAC;QACxC,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,CAAC;QAED,MAAM,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QAC/B,MAAM,MAAM,GAAG,WAAW,CAAC,MAAM,IAAI,OAAO,CAAC;QAC7C,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,IAAI,MAAM,CAAC;QAC9C,MAAM,MAAM,GAAG,WAAW,CAAC,iBAAiB,IAAI,WAAW,CAAC,MAAM,CAAC;QACnE,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC;QAChC,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,IAAI,YAAY,CAAC;QAEhD,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,EAAE,CAAC;YACtB,MAAM,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC;QACpE,CAAC;QAED,gDAAgD;QAChD,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,QAAQ;QACtE,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;QAEpC,MAAM,MAAM,GAAG;YACb,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,GAAG;YACZ,OAAO,EAAE,KAAK;YACd,iBAAiB,EAAE,KAAsB;SAC1C,CAAC;QAEF,MAAM,KAAK,GAAG;YACZ,yBAAyB,EAAE;gBACzB,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE;gBACjC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE;gBAC/B,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE;gBAClC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,SAAS,EAAE;gBACvC,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE,SAAS,EAAE;gBACxC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE;aACnC;SACF,CAAC;QAEF,0BAA0B;QAC1B,MAAM,UAAU,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;QACtC,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC;QACnC,MAAM,KAAK,GAAG,KAAK,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAmB,CAAC;QAEhH,MAAM,OAAO,GAAG;YACd,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;YAC1B,EAAE,EAAE,KAAsB;YAC1B,KAAK,EAAE,YAAY;YACnB,UAAU,EAAE,EAAE;YACd,WAAW,EAAE,QAAQ;YACrB,KAAK;SACN,CAAC;QAEF,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;YAChD,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,MAAM;YACN,KAAK;YACL,WAAW,EAAE,2BAA2B;YACxC,OAAO;SACR,CAAC,CAAC;QAEH,4BAA4B;QAC5B,MAAM,cAAc,GAAG;YACrB,WAAW,EAAE,eAAe,CAAC,WAAW,IAAI,CAAC;YAC7C,MAAM;YACN,OAAO;YACP,OAAO,EAAE;gBACP,SAAS;gBACT,aAAa,EAAE;oBACb,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,OAAO;oBAC1B,EAAE,EAAE,KAAK;oBACT,KAAK,EAAE,MAAM,CAAC,QAAQ,EAAE;oBACxB,UAAU,EAAE,GAAG;oBACf,WAAW,EAAE,QAAQ,CAAC,QAAQ,EAAE;oBAChC,KAAK;iBACN;aACF;SACF,CAAC;QAEF,0CAA0C;QAC1C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAE/E,8CAA8C;QAC9C,IAAI,eAAe,CAAC,WAAW,KAAK,CAAC,EAAE,CAAC;YACtC,OAAO,EAAE,mBAAmB,EAAE,OAAO,EAAE,CAAC;QAC1C,CAAC;QACD,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC;IAClC,CAAC;CACF"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Type definitions for the Obolos MCP Server
3
+ */
4
+ export interface MarketplaceApi {
5
+ id: string;
6
+ name: string;
7
+ slug: string | null;
8
+ description: string;
9
+ category: string;
10
+ price_per_call: number;
11
+ http_method: string;
12
+ seller_name: string;
13
+ total_calls: number;
14
+ example_request: string | null;
15
+ example_response: string | null;
16
+ api_type: 'native' | 'external';
17
+ average_rating: number | null;
18
+ review_count: number;
19
+ input_schema?: InputSchema | null;
20
+ input_type?: string;
21
+ response_type?: string;
22
+ proxy_endpoint?: string;
23
+ resource_url?: string;
24
+ }
25
+ export interface InputSchema {
26
+ method: string;
27
+ bodyType: string;
28
+ fields: Record<string, FieldSchema>;
29
+ exampleResponse?: unknown;
30
+ }
31
+ export interface FieldSchema {
32
+ type: string;
33
+ required?: boolean;
34
+ example?: unknown;
35
+ description?: string;
36
+ enum?: string[];
37
+ }
38
+ export interface MarketplaceListResponse {
39
+ apis: MarketplaceApi[];
40
+ pagination: {
41
+ page: number;
42
+ limit: number;
43
+ total: number;
44
+ total_pages: number;
45
+ has_next: boolean;
46
+ has_prev: boolean;
47
+ };
48
+ timestamp: string;
49
+ }
50
+ export interface MarketplaceSearchResponse extends MarketplaceListResponse {
51
+ query: string | null;
52
+ category: string | null;
53
+ sort: string;
54
+ }
55
+ export interface CategoryResponse {
56
+ categories: Array<{
57
+ name: string;
58
+ count: number;
59
+ }>;
60
+ nativeCount: number;
61
+ externalCount: number;
62
+ count: number;
63
+ }
64
+ export interface PaymentRequiredResponse {
65
+ x402Version: number;
66
+ accepts: Array<{
67
+ scheme: string;
68
+ network: string;
69
+ maxAmountRequired?: string;
70
+ amount?: string;
71
+ resource?: string;
72
+ payTo: string;
73
+ asset: string;
74
+ }>;
75
+ error?: string;
76
+ }
package/dist/types.js ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Type definitions for the Obolos MCP Server
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@obolos_tech/mcp-server",
3
+ "version": "0.1.0",
4
+ "description": "MCP server for Obolos x402 API marketplace — lets AI agents discover and pay for APIs",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "files": ["dist", "README.md"],
8
+ "bin": {
9
+ "obolos-mcp": "dist/index.js"
10
+ },
11
+ "scripts": {
12
+ "build": "tsc",
13
+ "dev": "tsx src/index.ts",
14
+ "start": "node dist/index.js"
15
+ },
16
+ "keywords": [
17
+ "mcp",
18
+ "x402",
19
+ "obolos",
20
+ "ai-agents",
21
+ "micropayments",
22
+ "marketplace"
23
+ ],
24
+ "license": "MIT",
25
+ "dependencies": {
26
+ "@modelcontextprotocol/sdk": "^1.12.1",
27
+ "viem": "^2.45.2",
28
+ "zod": "^3.25.76"
29
+ },
30
+ "devDependencies": {
31
+ "@types/node": "^22.0.0",
32
+ "tsx": "^4.21.0",
33
+ "typescript": "^5.9.3"
34
+ }
35
+ }