@mrfentmen/dexscreener-mcp 1.0.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/README.md ADDED
@@ -0,0 +1,21 @@
1
+ # DexScreener MCP
2
+
3
+ DEX pair data from the public DexScreener API. No key required.
4
+
5
+ This file is self contained. It reads public data only and never writes to the machine. All output is bounded and honest about what could not be fetched.
6
+
7
+ ## Tools
8
+
9
+
10
+ * `search` Search token pairs.
11
+ * `tokens` Top pairs for a token.
12
+
13
+ ## Usage
14
+
15
+ ```bash
16
+ npm install
17
+ npm run build
18
+ node dist/index.js
19
+ ```
20
+
21
+ Data comes from the public DexScreener API.
package/dist/api.js ADDED
@@ -0,0 +1,46 @@
1
+ const BASE = 'https://api.dexscreener.com/latest/dex';
2
+ const UA = 'mrfentmen-dexscreener-mcp/1.0';
3
+ export async function search(args) {
4
+ const query = (args.query ?? '').trim();
5
+ if (!query)
6
+ return 'Provide a token symbol or name.';
7
+ const res = await fetch(`${BASE}/search?q=${encodeURIComponent(query)}`, {
8
+ headers: { 'User-Agent': UA, Accept: 'application/json' },
9
+ signal: AbortSignal.timeout(20000),
10
+ });
11
+ if (!res.ok)
12
+ throw new Error(`DexScreener returned ${res.status}`);
13
+ const d = (await res.json());
14
+ const pairs = d.pairs ?? [];
15
+ if (!pairs.length)
16
+ return `No pairs for "${query}".`;
17
+ return `DexScreener results for "${query}" (${pairs.length}):\n` +
18
+ pairs.slice(0, 10).map((p, i) => {
19
+ const bt = p.baseToken ?? {};
20
+ const qt = p.quoteToken ?? {};
21
+ const chg = p.priceChange?.h24 != null ? `${p.priceChange.h24 >= 0 ? '+' : ''}${p.priceChange.h24.toFixed(2)}%` : '?';
22
+ return `${i + 1}. ${bt.symbol ?? '?'}/${qt.symbol ?? '?'} on ${p.dexId ?? '?'} (${p.chainId ?? '?'}) $${p.priceUsd ?? '?'} ${chg} 24h vol $${p.volume?.h24 != null ? p.volume.h24.toFixed(0) : '?'}`;
23
+ }).join('\n');
24
+ }
25
+ export async function tokens(args) {
26
+ const address = (args.address ?? '').trim();
27
+ if (!address)
28
+ return 'Provide a token address.';
29
+ const res = await fetch(`${BASE}/tokens/${encodeURIComponent(address)}`, {
30
+ headers: { 'User-Agent': UA, Accept: 'application/json' },
31
+ signal: AbortSignal.timeout(20000),
32
+ });
33
+ if (!res.ok)
34
+ throw new Error(`DexScreener returned ${res.status}`);
35
+ const d = (await res.json());
36
+ const pairs = d.pairs ?? [];
37
+ if (!pairs.length)
38
+ return `No pairs for ${address.slice(0, 12)}...`;
39
+ const best = pairs.slice().sort((a, b) => (b.volume?.h24 ?? 0) - (a.volume?.h24 ?? 0));
40
+ const rows = best.slice(0, 8).map((p, i) => {
41
+ const bt = p.baseToken ?? {};
42
+ const chg = p.priceChange?.h24 != null ? `${p.priceChange.h24 >= 0 ? '+' : ''}${p.priceChange.h24.toFixed(2)}%` : '?';
43
+ return `${i + 1}. ${bt.symbol ?? '?'} $${p.priceUsd ?? '?'} ${chg} on ${p.dexId ?? '?'} (${p.chainId ?? '?'}) vol $${p.volume?.h24 != null ? p.volume.h24.toFixed(0) : '?'}`;
44
+ });
45
+ return `Top DexScreener pairs for ${address.slice(0, 12)}...:\n${rows.join('\n')}`;
46
+ }
package/dist/index.js ADDED
@@ -0,0 +1,4 @@
1
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
2
+ import { createServer } from "./server.js";
3
+ const main = async () => { const server = createServer(); await server.connect(new StdioServerTransport()); };
4
+ main().catch((error) => { console.error("Fatal error:", error); process.exit(1); });
package/dist/server.js ADDED
@@ -0,0 +1,38 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { z } from "zod";
3
+ import { search } from "./api.js";
4
+ import { tokens } from "./api.js";
5
+ const text = (value) => ({ content: [{ type: "text", text: value }] });
6
+ const textError = (t) => ({ content: [{ type: "text", text: t }], isError: true });
7
+ const READ_ONLY = { readOnlyHint: true, openWorldHint: true };
8
+ const error = (e) => `Error: ${e instanceof Error ? e.message : String(e)}`;
9
+ export function createServer() {
10
+ const server = new McpServer({ name: "dexscreener-mcp", version: "1.0.0" });
11
+ server.registerTool("search", {
12
+ title: "Search",
13
+ description: "Search token pairs.",
14
+ inputSchema: z.object({ query: z.string().describe("Token symbol or name.") }),
15
+ annotations: READ_ONLY,
16
+ }, async (args) => {
17
+ try {
18
+ return text(await search(args));
19
+ }
20
+ catch (e) {
21
+ return textError(error(e));
22
+ }
23
+ });
24
+ server.registerTool("tokens", {
25
+ title: "Tokens",
26
+ description: "Top pairs for a token.",
27
+ inputSchema: z.object({ address: z.string().describe("Token address.") }),
28
+ annotations: READ_ONLY,
29
+ }, async (args) => {
30
+ try {
31
+ return text(await tokens(args));
32
+ }
33
+ catch (e) {
34
+ return textError(error(e));
35
+ }
36
+ });
37
+ return server;
38
+ }
package/package.json ADDED
@@ -0,0 +1,44 @@
1
+ {
2
+ "version": "1.0.0",
3
+ "type": "module",
4
+ "repository": {
5
+ "type": "git",
6
+ "url": "https://github.com/mrfentmen/dexscreener-mcp.git"
7
+ },
8
+ "bin": {
9
+ "dexscreener-mcp": "./dist/index.js"
10
+ },
11
+ "main": "./dist/index.js",
12
+ "files": [
13
+ "dist",
14
+ "server.json",
15
+ "README.md"
16
+ ],
17
+ "scripts": {
18
+ "build": "tsc -p tsconfig.json",
19
+ "start": "node dist/index.js",
20
+ "dev": "npm run build && node dist/index.js"
21
+ },
22
+ "license": "MIT",
23
+ "dependencies": {
24
+ "@modelcontextprotocol/sdk": "^1.0.4",
25
+ "zod": "^3.23.8"
26
+ },
27
+ "devDependencies": {
28
+ "@types/node": "^22.0.0",
29
+ "typescript": "^5.6.0"
30
+ },
31
+ "name": "@mrfentmen/dexscreener-mcp",
32
+ "description": "DEX pair data from DexScreener. No key required.",
33
+ "mcpName": "io.github.mrfentmen/dexscreener-mcp",
34
+ "keywords": [
35
+ "mcp",
36
+ "dexscreener",
37
+ "dex",
38
+ "crypto",
39
+ "defi"
40
+ ],
41
+ "engines": {
42
+ "node": ">=20"
43
+ }
44
+ }
package/server.json ADDED
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.mrfentmen/dexscreener-mcp",
4
+ "description": "DEX pair data from DexScreener. No key required.",
5
+ "repository": {
6
+ "url": "https://github.com/mrfentmen/dexscreener-mcp",
7
+ "source": "github"
8
+ },
9
+ "version": "1.0.0",
10
+ "packages": [
11
+ {
12
+ "registryType": "npm",
13
+ "identifier": "@mrfentmen/dexscreener-mcp",
14
+ "version": "1.0.0",
15
+ "transport": {
16
+ "type": "stdio"
17
+ }
18
+ }
19
+ ]
20
+ }