#
tokens: 1874/50000 9/9 files
lines: on (toggle) GitHub
raw markdown copy reset
# Directory Structure

```
├── .gitignore
├── .python-version
├── cryptopanic_mcp_server.egg-info
│   ├── dependency_links.txt
│   ├── PKG-INFO
│   ├── requires.txt
│   ├── SOURCES.txt
│   └── top_level.txt
├── LICENSE
├── main.py
├── pyproject.toml
├── README.md
└── uv.lock
```

# Files

--------------------------------------------------------------------------------
/.python-version:
--------------------------------------------------------------------------------

```
1 | 3.13
2 | 
```

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
1 | .env
2 | .venv
3 | __pycache__
4 | *.egg-info/
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
 1 | # cryptopanic-mcp-server
 2 | 
 3 | [![Discord](https://img.shields.io/discord/1353556181251133481?cacheSeconds=3600)](https://discord.gg/aRnuu2eJ)
 4 | ![GitHub License](https://img.shields.io/github/license/kukapay/blockbeats-mcp)
 5 | 
 6 | Provide the latest cryptocurrency news to AI agents, powered by [CryptoPanic](https://cryptopanic.com/).
 7 | 
 8 | <a href="https://glama.ai/mcp/servers/dp6kztv7yx">
 9 |   <img width="380" height="200" src="https://glama.ai/mcp/servers/dp6kztv7yx/badge" alt="cryptopanic-mcp-server MCP server" />
10 | </a>
11 | 
12 | ## Tools
13 | 
14 | The server implements only one tool: 
15 | 
16 | ```python
17 | get_crypto_news(kind: str = "news", num_pages: int = 1) -> str
18 | ```
19 | - `kind`: Content type (news, media)
20 | - `num_pages`: Number of pages to fetch (default: 1, max: 10)
21 | 
22 | Example Output: 
23 | 
24 | ```
25 | - Bitcoin Breaks $60k Resistance Amid ETF Optimism
26 | - Ethereum Layer 2 Solutions Gain Traction
27 | - New Crypto Regulations Proposed in EU
28 | - ...
29 | ```
30 | 
31 | 
32 | ## Configuration
33 | 
34 | - CryptoPanic API key & API plan: get one [here](https://cryptopanic.com/developers/api/)
35 | - Add a server entry to your configuration file:
36 | 
37 | ```
38 | "mcpServers": { 
39 |   "cryptopanic-mcp-server": { 
40 |     "command": "uv", 
41 |     "args": [ 
42 |       "--directory", 
43 |       "/your/path/to/cryptopanic-mcp-server", 
44 |       "run", 
45 |       "main.py" 
46 |     ], 
47 |     "env": { 
48 |       "CRYPTOPANIC_API_PLAN": "your_api_plan",
49 |       "CRYPTOPANIC_API_KEY": "your_api_key" 
50 |     } 
51 |   } 
52 | }
53 | ```
54 | 
55 | - Replace `/your/path/to/cryptopanic-mcp-server` with your actual installation path.
56 | - Replace `CRYPTOPANIC_API_PLAN` and `CRYPTOPANIC_API_KEY` with your API plan and key from CryptoPanic. 
57 | 
58 | ## License
59 | 
60 | MIT License - see `LICENSE` file
```

--------------------------------------------------------------------------------
/cryptopanic_mcp_server.egg-info/dependency_links.txt:
--------------------------------------------------------------------------------

```
1 | 
2 | 
```

--------------------------------------------------------------------------------
/cryptopanic_mcp_server.egg-info/top_level.txt:
--------------------------------------------------------------------------------

```
1 | main
2 | 
```

--------------------------------------------------------------------------------
/cryptopanic_mcp_server.egg-info/requires.txt:
--------------------------------------------------------------------------------

```
1 | dotenv>=0.9.9
2 | mcp[cli]>=1.3.0
3 | requests>=2.32.3
4 | 
```

--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------

```toml
 1 | [project]
 2 | name = "cryptopanic-mcp-server"
 3 | version = "0.1.0"
 4 | description = "Provide the latest cryptocurrency news for AI agents."
 5 | readme = "README.md"
 6 | requires-python = ">=3.13"
 7 | dependencies = [
 8 |     "dotenv>=0.9.9",
 9 |     "mcp[cli]>=1.3.0",
10 |     "requests>=2.32.3",
11 | ]
12 | 
```

--------------------------------------------------------------------------------
/cryptopanic_mcp_server.egg-info/SOURCES.txt:
--------------------------------------------------------------------------------

```
1 | LICENSE
2 | README.md
3 | main.py
4 | pyproject.toml
5 | cryptopanic_mcp_server.egg-info/PKG-INFO
6 | cryptopanic_mcp_server.egg-info/SOURCES.txt
7 | cryptopanic_mcp_server.egg-info/dependency_links.txt
8 | cryptopanic_mcp_server.egg-info/requires.txt
9 | cryptopanic_mcp_server.egg-info/top_level.txt
```

--------------------------------------------------------------------------------
/main.py:
--------------------------------------------------------------------------------

```python
 1 | import requests
 2 | from mcp.server.fastmcp import FastMCP
 3 | import os
 4 | from dotenv import load_dotenv
 5 | 
 6 | load_dotenv()
 7 | API_KEY = os.getenv("CRYPTOPANIC_API_KEY")
 8 | API_PLAN = os.getenv("CRYPTOPANIC_API_PLAN", "developer")
 9 | 
10 | # Validate API_KEY
11 | if not API_KEY:
12 |     raise ValueError("CRYPTOPANIC_API_KEY environment variable is not set")
13 | 
14 | mcp = FastMCP("crypto news")
15 |         
16 | @mcp.tool()
17 | def get_crypto_news(kind: str = "news", num_pages: int = 1) -> str:
18 |     """
19 |     Fetch the latest cryptocurrency news from CryptoPanic.
20 | 
21 |     Args:
22 |         kind (str, optional): Type of content to fetch. Valid options are:
23 |             - 'news': Fetch news articles (default).
24 |             - 'media': Fetch media content like videos.
25 |         num_pages (int, optional): Number of pages to fetch (each page contains multiple news items).
26 |             Defaults to 1. Maximum is 10 to avoid API rate limits.
27 | 
28 |     Returns:
29 |         str: A concatenated string of news titles, each prefixed with a dash (-).
30 | 
31 |     Raises:
32 |         ValueError: If the API key is not set or if the API request fails.
33 |     """
34 |     news = fetch_crypto_news(kind, num_pages)
35 |     readable = concatenate_news(news)
36 |     return readable
37 | 
38 | def fetch_crypto_news_page(kind: str = "news", page: int = 1) -> list:
39 |     try:
40 |         url = f"https://cryptopanic.com/api/{API_PLAN}/v2/posts/"
41 |         params = {
42 |             "auth_token": API_KEY,
43 |             "kind": kind,
44 |             "regions": "en",
45 |             "page": page
46 |         }
47 |         response = requests.get(url, params=params)
48 |         return response.json().get("results", [])
49 |     except Exception:
50 |         return []
51 |         
52 | def fetch_crypto_news(kind: str = "news", num_pages: int = 10) -> list:
53 |     all_news = []
54 |     for page in range(1, num_pages + 1):
55 |         news_items = fetch_crypto_news_page(kind, page)
56 |         if not news_items:
57 |             break
58 |         all_news.extend(news_items)
59 |     return all_news        
60 | 
61 | def concatenate_news(news_items: list) -> str:
62 |     concatenated_text = ""
63 |     for idx, news in enumerate(news_items):  
64 |         title = news.get("title", "No Title")
65 |         concatenated_text += f"- {title}\n"
66 |     return concatenated_text.strip()
67 | 
68 | if __name__ == "__main__":
69 |     mcp.run(transport="stdio")
70 | 
```