nullpath-mcp 1.1.0 → 1.2.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/dist/__tests__/tools.test.d.ts +2 -0
- package/dist/__tests__/tools.test.d.ts.map +1 -0
- package/dist/__tests__/tools.test.js +157 -0
- package/dist/__tests__/tools.test.js.map +1 -0
- package/dist/index.d.ts +2 -87
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +219 -215
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/__tests__/tools.test.ts +197 -0
- package/src/index.ts +246 -321
- package/src/__tests__/x402.test.ts +0 -229
package/src/index.ts
CHANGED
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* nullpath MCP Client
|
|
5
|
-
*
|
|
6
|
-
* Connects to nullpath.com
|
|
7
|
-
*
|
|
5
|
+
*
|
|
6
|
+
* Connects to nullpath.com API - AI agent marketplace with x402 micropayments.
|
|
7
|
+
*
|
|
8
8
|
* Available tools:
|
|
9
9
|
* - discover_agents: Search agents by capability
|
|
10
10
|
* - lookup_agent: Get agent details by ID
|
|
@@ -14,249 +14,223 @@
|
|
|
14
14
|
* - check_reputation: Get agent trust score
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
18
|
-
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
|
|
19
|
-
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
20
17
|
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
18
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
21
19
|
import {
|
|
22
|
-
ListToolsRequestSchema,
|
|
23
20
|
CallToolRequestSchema,
|
|
21
|
+
ListToolsRequestSchema,
|
|
24
22
|
} from '@modelcontextprotocol/sdk/types.js';
|
|
25
|
-
import { privateKeyToAccount } from 'viem/accounts';
|
|
26
|
-
import type { Address, Hex } from 'viem';
|
|
27
|
-
|
|
28
|
-
const NULLPATH_MCP_URL = process.env.NULLPATH_MCP_URL || 'https://nullpath.com/mcp';
|
|
29
|
-
|
|
30
|
-
/**
|
|
31
|
-
* Payment requirements from x402 402 response
|
|
32
|
-
*/
|
|
33
|
-
export interface PaymentRequirements {
|
|
34
|
-
scheme: 'exact';
|
|
35
|
-
network: 'base' | 'base-sepolia';
|
|
36
|
-
maxAmountRequired: string;
|
|
37
|
-
resource: string;
|
|
38
|
-
description: string;
|
|
39
|
-
mimeType: string;
|
|
40
|
-
payTo: Address;
|
|
41
|
-
maxTimeoutSeconds: number;
|
|
42
|
-
asset: Address;
|
|
43
|
-
extra: Record<string, unknown>;
|
|
44
|
-
}
|
|
45
23
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
24
|
+
const NULLPATH_API_URL = process.env.NULLPATH_API_URL || 'https://nullpath.com/api/v1';
|
|
25
|
+
|
|
26
|
+
// Tool definitions
|
|
27
|
+
const TOOLS = [
|
|
28
|
+
{
|
|
29
|
+
name: 'discover_agents',
|
|
30
|
+
description: 'Search for agents by capability, category, or query. Returns a list of matching agents with their pricing and reputation.',
|
|
31
|
+
inputSchema: {
|
|
32
|
+
type: 'object' as const,
|
|
33
|
+
properties: {
|
|
34
|
+
query: { type: 'string', description: 'Search query (e.g., "summarize", "translate", "code review")' },
|
|
35
|
+
category: { type: 'string', description: 'Filter by category (e.g., "text", "code", "data")' },
|
|
36
|
+
limit: { type: 'number', description: 'Maximum results to return (default: 10)' },
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: 'lookup_agent',
|
|
42
|
+
description: 'Get detailed information about a specific agent by ID, including capabilities, pricing, and reputation.',
|
|
43
|
+
inputSchema: {
|
|
44
|
+
type: 'object' as const,
|
|
45
|
+
properties: {
|
|
46
|
+
agentId: { type: 'string', description: 'The agent UUID' },
|
|
47
|
+
},
|
|
48
|
+
required: ['agentId'],
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
name: 'get_capabilities',
|
|
53
|
+
description: 'List all capability categories available in the marketplace.',
|
|
54
|
+
inputSchema: {
|
|
55
|
+
type: 'object' as const,
|
|
56
|
+
properties: {},
|
|
57
|
+
},
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
name: 'check_reputation',
|
|
61
|
+
description: 'Get the reputation score and trust tier for an agent.',
|
|
62
|
+
inputSchema: {
|
|
63
|
+
type: 'object' as const,
|
|
64
|
+
properties: {
|
|
65
|
+
agentId: { type: 'string', description: 'The agent UUID' },
|
|
66
|
+
},
|
|
67
|
+
required: ['agentId'],
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
name: 'execute_agent',
|
|
72
|
+
description: 'Execute an agent capability. Requires payment via x402 (USDC on Base). Set NULLPATH_WALLET_KEY env var for payments.',
|
|
73
|
+
inputSchema: {
|
|
74
|
+
type: 'object' as const,
|
|
75
|
+
properties: {
|
|
76
|
+
agentId: { type: 'string', description: 'The agent UUID' },
|
|
77
|
+
capabilityId: { type: 'string', description: 'The capability to execute' },
|
|
78
|
+
input: { type: 'object', description: 'Input parameters for the capability' },
|
|
79
|
+
},
|
|
80
|
+
required: ['agentId', 'capabilityId', 'input'],
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
name: 'register_agent',
|
|
85
|
+
description: 'Register a new agent on the marketplace. Requires $0.10 USDC payment. Set NULLPATH_WALLET_KEY env var.',
|
|
86
|
+
inputSchema: {
|
|
87
|
+
type: 'object' as const,
|
|
88
|
+
properties: {
|
|
89
|
+
name: { type: 'string', description: 'Agent name' },
|
|
90
|
+
description: { type: 'string', description: 'Agent description' },
|
|
91
|
+
wallet: { type: 'string', description: 'Wallet address for receiving payments' },
|
|
92
|
+
capabilities: {
|
|
93
|
+
type: 'array',
|
|
94
|
+
description: 'List of capabilities with pricing',
|
|
95
|
+
items: {
|
|
96
|
+
type: 'object',
|
|
97
|
+
properties: {
|
|
98
|
+
id: { type: 'string' },
|
|
99
|
+
name: { type: 'string' },
|
|
100
|
+
description: { type: 'string' },
|
|
101
|
+
price: { type: 'string', description: 'Price in USDC (e.g., "0.01")' },
|
|
102
|
+
},
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
endpoint: { type: 'string', description: 'Execution endpoint URL' },
|
|
106
|
+
},
|
|
107
|
+
required: ['name', 'description', 'wallet', 'capabilities', 'endpoint'],
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
];
|
|
111
|
+
|
|
112
|
+
// API helper
|
|
113
|
+
async function apiCall(endpoint: string, options: RequestInit = {}): Promise<unknown> {
|
|
114
|
+
const url = `${NULLPATH_API_URL}${endpoint}`;
|
|
115
|
+
const response = await fetch(url, {
|
|
116
|
+
...options,
|
|
117
|
+
headers: {
|
|
118
|
+
'Content-Type': 'application/json',
|
|
119
|
+
...options.headers,
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
if (!response.ok) {
|
|
124
|
+
const error = await response.text();
|
|
125
|
+
throw new Error(`API error (${response.status}): ${error}`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return response.json();
|
|
103
129
|
}
|
|
104
130
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
131
|
+
// Tool handlers
|
|
132
|
+
async function handleDiscoverAgents(args: { query?: string; category?: string; limit?: number }) {
|
|
133
|
+
const params = new URLSearchParams();
|
|
134
|
+
if (args.query) params.set('q', args.query);
|
|
135
|
+
if (args.category) params.set('category', args.category);
|
|
136
|
+
if (args.limit) params.set('limit', args.limit.toString());
|
|
137
|
+
|
|
138
|
+
const queryString = params.toString();
|
|
139
|
+
const endpoint = `/discover${queryString ? `?${queryString}` : ''}`;
|
|
140
|
+
|
|
141
|
+
return apiCall(endpoint);
|
|
112
142
|
}
|
|
113
143
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
*/
|
|
117
|
-
export interface Wallet {
|
|
118
|
-
address: Address;
|
|
119
|
-
privateKey: Hex;
|
|
144
|
+
async function handleLookupAgent(args: { agentId: string }) {
|
|
145
|
+
return apiCall(`/agents/${args.agentId}`);
|
|
120
146
|
}
|
|
121
147
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
requirements: PaymentRequirements
|
|
128
|
-
): Promise<PaymentPayload> {
|
|
129
|
-
const network = requirements.network;
|
|
130
|
-
const contractMeta = USDC_CONTRACTS[network];
|
|
148
|
+
async function handleGetCapabilities() {
|
|
149
|
+
// Return the capability categories from discover endpoint
|
|
150
|
+
const result = await apiCall('/discover') as { data?: { agents?: Array<{ capabilities?: unknown[] }> } };
|
|
151
|
+
const agents = result?.data?.agents || [];
|
|
152
|
+
const categories = new Set<string>();
|
|
131
153
|
|
|
132
|
-
|
|
133
|
-
|
|
154
|
+
for (const agent of agents) {
|
|
155
|
+
if (agent.capabilities) {
|
|
156
|
+
for (const cap of agent.capabilities as Array<{ id?: string }>) {
|
|
157
|
+
if (cap.id) categories.add(cap.id.split('-')[0]);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
134
160
|
}
|
|
161
|
+
|
|
162
|
+
return { categories: Array.from(categories) };
|
|
163
|
+
}
|
|
135
164
|
|
|
136
|
-
|
|
137
|
-
const
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
to: requirements.payTo,
|
|
144
|
-
value: BigInt(requirements.maxAmountRequired),
|
|
145
|
-
validAfter: BigInt(validAfter),
|
|
146
|
-
validBefore: BigInt(validBefore),
|
|
147
|
-
nonce,
|
|
165
|
+
async function handleCheckReputation(args: { agentId: string }) {
|
|
166
|
+
const result = await apiCall(`/agents/${args.agentId}`) as {
|
|
167
|
+
data?: {
|
|
168
|
+
reputation_score?: number;
|
|
169
|
+
trustTier?: string;
|
|
170
|
+
avgLatencyMs?: number;
|
|
171
|
+
}
|
|
148
172
|
};
|
|
149
|
-
|
|
150
|
-
// Create account for signing
|
|
151
|
-
const account = privateKeyToAccount(wallet.privateKey);
|
|
152
173
|
|
|
153
|
-
const signature = await account.signTypedData({
|
|
154
|
-
domain: {
|
|
155
|
-
name: contractMeta.name,
|
|
156
|
-
version: contractMeta.version,
|
|
157
|
-
chainId: contractMeta.chainId,
|
|
158
|
-
verifyingContract: requirements.asset,
|
|
159
|
-
},
|
|
160
|
-
types: TRANSFER_WITH_AUTHORIZATION_TYPES,
|
|
161
|
-
primaryType: 'TransferWithAuthorization',
|
|
162
|
-
message: authorization,
|
|
163
|
-
});
|
|
164
|
-
|
|
165
174
|
return {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
signature,
|
|
171
|
-
authorization: {
|
|
172
|
-
from: wallet.address,
|
|
173
|
-
to: requirements.payTo,
|
|
174
|
-
value: authorization.value.toString(),
|
|
175
|
-
validAfter: authorization.validAfter.toString(),
|
|
176
|
-
validBefore: authorization.validBefore.toString(),
|
|
177
|
-
nonce,
|
|
178
|
-
},
|
|
179
|
-
},
|
|
175
|
+
agentId: args.agentId,
|
|
176
|
+
reputationScore: result?.data?.reputation_score,
|
|
177
|
+
trustTier: result?.data?.trustTier,
|
|
178
|
+
avgLatencyMs: result?.data?.avgLatencyMs,
|
|
180
179
|
};
|
|
181
180
|
}
|
|
182
181
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
return Buffer.from(JSON.stringify(payment)).toString('base64');
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Check if an error response is an x402 payment required error
|
|
192
|
-
*/
|
|
193
|
-
export function isX402Error(error: unknown): error is { code: number; message: string; data: X402ErrorData } {
|
|
194
|
-
if (typeof error !== 'object' || error === null) return false;
|
|
195
|
-
const err = error as Record<string, unknown>;
|
|
196
|
-
if (err.code !== -32000) return false;
|
|
197
|
-
if (typeof err.data !== 'object' || err.data === null) return false;
|
|
198
|
-
const data = err.data as Record<string, unknown>;
|
|
199
|
-
return typeof data.x402Version === 'number' && Array.isArray(data.accepts);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
/**
|
|
203
|
-
* Get wallet from environment variable
|
|
204
|
-
*/
|
|
205
|
-
export function getWallet(): Wallet {
|
|
206
|
-
const privateKey = process.env.NULLPATH_WALLET_KEY;
|
|
182
|
+
async function handleExecuteAgent(args: { agentId: string; capabilityId: string; input: unknown }) {
|
|
183
|
+
// Note: This would need x402 payment handling for production
|
|
184
|
+
// For now, return info about what would happen
|
|
185
|
+
const walletKey = process.env.NULLPATH_WALLET_KEY;
|
|
207
186
|
|
|
208
|
-
if (!
|
|
209
|
-
|
|
210
|
-
'NULLPATH_WALLET_KEY environment variable
|
|
211
|
-
'Set
|
|
212
|
-
|
|
187
|
+
if (!walletKey) {
|
|
188
|
+
return {
|
|
189
|
+
error: 'NULLPATH_WALLET_KEY environment variable not set. Payment required for execution.',
|
|
190
|
+
info: 'Set your wallet private key to enable paid agent execution.',
|
|
191
|
+
};
|
|
213
192
|
}
|
|
214
|
-
|
|
215
|
-
// Ensure the key is properly formatted
|
|
216
|
-
const formattedKey = privateKey.startsWith('0x')
|
|
217
|
-
? privateKey as Hex
|
|
218
|
-
: `0x${privateKey}` as Hex;
|
|
219
|
-
|
|
220
|
-
const account = privateKeyToAccount(formattedKey);
|
|
221
193
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
194
|
+
// TODO: Implement full x402 payment flow
|
|
195
|
+
return apiCall('/execute', {
|
|
196
|
+
method: 'POST',
|
|
197
|
+
body: JSON.stringify({
|
|
198
|
+
targetAgentId: args.agentId,
|
|
199
|
+
capabilityId: args.capabilityId,
|
|
200
|
+
input: args.input,
|
|
201
|
+
}),
|
|
202
|
+
});
|
|
226
203
|
}
|
|
227
204
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
errorData: X402ErrorData
|
|
237
|
-
): Promise<string> {
|
|
238
|
-
const wallet = getWallet();
|
|
205
|
+
async function handleRegisterAgent(args: {
|
|
206
|
+
name: string;
|
|
207
|
+
description: string;
|
|
208
|
+
wallet: string;
|
|
209
|
+
capabilities: unknown[];
|
|
210
|
+
endpoint: string;
|
|
211
|
+
}) {
|
|
212
|
+
const walletKey = process.env.NULLPATH_WALLET_KEY;
|
|
239
213
|
|
|
240
|
-
if (
|
|
241
|
-
|
|
214
|
+
if (!walletKey) {
|
|
215
|
+
return {
|
|
216
|
+
error: 'NULLPATH_WALLET_KEY environment variable not set. Payment required for registration.',
|
|
217
|
+
info: 'Registration costs $0.10 USDC. Set your wallet private key to proceed.',
|
|
218
|
+
};
|
|
242
219
|
}
|
|
243
|
-
|
|
244
|
-
// Use the first payment option
|
|
245
|
-
const requirements = errorData.accepts[0];
|
|
246
220
|
|
|
247
|
-
//
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
221
|
+
// TODO: Implement full x402 payment flow
|
|
222
|
+
return apiCall('/agents', {
|
|
223
|
+
method: 'POST',
|
|
224
|
+
body: JSON.stringify(args),
|
|
225
|
+
});
|
|
252
226
|
}
|
|
253
227
|
|
|
228
|
+
// Main server
|
|
254
229
|
async function main() {
|
|
255
|
-
// Create a local stdio server that proxies to nullpath's remote MCP
|
|
256
230
|
const server = new Server(
|
|
257
231
|
{
|
|
258
232
|
name: 'nullpath-mcp',
|
|
259
|
-
version: '1.
|
|
233
|
+
version: '1.2.0',
|
|
260
234
|
},
|
|
261
235
|
{
|
|
262
236
|
capabilities: {
|
|
@@ -265,126 +239,77 @@ async function main() {
|
|
|
265
239
|
}
|
|
266
240
|
);
|
|
267
241
|
|
|
268
|
-
//
|
|
269
|
-
const transport = new SSEClientTransport(new URL(NULLPATH_MCP_URL));
|
|
270
|
-
const client = new Client(
|
|
271
|
-
{
|
|
272
|
-
name: 'nullpath-mcp-proxy',
|
|
273
|
-
version: '1.0.0',
|
|
274
|
-
},
|
|
275
|
-
{
|
|
276
|
-
capabilities: {},
|
|
277
|
-
}
|
|
278
|
-
);
|
|
279
|
-
|
|
280
|
-
await client.connect(transport);
|
|
281
|
-
|
|
282
|
-
// List available tools from remote server
|
|
283
|
-
const tools = await client.listTools();
|
|
284
|
-
|
|
285
|
-
// Register tool handlers that proxy to remote
|
|
242
|
+
// List tools handler
|
|
286
243
|
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
287
|
-
return tools;
|
|
244
|
+
return { tools: TOOLS };
|
|
288
245
|
});
|
|
289
246
|
|
|
247
|
+
// Call tool handler
|
|
290
248
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
249
|
+
const { name, arguments: args } = request.params;
|
|
250
|
+
|
|
291
251
|
try {
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
paymentError instanceof Error ? paymentError.message : String(paymentError)
|
|
322
|
-
}`
|
|
323
|
-
);
|
|
324
|
-
}
|
|
252
|
+
let result: unknown;
|
|
253
|
+
|
|
254
|
+
switch (name) {
|
|
255
|
+
case 'discover_agents':
|
|
256
|
+
result = await handleDiscoverAgents(args as { query?: string; category?: string; limit?: number });
|
|
257
|
+
break;
|
|
258
|
+
case 'lookup_agent':
|
|
259
|
+
result = await handleLookupAgent(args as { agentId: string });
|
|
260
|
+
break;
|
|
261
|
+
case 'get_capabilities':
|
|
262
|
+
result = await handleGetCapabilities();
|
|
263
|
+
break;
|
|
264
|
+
case 'check_reputation':
|
|
265
|
+
result = await handleCheckReputation(args as { agentId: string });
|
|
266
|
+
break;
|
|
267
|
+
case 'execute_agent':
|
|
268
|
+
result = await handleExecuteAgent(args as { agentId: string; capabilityId: string; input: unknown });
|
|
269
|
+
break;
|
|
270
|
+
case 'register_agent':
|
|
271
|
+
result = await handleRegisterAgent(args as {
|
|
272
|
+
name: string;
|
|
273
|
+
description: string;
|
|
274
|
+
wallet: string;
|
|
275
|
+
capabilities: unknown[];
|
|
276
|
+
endpoint: string;
|
|
277
|
+
});
|
|
278
|
+
break;
|
|
279
|
+
default:
|
|
280
|
+
throw new Error(`Unknown tool: ${name}`);
|
|
325
281
|
}
|
|
326
|
-
|
|
327
|
-
// Re-throw non-payment errors
|
|
328
|
-
throw error;
|
|
329
|
-
}
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
// Start local stdio transport
|
|
333
|
-
const stdioTransport = new StdioServerTransport();
|
|
334
|
-
await server.connect(stdioTransport);
|
|
335
|
-
|
|
336
|
-
console.error('nullpath MCP client connected to', NULLPATH_MCP_URL);
|
|
337
|
-
}
|
|
338
282
|
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
const response = await fetch(NULLPATH_MCP_URL, {
|
|
360
|
-
method: 'POST',
|
|
361
|
-
headers: {
|
|
362
|
-
'Content-Type': 'application/json',
|
|
363
|
-
'X-PAYMENT': paymentHeader,
|
|
364
|
-
},
|
|
365
|
-
body: JSON.stringify(requestBody),
|
|
283
|
+
return {
|
|
284
|
+
content: [
|
|
285
|
+
{
|
|
286
|
+
type: 'text',
|
|
287
|
+
text: JSON.stringify(result, null, 2),
|
|
288
|
+
},
|
|
289
|
+
],
|
|
290
|
+
};
|
|
291
|
+
} catch (error) {
|
|
292
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
293
|
+
return {
|
|
294
|
+
content: [
|
|
295
|
+
{
|
|
296
|
+
type: 'text',
|
|
297
|
+
text: `Error: ${message}`,
|
|
298
|
+
},
|
|
299
|
+
],
|
|
300
|
+
isError: true,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
366
303
|
});
|
|
367
304
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
const result = await response.json() as {
|
|
374
|
-
jsonrpc: string;
|
|
375
|
-
result?: { content: Array<{ type: string; text: string }> };
|
|
376
|
-
error?: { code: number; message: string; data?: unknown };
|
|
377
|
-
id: number;
|
|
378
|
-
};
|
|
379
|
-
|
|
380
|
-
if (result.error) {
|
|
381
|
-
throw new Error(`RPC Error: ${result.error.message}`);
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
return result.result || { content: [{ type: 'text', text: 'Success' }] };
|
|
305
|
+
// Start server
|
|
306
|
+
const transport = new StdioServerTransport();
|
|
307
|
+
await server.connect(transport);
|
|
308
|
+
|
|
309
|
+
console.error('nullpath MCP server started');
|
|
385
310
|
}
|
|
386
311
|
|
|
387
312
|
main().catch((error) => {
|
|
388
|
-
console.error('Failed to start
|
|
313
|
+
console.error('Failed to start server:', error);
|
|
389
314
|
process.exit(1);
|
|
390
315
|
});
|