oom-x402-mcp 1.0.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.
Files changed (3) hide show
  1. package/mcp.js +203 -0
  2. package/package.json +14 -0
  3. package/products-all.json +16489 -0
package/mcp.js ADDED
@@ -0,0 +1,203 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { Server } = require('@modelcontextprotocol/sdk/server/index.js');
4
+ const { StdioServerTransport } = require('@modelcontextprotocol/sdk/server/stdio.js');
5
+ const {
6
+ CallToolRequestSchema,
7
+ ListToolsRequestSchema,
8
+ ListResourcesRequestSchema,
9
+ ReadResourceRequestSchema,
10
+ } = require('@modelcontextprotocol/sdk/types.js');
11
+ const fs = require('fs');
12
+ const path = require('path');
13
+
14
+ // Load products-all.json at startup
15
+ const productsPath = path.join(__dirname, 'products-all.json');
16
+ let productsData = [];
17
+
18
+ try {
19
+ const rawData = fs.readFileSync(productsPath, 'utf8');
20
+ productsData = JSON.parse(rawData);
21
+ console.error(`Loaded ${productsData.length} endpoints from products-all.json`);
22
+ } catch (error) {
23
+ console.error(`Error loading products-all.json: ${error.message}`);
24
+ process.exit(1);
25
+ }
26
+
27
+ // Create MCP server
28
+ const server = new Server(
29
+ {
30
+ name: 'x402-endpoint-catalog',
31
+ version: '1.0.0',
32
+ },
33
+ {
34
+ capabilities: {
35
+ tools: {},
36
+ resources: {},
37
+ },
38
+ }
39
+ );
40
+
41
+ // List available tools
42
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
43
+ return {
44
+ tools: [
45
+ {
46
+ name: 'search_endpoints',
47
+ description: 'Search for API endpoints by query string. Searches across endpoint names, descriptions, and categories.',
48
+ inputSchema: {
49
+ type: 'object',
50
+ properties: {
51
+ query: {
52
+ type: 'string',
53
+ description: 'Search query to match against endpoint names, descriptions, and categories',
54
+ },
55
+ },
56
+ required: ['query'],
57
+ },
58
+ },
59
+ {
60
+ name: 'list_categories',
61
+ description: 'List all unique endpoint categories with their counts',
62
+ inputSchema: {
63
+ type: 'object',
64
+ properties: {},
65
+ },
66
+ },
67
+ ],
68
+ };
69
+ });
70
+
71
+ // Handle tool calls
72
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
73
+ const { name, arguments: args } = request.params;
74
+
75
+ try {
76
+ if (name === 'search_endpoints') {
77
+ const { query } = args;
78
+ const searchQuery = query.toLowerCase();
79
+
80
+ // Search across name, description, and category
81
+ const results = productsData.filter((endpoint) => {
82
+ return (
83
+ endpoint.name?.toLowerCase().includes(searchQuery) ||
84
+ endpoint.description?.toLowerCase().includes(searchQuery) ||
85
+ endpoint.category?.toLowerCase().includes(searchQuery) ||
86
+ endpoint.id?.toLowerCase().includes(searchQuery)
87
+ );
88
+ });
89
+
90
+ return {
91
+ content: [
92
+ {
93
+ type: 'text',
94
+ text: JSON.stringify(
95
+ {
96
+ query,
97
+ count: results.length,
98
+ results: results.map((ep) => ({
99
+ id: ep.id,
100
+ name: ep.name,
101
+ category: ep.category,
102
+ price_usd: ep.price_usd,
103
+ description: ep.description,
104
+ route_path: ep.route_path,
105
+ source_url: ep.source_url,
106
+ response_fields: ep.response_fields,
107
+ })),
108
+ },
109
+ null,
110
+ 2
111
+ ),
112
+ },
113
+ ],
114
+ };
115
+ } else if (name === 'list_categories') {
116
+ // Count endpoints per category
117
+ const categoryCounts = {};
118
+ productsData.forEach((endpoint) => {
119
+ const category = endpoint.category || 'uncategorized';
120
+ categoryCounts[category] = (categoryCounts[category] || 0) + 1;
121
+ });
122
+
123
+ // Convert to sorted array
124
+ const categories = Object.entries(categoryCounts)
125
+ .map(([category, count]) => ({ category, count }))
126
+ .sort((a, b) => b.count - a.count);
127
+
128
+ return {
129
+ content: [
130
+ {
131
+ type: 'text',
132
+ text: JSON.stringify(
133
+ {
134
+ total_categories: categories.length,
135
+ total_endpoints: productsData.length,
136
+ categories,
137
+ },
138
+ null,
139
+ 2
140
+ ),
141
+ },
142
+ ],
143
+ };
144
+ } else {
145
+ throw new Error(`Unknown tool: ${name}`);
146
+ }
147
+ } catch (error) {
148
+ return {
149
+ content: [
150
+ {
151
+ type: 'text',
152
+ text: JSON.stringify({ error: error.message }),
153
+ },
154
+ ],
155
+ isError: true,
156
+ };
157
+ }
158
+ });
159
+
160
+ // List available resources
161
+ server.setRequestHandler(ListResourcesRequestSchema, async () => {
162
+ return {
163
+ resources: [
164
+ {
165
+ uri: 'endpoint_catalog',
166
+ name: 'Endpoint Catalog',
167
+ description: 'Complete catalog of all available API endpoints with full details',
168
+ mimeType: 'application/json',
169
+ },
170
+ ],
171
+ };
172
+ });
173
+
174
+ // Handle resource reads
175
+ server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
176
+ const { uri } = request.params;
177
+
178
+ if (uri === 'endpoint_catalog') {
179
+ return {
180
+ contents: [
181
+ {
182
+ uri,
183
+ mimeType: 'application/json',
184
+ text: JSON.stringify(productsData, null, 2),
185
+ },
186
+ ],
187
+ };
188
+ } else {
189
+ throw new Error(`Unknown resource: ${uri}`);
190
+ }
191
+ });
192
+
193
+ // Start server with stdio transport
194
+ async function main() {
195
+ const transport = new StdioServerTransport();
196
+ await server.connect(transport);
197
+ console.error('x402 MCP server running on stdio');
198
+ }
199
+
200
+ main().catch((error) => {
201
+ console.error('Fatal error:', error);
202
+ process.exit(1);
203
+ });
package/package.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "oom-x402-mcp",
3
+ "version": "1.0.0",
4
+ "description": "MCP server for the Orders of Magnitude x402 endpoint catalog — search 1,459 pay-per-call API endpoints",
5
+ "main": "mcp.js",
6
+ "bin": { "oom-x402-mcp": "mcp.js" },
7
+ "files": ["mcp.js", "products-all.json"],
8
+ "publishConfig": { "access": "public" },
9
+ "keywords": ["mcp", "model-context-protocol", "x402", "api-catalog", "agents"],
10
+ "license": "MIT",
11
+ "dependencies": {
12
+ "@modelcontextprotocol/sdk": "*"
13
+ }
14
+ }