@trustrails/mcp-server 1.0.24 → 1.0.26
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 +32 -23
- package/dist/index.js +122 -127
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -66,8 +66,9 @@ Just ask Claude naturally — it will decompose your request into the right quer
|
|
|
66
66
|
|
|
67
67
|
Claude will search across multiple UK retailers and show you:
|
|
68
68
|
- Real-time prices & availability
|
|
69
|
-
-
|
|
70
|
-
-
|
|
69
|
+
- Purchase links (trustrails.app/go/ redirects to the retailer, through an affiliate link)
|
|
70
|
+
- Every known structured spec (`attributes`), so products can be compared from the search alone
|
|
71
|
+
- Then `get_product` for your final 1-3 picks, only when you need what search lacks: the retailer's description, or every retailer's offer and buy link (search carries only the best offer's `purchase_url`, cheapest in stock)
|
|
71
72
|
|
|
72
73
|
---
|
|
73
74
|
|
|
@@ -75,33 +76,41 @@ Claude will search across multiple UK retailers and show you:
|
|
|
75
76
|
|
|
76
77
|
### `search_products`
|
|
77
78
|
|
|
78
|
-
Search 26,000+ UK electronics products.
|
|
79
|
+
Search 26,000+ UK electronics products across 7 retailers with price comparison. Prices are in GBP. The tool text tells the assistant to split the request into filters first: brand, category and price go in their own arguments, RAM, storage, screen size, resolution, refresh rate, wattage and Wi-Fi generation go in `constraints`, and only what is left over goes in `query`.
|
|
79
80
|
|
|
80
81
|
**Parameters:**
|
|
81
|
-
- `query` (string) - Refinement terms
|
|
82
|
-
- `min_price` (number, optional) - Minimum price in GBP
|
|
83
|
-
- `max_price` (number, optional) - Maximum price in GBP
|
|
84
|
-
- `brand` (string, optional) - Filter by brand
|
|
85
|
-
- `category` (string, optional) - Filter by category: Laptops, Desktops, Tablets, Phones, TVs, Monitors, Headphones, Speakers, Cameras, Keyboards, Mice, Printers, Networking, Storage, Gaming, Wearables, Drones, Audio, Cables & Chargers.
|
|
86
|
-
- `constraints` (object, optional) - Hard spec requirements, checked per product against its `attributes
|
|
87
|
-
- `lite` (boolean, optional) - Return trimmed product objects (
|
|
88
|
-
- `limit` (number, optional) - Maximum products to return (default 50, max 100)
|
|
89
|
-
- `sort` (string, optional) - Sort order:
|
|
90
|
-
|
|
91
|
-
**Returns:**
|
|
82
|
+
- `query` (string, optional) - Refinement terms ONLY: model lines, series, variants, model numbers (e.g. 'neo', 'ultra', 'oled', 'WH-1000XM5', 's25 ultra'). Never a category name (BAD query='tablet', query='smartwatch', query='laptop': set the category filter instead), never a brand name (BAD query='Sony': set the brand filter instead), never a price. Omit entirely when browsing a category or brand: 'show me tablets' = category='Tablets', no query. Query words must appear in the title, except words naming the category ('router' in Networking) and bare numbers or specs ('4070', '16GB'), which are ignored when finding products and only rank them. Put a model number with its prefix ('RTX 4070', not '4070') and check each title for it. Leave out use-case words like gaming, cheap or best.
|
|
83
|
+
- `min_price` (number, optional) - Minimum price in GBP.
|
|
84
|
+
- `max_price` (number, optional) - Maximum price in GBP.
|
|
85
|
+
- `brand` (string, optional) - Filter by brand name (exact match, case-insensitive). Examples: Apple, Samsung, Sony, HP, Dell, Lenovo, Anker, Bose, LG
|
|
86
|
+
- `category` (string, optional) - Filter by product category. Use ONLY these exact values: Laptops, Desktops, Tablets, Phones, TVs, Monitors, Headphones, Speakers, Cameras, Keyboards, Mice, Printers, Networking, Storage, Gaming, Wearables, Drones, Audio, Cables & Chargers. 'Smartphones' is not valid (use 'Phones'), nor is 'Televisions' (use 'TVs'). Gaming headsets are category='Headphones', query='gaming headset': the Gaming category is consoles, controllers and accessories only.
|
|
87
|
+
- `constraints` (object, optional) - Hard spec requirements, checked per product against its `attributes`. Shape `{name: {op: number}}` with op `eq`, `gte` or `lte`; a range is `{gte, lte}`. On every operator, storage matches within 3% and screen size within 0.5 inch; a whole-number screen size N also covers up to N+1 on `eq` and `lte` (`gte` is unchanged); other specs exactly: `gte 1024` accepts a 1TB drive, `eq 22` a 21.5" screen, `eq 13` a 13.6" one, `lte 15` a 15.6" one. Example: `{"memory_gb": {"gte": 24}, "storage_gb": {"gte": 1000}, "screen_in": {"eq": 15}}`. Names and units: `memory_gb` (RAM, GB), `storage_gb` (GB, 1TB = 1000), `screen_in` (inches), `resolution_p` (pixels high: 4K = 2160, QHD = 1440, Full HD = 1080), `refresh_hz` (Hz), `power_w` (W), `wifi_gen` (Wi-Fi generation: 6, 6E = 6.5, 7). A spec written in `query` counts only when it says what it is ('24GB RAM', '1TB', '144Hz', '55"') and means at least, except screen size (that size); a bare '24GB' stays a search word. Explicit constraints win over it. A plain `16GB` or `65W` is `gte`; use `eq` only when the user says exactly, and for screen size. Always set `category` (and brand if known) with constraints: a search of only specs is rejected, as is a bad request (unknown name or operator, negative value, a combination nothing can meet such as `gte` above `lte`); the error lists the valid ones. See [Structured specs](#structured-specs).
|
|
88
|
+
- `lite` (boolean, optional) - Return trimmed product objects with only essential fields (id, title, brand, price, currency, availability, image_url, purchase_url, offer_count, attributes (every known spec as {status, value}, without sources) and, with constraints, constraint_status). Always set to true; it still carries attributes. Use false only for ean, category, provenance or all sources at once.
|
|
89
|
+
- `limit` (number, optional) - Maximum number of products to return (default 50, max 100)
|
|
90
|
+
- `sort` (string, optional) - Sort order: 'relevance' (default), 'price_asc' (in stock first, then cheapest), 'price_desc' (in stock first, then most expensive). With constraints, matched products still come first.
|
|
91
|
+
|
|
92
|
+
**Returns:** `products` and a `total`. Each product carries every known `attributes` spec (a product with no `attributes` key has none of these seven specs known: say so only if the user asked about one): compare specs from these. State the value of a `confirmed` or `inferred` spec; only `conflicting` (retailers disagree) or a missing name (unknown) needs a caveat. With constraints, each product has `constraint_status` per name (`matched`: a retailer's title states a value that meets it; `unverified`: not known to meet it, so never treat it as a match), `total` counts the products that match every constraint, `unverified_total` the unverified ones that passed the other filters, and `excluded_by_constraints` the products whose stated value fails. `candidates_truncated: true` means the first 2,000 candidates in the chosen sort order were checked and more exist: add a brand or category, or a narrower query, and search again. `availability` is `in_stock`, `low_stock`, `out_of_stock` or `unknown` (the retailer gave no stock signal), and with `purchase_url` and `price` it comes from the product's best offer: in stock first, then cheapest. If `offer_count` is above 1, call `get_product` for your final 1-3 picks to compare retailers. Before claiming a saving, read `offers[].title` (from `get_product`): they must name the same model; if they differ, don't claim one. Before recommending any pick, check its title is the product type asked for (not a cable, accessory or adapter).
|
|
92
93
|
|
|
93
94
|
### `get_product`
|
|
94
95
|
|
|
95
|
-
Get full details for a single product. Returns structured `attributes` (see [Structured specs](#structured-specs)), `specs.description` (the retailer's own prose, for processor, ports,
|
|
96
|
+
Get full details for a single product by ID. Returns structured `attributes` (see [Structured specs](#structured-specs)), `specs.description` (the retailer's own prose, for processor, GPU, ports, weight, battery and features that `attributes` does not cover), pricing, availability, delivery time, and all retailer offers with per-retailer pricing (`offers[].stock` is a unit count only when the retailer supplies one, otherwise null). Accepts both canonical product IDs and original retailer offer IDs. Use after `search_products` only for your final 1-3 picks, and only when you need what search lacks: details only the description has (if it doesn't give a detail, tell the user it isn't listed), or every retailer's offer and buy link (search carries only the best offer's `purchase_url`, cheapest in stock). Search results already carry `attributes` to compare specs. A pick with `offer_count` 1 needs no call unless the user asked for a description-only detail.
|
|
96
97
|
|
|
97
98
|
**Parameters:**
|
|
98
|
-
- `product_id` (string) - The product ID from search results
|
|
99
|
+
- `product_id` (string) - The unique product ID from search results
|
|
99
100
|
|
|
100
|
-
**Returns:** Complete product with structured `attributes`, `specs` (including the retailer's `specs.description`),
|
|
101
|
+
**Returns:** Complete product with structured `attributes`, `specs` (including the retailer's `specs.description`), `offers` sorted in stock first then cheapest, and provenance information
|
|
101
102
|
|
|
102
103
|
### Structured specs
|
|
103
104
|
|
|
104
|
-
`get_product`
|
|
105
|
+
Search results and `get_product` return `attributes`: structured specs (RAM, storage, screen size, resolution, refresh rate, power, Wi-Fi generation) read from retailer titles when the catalogue is imported. Each has a `status`, and a spec nobody states is absent (unknown); a product with no `attributes` key has none of these seven specs known (say so only if the user asked about one). What each call returns:
|
|
106
|
+
|
|
107
|
+
| Call | Returns |
|
|
108
|
+
|------|---------|
|
|
109
|
+
| `search_products` with `lite=true` (what agents should always set) | `id`, `title`, `brand`, `price`, `currency`, `availability`, `image_url`, `purchase_url`, `offer_count`, every known attribute as `{status, value}` (or `{status, values}` when conflicting) without sources, and `constraint_status` when constrained |
|
|
110
|
+
| `search_products` without `lite` | the lite fields plus `ean`, `category`, `product_type`, `provenance` and every attribute with its `sources` |
|
|
111
|
+
| `get_product` | everything, including `specs.description` and dimensions, `offers` and `delivery_time` |
|
|
112
|
+
|
|
113
|
+
Names and units are as in `constraints`. State the value for `confirmed` and `inferred`; only `conflicting` or a missing name needs a caveat. The statuses:
|
|
105
114
|
|
|
106
115
|
- `confirmed`: two or more retailers state the same value.
|
|
107
116
|
- `inferred`: one retailer's title states it.
|
|
@@ -121,7 +130,7 @@ For one Galaxy S26 Ultra, where only JoyBuy states the RAM (12GB) and two retail
|
|
|
121
130
|
}
|
|
122
131
|
```
|
|
123
132
|
|
|
124
|
-
Searches with constraints return the constraints applied, `excluded_by_constraints`, `unverified_total`, and a `constraint_status` on each product: `matched` (a retailer's title states a value that meets the constraint) or `unverified` (not known to meet it: never treat as a match, tell the user it is unconfirmed; check `attributes[name]`, where `conflicting` means retailers disagree and missing means unknown). Products whose stated value fails a constraint are left out. A lite result
|
|
133
|
+
Searches with constraints return the constraints applied, `excluded_by_constraints`, `unverified_total`, and a `constraint_status` on each product: `matched` (a retailer's title states a value that meets the constraint) or `unverified` (not known to meet it: never treat as a match, tell the user it is unconfirmed; check `attributes[name]`, where `conflicting` means retailers disagree and missing means unknown). Products whose stated value fails a constraint are left out. A lite result carries the `status` and value of every known spec, without `sources`, so a 64GB laptop is told apart from a 16GB one and disagreeing from unknown.
|
|
125
134
|
|
|
126
135
|
- **Tolerance:** storage within 3% (1TB = 1000–1024GB) and screen size within 0.5 inch, on every operator. Retailers round sizes down, so a whole-number screen size N also covers up to N+1 on `eq` and `lte` (`eq 13` accepts 13.6", `lte 15` accepts 15.6", `gte` is unchanged). Other specs, memory included, are exact.
|
|
127
136
|
- **Specs in `query`:** only a spec that says what it is counts ("24GB RAM", "1TB", "512GB SSD", "144Hz", `55"`). A bare "24GB" stays a search word. Memory, storage, resolution, refresh rate, power and Wi-Fi mean at least; screen size means that size.
|
|
@@ -141,8 +150,8 @@ Search across **26,000+ electronics products** from major UK retailers including
|
|
|
141
150
|
|
|
142
151
|
**Budget shopping:**
|
|
143
152
|
```
|
|
144
|
-
"Find
|
|
145
|
-
→ category='Laptops',
|
|
153
|
+
"Find laptops with at least 16GB RAM under £800"
|
|
154
|
+
→ category='Laptops', constraints={"memory_gb": {"gte": 16}}, max_price=800, sort='price_asc', lite=true
|
|
146
155
|
```
|
|
147
156
|
|
|
148
157
|
**Brand search:**
|
|
@@ -166,7 +175,7 @@ Search across **26,000+ electronics products** from major UK retailers including
|
|
|
166
175
|
**Detailed specs:**
|
|
167
176
|
```
|
|
168
177
|
"Tell me the specs of this laptop"
|
|
169
|
-
→ get_product(product_id)
|
|
178
|
+
→ compare specs from search; get_product(product_id) only for description-only details or every offer
|
|
170
179
|
```
|
|
171
180
|
|
|
172
181
|
**Price range:**
|
|
@@ -197,7 +206,7 @@ Search across **26,000+ electronics products** from major UK retailers including
|
|
|
197
206
|
- ✅ **Real-time data** - Product feeds updated twice daily
|
|
198
207
|
- ✅ **Multiple retailers** - Compare prices in one search
|
|
199
208
|
- ✅ **Stock information** - See what's actually available to buy
|
|
200
|
-
- ✅ **
|
|
209
|
+
- ✅ **Purchase links** - Click through to the retailer to buy (affiliate links)
|
|
201
210
|
- ✅ **Zero setup** - Works out of the box with shared public key
|
|
202
211
|
- ✅ **UK-focused** - Optimized for UK electronics shopping
|
|
203
212
|
|
package/dist/index.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
2
3
|
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
3
4
|
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
4
5
|
import { CallToolRequestSchema, ListToolsRequestSchema, } from "@modelcontextprotocol/sdk/types.js";
|
|
5
6
|
// TrustRails API configuration
|
|
6
7
|
const API_KEY = process.env.TRUSTRAILS_API_KEY || "mcp-public-2026";
|
|
7
8
|
const BASE_URL = process.env.TRUSTRAILS_BASE_URL || "https://trustrails.app";
|
|
8
|
-
|
|
9
|
+
// package.json sits one level above both src/ and dist/
|
|
10
|
+
const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf-8"));
|
|
11
|
+
const CONSTRAINT_NAMES = ["memory_gb", "storage_gb", "power_w", "refresh_hz", "resolution_p", "screen_in", "wifi_gen"];
|
|
9
12
|
// Create server instance
|
|
10
13
|
const server = new Server({
|
|
11
14
|
name: "trustrails",
|
|
12
|
-
version:
|
|
15
|
+
version: pkg.version,
|
|
13
16
|
}, {
|
|
14
17
|
capabilities: {
|
|
15
18
|
tools: {},
|
|
@@ -35,13 +38,13 @@ async function searchProducts(params) {
|
|
|
35
38
|
if (params.category) {
|
|
36
39
|
searchParams.append("category", params.category);
|
|
37
40
|
}
|
|
38
|
-
if (params.constraints
|
|
41
|
+
if (params.constraints != null) {
|
|
39
42
|
searchParams.append("constraints", JSON.stringify(params.constraints));
|
|
40
43
|
}
|
|
41
|
-
if (params.lite) {
|
|
44
|
+
if (params.lite === true) {
|
|
42
45
|
searchParams.append("lite", "true");
|
|
43
46
|
}
|
|
44
|
-
if (
|
|
47
|
+
if (typeof params.limit === "number") {
|
|
45
48
|
searchParams.append("limit", params.limit.toString());
|
|
46
49
|
}
|
|
47
50
|
if (params.sort) {
|
|
@@ -68,7 +71,7 @@ async function searchProducts(params) {
|
|
|
68
71
|
* Get detailed information about a specific product
|
|
69
72
|
*/
|
|
70
73
|
async function getProduct(productId) {
|
|
71
|
-
const url = `${BASE_URL}/api/product/${productId}`;
|
|
74
|
+
const url = `${BASE_URL}/api/product/${encodeURIComponent(productId)}`;
|
|
72
75
|
const response = await fetch(url, {
|
|
73
76
|
headers: {
|
|
74
77
|
...(API_KEY && { "Authorization": `Bearer ${API_KEY}` }),
|
|
@@ -82,130 +85,122 @@ async function getProduct(productId) {
|
|
|
82
85
|
}
|
|
83
86
|
return await response.json();
|
|
84
87
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
88
|
+
const TOOLS = [
|
|
89
|
+
{
|
|
90
|
+
name: "search_products",
|
|
91
|
+
description: "HOW TO CALL THIS TOOL — read before every call: " +
|
|
92
|
+
"Decompose the user's request into filters first. Only what's left over goes in query. " +
|
|
93
|
+
"STEP 1: brand name → brand filter. STEP 2: product category → category filter. STEP 3: price → min_price/max_price. STEP 4: RAM, storage, screen size, resolution, refresh rate, wattage, Wi-Fi generation → constraints. STEP 5: what remains → query. " +
|
|
94
|
+
"BAD: query='Sony headphones under £200' | GOOD: brand='Sony', category='Headphones', max_price=200, no query. " +
|
|
95
|
+
"BAD: query='tablet' | GOOD: category='Tablets', no query. " +
|
|
96
|
+
"BAD: query='macbook neo' | GOOD: brand='Apple', category='Laptops', query='neo'. " +
|
|
97
|
+
"BAD: query='Samsung QLED TV' | GOOD: brand='Samsung', category='TVs', query='qled'. " +
|
|
98
|
+
"If brand+category alone cover what the user wants, omit query entirely. " +
|
|
99
|
+
"Only put differentiating terms in query: model lines (neo, ultra, oled), variants, model numbers (WH-1000XM5, s25 ultra). " +
|
|
100
|
+
"Query words must appear in the title, except words naming the category ('router' in Networking) and bare numbers or specs ('4070', '16GB'), which are ignored when finding products and only rank them. Put a model number with its prefix ('RTX 4070', not '4070') and check each title for it. Leave out use-case words like gaming, cheap or best. " +
|
|
101
|
+
"CROSS-CATEGORY NOTE: Gaming headsets → category='Headphones', query='gaming headset'. The Gaming category is consoles/controllers/accessories only. " +
|
|
102
|
+
"Always set lite=true (it still carries `attributes`). If 0 results, broaden the query or drop filters (but never present a near miss as meeting a requirement). " +
|
|
103
|
+
"Searches 26,000+ UK electronics products across 7 retailers with price comparison. Prices are in GBP. Every listing is new (refurbished and used are excluded). " +
|
|
104
|
+
"PRICE COMPARISON: for a final pick with offer_count > 1, get_product returns offers[] (sorted in-stock first, then cheapest): show the cheapest in-stock retailer, the other prices with the difference and the exact saving among in-stock offers. " +
|
|
105
|
+
"Before claiming a saving, read offers[].title (from get_product): they must name the same model; if they differ, don't claim one. Before recommending any pick, check its title is the product type asked for (not a cable, accessory or adapter). " +
|
|
106
|
+
"COMPARING SPECS: compare products from the `attributes` in the search results, not by calling get_product on each. Every spec known for a product is there as {status, value}, or {status, values} when conflicting, without sources; names and units are as in `constraints`. 'confirmed' (two or more retailers state the same value) and 'inferred' (one retailer's title states it) are both the product's spec: state the value. Only `conflicting` (retailers disagree: say so, don't pick one) or a missing name (unknown) needs a caveat. A product with no `attributes` has none of these seven specs known: say so only if the user asked about one. " +
|
|
107
|
+
"Call get_product only for your final 1-3 picks, and only when you need what search lacks: what only the retailer's description has (processor, GPU, ports, weight, battery), or every retailer's offer and buy link (search results carry only the best offer's purchase_url (cheapest in stock)). A pick with offer_count 1 needs no call unless the user asked for a description-only detail. Don't guess those details from titles. " +
|
|
108
|
+
"SPEC REQUIREMENTS: put exact requirements in `constraints`, not in query, and always set `category` (and brand if known) with `constraints`: a search of only specs is rejected. " +
|
|
109
|
+
"If a requirement is ambiguous (e.g. '16GB' could be RAM or storage), ask the user or search without that constraint. " +
|
|
110
|
+
"With constraints, every product has `constraint_status` per name: " +
|
|
111
|
+
"'matched' = a retailer's title states a value that meets it. 'unverified' = not known to meet it: check `attributes[name]`, where `conflicting` means retailers disagree and missing means unknown. " +
|
|
112
|
+
"Never treat 'unverified' as a match or say a product meets a requirement because it was returned: tell the user it is unconfirmed. " +
|
|
113
|
+
"Products whose stated value fails are left out (`excluded_by_constraints`). Matched results come first, also with sort='price_asc'. " +
|
|
114
|
+
"With constraints, `total` counts the products that match every constraint and `unverified_total` the unverified products that passed the other filters (only some may be in `products`). If `total` is 0, say no product is known to meet every requirement and offer the unverified ones only as unconfirmed. " +
|
|
115
|
+
"If `candidates_truncated` is true, the first 2,000 candidates in the chosen sort order were checked and more exist: add a brand or category, or a narrower query, and search again before saying nothing matches. If the search was already narrowed, tell the user the results may be incomplete. " +
|
|
116
|
+
"STOCK: availability is in_stock, low_stock, out_of_stock or unknown (the retailer gave no stock signal: say so, don't assume). When availability is out_of_stock, mention it as an alternative and suggest checking back — do not silently omit it. " +
|
|
117
|
+
"purchase_url is a trustrails.app/go/ redirect through an affiliate link; TrustRails may earn a commission, and the price is the same. " +
|
|
118
|
+
"Colour variants have separate barcodes and are separate products: when price matters, search again without the colour or check other colours of the same model.",
|
|
119
|
+
inputSchema: {
|
|
120
|
+
type: "object",
|
|
121
|
+
properties: {
|
|
122
|
+
query: {
|
|
123
|
+
type: "string",
|
|
124
|
+
description: "Refinement terms ONLY — model lines, series, variants, model numbers (e.g. 'neo', 'ultra', 'oled', 'WH-1000XM5', 's25 ultra'). " +
|
|
125
|
+
"NEVER a category name: BAD query='tablet', query='smartwatch', query='laptop'. Set the category filter instead. " +
|
|
126
|
+
"NEVER a brand name: BAD query='Sony'. Set the brand filter instead. " +
|
|
127
|
+
"NEVER a price. " +
|
|
128
|
+
"Omit entirely when browsing a category or brand — 'show me tablets' = category='Tablets', no query.",
|
|
129
|
+
},
|
|
130
|
+
min_price: {
|
|
131
|
+
type: "number",
|
|
132
|
+
description: "Minimum price in GBP.",
|
|
133
|
+
},
|
|
134
|
+
max_price: {
|
|
135
|
+
type: "number",
|
|
136
|
+
description: "Maximum price in GBP.",
|
|
137
|
+
},
|
|
138
|
+
brand: {
|
|
139
|
+
type: "string",
|
|
140
|
+
description: "Filter by brand name (exact match, case-insensitive). Examples: Apple, Samsung, Sony, HP, Dell, Lenovo, Anker, Bose, LG",
|
|
141
|
+
},
|
|
142
|
+
category: {
|
|
143
|
+
type: "string",
|
|
144
|
+
description: "Filter by product category. Use ONLY these exact values: " +
|
|
145
|
+
"Laptops, Desktops, Tablets, Phones, TVs, Monitors, " +
|
|
146
|
+
"Headphones, Speakers, Cameras, Keyboards, Mice, Printers, Networking, " +
|
|
147
|
+
"Storage, Gaming, Wearables, Drones, Audio, Cables & Chargers. " +
|
|
148
|
+
"NOTE: 'Smartphones' is not valid — use 'Phones'. 'Televisions' is not valid — use 'TVs'.",
|
|
149
|
+
},
|
|
150
|
+
constraints: {
|
|
123
151
|
type: "object",
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
category: {
|
|
147
|
-
type: "string",
|
|
148
|
-
description: "Filter by product category. Use ONLY these exact values: " +
|
|
149
|
-
"Laptops, Desktops, Tablets, Phones, TVs, Monitors, " +
|
|
150
|
-
"Headphones, Speakers, Cameras, Keyboards, Mice, Printers, Networking, " +
|
|
151
|
-
"Storage, Gaming, Wearables, Drones, Audio, Cables & Chargers. " +
|
|
152
|
-
"NOTE: 'Smartphones' is not valid — use 'Phones'. 'Televisions' is not valid — use 'TVs'.",
|
|
153
|
-
},
|
|
154
|
-
constraints: {
|
|
155
|
-
type: "object",
|
|
156
|
-
description: "Hard spec requirements, checked per product against its attributes. Shape {name: {op: number}} with op eq, gte or lte; a range is {gte, lte}. " +
|
|
157
|
-
"On every operator, storage matches within 3% and screen size within 0.5 inch; a whole-number screen size N also covers up to N+1 on eq and lte (gte is unchanged); other specs exactly: gte 1024 accepts a 1TB drive, eq 22 a 21.5\" screen, eq 13 a 13.6\" one, lte 15 a 15.6\" one. " +
|
|
158
|
-
"Example: {\"memory_gb\": {\"gte\": 24}, \"storage_gb\": {\"gte\": 1000}, \"screen_in\": {\"eq\": 15}}. " +
|
|
159
|
-
"Names and units: memory_gb (RAM, GB), storage_gb (GB, 1TB = 1000), screen_in (inches), resolution_p (pixels high: 4K = 2160, QHD = 1440, Full HD = 1080), " +
|
|
160
|
-
"refresh_hz (Hz), power_w (W), wifi_gen (Wi-Fi generation: 6, 6E = 6.5, 7). " +
|
|
161
|
-
"A spec written in query counts only when it says what it is ('24GB RAM', '1TB', '144Hz', '55\"') and means at least, except screen size (that size); a bare '24GB' stays a search word. Explicit constraints win over it.",
|
|
162
|
-
properties: Object.fromEntries(CONSTRAINT_NAMES.map((name) => [
|
|
163
|
-
name,
|
|
164
|
-
{ type: "object", properties: { eq: { type: "number" }, gte: { type: "number" }, lte: { type: "number" } } },
|
|
165
|
-
])),
|
|
166
|
-
},
|
|
167
|
-
lite: {
|
|
168
|
-
type: "boolean",
|
|
169
|
-
description: "Return trimmed product objects with only essential fields " +
|
|
170
|
-
"(id, title, brand, price, currency, availability, image_url, purchase_url, offer_count and, with constraints, constraint_status and the status and value of the constrained names). " +
|
|
171
|
-
"Always set to true unless the user specifically needs full product objects.",
|
|
172
|
-
},
|
|
173
|
-
limit: {
|
|
174
|
-
type: "number",
|
|
175
|
-
description: "Maximum number of products to return (default 50, max 100)",
|
|
176
|
-
},
|
|
177
|
-
sort: {
|
|
178
|
-
type: "string",
|
|
179
|
-
description: "Sort order: 'relevance' (default), 'price_asc' (cheapest first), 'price_desc' (most expensive first). Use 'price_asc' when comparing prices.",
|
|
180
|
-
},
|
|
181
|
-
},
|
|
152
|
+
description: "Hard spec requirements, checked per product against its attributes. Shape {name: {op: number}} with op eq, gte or lte; a range is {gte, lte}. " +
|
|
153
|
+
"On every operator, storage matches within 3% and screen size within 0.5 inch; a whole-number screen size N also covers up to N+1 on eq and lte (gte is unchanged); other specs exactly: gte 1024 accepts a 1TB drive, eq 22 a 21.5\" screen, eq 13 a 13.6\" one, lte 15 a 15.6\" one. " +
|
|
154
|
+
"Example: {\"memory_gb\": {\"gte\": 24}, \"storage_gb\": {\"gte\": 1000}, \"screen_in\": {\"eq\": 15}}. " +
|
|
155
|
+
"Names and units: memory_gb (RAM, GB), storage_gb (GB, 1TB = 1000), screen_in (inches), resolution_p (pixels high: 4K = 2160, QHD = 1440, Full HD = 1080), " +
|
|
156
|
+
"refresh_hz (Hz), power_w (W), wifi_gen (Wi-Fi generation: 6, 6E = 6.5, 7). " +
|
|
157
|
+
"A spec written in query counts only when it says what it is ('24GB RAM', '1TB', '144Hz', '55\"') and means at least, except screen size (that size); a bare '24GB' stays a search word. Explicit constraints win over it. A plain '16GB' or '65W' is gte; use eq only when the user says exactly, and for screen size.",
|
|
158
|
+
properties: Object.fromEntries(CONSTRAINT_NAMES.map((name) => [
|
|
159
|
+
name,
|
|
160
|
+
{ type: "object", properties: { eq: { type: "number" }, gte: { type: "number" }, lte: { type: "number" } } },
|
|
161
|
+
])),
|
|
162
|
+
},
|
|
163
|
+
lite: {
|
|
164
|
+
type: "boolean",
|
|
165
|
+
description: "Return trimmed product objects with only essential fields (id, title, brand, price, currency, availability, image_url, purchase_url, offer_count, attributes (every known spec as {status, value}, without sources) and, with constraints, constraint_status). Always set to true; it still carries attributes. Use false only for ean, category, provenance or all sources at once.",
|
|
166
|
+
},
|
|
167
|
+
limit: {
|
|
168
|
+
type: "number",
|
|
169
|
+
description: "Maximum number of products to return (default 50, max 100)",
|
|
170
|
+
},
|
|
171
|
+
sort: {
|
|
172
|
+
type: "string",
|
|
173
|
+
description: "Sort order: 'relevance' (default), 'price_asc' (in stock first, then cheapest), 'price_desc' (in stock first, then most expensive).",
|
|
182
174
|
},
|
|
183
175
|
},
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
},
|
|
204
|
-
required: ["product_id"],
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
{
|
|
179
|
+
name: "get_product",
|
|
180
|
+
description: "Get full details for a single product by ID. " +
|
|
181
|
+
"Returns `attributes`: structured specs read from retailer titles, each name mapping to {status, value, sources}; a conflicting one has values: [{value, sources}] instead of value and sources. " +
|
|
182
|
+
"Names and units as in the search constraints argument. status: 'confirmed' = two or more retailers state the same value; 'inferred' = one retailer's title states it; " +
|
|
183
|
+
"'conflicting' = retailers state different values (none is picked, tell the user they disagree; a retailer can appear under two values, so read offers[].title to see which listing states which); a missing name = unknown. " +
|
|
184
|
+
"Also returns specs.description, the retailer's own prose: use it only for details attributes do not cover (processor, GPU, ports, weight, battery, features); if it doesn't give a detail, tell the user it isn't listed. " +
|
|
185
|
+
"It can describe another configuration or a maximum ('up to 32GB'), so it never overrides or fills in an attribute: if an attribute is missing or conflicting, that spec is unknown or unconfirmed, and you may mention what the description says only as 'the retailer's description mentions X, unconfirmed'. " +
|
|
186
|
+
"It also returns pricing, availability, delivery time, and all retailer offers with per-retailer pricing (offers[].stock is a unit count only when the retailer supplies one, otherwise null). " +
|
|
187
|
+
"Accepts both canonical product IDs and original retailer offer IDs. " +
|
|
188
|
+
"Use this after search_products only for your final 1-3 picks, and only when you need what search lacks: details only the description has, or every retailer's offer and buy link. Search results already carry `attributes` to compare specs.",
|
|
189
|
+
inputSchema: {
|
|
190
|
+
type: "object",
|
|
191
|
+
properties: {
|
|
192
|
+
product_id: {
|
|
193
|
+
type: "string",
|
|
194
|
+
description: "The unique product ID from search results",
|
|
205
195
|
},
|
|
206
196
|
},
|
|
207
|
-
|
|
208
|
-
|
|
197
|
+
required: ["product_id"],
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
];
|
|
201
|
+
// Handle tool listing
|
|
202
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => {
|
|
203
|
+
return { tools: TOOLS };
|
|
209
204
|
});
|
|
210
205
|
// Handle tool execution
|
|
211
206
|
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
@@ -219,7 +214,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
219
214
|
content: [
|
|
220
215
|
{
|
|
221
216
|
type: "text",
|
|
222
|
-
text: JSON.stringify(results
|
|
217
|
+
text: JSON.stringify(results),
|
|
223
218
|
},
|
|
224
219
|
],
|
|
225
220
|
};
|
|
@@ -234,7 +229,7 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
234
229
|
content: [
|
|
235
230
|
{
|
|
236
231
|
type: "text",
|
|
237
|
-
text: JSON.stringify(product
|
|
232
|
+
text: JSON.stringify(product),
|
|
238
233
|
},
|
|
239
234
|
],
|
|
240
235
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EACL,qBAAqB,EACrB,sBAAsB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trustrails/mcp-server",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.26",
|
|
4
4
|
"mcpName": "app.trustrails/server",
|
|
5
5
|
"description": "MCP server for searching UK electronics products across multiple retailers",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
8
|
-
"trustrails-mcp": "
|
|
8
|
+
"trustrails-mcp": "dist/index.js"
|
|
9
9
|
},
|
|
10
10
|
"files": [
|
|
11
11
|
"dist"
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"repository": {
|
|
32
32
|
"type": "git",
|
|
33
|
-
"url": "https://github.com/james-webdev/trustrails-mcp-server.git"
|
|
33
|
+
"url": "git+https://github.com/james-webdev/trustrails-mcp-server.git"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@modelcontextprotocol/sdk": "^1.25.1"
|