Using the MCP servers
Last updated
Overview#
GPU Ninja runs two remote MCP servers. Both offer exactly the same ten read-only tools, answer from the same public data, and return the same results for the same call. They differ only in sign-in, hostname and rate limiting.
| Consumer MCP | Connector | |
|---|---|---|
| Endpoint | https://mcp.gpuninja.com/mcp | https://connector.gpuninja.com/mcp |
| Sign-in | Free registration, through OAuth | None |
| Listed in | Claude's Connectors Directory | ChatGPT's plugin directory |
| Rate limits | Per account: 60 tool calls and 300 requests a minute, 5,000 tool calls a day | One global ceiling shared by everyone |
| Source code | Open source, in gpuninja-mcp | Runs the same open-source core |
Use the consumer MCP from Claude or any MCP client that supports OAuth sign-in. Use the connector from ChatGPT, or from any client where you'd rather not sign in.
Registration is not access control. Every tool reads GPU Ninja's public data, which is also open to anyone through the public API with no key, and through the sign-in-free connector. Registering gives you an identity, your own rate limits and, unless you opt out, the daily digest.
Step-by-step setup guides:
- Using GPU Ninja in Claude: the directory listing, claude.ai, Claude Code and other MCP clients.
- Using GPU Ninja in ChatGPT: the sign-in-free connector.
Sign in#
The consumer MCP at https://mcp.gpuninja.com/mcp requires a free GPU Ninja account. You don't create one in advance: the first time your MCP client connects, it opens GPU Ninja's sign-in page, and signing in for the first time registers you.
What registering means#
- Your identity is a verified email address. There are no passwords. You sign in by opening a link GPU Ninja emails to you.
- Registering subscribes you to the daily digest by default. The sign-in form has a checkbox for it. In the EEA, the UK, or when your country can't be determined, the box starts unticked; elsewhere it starts ticked. Either way, you choose before you submit. The choice applies only when the sign-in creates a new account.
- Opting out of the digest never affects MCP access. You can unsubscribe from any digest email, or from your account page, at any time.
- Registration doesn't unlock any data. The same data is open through the public API and the connector at
https://connector.gpuninja.com/mcp.
See Your account for managing the digest, exporting your data and deleting your account.
Sign in from Claude#
GPU Ninja is listed in Claude's Connectors Directory at https://claude.ai/directory/connectors/gpu-ninja. Add it from there, or add https://mcp.gpuninja.com/mcp yourself as a custom connector in claude.ai or as an HTTP MCP server in Claude Code. Claude then walks you through the sign-in below. Using GPU Ninja in Claude has the step-by-step version.
The sign-in flow#
- Your client calls the MCP endpoint without a token. The server answers
401with aWWW-Authenticateheader pointing at its protected resource metadata, which nameshttps://app.gpuninja.comas the authorization server. - Your client opens GPU Ninja's sign-in page at
app.gpuninja.comin your browser. Enter your email address, complete the bot check, and choose whether to receive the digest. If you're already signed in there, you skip straight to step 5. - GPU Ninja emails you a sign-in link. It works once and expires after 15 minutes.
- Open the link. If you open it in the same browser, you're signed in straight away. If you open it on another device, such as your phone, choose Approve sign-in on that device, and the original browser tab signs in on its own within a few seconds. You can instead choose Sign in on this device instead.
- A consent page names the app asking for access (as the app calls itself), where its sign-in information comes from, where the approval will be sent, the address you're signed in as, and what the app may do: "Use GPU Ninja's read-only MCP tools as you", plus "Stay connected" when the app asks for
offline_access. If every return address the app registered is on your own computer, as with Claude Code, the page says that only apps running on this computer can receive the approval. Choose Allow or Deny. - Your browser returns to the app, which exchanges the approval for tokens. You're connected.
Access tokens last 15 minutes and your client refreshes them on its own. A refresh token lasts 30 days from its last use, so a client you use at least once a month stays connected.
Connected apps and signing out#
Your account page at https://app.gpuninja.com/account lists every connected app with when it was connected and last used. Revoke disconnects one. Because access tokens are verified without a call back to the account service, a revoked app can keep working for up to 15 minutes.
If you delete your account, every connected app stops working. Tool calls then fail with "Your GPU Ninja account no longer exists. Reconnect to sign in again." Reconnecting signs you in afresh, as a new account.
Any other OAuth client#
Any MCP client that implements MCP authorization can sign in. The details it needs are all published:
| Item | Value |
|---|---|
| Protected resource metadata | https://mcp.gpuninja.com/.well-known/oauth-protected-resource/mcp (also at /.well-known/oauth-protected-resource) |
| Resource | https://mcp.gpuninja.com/mcp |
| Authorization server | https://app.gpuninja.com |
| Authorization server metadata | https://app.gpuninja.com/.well-known/oauth-authorization-server |
| Grant | Authorization code with PKCE (S256 only); public clients only, with no client secret |
| Client identification | A Client ID Metadata Document (an https:// client_id), preferred; or dynamic client registration at https://app.gpuninja.com/oauth/register |
| Redirect URIs | https:// on a non-loopback host, or http:// on localhost, 127.0.0.1 or [::1]. A loopback redirect matches on any port |
| Scopes | mcp (always granted) and offline_access. You get a refresh token when you ask for offline_access or your client registered the refresh_token grant type |
| Tokens | ES256-signed JWT access tokens, 15 minutes; rotating refresh tokens, 30 days from last use |
| Revocation | https://app.gpuninja.com/oauth/revoke, with a refresh token, disconnects the app |
Send the access token in the Authorization: Bearer header. A token in the query string is ignored. Refresh tokens rotate on every use; presenting a used refresh token again (outside a 60-second retry grace) revokes the whole connection, and you have to sign in again.
Note
A dynamically registered client that never completes a sign-in is deleted after 24 hours, and any client unused for 90 days is deleted. Your client simply registers or identifies itself again.
Enable the connector in ChatGPT#
ChatGPT lists the sign-in-free connector, https://connector.gpuninja.com/mcp. Find GPU Ninja in ChatGPT's plugin directory and enable it. There is no account and no sign-in step, and ChatGPT sends GPU Ninja no identity. See Using GPU Ninja in ChatGPT for details and for how the connector differs from the consumer MCP.
The connector isn't limited to ChatGPT: any MCP client can use it without authentication.
Protocol#
Both servers speak MCP over Streamable HTTP at a single endpoint, /mcp.
- Methods. Send JSON-RPC requests with
POSTandContent-Type: application/json.GETreturns405; there is no SSE stream, and responses are always plain JSON, whatever yourAcceptheader says. - Protocol versions.
2026-07-28and2025-11-25, plus2025-06-18and2025-03-26for older clients that propose them. The server is stateless: it never issues a session ID, and no request depends on an earlier one. - Capabilities. Tools only. There are no resources, prompts or logging, and the tool list is the same for every caller.
- Requests. Bodies are limited to 65,536 bytes, and batch (array) requests are rejected.
- Health.
https://mcp.gpuninja.com/healthreports whether the consumer server can read GPU Ninja's data. The connector's ishttps://connector.gpuninja.com/healthz.
Every successful tool result carries both a readable text item for the model and structuredContent that matches the tool's declared output schema. Output property names are the public API's camelCase names, such as chipSlug, lowestPriceUsd, nextCursor and asOf. Tool names and input argument names are snake_case.
Every tool is read-only and annotated with readOnlyHint: true, destructiveHint: false, idempotentHint: true and openWorldHint: false.
Tools#
Most tools take a slug, the identifier GPU Ninja uses in every URL: for example asus-rog-strix-4090 for a card or ad102 for a chip. If you don't know a slug, search for it first with search_boards or search_chips.
List tools take limit (1 to 20, default 10) and cursor, and return total, nextCursor and asOf. Searching and paging explains how they behave.
search_boards#
Finds graphics cards (boards) by name text and by filters. Discontinued cards are excluded unless you ask for them.
| Argument | Type | Meaning |
|---|---|---|
query | string, 1 to 100 characters | Text to match against cards |
vendor | array of 1 to 10 distinct strings | Board vendors to include, such as ASUS or MSI |
chip | slug | Only cards built on this chip, such as ad102 |
min_vram_gb | number, 0 to 1024 | Smallest VRAM to include, in GB |
max_vram_gb | number, 0 to 1024 | Largest VRAM to include, in GB |
max_length_mm | integer, 50 to 1000 | Longest card you can fit, in millimetres |
max_slot_width | number, 1 to 6 | Thickest card you can fit, in expansion slots, such as 2.5 |
max_tdp_w | integer, 1 to 3000 | Highest board power to include, in watts |
max_price | number, 0 to 1,000,000 | Upper bound, in US dollars, on the lowest current offer |
in_stock_only | boolean, default false | Only cards with at least one in-stock offer |
include_discontinued | boolean, default false | Also return discontinued cards |
limit | integer, 1 to 20, default 10 | Maximum results to return |
cursor | string | nextCursor from a previous call, to fetch the next page |
All arguments are optional. If min_vram_gb is greater than max_vram_gb, the call fails.
Each item has slug, name, chipSlug, vendor, vramGb, tdpW, lengthMm, slotWidth, lowestPriceUsd, inStock, status and links (the card's API URL, page and .txt page). A page may hold fewer than limit items; keep calling with nextCursor until it is null.
Example#
Cards with at least 16 GB of VRAM that are no longer than 300 mm:
{
"jsonrpc": "2.0",
"id": 7,
"method": "tools/call",
"params": {
"name": "search_boards",
"arguments": { "min_vram_gb": 16, "max_length_mm": 300, "limit": 2 }
}
}The structuredContent of the result looks like this (one item shown):
{
"items": [
{
"slug": "gigabyte-rtx-4070-ti-super-windforce-oc",
"name": "Gigabyte RTX 4070 Ti Super Windforce OC",
"chipSlug": "ad103",
"vendor": "Gigabyte",
"vramGb": 16,
"tdpW": 285,
"lengthMm": 261,
"slotWidth": 2.5,
"lowestPriceUsd": 799,
"inStock": true,
"status": "active",
"links": {
"self": "https://gpuninja.com/api/v1/boards/gigabyte-rtx-4070-ti-super-windforce-oc",
"page": "https://gpuninja.com/boards/gigabyte-rtx-4070-ti-super-windforce-oc",
"text": "https://gpuninja.com/boards/gigabyte-rtx-4070-ti-super-windforce-oc.txt"
}
}
],
"total": 14,
"nextCursor": "c1.eyJ0Ijoic2VhcmNoX2JvYXJkcyIsImgiOiI5ZjJjMWQwYTRiN2U4YzMxIiwiYSI6IjIwMjYtMTAtMDRUMDY6MDA6MDBaIiwicSI6IjEwIn0",
"asOf": "2026-10-04T06:00:00Z"
}The text item gives the same results as a numbered list, and ends by telling the model how to get the next page:
GPU Ninja · search_boards · 2 of 14 results · data as of 2026-10-04T06:00:00Z
1. Gigabyte RTX 4070 Ti Super Windforce OC — gigabyte-rtx-4070-ti-super-windforce-oc
chip ad103 · 16 GB · 285 W · 261 mm · 2.5 slots · from 799.00 USD · in stock
https://gpuninja.com/boards/gigabyte-rtx-4070-ti-super-windforce-oc
2. …
More results: call search_boards again with the same arguments and cursor "c1.eyJ…".search_chips#
Finds GPU chips, the processor a card is built on, such as AD102. Discontinued chips are excluded unless you ask for them.
| Argument | Type | Meaning |
|---|---|---|
query | string, 1 to 100 characters | Text to match against chips |
vendor | array of 1 to 10 distinct strings | Chip designers to include, such as NVIDIA, AMD or Intel |
min_vram_gb | number, 0 to 1024 | Smallest maximum VRAM the chip supports, in GB |
max_tdp_w | integer, 1 to 3000 | Highest reference power to include, in watts |
pci_device_id | string | PCI device ID as the operating system reports it: four hex digits, such as 2684 or 0x2684, in either case |
include_discontinued | boolean, default false | Also return discontinued chips |
limit | integer, 1 to 20, default 10 | Maximum results to return |
cursor | string | nextCursor from a previous call |
All arguments are optional. Each item has slug, name, vendor, vramGb (the maximum the chip supports), tdpW (reference power), pciVendorId, pciDeviceIds, status and links. A page may hold fewer than limit items; keep calling with nextCursor until it is null.
Example#
Identify a GPU from the PCI device ID your operating system reports:
{ "name": "search_chips", "arguments": { "pci_device_id": "0x2684" } }This returns one item, with slug ad102 and pciVendorId 10de, total: 1 and nextCursor: null.
get_board#
Returns the full specification of one graphics card: chip, VRAM, clocks, dimensions, power connectors, cooling, current offers, benchmark results and data freshness.
| Argument | Type | Meaning |
|---|---|---|
slug | slug, required | The card's slug, such as asus-rog-strix-4090 |
structuredContent has board (the data of the card's API document), omittedMembers, links and asOf. omittedMembers names any members left out to keep the answer under 24,000 characters; the text holds the full page. When nothing is left out it is [], and board is the document's data unchanged. Members are left out in this order, only as far as needed: provenance, then benchmarkResults, then offers.
The text item is the card's .txt page, the same content as its page on gpuninja.com. If that text is over 24,000 characters it is cut at a line break and ends with a link to the full text. If the .txt page can't be fetched, the call still succeeds, and the text gives the card's name, slug, status and page link instead.
Example#
{ "name": "get_board", "arguments": { "slug": "asus-rog-strix-4090" } }The text comes from https://gpuninja.com/boards/asus-rog-strix-4090.txt, links.self is https://gpuninja.com/api/v1/boards/asus-rog-strix-4090, and omittedMembers is [].
If a card's slug has been renamed, the old slug still works: the result reports the card under its current slug.
get_chip#
Returns the full specification of one GPU chip: architecture, die, core counts, memory bus, reference clocks and power, launch details, and the cards built on it.
| Argument | Type | Meaning |
|---|---|---|
slug | slug, required | The chip's slug, such as ad102 |
structuredContent has chip, omittedMembers, links and asOf, and the text item is the chip's .txt page, exactly as for get_board. omittedMembers names any members left out to keep the answer under 24,000 characters; the text holds the full page. For a chip they are left out in this order: provenance, then benchmarkResults, then boards.
Example#
{ "name": "get_chip", "arguments": { "slug": "ad102" } }compare_boards#
Compares two or three graphics cards side by side: key specs, lowest current price, and benchmark results.
| Argument | Type | Meaning |
|---|---|---|
slugs | array of 2 or 3 distinct slugs, required | The cards to compare, in the order to show them |
structuredContent has:
boards: each card'sslug,name,statusandlinks, in your order.specs: one row per field, always in this order:chipSlug,vendor,vramGb,vramType,factoryBoostClockMhz,tdpW,lengthMm,widthMm,slotWidth,powerConnectors,recommendedPsuW,coolingType,lowestPriceUsd,inStockandstatus. Each row hasfield, a readablelabel, aunit(ornull) andvalues, which follow the order ofboards, withnullwhere a value isn't recorded.benchmarks: one row per combination of benchmark, AI model and test platform for which at least one card has a result. Results only share a row when all three match, because numbers from different platforms aren't comparable. When a card has several results for one row, the latest run wins. Rows are sorted by benchmark, then model, then platform, and capped at 40;benchmarksTruncatedistruewhen rows were left out, either by the cap or to keep the answer under 24,000 characters.asOf.
If any slug doesn't exist, the call fails and lists every missing slug. If two of your slugs turn out to be the same card (an old slug and its renamed one), the call fails and says so.
Example#
{
"name": "compare_boards",
"arguments": { "slugs": ["asus-rog-strix-4090", "msi-rtx-4080-super-gaming-x"] }
}The text item is a fixed-width table (some rows left out here), one block per benchmark row, and a link to each card's page:
GPU Ninja · compare_boards · 2 cards · data as of 2026-10-04T06:00:00Z
asus-rog-strix-4090 msi-rtx-4080-super-gaming-x
Chip ad102 ad103
VRAM (GB) 24 16
Length (mm) 358 322
Lowest price (USD) 1799.00 999.00
In stock yes yes
Status active active
llama-cpp-tg128 / llama-3-3-70b-q4 on pl-ryzen-9950x-cuda-12-6 — tok/s (higher is better)
41.2 —
asus-rog-strix-4090: https://gpuninja.com/boards/asus-rog-strix-4090
msi-rtx-4080-super-gaming-x: https://gpuninja.com/boards/msi-rtx-4080-super-gaming-xwhich_chassis_fit#
Lists the PC cases and enclosures a graphics card fits in. Each result has a verdict: fits, check (within 10 mm of the case's clearance) or does-not-fit, with the reasons and a power supply note.
| Argument | Type | Meaning |
|---|---|---|
board | slug, required | The card's slug |
fit | array of 1 to 3 distinct verdicts, default ["fits", "check"] | Verdicts to include: fits, check, does-not-fit |
include_discontinued | boolean, default false | Also return discontinued cases |
limit | integer, 1 to 20, default 10 | Maximum results to return |
cursor | string | nextCursor from a previous call |
structuredContent has board (its slug, name and links) and items, each with chassis, fit and psu, plus total, nextCursor and asOf. A page may hold fewer than limit items; keep calling with nextCursor until it is null.
The verdicts are GPU Ninja's precomputed ones, the same as on the website, in GPU Ninja's order; the server never works out fit itself. Each reason has a code (length-clear, length-tight, length-exceeds, length-unknown, slots-ok, slots-exceed, slots-unknown or override) and the measurements behind it, with null for members that code doesn't use. The text item turns each reason into a sentence, such as "Card length 358 mm exceeds the 355 mm clearance by 3 mm."
Example#
{
"name": "which_chassis_fit",
"arguments": { "board": "asus-rog-strix-4090", "fit": ["does-not-fit"] }
}One item from the result: the 358 mm, 3.5-slot card against a case with 355 mm and 3 slots of clearance.
{
"chassis": {
"slug": "fractal-north",
"name": "Fractal Design North",
"vendor": "Fractal Design",
"formFactor": "mid-tower",
"maxGpuLengthMm": 355,
"maxGpuSlots": 3,
"psuIncludedW": null,
"lowestPriceUsd": 139.99,
"inStock": true,
"status": "active",
"links": {
"self": "https://gpuninja.com/api/v1/chassis/fractal-north",
"page": "https://gpuninja.com/chassis/fractal-north",
"text": "https://gpuninja.com/chassis/fractal-north.txt"
}
},
"fit": {
"verdict": "does-not-fit",
"basis": "dimensions",
"reasons": [
{ "code": "length-exceeds", "boardLengthMm": 358, "clearanceMm": 355, "marginMm": -3,
"boardSlotWidth": null, "maxSlots": null, "fits": null, "note": null },
{ "code": "slots-exceed", "boardLengthMm": null, "clearanceMm": null, "marginMm": null,
"boardSlotWidth": 3.5, "maxSlots": 3, "fits": null, "note": null }
]
},
"psu": { "includedW": null, "recommendedW": 1000, "sufficient": null }
}what_fits_in_chassis#
Lists the graphics cards that fit in a PC case or enclosure, with the same verdicts and reasons as which_chassis_fit, plus each card's specs and price.
| Argument | Type | Meaning |
|---|---|---|
chassis | slug, required | The case's slug, such as fractal-north |
fit | array of 1 to 3 distinct verdicts, default ["fits", "check"] | Verdicts to include: fits, check, does-not-fit |
include_discontinued | boolean, default false | Also return discontinued cards |
limit | integer, 1 to 20, default 10 | Maximum results to return |
cursor | string | nextCursor from a previous call |
structuredContent has chassis (its slug, name and links) and items, each with board (the same fields as a search_boards item), fit and psu, plus total, nextCursor and asOf. A page may hold fewer than limit items; keep calling with nextCursor until it is null.
Example#
{
"name": "what_fits_in_chassis",
"arguments": { "chassis": "fractal-north", "fit": ["fits"], "limit": 5 }
}which_models_run#
Lists the AI models a graphics card has enough VRAM to run, with each model's parameter count, quantization, minimum VRAM and the VRAM left over.
| Argument | Type | Meaning |
|---|---|---|
board | slug, required | The card's slug |
limit | integer, 1 to 20, default 10 | Maximum results to return |
cursor | string | nextCursor from a previous call |
structuredContent has board, determinable and items, each with model and headroomGb, plus total, nextCursor and asOf. determinable is false when the card's VRAM isn't recorded, in which case nothing can be listed. A page may hold fewer than limit items; keep calling with nextCursor until it is null. For measured performance, use get_benchmark_results.
Example#
{ "name": "which_models_run", "arguments": { "board": "asus-rog-strix-4090", "limit": 3 } }which_boards_run_model#
Lists the graphics cards with enough VRAM to run an AI model, with each card's specs, price, stock and the VRAM left over.
| Argument | Type | Meaning |
|---|---|---|
model | slug, required | The AI model's slug, such as llama-3-3-70b-q4 |
in_stock_only | boolean, default false | Only cards with at least one in-stock offer |
include_discontinued | boolean, default false | Also return discontinued cards |
limit | integer, 1 to 20, default 10 | Maximum results to return |
cursor | string | nextCursor from a previous call |
structuredContent has model, determinable and items, each with board (the same fields as a search_boards item) and headroomGb, plus total, nextCursor and asOf. determinable is false when the model's minimum VRAM isn't recorded, in which case no cards can be listed. A page may hold fewer than limit items; keep calling with nextCursor until it is null.
Example#
{
"name": "which_boards_run_model",
"arguments": { "model": "llama-3-3-70b-q4", "in_stock_only": true }
}get_benchmark_results#
Lists benchmark measurements for a graphics card, an AI model or a test platform, optionally narrowed by benchmark. Each result names the benchmark, metric, unit, value, model, platform, run date and source.
| Argument | Type | Meaning |
|---|---|---|
board | slug | A card's slug |
model | slug | An AI model's slug |
platform | slug | A test platform's slug |
benchmark | slug | A benchmark's slug, to narrow the results |
limit | integer, 1 to 20, default 10 | Maximum results to return |
cursor | string | nextCursor from a previous call |
Provide at least one of board, model or platform; otherwise the call fails with "Provide at least one of board, model or platform." The results come from the first of those you give, in that order, and are narrowed by every other slug you give. A narrowing slug that matches nothing gives an empty list, not an error.
structuredContent has scope (the kind and slug the results came from), items, total, nextCursor and asOf. Each item has benchmark (with metric, unit and higherIsBetter), subject, model (or null), platform, value, runDate and sourceUrl. Items are ordered by benchmark, then model, then platform, then subject, then newest run first. A page may hold fewer than limit items; keep calling with nextCursor until it is null.
Example#
{
"name": "get_benchmark_results",
"arguments": { "board": "asus-rog-strix-4090", "benchmark": "llama-cpp-tg128" }
}Searching and paging#
search_boards and search_chips use the same search library as the website's buyer's guide and the desktop app, so the same filters give the same results in the same order. Searching the index describes the library itself.
Text matching#
query is matched against each item's name, vendor, chip and slug.
- Case and accents are ignored, and so are symbols such as
™.GeForce,geforceandGEFORCEare the same. - Letters and digits are separate words.
rtx4090searches forrtxand4090, and16GBfor16andgb. - Every word must match. A word matches when it equals a word in the item, or when it has at least two characters and is the start of one:
40matches both4080and4090. - Small typos are forgiven in words made of letters. A word of 5 or more letters can be one edit away (a wrong, missing, extra or swapped letter), so
geforecfindsgeforce. A word of 9 or more letters can be two edits away. - Numbers are never fuzzy.
4080never matches4090. A single character matches only an identical word. - At most 16 different words. A longer
queryfails with an "Invalid search" error.
Filters#
- Filters combine with each other and with
query: an item must satisfy all of them. - Ranges are inclusive.
max_length_mm: 300includes a 300 mm card. vendorignores case, accents and extra spaces.- An item whose value for a filtered field isn't recorded doesn't match that filter. For example,
max_priceexcludes cards with no current offer. - Discontinued items are excluded by default. Set
include_discontinued: trueto include them. Discontinued items carrystatus: "discontinued", and their line in the text ends with· DISCONTINUED.
Ordering#
- With
query, the best matches come first, then by name, A to Z. - Without
query, results are ordered by name, A to Z. - Ties are broken by slug, so the same call always returns the same order.
A word scores more when it matches exactly than as a prefix, and more as a prefix than as a typo. It also scores more in the name than in the vendor or chip, and least in the slug: an exact word in the name is worth 24, a prefix in the name 16, a one-letter typo in the name 8, and an exact word in the vendor or chip 12. Your words appearing in order in the name add 8, and a name made of exactly your words adds 16 more.
These are the search library's worked examples, over three test cards with discontinued cards included: A is "ASUS ROG Strix GeForce RTX 4090 OC" (chip ad102), B is "MSI GeForce RTX 4080 Gaming X Trio" (chip ad103), and C is "NVIDIA GeForce RTX 4090 Founders Edition" (chip ad102, discontinued).
| Text | Results in order (score) |
|---|---|
rtx 4090 | A (56), C (56) |
4090 | A (24), C (24) |
40 | A (16), B (16), C (16) |
rtx 40 | A (48), B (48), C (48) |
geforec 4080 | B (32) |
asus | A (24) |
4 | (none) |
nvidia geforce rtx 4090 founders edition | C (168) |
ad102 | A (24), C (24) |
The search tools take no sort argument. These are the library's defaults they use:
| Search fact | Value | Meaning |
|---|---|---|
LIMITS.maxTextTokens | 16 | Most different words a query may hold |
DEFAULT_SORT.withText | [{"by":"relevance","dir":"desc"},{"by":"name","dir":"asc"}] | Order with a query, before the final tie-break by slug |
DEFAULT_SORT.withoutText | [{"by":"name","dir":"asc"}] | Order without a query, before the final tie-break by slug |
includeDiscontinued | false | Discontinued items are left out unless you ask for them |
The compatibility and benchmark tools keep GPU Ninja's own order for their lists.
Cursors#
When more results remain, nextCursor holds an opaque string. To get the next page, call the same tool again with the same arguments and cursor set to that string. You can change limit between pages. On the last page, nextCursor is null.
- A page may hold fewer than
limititems even when more remain, because the server shortens a page that would not fit in 24,000 characters. Keep calling withnextCursoruntil it isnull; no item is skipped or repeated. totalcounts every matching item across all pages.- A cursor only works with the tool and arguments that produced it. Otherwise the call fails with "This cursor doesn't match the call. Repeat the call without cursor to start again."
- A cursor stops working when GPU Ninja's data is updated, so a walk through the pages never mixes two versions of the catalogue. The call fails with "GPU Ninja's data was updated since the first page. Repeat the call without cursor to start again."
Results and errors#
asOf is when the data was generated, as an absolute UTC timestamp. It is never the time of your request. Results can lag the website by up to five minutes after an update, while caches refresh.
Every text item and every structuredContent is at most 24,000 characters. Long results are shortened, as each tool describes, rather than failing.
Problems with a call come back as a tool error, with isError: true, no structuredContent, and one plain-English text the model can act on:
- Unknown slug. For
get_boardandget_chip:No board with slug "…".(orchip), then up to five similar slugs under "Did you mean:", then "Use search_boards to find slugs." (orsearch_chips). Other tools name the kind and the slug, and for a card add the pointer tosearch_boards. - Invalid arguments. The message names the argument and the rule it broke. A call whose
argumentshold more than 64 values in total fails with "Too many values in arguments: the limit is 64." - Data unavailable. "GPU Ninja's data service didn't respond. Try again in a minute."
- Unexpected data. "GPU Ninja returned data in an unexpected format. This has been logged."
- Too large. "GPU Ninja's data for this request is too large to return." This happens only when even a single item or a shortened result can't fit.
A search with no matches isn't an error: it returns items: [], total: 0 and a text saying no items match, followed by the filters you used.
Limits#
| Limit | Consumer MCP | Connector |
|---|---|---|
| Items per result | Up to 20 (10 by default) | Up to 20 (10 by default) |
| Tool calls | 60 a minute and 5,000 a day, per account | Shared ceiling of 200 requests every 10 seconds |
| All requests | 300 a minute, per account | Included in the ceiling above |
| Request body | 65,536 bytes | 65,536 bytes |
- On the consumer MCP, that's 60 tool calls and 300 requests per minute per account, and 5,000 tool calls per day. Over a limit, the server answers HTTP
429with aRetry-Afterheader giving the seconds to wait. - The daily count resets at 00:00 UTC. Only
tools/callcounts towards the per-minute tool limit and the daily limit; every request, including listing tools and other protocol messages, counts towards the 300 a minute. - The connector's ceiling is shared by every user of the connector and counted separately at each Cloudflare location, so it isn't a per-person allowance. Over it, the connector also answers
429withRetry-After. - There is no per-IP limit on either server.
When you hit a limit: the busy message#
The message for an over-limit call starts "GPU Ninja is busy" and ends by saying how long to wait, for example "Try again in 60 seconds." On the consumer MCP it names the limit you reached; for the daily limit it also gives the reset time in UTC.
It means what it says: wait the given time and try again. On the connector, it usually means the service as a whole is busy for a few seconds, not that you did anything wrong. Some clients show a 429 as a connection error rather than passing the message to the assistant.
What is logged#
Each server writes one log line per request. It records the time, the HTTP status, the protocol method and version, the tool name, which argument names were used, the public catalogue item looked up (only when it exists), the client software's name, whether sign-in and the rate limits let the request through, the outcome, the number of results, the latency and a Cloudflare request ID.
Neither server logs your IP address, your account identifier, the app's client ID, your token, the values of your arguments (so never the text of a search), cursors, or the results. The connector never logs the identifiers ChatGPT attaches to requests, and it logs only a quarter of successful requests, while logging every error and every 429.
On the consumer MCP, the user ID inside your access token is used only to apply your rate limits. Your daily count is kept by GPU Ninja's account service for 30 days. Logs are kept by Cloudflare, as processor, for the Workers Logs default, currently 7 days. The privacy policy is the authoritative statement.
Open source#
The consumer MCP server, including the search component and the data types it uses, is open source under the Apache License 2.0, in the public gpuninja-mcp repository at https://github.com/gpuninja/gpuninja-mcp. The connector runs the same core. See Open source for what the repository contains, how to run your own copy, and how to contribute.
Help#
Report problems through Support.