@tcliplab/transit-mcp 0.1.0 → 0.1.2

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/README.md +60 -4
  2. package/build/index.js +44 -15
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,11 +1,67 @@
1
1
  # Transit API Server
2
2
 
3
- An MCP server for Transit API, a Japanese public transit API built on `https://api.transit.ls8h.com/`.
3
+ An unofficial local MCP server for Transit API, a Japanese public transit API built on `https://api.transit.ls8h.com/`.
4
4
 
5
- This server wraps the REST API and is still unofficial.
5
+ In most cases, you should use the official MCP connector at `https://api.transit.ls8h.com/mcp`.
6
6
 
7
- I made this to search Japanese transit information seamlessly from LLM chat.
7
+ This package exists as a local `npm` / `npx`-based wrapper and as a base for future wrapper tools and experiments.
8
+ It also includes lightweight result previews, which may make the first-step UX a little smoother.
8
9
 
9
- ## LICENSE
10
+ Why `npx`: this package is packaged so it can be tried without a local install or a separate service setup.
11
+ That may make it a useful example of how the same API can be wrapped as a local `npm` / `npx`-driven MCP server, with the distribution model and adapter layer being part of the value.
12
+
13
+ ## Available Tools
14
+
15
+ These tools follow the shape and coverage of the original Transit API.
16
+
17
+ - `plan_journey` - search a route between two places
18
+ - `guidance_plan` - generate route guidance text
19
+ - `suggest_locations` - search location candidates
20
+ - `suggest_places` - search stations and place candidates
21
+ - `get_station` - fetch station details
22
+ - `get_station_departures` - fetch departures from a station
23
+ - `list_feeds` - list available feeds
24
+ - `list_operators` - list available operators
25
+
26
+ ## Install
27
+
28
+ Use `npx` for quick access.
29
+
30
+ If you prefer, you can build and run it yourself.
31
+
32
+ ## Connect Claude Desktop
33
+
34
+ Add the server to your Claude Desktop config:
35
+
36
+ ```json
37
+ {
38
+ "mcpServers": {
39
+ "transit-mcp": {
40
+ "command": "npx",
41
+ "args": ["-y", "@tcliplab/transit-mcp@beta"]
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ ## Connect Codex
48
+
49
+ Add the server to your Codex config:
50
+
51
+ ```toml
52
+ [mcp_servers.transit_mcp]
53
+ command = "npx"
54
+ args = ["-y", "@tcliplab/transit-mcp@beta"]
55
+ ```
56
+
57
+ ## API Documentation
58
+
59
+ Transit API is available at `https://api.transit.ls8h.com/`.
60
+
61
+ The server uses the public REST API directly and does not require extra credentials.
62
+
63
+ ## About
64
+
65
+ This package is currently unofficial.
10
66
 
11
67
  No license is granted at this time. OSS release is planned after permission and scope are clarified.
package/build/index.js CHANGED
@@ -1,7 +1,20 @@
1
+ #!/usr/bin/env node
2
+ import { readFileSync } from "node:fs";
1
3
  import { McpServer } from "@modelcontextprotocol/server";
2
4
  import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
3
5
  import * as z from "zod/v4";
4
6
  const API_BASE = "https://api.transit.ls8h.com";
7
+ const REQUEST_TIMEOUT_MS = 20_000;
8
+ function readPackageVersion() {
9
+ try {
10
+ const packageJson = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
11
+ return typeof packageJson.version === "string" ? packageJson.version : "0.0.0";
12
+ }
13
+ catch {
14
+ return "0.0.0";
15
+ }
16
+ }
17
+ const SERVER_VERSION = readPackageVersion();
5
18
  function toSearchParams(params) {
6
19
  const searchParams = new URLSearchParams();
7
20
  for (const [key, value] of Object.entries(params)) {
@@ -18,24 +31,40 @@ async function fetchTransit(path, params = {}) {
18
31
  searchParams.forEach((value, key) => {
19
32
  url.searchParams.set(key, value);
20
33
  });
21
- const response = await fetch(url, {
22
- headers: {
23
- accept: "application/json",
24
- },
25
- });
26
- const rawText = await response.text();
27
- let data = rawText;
34
+ const controller = new AbortController();
35
+ const timeoutId = setTimeout(() => {
36
+ controller.abort();
37
+ }, REQUEST_TIMEOUT_MS);
28
38
  try {
29
- data = JSON.parse(rawText);
39
+ const response = await fetch(url, {
40
+ headers: {
41
+ accept: "application/json",
42
+ },
43
+ signal: controller.signal,
44
+ });
45
+ const rawText = await response.text();
46
+ let data = rawText;
47
+ try {
48
+ data = JSON.parse(rawText);
49
+ }
50
+ catch {
51
+ // Keep raw text when the endpoint does not return JSON.
52
+ }
53
+ if (!response.ok) {
54
+ const detail = typeof data === "string" ? data : JSON.stringify(data, null, 2);
55
+ throw new Error(`Transit API ${response.status} ${response.statusText}: ${detail}`);
56
+ }
57
+ return data;
30
58
  }
31
- catch {
32
- // Keep raw text when the endpoint does not return JSON.
59
+ catch (error) {
60
+ if (error instanceof Error && error.name === "AbortError") {
61
+ throw new Error(`Transit API request timed out after ${REQUEST_TIMEOUT_MS}ms`);
62
+ }
63
+ throw error;
33
64
  }
34
- if (!response.ok) {
35
- const detail = typeof data === "string" ? data : JSON.stringify(data, null, 2);
36
- throw new Error(`Transit API ${response.status} ${response.statusText}: ${detail}`);
65
+ finally {
66
+ clearTimeout(timeoutId);
37
67
  }
38
- return data;
39
68
  }
40
69
  function formatServiceSeconds(seconds) {
41
70
  const day = 86_400;
@@ -195,7 +224,7 @@ const stationInput = z.object({
195
224
  });
196
225
  const server = new McpServer({
197
226
  name: "transit-mcp",
198
- version: "1.0.0",
227
+ version: SERVER_VERSION,
199
228
  });
200
229
  server.registerTool("plan_journey", {
201
230
  title: "Plan journey",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tcliplab/transit-mcp",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "publishConfig": {