gorz-mcp 0.0.0-stage → 0.1.0
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/LICENSE +9 -0
- package/README.md +69 -2
- package/index.mjs +115 -0
- package/package.json +14 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 GORZ
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
6
|
+
|
|
7
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,70 @@
|
|
|
1
|
-
#
|
|
1
|
+
# GORZ MCP server
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Solana memecoin safety checks for AI assistants and trading agents.
|
|
4
|
+
|
|
5
|
+
Ask your assistant "is this coin safe?" and it checks the coin with [GORZ](https://gorz.app). You get the grade, every red flag with its reason, launch bundles, wallets selling in the same second, and links to known rug farms.
|
|
6
|
+
|
|
7
|
+
GORZ reports what public on-chain data shows. It does not predict prices, and nothing it returns is financial advice.
|
|
8
|
+
|
|
9
|
+
## Tools
|
|
10
|
+
|
|
11
|
+
| Tool | What it does | Key needed |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| `gorz_check_coin` | Full safety read for a coin by its mint address. Includes the grade (safer / caution / risky / checking), hard stops, red flags, launch bundle, same-second sellers, rug-farm link, AI dump warning, and what happened in the hour after GORZ first graded it. | No |
|
|
14
|
+
| `gorz_search_coins` | Find coins by ticker or name (`$BONK`, `fuzzy bear`). Returns their addresses and first GORZ grade. | No |
|
|
15
|
+
| `gorz_check_wallet` | What GORZ has seen a wallet do: rug-farm group, launch bundles, snipes, and its record as a coin creator. | Yes |
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
Requires Node.js 18 or newer.
|
|
20
|
+
|
|
21
|
+
### Claude Desktop, Cursor and other MCP clients
|
|
22
|
+
|
|
23
|
+
Add this to your MCP config (for Claude Desktop that's `claude_desktop_config.json`):
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"mcpServers": {
|
|
28
|
+
"gorz": {
|
|
29
|
+
"command": "npx",
|
|
30
|
+
"args": ["-y", "gorz-mcp"],
|
|
31
|
+
"env": { "GORZ_API_KEY": "" }
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Leave `GORZ_API_KEY` empty to use the free tier.
|
|
38
|
+
|
|
39
|
+
### Claude Code
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
claude mcp add gorz -- npx -y gorz-mcp
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Limits and keys
|
|
46
|
+
|
|
47
|
+
| Plan | Checks per day | Price |
|
|
48
|
+
|---|---|---|
|
|
49
|
+
| Free | 300, no key | $0 |
|
|
50
|
+
| Starter | 20,000, plus wallet lookups | $49 / 30 days |
|
|
51
|
+
| Pro | 200,000 | $199 / 30 days |
|
|
52
|
+
|
|
53
|
+
Get a key at [gorz.app/developers](https://gorz.app/developers), paid in SOL or USDC. GORZ is also on RapidAPI, where you can pay by card.
|
|
54
|
+
|
|
55
|
+
## Settings
|
|
56
|
+
|
|
57
|
+
| Variable | Default | Purpose |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| `GORZ_API_KEY` | (empty) | Your GORZ key, for higher limits and wallet lookups |
|
|
60
|
+
| `GORZ_API_URL` | `https://gorz.app/api/v1` | Only change this for testing |
|
|
61
|
+
|
|
62
|
+
## Example
|
|
63
|
+
|
|
64
|
+
> **You:** Is 2DtF5QVs1zPwpZVR7PGiCcnNsi36gJvMWxNbeDVCpump safe to buy?
|
|
65
|
+
>
|
|
66
|
+
> **Assistant** (after calling `gorz_check_coin`): GORZ first graded $YMB as risky at a $585K market cap, and it dumped within the hour…
|
|
67
|
+
|
|
68
|
+
## License
|
|
69
|
+
|
|
70
|
+
MIT
|
package/index.mjs
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// GORZ MCP server: lets AI assistants and trading agents check Solana memecoins with GORZ (https://gorz.app).
|
|
3
|
+
// Tools: gorz_check_coin, gorz_search_coins, gorz_check_wallet. Talks to the public GORZ API v1 over HTTPS.
|
|
4
|
+
// Optional env: GORZ_API_KEY (higher limits + wallet lookups; get one at https://gorz.app/developers),
|
|
5
|
+
// GORZ_API_URL (default https://gorz.app/api/v1).
|
|
6
|
+
import {McpServer} from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
7
|
+
import {StdioServerTransport} from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
8
|
+
import {z} from 'zod';
|
|
9
|
+
|
|
10
|
+
const VERSION = '0.1.0';
|
|
11
|
+
const BASE = (process.env.GORZ_API_URL || 'https://gorz.app/api/v1').replace(/\/+$/, '');
|
|
12
|
+
const KEY = (process.env.GORZ_API_KEY || '').trim();
|
|
13
|
+
const ADDRESS = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
|
|
14
|
+
|
|
15
|
+
async function call(path, params) {
|
|
16
|
+
const url = BASE + path + '?' + new URLSearchParams(params).toString();
|
|
17
|
+
const headers = {'user-agent': 'gorz-mcp/' + VERSION, accept: 'application/json'};
|
|
18
|
+
if (KEY) headers['x-api-key'] = KEY;
|
|
19
|
+
let r;
|
|
20
|
+
try { r = await fetch(url, {headers, signal: AbortSignal.timeout(15000)}); }
|
|
21
|
+
catch (e) { return {ok: false, status: 0, body: {error: 'Could not reach GORZ (' + (e?.name === 'TimeoutError' ? 'timed out' : e?.message || 'network error') + '). Try again shortly.'}}; }
|
|
22
|
+
const body = await r.json().catch(() => ({error: 'GORZ sent an unreadable reply (HTTP ' + r.status + ').'}));
|
|
23
|
+
return {ok: r.ok, status: r.status, body, left: r.headers.get('x-ratelimit-remaining'), plan: r.headers.get('x-gorz-plan')};
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const text = (s) => ({content: [{type: 'text', text: s}]});
|
|
27
|
+
const fail = (s) => ({content: [{type: 'text', text: s}], isError: true});
|
|
28
|
+
const usd = (n) => n == null || !Number.isFinite(Number(n)) ? 'n/a' : '$' + Number(n).toLocaleString('en-US', {maximumFractionDigits: Number(n) < 1 ? 8 : 0});
|
|
29
|
+
const pct = (n) => n == null || !Number.isFinite(Number(n)) ? 'n/a' : Number(n).toFixed(1) + '%';
|
|
30
|
+
function limitNote(res) {
|
|
31
|
+
if (res.status === 429) return '\n\nDaily limit reached. ' + (KEY ? 'Your plan limit resets at 00:00 UTC.' : 'The free tier is 300 checks a day. A key raises it: https://gorz.app/developers');
|
|
32
|
+
if (res.status === 402) return '\n\nThis GORZ key has expired. Renew it at https://gorz.app/developers';
|
|
33
|
+
if (res.status === 401) return '\n\n' + (KEY ? 'The GORZ_API_KEY was not accepted.' : 'This needs a GORZ API key (set GORZ_API_KEY). Get one at https://gorz.app/developers');
|
|
34
|
+
return '';
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function coinReport(b) {
|
|
38
|
+
const lines = [];
|
|
39
|
+
lines.push(`${b.symbol ? '$' + b.symbol : 'Unknown coin'}${b.name ? ' (' + b.name + ')' : ''}`);
|
|
40
|
+
lines.push(`Address: ${b.mint}`);
|
|
41
|
+
if (b.live) {
|
|
42
|
+
lines.push(`GORZ grade right now: ${String(b.grade || 'n/a').toUpperCase()}${b.score != null ? ` (score ${b.score}/100)` : ''}${b.limitedData ? ' (limited data so far)' : ''}`);
|
|
43
|
+
if (b.hardStops?.length) lines.push(`Hard stops (GORZ Safe Mode would hide this coin): ${b.hardStops.join('; ')}`);
|
|
44
|
+
if (b.aiWarning) lines.push('GORZ AI warning: the trading pattern matches coins that went on to dump.');
|
|
45
|
+
if (b.flags?.length) { lines.push('Red flags:'); for (const f of b.flags) lines.push(` - [${f.status}] ${f.label}: ${f.detail}`); }
|
|
46
|
+
else lines.push('Red flags: none right now.');
|
|
47
|
+
const m = b.market, w = b.wallets;
|
|
48
|
+
if (m) lines.push(`Market: price ${usd(m.priceUsd)}, market cap ${usd(m.marketCapUsd)}, liquidity ${usd(m.liquidityUsd)}, 5 min change ${pct(m.change5mPct)}, buyers in last 5 min ${m.buyers5m ?? 'n/a'}${m.graduated ? ', graduated' : ''}`);
|
|
49
|
+
if (w) {
|
|
50
|
+
lines.push(`Holders: top 10 hold ${pct(w.top10Pct)}, snipers ${w.snipers ?? 'n/a'}, bundled ${pct(w.bundledPct)}${w.devExited ? ', creator has sold out' : ''}`);
|
|
51
|
+
const lb = w.launchBundle || {};
|
|
52
|
+
if (lb.wallets) lines.push(`Launch bundle: ${lb.wallets} wallets took ${pct(lb.supplyPct)} at launch and have sold ${pct(lb.soldPct)}${lb.repeatBundlers ? ` (${lb.repeatBundlers} seen bundling before)` : ''}`);
|
|
53
|
+
if (w.soldTogetherMax || w.boughtTogetherMax) lines.push(`Same-second trading (most seen): ${w.soldTogetherMax ?? 0} wallets sold together, ${w.boughtTogetherMax ?? 0} bought together`);
|
|
54
|
+
}
|
|
55
|
+
} else lines.push('Not trading on the GORZ radar right now (GORZ has seen it before).');
|
|
56
|
+
if (b.farm) lines.push(`Rug-farm link: wallet group ${b.farm.code} has launched ${b.farm.coins} coins, ${b.farm.diedWithinHour} died within an hour. Case file: ${b.farm.caseFile}`);
|
|
57
|
+
if (b.firstGrade) lines.push(`First GORZ grade: ${b.firstGrade.grade} at ${usd(b.firstGrade.marketCapUsd)} market cap; 1 hour later: ${b.firstGrade.after1h || 'still being checked'}.`);
|
|
58
|
+
lines.push(`Full page: ${b.page}`);
|
|
59
|
+
lines.push(`\n${b.disclaimer || 'Not financial advice.'}`);
|
|
60
|
+
return lines.join('\n');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const server = new McpServer({name: 'gorz', version: VERSION});
|
|
64
|
+
|
|
65
|
+
server.registerTool('gorz_check_coin', {
|
|
66
|
+
title: 'Check a Solana coin with GORZ',
|
|
67
|
+
description: 'Safety read for a Solana memecoin by its contract (mint) address: GORZ grade (safer / caution / risky / checking), every red flag with its reason, hard stops, launch bundles, wallets buying or selling in the same second, rug-farm links, an AI dump warning, and what happened in the hour after GORZ first graded it. Use before buying or recommending a coin. Facts from public on-chain data, not price predictions.',
|
|
68
|
+
inputSchema: {mint: z.string().describe('Solana token mint (contract) address, e.g. 2DtF5QVs1zPwpZVR7PGiCcnNsi36gJvMWxNbeDVCpump')},
|
|
69
|
+
annotations: {readOnlyHint: true, openWorldHint: true},
|
|
70
|
+
}, async ({mint}) => {
|
|
71
|
+
mint = String(mint || '').trim();
|
|
72
|
+
if (!ADDRESS.test(mint)) return fail('That is not a Solana address. If you only have a ticker or name, use gorz_search_coins first.');
|
|
73
|
+
const res = await call('/check', {mint});
|
|
74
|
+
if (res.status === 404 && res.body?.found === false) return text(`GORZ has not seen ${mint}. It may be too old, not on Solana, or not traded recently.`);
|
|
75
|
+
if (!res.ok) return fail((res.body?.error || `GORZ returned HTTP ${res.status}.`) + limitNote(res));
|
|
76
|
+
return text(coinReport(res.body) + (res.left != null ? `\n(GORZ calls left today: ${res.left})` : ''));
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
server.registerTool('gorz_search_coins', {
|
|
80
|
+
title: 'Find a Solana coin on GORZ by ticker or name',
|
|
81
|
+
description: 'Look up coins GORZ has graded by ticker, name or address (e.g. "$BONK", "fuzzy bear"). Returns up to 8 matches with their contract address, first GORZ grade and what happened an hour later. Use this to get the address, then gorz_check_coin for the full safety read. Tickers are not unique: many coins copy the same name.',
|
|
82
|
+
inputSchema: {query: z.string().describe('Ticker, name or address to look for')},
|
|
83
|
+
annotations: {readOnlyHint: true, openWorldHint: true},
|
|
84
|
+
}, async ({query}) => {
|
|
85
|
+
const q = String(query || '').trim();
|
|
86
|
+
if (q.replace(/[\s$]/g, '').length < 2) return fail('Give at least 2 characters to search for.');
|
|
87
|
+
const res = await call('/search', {q});
|
|
88
|
+
if (!res.ok) return fail((res.body?.error || `GORZ returned HTTP ${res.status}.`) + limitNote(res));
|
|
89
|
+
const rows = res.body?.results || [];
|
|
90
|
+
if (!rows.length) return text(`No coin matching "${q}" has been graded by GORZ.`);
|
|
91
|
+
return text(`${rows.length} match${rows.length > 1 ? 'es' : ''} for "${q}" (copycat names are common, check the address):\n` + rows.map((r, i) =>
|
|
92
|
+
`${i + 1}. $${r.symbol || '?'} (${r.name || 'no name'})\n address: ${r.mint}\n first GORZ grade: ${r.grade || 'n/a'} at ${usd(r.marketCapUsd)}; 1 hour later: ${r.after1h || 'unknown'}`).join('\n'));
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
server.registerTool('gorz_check_wallet', {
|
|
96
|
+
title: 'Check a Solana wallet with GORZ',
|
|
97
|
+
description: 'What GORZ has seen a Solana wallet do: membership in a rug-farm wallet group, launch bundles it took part in, how often it sniped, bundled or bought early, and its record as a coin creator. Needs a GORZ API key (GORZ_API_KEY).',
|
|
98
|
+
inputSchema: {address: z.string().describe('Solana wallet address')},
|
|
99
|
+
annotations: {readOnlyHint: true, openWorldHint: true},
|
|
100
|
+
}, async ({address}) => {
|
|
101
|
+
address = String(address || '').trim();
|
|
102
|
+
if (!ADDRESS.test(address)) return fail('That is not a Solana wallet address.');
|
|
103
|
+
if (!KEY) return fail('Wallet lookups need a GORZ API key. Set GORZ_API_KEY in this server\'s settings. Keys: https://gorz.app/developers');
|
|
104
|
+
const res = await call('/wallet', {address});
|
|
105
|
+
if (!res.ok) return fail((res.body?.error || `GORZ returned HTTP ${res.status}.`) + limitNote(res));
|
|
106
|
+
const b = res.body, s = b.seenAs || {}, out = [`Wallet ${b.wallet}`];
|
|
107
|
+
out.push(b.farmGroup ? `Rug-farm group ${b.farmGroup.code}: ${b.farmGroup.coins} coins launched, ${b.farmGroup.diedWithinHour} died within an hour.` : 'Not linked to a known rug-farm group.');
|
|
108
|
+
out.push(b.launchBundles ? `Took part in ${b.launchBundles.launches} launch bundles (last ${new Date(b.launchBundles.lastAt).toISOString().slice(0, 10)}).` : 'No launch bundles seen.');
|
|
109
|
+
out.push(`Seen as: sniper ${s.sniper ?? 0}x, bundler ${s.bundler ?? 0}x, early buyer ${s.earlyBuyer ?? 0}x.`);
|
|
110
|
+
if (b.creator?.summary) out.push('As a coin creator: ' + (typeof b.creator.summary === 'string' ? b.creator.summary : JSON.stringify(b.creator.summary)));
|
|
111
|
+
out.push(`\n${b.disclaimer || 'Not financial advice.'}`);
|
|
112
|
+
return text(out.join('\n'));
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
await server.connect(new StdioServerTransport());
|
package/package.json
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gorz-mcp",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
}
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "GORZ MCP server: Solana memecoin safety checks for AI assistants and trading agents (grade, red flags, launch bundles, same-second sellers, rug-farm links).",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {"gorz-mcp": "index.mjs"},
|
|
7
|
+
"main": "index.mjs",
|
|
8
|
+
"files": ["index.mjs", "README.md", "LICENSE"],
|
|
9
|
+
"engines": {"node": ">=18"},
|
|
10
|
+
"keywords": ["mcp", "model-context-protocol", "solana", "memecoin", "rug-check", "crypto", "safety", "ai-agent", "gorz"],
|
|
11
|
+
"homepage": "https://gorz.app/developers",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"mcpName": "io.github.GORZ-APP/gorz",
|
|
14
|
+
"repository": {"type": "git", "url": "https://github.com/GORZ-APP/gorz-mcp"},
|
|
15
|
+
"dependencies": {"@modelcontextprotocol/sdk": "1.32.2", "zod": "4.6.7"}
|
|
16
|
+
}
|