@jarib/pxweb-mcp 1.0.2 → 1.0.3
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 +3 -2
- package/build/index.js +50 -33
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,10 +5,11 @@ MCP server for accessing statistical data via the PxWeb API v2.
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
|
-
npx @jarib/pxweb-mcp
|
|
8
|
+
npx -y @jarib/pxweb-mcp
|
|
9
|
+
npx -y @jarib/pxweb-mcp --transport http --port 3000
|
|
9
10
|
```
|
|
10
11
|
|
|
11
|
-
|
|
12
|
+
|
|
12
13
|
|
|
13
14
|
## Known PxWeb v2 Instances
|
|
14
15
|
|
package/build/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { createServer } from "node:http";
|
|
3
3
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
4
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
5
|
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
|
|
5
6
|
import { z } from "zod";
|
|
6
7
|
import yargs from "yargs";
|
|
7
8
|
import { hideBin } from "yargs/helpers";
|
|
9
|
+
import fs from 'fs';
|
|
8
10
|
const DEFAULT_API_BASE = "https://data.ssb.no/api/pxwebapi/v2";
|
|
9
11
|
const DEFAULT_LANGUAGE = "no";
|
|
10
12
|
const USER_AGENT = "pxweb-mcp/1.0";
|
|
@@ -19,6 +21,12 @@ const argv = yargs(hideBin(process.argv))
|
|
|
19
21
|
type: "number",
|
|
20
22
|
description: "Port to listen on",
|
|
21
23
|
default: DEFAULT_PORT,
|
|
24
|
+
})
|
|
25
|
+
.option("transport", {
|
|
26
|
+
type: "string",
|
|
27
|
+
description: "Transport method (http or stdio)",
|
|
28
|
+
choices: ["http", "stdio"],
|
|
29
|
+
default: "stdio",
|
|
22
30
|
})
|
|
23
31
|
.help()
|
|
24
32
|
.parseSync();
|
|
@@ -39,9 +47,10 @@ async function makeRequest(url) {
|
|
|
39
47
|
return response;
|
|
40
48
|
}
|
|
41
49
|
function createMcpServer(apiBase) {
|
|
50
|
+
const pkg = JSON.parse(fs.readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
|
|
42
51
|
const server = new McpServer({
|
|
43
52
|
name: "pxweb-mcp",
|
|
44
|
-
version:
|
|
53
|
+
version: pkg.version
|
|
45
54
|
});
|
|
46
55
|
// Tool: search_tables
|
|
47
56
|
server.registerTool("search_tables", {
|
|
@@ -306,42 +315,50 @@ Use this to find newly published statistics.`,
|
|
|
306
315
|
return server;
|
|
307
316
|
}
|
|
308
317
|
async function main() {
|
|
309
|
-
const { url, port } = argv;
|
|
318
|
+
const { url, port, transport: transportType } = argv;
|
|
310
319
|
const mcpServer = createMcpServer(url);
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
320
|
+
if (transportType === "stdio") {
|
|
321
|
+
const transport = new StdioServerTransport();
|
|
322
|
+
await mcpServer.connect(transport);
|
|
323
|
+
console.error(`PxWeb MCP Server running on stdio`);
|
|
324
|
+
console.error(`Using API: ${url}`);
|
|
325
|
+
}
|
|
326
|
+
else {
|
|
327
|
+
const transport = new StreamableHTTPServerTransport({
|
|
328
|
+
sessionIdGenerator: () => crypto.randomUUID(),
|
|
329
|
+
});
|
|
330
|
+
const httpServer = createServer(async (req, res) => {
|
|
331
|
+
const pathname = req.url?.split("?")[0] || "/";
|
|
332
|
+
// Health check endpoint
|
|
333
|
+
if (pathname === "/health") {
|
|
334
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
335
|
+
res.end(JSON.stringify({ status: "ok" }));
|
|
336
|
+
return;
|
|
326
337
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
338
|
+
// MCP endpoint
|
|
339
|
+
if (pathname === "/mcp") {
|
|
340
|
+
try {
|
|
341
|
+
await transport.handleRequest(req, res);
|
|
342
|
+
}
|
|
343
|
+
catch (error) {
|
|
344
|
+
console.error("MCP error:", error);
|
|
345
|
+
if (!res.headersSent) {
|
|
346
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
347
|
+
res.end(JSON.stringify({ error: "Internal server error" }));
|
|
348
|
+
}
|
|
332
349
|
}
|
|
350
|
+
return;
|
|
333
351
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
});
|
|
352
|
+
// Not found
|
|
353
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
354
|
+
res.end(JSON.stringify({ error: "Not found" }));
|
|
355
|
+
});
|
|
356
|
+
await mcpServer.connect(transport);
|
|
357
|
+
httpServer.listen(port, () => {
|
|
358
|
+
console.error(`PxWeb MCP Server running on http://localhost:${port}/mcp`);
|
|
359
|
+
console.error(`Using API: ${url}`);
|
|
360
|
+
});
|
|
361
|
+
}
|
|
345
362
|
}
|
|
346
363
|
main().catch((error) => {
|
|
347
364
|
console.error("Fatal error:", error);
|