@chrischall/tripadvisor-mcp 0.3.3 → 0.3.5
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dist/bundle.js +109 -50
- package/dist/version.js +1 -1
- package/mint.yaml +63 -0
- package/package.json +7 -5
- package/server.json +2 -2
- package/skills/tripadvisor/SKILL.md +1 -1
|
@@ -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.
|
|
10
|
+
"version": "0.3.5"
|
|
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.
|
|
18
|
+
"version": "0.3.5",
|
|
19
19
|
"author": {
|
|
20
20
|
"name": "Chris Hall"
|
|
21
21
|
},
|
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
|
|
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.
|
|
35009
|
+
var VERSION = "0.3.5";
|
|
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.
|
|
2
|
+
export const VERSION = '0.3.5'; // x-release-please-version
|
package/mint.yaml
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
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
|
+
#
|
|
57
|
+
# NOT listed on purpose: www.tripadvisor.com (and the tripadvisor.com
|
|
58
|
+
# apex). The web tools reach the consumer site through the fetchproxy
|
|
59
|
+
# BROWSER BRIDGE — each request is a same-origin fetch executed in the
|
|
60
|
+
# user's signed-in tab, so the browser dials it, never this process, and
|
|
61
|
+
# there is no direct (bridge-less) mode. The only host the process itself
|
|
62
|
+
# fetches is the Terra API above; the www hostname appears in src only in
|
|
63
|
+
# error hints and returned deep-links.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chrischall/tripadvisor-mcp",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.5",
|
|
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.
|
|
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.
|
|
9
|
+
"version": "0.3.5",
|
|
10
10
|
"packages": [
|
|
11
11
|
{
|
|
12
12
|
"registryType": "npm",
|
|
13
13
|
"identifier": "@chrischall/tripadvisor-mcp",
|
|
14
|
-
"version": "0.3.
|
|
14
|
+
"version": "0.3.5",
|
|
15
15
|
"transport": {
|
|
16
16
|
"type": "stdio"
|
|
17
17
|
},
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: tripadvisor
|
|
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
|
|