@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 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
- Server runs at `http://localhost:3000/mcp` using Statistics Norway (SSB) by default.
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: "1.0.0",
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
- const transport = new StreamableHTTPServerTransport({
312
- sessionIdGenerator: () => crypto.randomUUID(),
313
- });
314
- const httpServer = createServer(async (req, res) => {
315
- const pathname = req.url?.split("?")[0] || "/";
316
- // Health check endpoint
317
- if (pathname === "/health") {
318
- res.writeHead(200, { "Content-Type": "application/json" });
319
- res.end(JSON.stringify({ status: "ok" }));
320
- return;
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
- catch (error) {
328
- console.error("MCP error:", error);
329
- if (!res.headersSent) {
330
- res.writeHead(500, { "Content-Type": "application/json" });
331
- res.end(JSON.stringify({ error: "Internal server error" }));
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
- return;
335
- }
336
- // Not found
337
- res.writeHead(404, { "Content-Type": "application/json" });
338
- res.end(JSON.stringify({ error: "Not found" }));
339
- });
340
- await mcpServer.connect(transport);
341
- httpServer.listen(port, () => {
342
- console.error(`PxWeb MCP Server running on http://localhost:${port}/mcp`);
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": "1.0.2",
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": {