@chrischall/tripadvisor-mcp 0.3.3 → 0.3.4

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.
@@ -7,7 +7,7 @@
7
7
  },
8
8
  "metadata": {
9
9
  "description": "MCP server for the TripAdvisor Terra API — location search, details, photos, and reviews",
10
- "version": "0.3.3"
10
+ "version": "0.3.4"
11
11
  },
12
12
  "plugins": [
13
13
  {
@@ -15,7 +15,7 @@
15
15
  "displayName": "TripAdvisor",
16
16
  "source": "./",
17
17
  "description": "TripAdvisor travel data via the Terra API — search hotels, restaurants, and attractions, with details, photos, and reviews",
18
- "version": "0.3.3",
18
+ "version": "0.3.4",
19
19
  "author": {
20
20
  "name": "Chris Hall"
21
21
  },
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tripadvisor-mcp",
3
3
  "displayName": "TripAdvisor",
4
- "version": "0.3.3",
4
+ "version": "0.3.4",
5
5
  "description": "MCP server for the TripAdvisor Terra API — location search, details, photos, and reviews",
6
6
  "author": {
7
7
  "name": "Chris Hall",
package/dist/bundle.js CHANGED
@@ -3651,7 +3651,12 @@ var require_fast_uri = __commonJS({
3651
3651
  }
3652
3652
  function resolve(baseURI, relativeURI, options) {
3653
3653
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
3654
- const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
3654
+ const { parsed: baseParsed, malformedAuthorityOrPort: baseMalformed } = parseWithStatus(baseURI, schemelessOptions);
3655
+ const { parsed: relativeParsed, malformedAuthorityOrPort: relativeMalformed } = parseWithStatus(relativeURI, schemelessOptions);
3656
+ if (baseMalformed || relativeMalformed) {
3657
+ throw new Error(baseParsed.error || relativeParsed.error || "URI is malformed.");
3658
+ }
3659
+ const resolved = resolveComponent(baseParsed, relativeParsed, schemelessOptions, true);
3655
3660
  schemelessOptions.skipEscape = true;
3656
3661
  return serialize(resolved, schemelessOptions);
3657
3662
  }
@@ -3777,6 +3782,7 @@ var require_fast_uri = __commonJS({
3777
3782
  }
3778
3783
  var URI_PARSE = /^(?:([^#/:?]+):)?(?:\/\/((?:([^#/?@]*)@)?(\[[^#/?\]]+\]|[^#/:?]*)(?::(\d*))?))?([^#?]*)(?:\?([^#]*))?(?:#((?:.|[\n\r])*))?/u;
3779
3784
  var AUTHORITY_PREFIX = /^(?:[^#/:?]+:)?\/\/([^/?#]*)/;
3785
+ var AUTHORITY_INTRODUCER_REGION = /^(?:[^#/:?]+:)?([/\\\t\n\r]*)/;
3780
3786
  function getParseError(parsed, matches) {
3781
3787
  if (matches[2] !== void 0 && parsed.path && parsed.path[0] !== "/") {
3782
3788
  return 'URI path must start with "/" when authority is present.';
@@ -3811,6 +3817,20 @@ var require_fast_uri = __commonJS({
3811
3817
  parsed.error = "URI authority must not contain a literal backslash.";
3812
3818
  malformedAuthorityOrPort = true;
3813
3819
  }
3820
+ const introducerMatch = uri.match(AUTHORITY_INTRODUCER_REGION);
3821
+ if (introducerMatch !== null) {
3822
+ const region = introducerMatch[1];
3823
+ const normalizedRegion = region.replace(/[\t\n\r]/g, "");
3824
+ if (normalizedRegion.length >= 2) {
3825
+ if (normalizedRegion.slice(0, 2) !== "//") {
3826
+ parsed.error = parsed.error || "URI authority must not contain a literal backslash.";
3827
+ malformedAuthorityOrPort = true;
3828
+ } else if (region.length !== normalizedRegion.length) {
3829
+ parsed.error = parsed.error || "URI authority introducer must not contain whitespace.";
3830
+ malformedAuthorityOrPort = true;
3831
+ }
3832
+ }
3833
+ }
3814
3834
  const matches = uri.match(URI_PARSE);
3815
3835
  if (matches) {
3816
3836
  parsed.scheme = matches[1];
@@ -34657,53 +34677,6 @@ var StdioServerTransport = class {
34657
34677
  }
34658
34678
  };
34659
34679
 
34660
- // node_modules/@chrischall/mcp-utils/dist/server/index.js
34661
- async function createMcpServer(opts) {
34662
- const server = new McpServer({ name: opts.name, version: opts.version });
34663
- if (opts.banner !== void 0) {
34664
- console.error(opts.banner);
34665
- }
34666
- const deps = opts.deps;
34667
- for (const register of opts.tools) {
34668
- await register(server, deps);
34669
- }
34670
- return server;
34671
- }
34672
- function withGracefulShutdown(server, opts = {}) {
34673
- const shouldExit = opts.exit ?? true;
34674
- let shuttingDown = false;
34675
- const handler = (signal) => {
34676
- if (shuttingDown)
34677
- return;
34678
- shuttingDown = true;
34679
- void (async () => {
34680
- try {
34681
- if (opts.onSignal)
34682
- await opts.onSignal(signal);
34683
- await server.close();
34684
- } catch (err) {
34685
- console.error(`[mcp-utils] error during graceful shutdown on ${signal}: ${err instanceof Error ? err.message : String(err)}`);
34686
- } finally {
34687
- if (shouldExit)
34688
- process.exit(0);
34689
- }
34690
- })();
34691
- };
34692
- process.on("SIGINT", () => handler("SIGINT"));
34693
- process.on("SIGTERM", () => handler("SIGTERM"));
34694
- }
34695
- async function runMcp(opts) {
34696
- const server = await createMcpServer(opts);
34697
- const shutdown = opts.shutdown ?? true;
34698
- if (shutdown !== false) {
34699
- withGracefulShutdown(server, shutdown === true ? {} : shutdown);
34700
- }
34701
- const spec = opts.transport ?? "stdio";
34702
- const transport = spec === "stdio" ? new StdioServerTransport() : spec;
34703
- await server.connect(transport);
34704
- return server;
34705
- }
34706
-
34707
34680
  // node_modules/@chrischall/mcp-utils/dist/errors/index.js
34708
34681
  var DEFAULT_ERROR_MESSAGE_MAX = 500;
34709
34682
  var McpToolError = class extends Error {
@@ -34763,6 +34736,81 @@ function textResult(data) {
34763
34736
  content: [{ type: "text", text: JSON.stringify(data, null, 2) }]
34764
34737
  };
34765
34738
  }
34739
+ function errorResult(message) {
34740
+ return {
34741
+ content: [{ type: "text", text: redactSecrets(message) }],
34742
+ isError: true
34743
+ };
34744
+ }
34745
+
34746
+ // node_modules/@chrischall/mcp-utils/dist/server/index.js
34747
+ function hintResultOrRethrow(err) {
34748
+ if (err instanceof McpToolError && err.hint) {
34749
+ return errorResult(`${err.message}
34750
+
34751
+ Hint: ${err.hint}`);
34752
+ }
34753
+ throw err;
34754
+ }
34755
+ function surfaceToolHints(server) {
34756
+ const register = server.registerTool.bind(server);
34757
+ server.registerTool = (name, config2, cb) => register(name, config2, (...args) => {
34758
+ let result;
34759
+ try {
34760
+ result = cb(...args);
34761
+ } catch (err) {
34762
+ return hintResultOrRethrow(err);
34763
+ }
34764
+ return result instanceof Promise ? result.catch(hintResultOrRethrow) : result;
34765
+ });
34766
+ }
34767
+ async function createMcpServer(opts) {
34768
+ const server = new McpServer({ name: opts.name, version: opts.version });
34769
+ if (opts.surfaceHints !== false)
34770
+ surfaceToolHints(server);
34771
+ if (opts.banner !== void 0) {
34772
+ console.error(opts.banner);
34773
+ }
34774
+ const deps = opts.deps;
34775
+ for (const register of opts.tools) {
34776
+ await register(server, deps);
34777
+ }
34778
+ return server;
34779
+ }
34780
+ function withGracefulShutdown(server, opts = {}) {
34781
+ const shouldExit = opts.exit ?? true;
34782
+ let shuttingDown = false;
34783
+ const handler = (signal) => {
34784
+ if (shuttingDown)
34785
+ return;
34786
+ shuttingDown = true;
34787
+ void (async () => {
34788
+ try {
34789
+ if (opts.onSignal)
34790
+ await opts.onSignal(signal);
34791
+ await server.close();
34792
+ } catch (err) {
34793
+ console.error(`[mcp-utils] error during graceful shutdown on ${signal}: ${err instanceof Error ? err.message : String(err)}`);
34794
+ } finally {
34795
+ if (shouldExit)
34796
+ process.exit(0);
34797
+ }
34798
+ })();
34799
+ };
34800
+ process.on("SIGINT", () => handler("SIGINT"));
34801
+ process.on("SIGTERM", () => handler("SIGTERM"));
34802
+ }
34803
+ async function runMcp(opts) {
34804
+ const server = await createMcpServer(opts);
34805
+ const shutdown = opts.shutdown ?? true;
34806
+ if (shutdown !== false) {
34807
+ withGracefulShutdown(server, shutdown === true ? {} : shutdown);
34808
+ }
34809
+ const spec = opts.transport ?? "stdio";
34810
+ const transport = spec === "stdio" ? new StdioServerTransport() : spec;
34811
+ await server.connect(transport);
34812
+ return server;
34813
+ }
34766
34814
 
34767
34815
  // node_modules/@chrischall/mcp-utils/dist/config/index.js
34768
34816
  var PLACEHOLDER_RE = /^\$\{[^}]*\}$/;
@@ -34958,7 +35006,7 @@ var pageSchema = {
34958
35006
  };
34959
35007
 
34960
35008
  // src/version.ts
34961
- var VERSION = "0.3.3";
35009
+ var VERSION = "0.3.4";
34962
35010
 
34963
35011
  // src/client.ts
34964
35012
  import { dirname, join } from "node:path";
@@ -37318,6 +37366,17 @@ function classifyBridgeError(err) {
37318
37366
  }
37319
37367
 
37320
37368
  // node_modules/@fetchproxy/server/dist/ws-server.js
37369
+ function envWsPort() {
37370
+ const raw = process.env.FETCHPROXY_WS_PORT;
37371
+ if (raw === void 0 || raw.trim() === "")
37372
+ return void 0;
37373
+ if (!/^\d+$/.test(raw.trim()))
37374
+ return void 0;
37375
+ const port = Number(raw.trim());
37376
+ if (!Number.isInteger(port) || port < 1 || port > 65535)
37377
+ return void 0;
37378
+ return port;
37379
+ }
37321
37380
  var FetchproxyProtocolError = class extends Error {
37322
37381
  constructor(message) {
37323
37382
  super(message);
@@ -37565,7 +37624,7 @@ var FetchproxyServer = class {
37565
37624
  }
37566
37625
  }
37567
37626
  this.opts = {
37568
- port: opts.port ?? 37149,
37627
+ port: opts.port ?? envWsPort() ?? 37149,
37569
37628
  host: opts.host ?? "127.0.0.1",
37570
37629
  serverName: opts.serverName,
37571
37630
  version: opts.version,
package/dist/version.js CHANGED
@@ -1,2 +1,2 @@
1
1
  /** Single source of the server version. release-please bumps the literal below. */
2
- export const VERSION = '0.3.3'; // x-release-please-version
2
+ export const VERSION = '0.3.4'; // x-release-please-version
package/mint.yaml ADDED
@@ -0,0 +1,56 @@
1
+ version: 1
2
+ name: TripAdvisor
3
+ slug: tripadvisor
4
+ summary: >-
5
+ TripAdvisor location search, details, photos, and reviews for Claude via
6
+ the Terra API
7
+ #
8
+ # Hosting note (a comment, not user-facing summary text): this is a
9
+ # BROWSER-BRIDGE MCP — it reaches its site through the user's signed-in
10
+ # tab via the fetchproxy bridge. A bridged registration also needs runtime
11
+ # `fly-shared`, `bridge: true` and a `bridgePortEnv`, which are registration
12
+ # fields this manifest has no schema for (set them over the control API).
13
+ # `state.dataDir` below is required for `bridge`.
14
+ env:
15
+ - name: TRIPADVISOR_API_KEY
16
+ secret: true
17
+ required: true
18
+ help: >-
19
+ Your TripAdvisor Terra API key (tripadvisor.com/developers)
20
+ - name: TRIPADVISOR_REQUEST_TIMEOUT_MS
21
+ required: false
22
+ help: >-
23
+ Per-request timeout in milliseconds. Raise it if calls time out on slow
24
+ upstream responses.
25
+ - name: TRIPADVISOR_WS_PORT
26
+ required: false
27
+ help: >-
28
+ Concentrator port for the fetchproxy browser bridge (defaults to the
29
+ fleet-shared 37149). The runner injects a per-registration port for a
30
+ hosted bridged child, so this is the name to give bridgePortEnv at
31
+ registration.
32
+ - name: TRIPADVISOR_CACHE_TTL
33
+ required: false
34
+ help: >-
35
+ Seconds to cache search responses (default 300; 0 disables).
36
+ - name: TRIPADVISOR_STATIC_CACHE_TTL
37
+ required: false
38
+ help: >-
39
+ Seconds to cache details, photos and reviews (default 3600; 0 disables).
40
+ - name: TRIPADVISOR_DEBUG_LOG
41
+ required: false
42
+ help: >-
43
+ Set to 1 to log browser-bridge requests to stderr.
44
+ state:
45
+ dataDir: true
46
+ reason: >-
47
+ The fetchproxy identity lives at $HOME/.fetchproxy/identity/<name>.json
48
+ and the pair code derives from it. Without a persistent $HOME every cold
49
+ start mints a fresh identity and re-prompts pairing in the browser; the
50
+ API refuses bridge without it.
51
+ egress:
52
+ allow:
53
+ # Only hosts the SERVER process actually fetches. Hosts that appear
54
+ # solely in a URL this server BUILDS and returns are excluded.
55
+ - terra.tripadvisor.com
56
+ - tripadvisor.com
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chrischall/tripadvisor-mcp",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "mcpName": "io.github.chrischall/tripadvisor-mcp",
5
5
  "description": "TripAdvisor Terra API MCP server for Claude — search locations, details, photos, and reviews. Developed and maintained by AI (Claude Code).",
6
6
  "author": "Claude Code (AI) <https://www.anthropic.com/claude>",
@@ -33,18 +33,20 @@
33
33
  ".claude-plugin",
34
34
  "skills",
35
35
  ".mcp.json",
36
- "server.json"
36
+ "server.json",
37
+ "mint.yaml"
37
38
  ],
38
39
  "scripts": {
39
40
  "build": "tsc && npm run bundle",
40
41
  "bundle": "esbuild src/index.ts --bundle --platform=node --format=esm --external:dotenv --banner:js='import { createRequire as __createRequire } from \"module\"; const require = __createRequire(import.meta.url);' --outfile=dist/bundle.js",
41
42
  "dev": "node dist/index.js",
42
- "test": "vitest run",
43
+ "test": "npm run typecheck && vitest run",
43
44
  "test:watch": "vitest",
44
- "test:coverage": "vitest run --coverage"
45
+ "test:coverage": "npm run typecheck && vitest run --coverage",
46
+ "typecheck": "tsc -p tsconfig.json --noEmit"
45
47
  },
46
48
  "dependencies": {
47
- "@chrischall/mcp-utils": "^0.14.0",
49
+ "@chrischall/mcp-utils": "^0.15.0",
48
50
  "@fetchproxy/server": "^2.0.0",
49
51
  "@modelcontextprotocol/sdk": "^1.29.0",
50
52
  "dotenv": "^17.4.0",
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/chrischall/tripadvisor-mcp",
7
7
  "source": "github"
8
8
  },
9
- "version": "0.3.3",
9
+ "version": "0.3.4",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "@chrischall/tripadvisor-mcp",
14
- "version": "0.3.3",
14
+ "version": "0.3.4",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: tripadvisor-mcp
2
+ name: tripadvisor
3
3
  description: TripAdvisor travel data via the Terra API through MCP. Use when the user asks to find hotels, restaurants, or attractions, look up a place's TripAdvisor rating/reviews/photos, compare places to stay or eat, or find what's near a location. Triggers on phrases like "find a hotel in", "best restaurants near", "TripAdvisor reviews for", "what's the rating of", "things to do in", or "attractions near me". Requires the @chrischall/tripadvisor-mcp package installed and the tripadvisor server registered (see Setup), plus a TripAdvisor Terra API key.
4
4
  ---
5
5