Skip to content

Commit 523e52b

Browse files
committed
initial commit
1 parent 6e3aac4 commit 523e52b

File tree

5 files changed

+135
-0
lines changed

5 files changed

+135
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.venv
2+
.DS_Store
3+
**.egg-info**

.vscode/mcp.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"servers": {
3+
"pipy-info": {
4+
"url": "http://0.0.0.0:8000/sse"
5+
}
6+
}
7+
}

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# PyPI Info Demo
2+
3+
This project is a simple Model Context Protocol (MCP) server that provides information about Python packages on PyPI. It exposes a tool to fetch package maintainers, version, changelog, summary, and full project description using the PyPI JSON API.
4+
5+
## Features
6+
- Query PyPI for package metadata
7+
- Returns maintainers, version, changelog URL, summary, and full project description
8+
- Attempts to find changelog links from project homepages if not directly available
9+
10+
## Usage
11+
12+
1. **Install dependencies:**
13+
using the python environments extension run the command "create environment"
14+
or install via `pip install -e .`
15+
16+
2. **Run the server:**
17+
```sh
18+
python server.py
19+
```
20+
21+
3. **Call the tool:**
22+
You can call the `get_pypi_package_info` tool via the MCP protocol, or directly in Python:
23+
```python
24+
from server import get_pypi_package_info
25+
print(get_pypi_package_info("requests"))
26+
```
27+
28+
## File Overview
29+
- `server.py`: Main MCP server and PyPI info tool implementation
30+
- `pyproject.toml`: Project metadata and dependencies
31+
32+
## Requirements
33+
- Python 3.7+
34+
- `mcp`, `requests`, `beautifulsoup4`
35+
36+
## License
37+
MIT

pyproject.toml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[project]
2+
name = "mcp-demo-pypi"
3+
version = "0.1.0"
4+
description = "A MCP server to get info from pypi."
5+
requires-python = ">=3.10"
6+
license = "MIT"
7+
readme = "README.md"
8+
dependencies = [
9+
"mcp[cli]>=1.6",
10+
"fastapi>=0.115",
11+
"requests>=2.32",
12+
"beautifulsoup4>=4.13"
13+
]
14+
15+
[build-system]
16+
requires = ["setuptools>=61.0", "wheel"]
17+
build-backend = "setuptools.build_meta"

server.py

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
from mcp.server.fastmcp import FastMCP
2+
import requests
3+
from bs4 import BeautifulSoup
4+
5+
6+
# Create an MCP server
7+
mcp = FastMCP("PyPI Info Demo")
8+
9+
10+
# MCP tool for PyPI package info
11+
@mcp.tool()
12+
def get_pypi_package_info(package_name: str) -> dict:
13+
"""
14+
Fetches package info from PyPI for the given package name.
15+
Returns a dictionary with maintainers, version, changelog, and description.
16+
"""
17+
url = f"https://pypi.org/pypi/{package_name}/json"
18+
resp = requests.get(url)
19+
if resp.status_code != 200:
20+
raise ValueError(f"Package '{package_name}' not found on PyPI.")
21+
data = resp.json()
22+
info = data.get("info", {})
23+
# Maintainers: PyPI does not always provide maintainers, fallback to author/maintainer fields
24+
maintainers = info.get("maintainer")
25+
if not maintainers:
26+
maintainers = info.get("author")
27+
version = info.get("version")
28+
description = info.get("summary") or info.get("description")
29+
project_description = info.get("description")
30+
# Try to get changelog from project_urls or homepage
31+
changelog = None
32+
project_urls = info.get("project_urls", {})
33+
for key in project_urls:
34+
if "changelog" in key.lower() or "changes" in key.lower():
35+
changelog = project_urls[key]
36+
break
37+
if not changelog:
38+
# Try to find a changelog in the homepage or repository
39+
for key in project_urls:
40+
if "home" in key.lower() or "repo" in key.lower():
41+
homepage_url = project_urls[key]
42+
try:
43+
page = requests.get(homepage_url, timeout=5)
44+
if page.ok:
45+
soup = BeautifulSoup(page.text, "html.parser")
46+
for a in soup.find_all("a", href=True):
47+
if (
48+
"changelog" in a.text.lower()
49+
or "changes" in a.text.lower()
50+
):
51+
changelog = a["href"]
52+
break
53+
if changelog:
54+
break
55+
except Exception:
56+
pass
57+
return {
58+
"maintainers": maintainers,
59+
"version": version,
60+
"changelog": changelog,
61+
"description": description,
62+
"project_description": project_description,
63+
}
64+
65+
66+
if __name__ == "__main__":
67+
# Start the MCP server
68+
mcp.run(transport="sse")
69+
70+
# Example usage to call the function directly
71+
print(get_pypi_package_info("requests"))

0 commit comments

Comments
 (0)