mcp-advisor 0.1.0__tar.gz

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.
@@ -0,0 +1,9 @@
1
+ __pycache__/
2
+ *.py[cod]
3
+ *.egg-info/
4
+ dist/
5
+ build/
6
+ .venv/
7
+ venv/
8
+ .env
9
+ .DS_Store
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Luca Stucchi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,94 @@
1
+ Metadata-Version: 2.4
2
+ Name: mcp-advisor
3
+ Version: 0.1.0
4
+ Summary: MCP server to browse, search, and discover MCP servers from the MCP Advisor registry
5
+ Project-URL: Homepage, https://mcpadvisor.stucchi.consulting
6
+ Project-URL: Repository, https://github.com/stucchi/mcp-advisor
7
+ Project-URL: Issues, https://github.com/stucchi/mcp-advisor/issues
8
+ Author-email: Luca Stucchi <luca.stucchi@gmail.com>
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: advisor,mcp,model-context-protocol,registry
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Requires-Python: >=3.11
20
+ Requires-Dist: httpx>=0.27.0
21
+ Requires-Dist: mcp>=1.0.0
22
+ Description-Content-Type: text/markdown
23
+
24
+ # MCP Advisor
25
+
26
+ <!-- mcp-name: io.github.stucchi/mcp-advisor -->
27
+
28
+ <p align="center">
29
+ <img src="assets/icon.png" alt="MCP Advisor" width="200">
30
+ </p>
31
+
32
+ An MCP server that lets your AI assistant browse, search, and discover MCP servers from the [MCP Advisor](https://mcpadvisor.stucchi.consulting) registry.
33
+
34
+ ## Installation
35
+
36
+ ```bash
37
+ pip install mcp-advisor
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ ### With Claude Desktop
43
+
44
+ Add to your `claude_desktop_config.json`:
45
+
46
+ ```json
47
+ {
48
+ "mcpServers": {
49
+ "mcp-advisor": {
50
+ "command": "mcp-advisor"
51
+ }
52
+ }
53
+ }
54
+ ```
55
+
56
+ ### With Cursor
57
+
58
+ Add to `.cursor/mcp.json`:
59
+
60
+ ```json
61
+ {
62
+ "mcpServers": {
63
+ "mcp-advisor": {
64
+ "command": "mcp-advisor"
65
+ }
66
+ }
67
+ }
68
+ ```
69
+
70
+ ### Standalone
71
+
72
+ ```bash
73
+ mcp-advisor # stdio transport (default)
74
+ mcp-advisor --transport sse # SSE transport
75
+ mcp-advisor --api-token YOUR_TOKEN # authenticated (for starring)
76
+ ```
77
+
78
+ ## Tools
79
+
80
+ | Tool | Description |
81
+ |------|-------------|
82
+ | `search_servers` | Search MCP servers with filters (query, transport, registry type, tag, sort) |
83
+ | `get_server_details` | Get full details about a specific server |
84
+ | `get_install_instructions` | Get install config for Claude Desktop, Cursor, or generic |
85
+ | `star_server` | Star a server (requires auth token) |
86
+ | `unstar_server` | Remove a star (requires auth token) |
87
+ | `list_starred_servers` | List your starred servers (requires auth token) |
88
+ | `get_trending_servers` | Get trending servers by star count |
89
+ | `get_registry_stats` | Get registry statistics |
90
+ | `browse_tags` | List all tags with server counts |
91
+
92
+ ## License
93
+
94
+ MIT - Luca Stucchi
@@ -0,0 +1,71 @@
1
+ # MCP Advisor
2
+
3
+ <!-- mcp-name: io.github.stucchi/mcp-advisor -->
4
+
5
+ <p align="center">
6
+ <img src="assets/icon.png" alt="MCP Advisor" width="200">
7
+ </p>
8
+
9
+ An MCP server that lets your AI assistant browse, search, and discover MCP servers from the [MCP Advisor](https://mcpadvisor.stucchi.consulting) registry.
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ pip install mcp-advisor
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ### With Claude Desktop
20
+
21
+ Add to your `claude_desktop_config.json`:
22
+
23
+ ```json
24
+ {
25
+ "mcpServers": {
26
+ "mcp-advisor": {
27
+ "command": "mcp-advisor"
28
+ }
29
+ }
30
+ }
31
+ ```
32
+
33
+ ### With Cursor
34
+
35
+ Add to `.cursor/mcp.json`:
36
+
37
+ ```json
38
+ {
39
+ "mcpServers": {
40
+ "mcp-advisor": {
41
+ "command": "mcp-advisor"
42
+ }
43
+ }
44
+ }
45
+ ```
46
+
47
+ ### Standalone
48
+
49
+ ```bash
50
+ mcp-advisor # stdio transport (default)
51
+ mcp-advisor --transport sse # SSE transport
52
+ mcp-advisor --api-token YOUR_TOKEN # authenticated (for starring)
53
+ ```
54
+
55
+ ## Tools
56
+
57
+ | Tool | Description |
58
+ |------|-------------|
59
+ | `search_servers` | Search MCP servers with filters (query, transport, registry type, tag, sort) |
60
+ | `get_server_details` | Get full details about a specific server |
61
+ | `get_install_instructions` | Get install config for Claude Desktop, Cursor, or generic |
62
+ | `star_server` | Star a server (requires auth token) |
63
+ | `unstar_server` | Remove a star (requires auth token) |
64
+ | `list_starred_servers` | List your starred servers (requires auth token) |
65
+ | `get_trending_servers` | Get trending servers by star count |
66
+ | `get_registry_stats` | Get registry statistics |
67
+ | `browse_tags` | List all tags with server counts |
68
+
69
+ ## License
70
+
71
+ MIT - Luca Stucchi
Binary file
@@ -0,0 +1,43 @@
1
+ [project]
2
+ name = "mcp-advisor"
3
+ version = "0.1.0"
4
+ description = "MCP server to browse, search, and discover MCP servers from the MCP Advisor registry"
5
+ requires-python = ">=3.11"
6
+ license = "MIT"
7
+ readme = "README.md"
8
+ authors = [
9
+ {name = "Luca Stucchi", email = "luca.stucchi@gmail.com"},
10
+ ]
11
+ keywords = ["mcp", "model-context-protocol", "registry", "advisor"]
12
+ classifiers = [
13
+ "Development Status :: 4 - Beta",
14
+ "Intended Audience :: Developers",
15
+ "License :: OSI Approved :: MIT License",
16
+ "Programming Language :: Python :: 3",
17
+ "Programming Language :: Python :: 3.11",
18
+ "Programming Language :: Python :: 3.12",
19
+ "Programming Language :: Python :: 3.13",
20
+ ]
21
+ dependencies = [
22
+ "mcp>=1.0.0",
23
+ "httpx>=0.27.0",
24
+ ]
25
+
26
+ [project.urls]
27
+ Homepage = "https://mcpadvisor.stucchi.consulting"
28
+ Repository = "https://github.com/stucchi/mcp-advisor"
29
+ Issues = "https://github.com/stucchi/mcp-advisor/issues"
30
+
31
+ [project.scripts]
32
+ mcp-advisor = "mcp_advisor.server:main"
33
+
34
+ [build-system]
35
+ requires = ["hatchling"]
36
+ build-backend = "hatchling.build"
37
+
38
+ [tool.hatch.build.targets.wheel]
39
+ packages = ["src/mcp_advisor"]
40
+
41
+ [tool.ruff]
42
+ target-version = "py311"
43
+ line-length = 100
@@ -0,0 +1,29 @@
1
+ {
2
+ "$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
3
+ "name": "io.github.stucchi/mcp-advisor",
4
+ "title": "MCP Advisor",
5
+ "description": "Browse, search, and discover MCP servers from your AI assistant",
6
+ "repository": {
7
+ "url": "https://github.com/stucchi/mcp-advisor",
8
+ "source": "github"
9
+ },
10
+ "version": "0.1.0",
11
+ "websiteUrl": "https://mcpadvisor.stucchi.consulting",
12
+ "icons": [
13
+ {
14
+ "src": "https://raw.githubusercontent.com/stucchi/mcp-advisor/main/assets/icon.png",
15
+ "mimeType": "image/png",
16
+ "sizes": ["1024x1024"]
17
+ }
18
+ ],
19
+ "packages": [
20
+ {
21
+ "registryType": "pypi",
22
+ "identifier": "mcp-advisor",
23
+ "version": "0.1.0",
24
+ "transport": {
25
+ "type": "stdio"
26
+ }
27
+ }
28
+ ]
29
+ }
@@ -0,0 +1,3 @@
1
+ """MCP Advisor — browse and discover MCP servers from your AI assistant."""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1,56 @@
1
+ """MCP Advisor — browse and discover MCP servers from your AI assistant."""
2
+ import argparse
3
+
4
+ from mcp.server.fastmcp import FastMCP
5
+
6
+ from mcp_advisor import tools
7
+
8
+
9
+ def build_server(api_url: str, api_token: str | None = None) -> FastMCP:
10
+ """Create and return a configured FastMCP server instance."""
11
+ tools.configure(api_url, api_token)
12
+
13
+ mcp = FastMCP("MCP Advisor")
14
+
15
+ mcp.tool(name="search_servers")(tools.search_servers)
16
+ mcp.tool(name="get_server_details")(tools.get_server_details)
17
+ mcp.tool(name="get_install_instructions")(tools.get_install_instructions)
18
+ mcp.tool(name="star_server")(tools.star_server)
19
+ mcp.tool(name="unstar_server")(tools.unstar_server)
20
+ mcp.tool(name="list_starred_servers")(tools.list_starred_servers)
21
+ mcp.tool(name="get_trending_servers")(tools.get_trending_servers)
22
+ mcp.tool(name="get_registry_stats")(tools.get_registry_stats)
23
+ mcp.tool(name="browse_tags")(tools.browse_tags)
24
+
25
+ return mcp
26
+
27
+
28
+ def main():
29
+ parser = argparse.ArgumentParser(
30
+ prog="mcp-advisor",
31
+ description="MCP server to browse, search, and discover MCP servers",
32
+ )
33
+ parser.add_argument(
34
+ "--api-url",
35
+ default="https://mcpadvisor.stucchi.consulting",
36
+ help="Base URL of the MCP Advisor API (default: https://mcpadvisor.stucchi.consulting)",
37
+ )
38
+ parser.add_argument(
39
+ "--api-token",
40
+ default=None,
41
+ help="JWT token for authenticated operations (star/unstar)",
42
+ )
43
+ parser.add_argument(
44
+ "--transport",
45
+ choices=["stdio", "sse"],
46
+ default="stdio",
47
+ help="MCP transport (default: stdio)",
48
+ )
49
+ args = parser.parse_args()
50
+
51
+ mcp = build_server(args.api_url, args.api_token)
52
+ mcp.run(transport=args.transport)
53
+
54
+
55
+ if __name__ == "__main__":
56
+ main()
@@ -0,0 +1,177 @@
1
+ """MCP tool implementations — calls the MCP Advisor REST API over HTTP."""
2
+ import httpx
3
+
4
+ # Configured at startup via `configure()`
5
+ _api_url: str = "https://mcpadvisor.stucchi.consulting"
6
+ _api_token: str | None = None
7
+
8
+
9
+ def configure(api_url: str, api_token: str | None = None):
10
+ global _api_url, _api_token
11
+ _api_url = api_url.rstrip("/")
12
+ _api_token = api_token
13
+
14
+
15
+ def _headers() -> dict[str, str]:
16
+ h: dict[str, str] = {}
17
+ if _api_token:
18
+ h["Authorization"] = f"Bearer {_api_token}"
19
+ return h
20
+
21
+
22
+ async def _get(path: str, params: dict | None = None) -> dict:
23
+ async with httpx.AsyncClient(timeout=15.0) as client:
24
+ resp = await client.get(
25
+ f"{_api_url}{path}", params=params, headers=_headers()
26
+ )
27
+ resp.raise_for_status()
28
+ return resp.json()
29
+
30
+
31
+ async def _post(path: str) -> dict:
32
+ async with httpx.AsyncClient(timeout=15.0) as client:
33
+ resp = await client.post(f"{_api_url}{path}", headers=_headers())
34
+ resp.raise_for_status()
35
+ return resp.json()
36
+
37
+
38
+ async def _delete(path: str) -> dict:
39
+ async with httpx.AsyncClient(timeout=15.0) as client:
40
+ resp = await client.delete(f"{_api_url}{path}", headers=_headers())
41
+ resp.raise_for_status()
42
+ return resp.json()
43
+
44
+
45
+ # ---------------------------------------------------------------------------
46
+ # Tools
47
+ # ---------------------------------------------------------------------------
48
+
49
+
50
+ async def search_servers(
51
+ query: str | None = None,
52
+ transport: str | None = None,
53
+ registry_type: str | None = None,
54
+ tag: str | None = None,
55
+ sort: str = "stars",
56
+ limit: int = 10,
57
+ ) -> dict:
58
+ """Search for MCP servers with optional filters.
59
+
60
+ Args:
61
+ query: Free-text search query
62
+ transport: Filter by transport type (stdio, http, sse)
63
+ registry_type: Filter by package registry (npm, pypi, oci)
64
+ tag: Filter by tag name
65
+ sort: Sort by: stars, newest, updated, relevance
66
+ limit: Max results to return (1-50)
67
+ """
68
+ params: dict[str, str] = {"page_size": str(min(max(limit, 1), 50)), "sort": sort}
69
+ if query:
70
+ params["q"] = query
71
+ if transport:
72
+ params["transport"] = transport
73
+ if registry_type:
74
+ params["registry_type"] = registry_type
75
+ if tag:
76
+ params["tag"] = tag
77
+ return await _get("/api/v1/servers", params)
78
+
79
+
80
+ async def get_server_details(name: str) -> dict:
81
+ """Get detailed information about a specific MCP server.
82
+
83
+ Args:
84
+ name: The server name (e.g., 'io.github.org/my-server')
85
+ """
86
+ return await _get(f"/api/v1/servers/{name}")
87
+
88
+
89
+ async def get_install_instructions(
90
+ name: str, client: str = "claude-desktop"
91
+ ) -> dict:
92
+ """Get install instructions for an MCP server tailored to a specific client.
93
+
94
+ Args:
95
+ name: The server name
96
+ client: Target client: claude-desktop, cursor, or generic
97
+ """
98
+ detail = await _get(f"/api/v1/servers/{name}")
99
+
100
+ instructions = []
101
+ for pkg in detail.get("packages", []):
102
+ rt = pkg.get("registry_type", "")
103
+ tp = pkg.get("transport", "")
104
+ pkg_name = pkg.get("package_name") or name
105
+
106
+ if rt == "npm" and tp == "stdio":
107
+ config = {"mcpServers": {name: {"command": "npx", "args": ["-y", pkg_name]}}}
108
+ elif rt == "pypi" and tp == "stdio":
109
+ config = {"mcpServers": {name: {"command": "uvx", "args": [pkg_name]}}}
110
+ elif tp in ("http", "sse"):
111
+ instructions.append({
112
+ "type": client,
113
+ "description": f"Remote MCP server ({tp})",
114
+ "note": "Configure with the server URL provided by the operator",
115
+ })
116
+ continue
117
+ else:
118
+ continue
119
+
120
+ if client == "claude-desktop":
121
+ instructions.append({
122
+ "type": "claude-desktop",
123
+ "description": "Add to ~/Library/Application Support/Claude/claude_desktop_config.json",
124
+ "config": config,
125
+ })
126
+ elif client == "cursor":
127
+ instructions.append({
128
+ "type": "cursor",
129
+ "description": "Add to .cursor/mcp.json in your project root",
130
+ "config": config,
131
+ })
132
+ else:
133
+ instructions.append({"type": "generic", "config": config})
134
+
135
+ return {"server": name, "client": client, "instructions": instructions}
136
+
137
+
138
+ async def star_server(name: str) -> dict:
139
+ """Star an MCP server (requires authentication via --api-token).
140
+
141
+ Args:
142
+ name: The server name to star
143
+ """
144
+ return await _post(f"/api/v1/servers/{name}/star")
145
+
146
+
147
+ async def unstar_server(name: str) -> dict:
148
+ """Remove a star from an MCP server.
149
+
150
+ Args:
151
+ name: The server name to unstar
152
+ """
153
+ return await _delete(f"/api/v1/servers/{name}/star")
154
+
155
+
156
+ async def list_starred_servers() -> dict:
157
+ """List your starred MCP servers (requires authentication via --api-token)."""
158
+ return await _get("/api/v1/me/stars")
159
+
160
+
161
+ async def get_trending_servers(limit: int = 10) -> dict:
162
+ """Get trending MCP servers sorted by star count and recent activity.
163
+
164
+ Args:
165
+ limit: Max results (1-50)
166
+ """
167
+ return await _get("/api/v1/servers/trending", {"limit": str(min(max(limit, 1), 50))})
168
+
169
+
170
+ async def get_registry_stats() -> dict:
171
+ """Get overall statistics about the MCP server registry."""
172
+ return await _get("/api/v1/stats")
173
+
174
+
175
+ async def browse_tags() -> dict:
176
+ """List all available tags with their server counts."""
177
+ return await _get("/api/v1/tags")