Skip to content

Commit 8f333ff

Browse files
truss44claude
andauthored
fix: resolve HTTP 404 and COINCAP_API_KEY not applied when connecting via query params (#140)
* fix: resolve 404 and missing API key when connecting via query params Route matching used req.url (which includes the query string), so /mcp?coincapApiKey=xxx never matched the literal '/mcp' check, causing a 404. Also, handleMcp always read COINCAP_API_KEY from the environment instead of the query parameter Smithery passes per-session. Fix: parse req.url with new URL() and route on pathname; extract coincapApiKey from URLSearchParams and fall back to env var. Closes #138 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix: rename config key to COINCAP_API_KEY to match query param convention Aligns the configSchema property name, Smithery YAML, and HTTP query parameter parsing to use COINCAP_API_KEY instead of coincapApiKey, matching the environment variable name and the expected connection URL format: /mcp?COINCAP_API_KEY={key} Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * docs: update README and CLAUDE.md for correct build paths and HTTP query param - Fix build output path (.smithery/ → dist/) in both files - Remove nonexistent build:stdio script reference - Document COINCAP_API_KEY query parameter for HTTP connections - Add get-top-assets tool to both docs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 4ef593d commit 8f333ff

File tree

5 files changed

+40
-20
lines changed

5 files changed

+40
-20
lines changed

CLAUDE.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,11 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
99
npm run dev
1010

1111
# Build
12-
npm run build # HTTP bundle → .smithery/index.cjs
13-
npm run build:stdio # STDIO bundle → dist/
12+
npm run build # Compile TypeScript → dist/
1413

1514
# Run
16-
npm run start:http # Start HTTP server
17-
npm run start:stdio # Start STDIO server
15+
npm run start:http # Start HTTP server (dist/http.js)
16+
npm run start:stdio # Start STDIO server (dist/index.js)
1817

1918
# Test
2019
npm test # Run all tests
@@ -36,7 +35,7 @@ NODE_OPTIONS='--experimental-vm-modules --no-warnings' npx jest src/services/__t
3635

3736
This is an MCP (Model Context Protocol) server for cryptocurrency data. It supports two transports:
3837
- **STDIO**: built to `dist/` via `tsc`, entry point `dist/index.js`
39-
- **Streamable HTTP**: built to `.smithery/index.cjs` via Smithery CLI
38+
- **Streamable HTTP**: built to `dist/` via `tsc`, entry point `dist/http.js`. API key is passed as a query parameter: `/mcp?COINCAP_API_KEY={key}`
4039

4140
### Request flow
4241

@@ -55,13 +54,14 @@ MCP client → transport (stdio or HTTP) → src/index.ts (createServer)
5554
- **`src/services/formatters.ts`** — pure formatting functions for tool output text.
5655
- **`src/types/index.ts`** — shared TypeScript interfaces for CoinCap API responses.
5756

58-
### Three registered MCP tools
57+
### Four registered MCP tools
5958

6059
| Tool | Handler | API endpoint |
6160
|------|---------|--------------|
6261
| `get-crypto-price` | `handleGetPrice` | `/assets` |
6362
| `get-market-analysis` | `handleGetMarketAnalysis` | `/assets/{id}/markets` |
6463
| `get-historical-analysis` | `handleGetHistoricalAnalysis` | `/assets/{id}/history` |
64+
| `get-top-assets` | `handleGetTopAssets` | `/assets` |
6565

6666
### Releases & commits
6767

README.md

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ npm run dev
6464
- Build and run the HTTP server:
6565

6666
```bash
67-
# Build the HTTP bundle (outputs to .smithery/)
67+
# Build (outputs to dist/)
6868
npm run build
6969

7070
# Start the HTTP server
@@ -74,21 +74,33 @@ npm run start:http
7474
- Build and run the STDIO server:
7575

7676
```bash
77-
# Build the STDIO bundle (outputs to dist/)
78-
npm run build:stdio
77+
# Build (outputs to dist/)
78+
npm run build
7979

8080
# Start the STDIO server
8181
npm run start:stdio
8282
```
8383

84-
The dev/build commands will print the server address to the console. Use that URL in clients that support MCP over HTTP (for example, Smithery). You must provide an API key via `COINCAP_API_KEY` (see below).
84+
The server listens on port 3000 by default (override with `PORT`). For clients that connect over HTTP (e.g. Smithery, Claude.ai), pass your API key as a query parameter:
85+
86+
```
87+
http://localhost:3000/mcp?COINCAP_API_KEY=YOUR_API_KEY_HERE
88+
```
89+
90+
For remote deployments:
91+
92+
```
93+
https://your-server-host/mcp?COINCAP_API_KEY=YOUR_API_KEY_HERE
94+
```
8595

8696
## Required: CoinCap API Key
8797

8898
This server uses the CoinCap v3 API, which requires an API key. A **free tier** is available.
8999

90100
1. Sign up and get your API key at [pro.coincap.io/dashboard](https://pro.coincap.io/dashboard)
91-
2. Add the key to your MCP client configuration via the `COINCAP_API_KEY` environment variable (see Usage examples above)
101+
2. Add the key to your MCP client configuration:
102+
- **STDIO**: via the `COINCAP_API_KEY` environment variable (see Usage examples above)
103+
- **HTTP**: via the `COINCAP_API_KEY` query parameter in the connection URL (e.g. `/mcp?COINCAP_API_KEY=your_key`)
92104

93105
Without a valid API key, all tools will return an error with instructions on how to obtain one.
94106

@@ -161,6 +173,14 @@ Analyzes historical price data with:
161173
- Volatility metrics
162174
- High/low price ranges
163175

176+
#### get-top-assets
177+
178+
Lists top cryptocurrencies ranked by market cap, including:
179+
- Current price in USD
180+
- 24-hour price change
181+
- Market cap and rank
182+
- Configurable result count (1–50, default 10)
183+
164184
## Sample Prompts
165185

166186
- "What's the current price of Bitcoin?"

smithery.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ startCommand:
1111
configSchema:
1212
type: object
1313
properties:
14-
coincapApiKey:
14+
COINCAP_API_KEY:
1515
type: string
1616
description: "API key for CoinCap v3 API (required). Free tier available at https://pro.coincap.io/dashboard"
1717
required:
18-
- coincapApiKey
18+
- COINCAP_API_KEY

src/http.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@ import { SERVER_CONFIG } from './config/index.js';
88
const PORT = parseInt(process.env.PORT ?? '3000', 10);
99

1010
async function handleMcp(req: http.IncomingMessage, res: http.ServerResponse, searchParams: URLSearchParams) {
11-
const coincapApiKey = searchParams.get('coincapApiKey') ?? process.env.COINCAP_API_KEY;
11+
const coincapApiKey = searchParams.get('COINCAP_API_KEY') ?? process.env.COINCAP_API_KEY;
1212
const transport = new StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
13-
const server = createServer({ config: { coincapApiKey } });
13+
const server = createServer({ config: { COINCAP_API_KEY: coincapApiKey } });
1414
await server.connect(transport);
1515

1616
if (req.method === 'POST') {

src/index.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import {
2020
} from './tools/index.js';
2121

2222
export const configSchema = z.object({
23-
coincapApiKey: z
23+
COINCAP_API_KEY: z
2424
.string()
2525
.optional()
2626
.describe("API key for CoinCap v3 API (required). Free tier available at https://pro.coincap.io/dashboard"),
@@ -31,8 +31,8 @@ export function createServer({
3131
}: {
3232
config: z.infer<typeof configSchema>;
3333
}) {
34-
if (config?.coincapApiKey && !process.env.COINCAP_API_KEY) {
35-
process.env.COINCAP_API_KEY = config.coincapApiKey;
34+
if (config?.COINCAP_API_KEY && !process.env.COINCAP_API_KEY) {
35+
process.env.COINCAP_API_KEY = config.COINCAP_API_KEY;
3636
}
3737

3838
const server = new McpServer({
@@ -165,13 +165,13 @@ export default createServer;
165165

166166
export function createSandboxServer() {
167167
return createServer({
168-
config: { coincapApiKey: undefined },
168+
config: { COINCAP_API_KEY: undefined },
169169
});
170170
}
171171

172172
async function main() {
173173
const server = createServer({
174-
config: { coincapApiKey: process.env.COINCAP_API_KEY },
174+
config: { COINCAP_API_KEY: process.env.COINCAP_API_KEY },
175175
});
176176
const transport = new StdioServerTransport();
177177
await server.connect(transport);

0 commit comments

Comments
 (0)