@jarib/pxweb-mcp 1.0.2 → 2.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.
- package/README.md +3 -2
- package/build/index.js +49 -32
- package/package.json +1 -2
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 streamable-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 (streamable-http or stdio)",
|
|
28
|
+
choices: ["streamable-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
|
-
const
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
// MCP endpoint
|
|
323
|
-
if (pathname === "/mcp") {
|
|
324
|
-
try {
|
|
325
|
-
await transport.handleRequest(req, res);
|
|
320
|
+
if (transportType === "streamable-http") {
|
|
321
|
+
const transport = new StreamableHTTPServerTransport({
|
|
322
|
+
sessionIdGenerator: () => crypto.randomUUID(),
|
|
323
|
+
});
|
|
324
|
+
const httpServer = createServer(async (req, res) => {
|
|
325
|
+
const pathname = req.url?.split("?")[0] || "/";
|
|
326
|
+
// Health check endpoint
|
|
327
|
+
if (pathname === "/health") {
|
|
328
|
+
res.writeHead(200, { "Content-Type": "application/json" });
|
|
329
|
+
res.end(JSON.stringify({ status: "ok" }));
|
|
330
|
+
return;
|
|
326
331
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
+
// MCP endpoint
|
|
333
|
+
if (pathname === "/mcp") {
|
|
334
|
+
try {
|
|
335
|
+
await transport.handleRequest(req, res);
|
|
336
|
+
}
|
|
337
|
+
catch (error) {
|
|
338
|
+
console.error("MCP error:", error);
|
|
339
|
+
if (!res.headersSent) {
|
|
340
|
+
res.writeHead(500, { "Content-Type": "application/json" });
|
|
341
|
+
res.end(JSON.stringify({ error: "Internal server error" }));
|
|
342
|
+
}
|
|
332
343
|
}
|
|
344
|
+
return;
|
|
333
345
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
346
|
+
// Not found
|
|
347
|
+
res.writeHead(404, { "Content-Type": "application/json" });
|
|
348
|
+
res.end(JSON.stringify({ error: "Not found" }));
|
|
349
|
+
});
|
|
350
|
+
await mcpServer.connect(transport);
|
|
351
|
+
httpServer.listen(port, () => {
|
|
352
|
+
console.error(`PxWeb MCP Server running on http://localhost:${port}/mcp`);
|
|
353
|
+
console.error(`Using API: ${url}`);
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
else {
|
|
357
|
+
const transport = new StdioServerTransport();
|
|
358
|
+
await mcpServer.connect(transport);
|
|
359
|
+
console.error(`PxWeb MCP Server running on stdio`);
|
|
343
360
|
console.error(`Using API: ${url}`);
|
|
344
|
-
}
|
|
361
|
+
}
|
|
345
362
|
}
|
|
346
363
|
main().catch((error) => {
|
|
347
364
|
console.error("Fatal error:", error);
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jarib/pxweb-mcp",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "MCP server for accessing statistical data via the PxWeb API v2",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "build/index.js",
|
|
7
7
|
"bin": {
|
|
8
|
-
"@jarib/pxweb-mcp": "build/index.js",
|
|
9
8
|
"pxweb-mcp": "build/index.js"
|
|
10
9
|
},
|
|
11
10
|
"scripts": {
|