Open source
Last updated
The gpuninja-mcp repository#
The code behind GPU Ninja's MCP servers is open source, in the public repository https://github.com/gpuninja/gpuninja-mcp, under the Apache License 2.0.
It's published for two reasons. When you connect an AI assistant to a server, you should be able to see what that server does with your requests. And the code is a working example of a read-only MCP server over a public JSON API, which you're welcome to learn from and build on.
The Apache License 2.0 is permissive and includes an explicit patent grant. The repository carries the full licence text in LICENSE, an attribution notice in NOTICE, and every source file starts with an SPDX licence header.
What's in it#
The repository holds exactly the code the consumer MCP server at https://mcp.gpuninja.com/mcp runs, with the same paths as in GPU Ninja's own repository:
| Folder | What it is |
|---|---|
src/mcp-server/ | The shared MCP core (protocol handling, the ten tools, reading the public API, output limits, logging) and the consumer server's Worker entry: token verification, protected resource metadata, per-user rate limits and the health endpoint |
src/query/ | The search component: text matching, filters, ordering and cursors over GPU Ninja's compact search index. The website's buyer's guide and the desktop app use the same code |
src/types/ | The schemas of GPU Ninja's public API, which the server uses to check every response it reads |
Beside those folders sit the files that make it build on its own: package.json (with the exact dependency versions GPU Ninja runs), pnpm-lock.yaml, tsconfig.json, biome.json, vitest.config.ts, README.md, CONTRIBUTING.md, LICENSE and NOTICE.
Tests travel with the code, and the repository runs the same type check, lint and unit tests, with the same 90% coverage floor, as GPU Ninja's own repository. Internal tooling, such as the scripts that publish the mirror and the deployment health checks, isn't included, and neither are the tests that check the server against other parts of GPU Ninja's codebase.
The sign-in-free connector that ChatGPT uses, at https://connector.gpuninja.com/mcp, runs this same core with no sign-in. Its small wrapper isn't part of the repository.
Nothing in the repository is secret. The server needs no secrets at all: the only key material it uses is GPU Ninja's public token-signing keys, and the published tree is scanned for credentials before every update.
How it's kept up to date#
The repository is a read-only mirror. GPU Ninja's own repository is the source of truth, and the mirror is updated automatically:
- only after the deploy that carries the change has succeeded, so the mirror never shows code that isn't live;
- only when a mirrored file, or one of the build files above, changed;
- only after the copy has passed its own header check, credential scan, type check, lint and tests;
- as a single commit per sync, titled
sync: gpuninja.com@<commit>with aSource-Commit:trailer, pushed by GPU Ninja's GitHub App and never force-pushed. GPU Ninja's own commit history isn't replayed.
So the code you read is the code that answers your requests.
Run your own copy#
You can run the server yourself. The data it reads is public, so a self-hosted copy has the same data as the hosted one. Registration is enforced by the hosted instance at mcp.gpuninja.com, not by the code.
You'll need Node 24 (24.15 or later) and pnpm 12 (the repository pins the exact version in packageManager). The server is a Cloudflare Worker, configured in src/mcp-server/wrangler.jsonc and run with Wrangler.
git clone https://github.com/gpuninja/gpuninja-mcp.git
cd gpuninja-mcp
pnpm install
pnpm typecheck
pnpm check
pnpm testpnpm dev starts the server locally with wrangler dev, using the dev environment in wrangler.jsonc. That environment is set up for tests: it reads the API from http://localhost:8788 and has an empty AUTH_JWKS, so until you supply your issuer's public keys (for example with --var AUTH_JWKS:<json>) it answers every request with "Server misconfigured". To read GPU Ninja's live data, set PUBLIC_API_ORIGIN to https://gpuninja.com.
Configuration#
The Worker is configured entirely through variables and bindings in wrangler.jsonc. It has no secrets.
| Name | Purpose |
|---|---|
PUBLIC_API_ORIGIN | Where to read data from. https://gpuninja.com for GPU Ninja's public API |
MCP_RESOURCE_URL | Your server's MCP endpoint URL, as published in its protected resource metadata |
AUTH_ISSUER | The OAuth authorization server whose tokens the server accepts |
AUTH_AUDIENCE | The audience tokens must be issued for, normally your endpoint URL |
AUTH_REQUIRED_SCOPE | The scope tokens must carry. mcp by default |
AUTH_JWKS | The issuer's public ES256 signing keys, as a JSON Web Key Set |
ALLOWED_HOSTS | Hostnames the server answers on, comma-separated |
ALLOWED_ORIGINS | Hostnames of https web pages allowed to call the server from a browser, comma-separated. Requests without an Origin header are always allowed |
BUILD_SHA | The commit the build came from, written to every log line and to /health. dev locally |
USER_MINUTE_LIMITER, USER_REQUEST_LIMITER | Workers Rate Limiting bindings for the per-user limits: 60 tool calls and 300 requests a minute |
APP_USAGE | A service binding to GPU Ninja's account service (gpuninja-app, entrypoint UsageService), for the daily quota |
When you self-host:
- Remove the
APP_USAGEbinding. It points at GPU Ninja's own account service, which isn't available to you. Without it, there's no daily quota, and the per-minute limits still apply. - Point the
AUTH_*variables at your own OAuth issuer. Tokens issued byapp.gpuninja.comare only valid forhttps://mcp.gpuninja.com/mcp, so you can't reuse GPU Ninja's sign-in. Your issuer must sign ES256 JWT access tokens with headertypat+jwtand akidfromAUTH_JWKS, carryingiss,sub,aud,expand a space-separatedscopethat includesAUTH_REQUIRED_SCOPE. - Or run without sign-in. The core exports
anonymousPolicy, an edge policy that authenticates no one, which you can use to build your own sign-in-free entry point, as GPU Ninja's connector does.
If any variable is missing or malformed, the server refuses to serve: every request gets 500 with "Server misconfigured", except /health, which returns 503. The logs name the variables at fault, never their values.
The repository's README.md is the reference for self-hosting and is kept in step with the code.
Contributing#
Contributions are welcome as pull requests on gpuninja-mcp. Because the mirror is read-only, they aren't merged there. Instead:
- A maintainer reviews your pull request for intent, licensing and the absence of secrets.
- If it's accepted, they apply your commits to GPU Ninja's own repository on a branch, crediting you as co-author, and add or update the specification and tests the change needs.
- That change is reviewed and merged there like any other.
- Once it's deployed, the next mirror sync brings it back to
gpuninja-mcp, and your pull request is closed with a link to where it landed.
Unless the repository's CONTRIBUTING.md says otherwise, a contribution you submit is made under the Apache License 2.0, as section 5 of the licence provides. CONTRIBUTING.md explains the process and is the place to check before you start.
Changes to a tool's behaviour also change the MCP documentation and both AI directory listings, so expect a tool change to take longer than a fix.
To report a bug without writing code, see Support.
Related#
- Using the MCP servers: the tools, sign-in and limits.
- Public API: the open data the server reads.
- Searching the index: how the compact search index works.