AgentStack
Browse Sign in
Browse Why AgentStack Sell Docs
Sign in
MCP unreviewed MIT Self-run

Mcp2py

mcp-maximerivest-mcp2py · by MaximeRivest

Turn any MCP server into a Python module

No reviews yet
0 installs
0 views
view→install

Install

$ agentstack add mcp-maximerivest-mcp2py

Open-source listing, not yet scanned by AgentStack. Follow the source repository for install instructions.

Security review

⚠ Flagged

1 finding(s); flagged for manual review. · v0.1.0 How review works →

  • Prompt-injection patterns
  • Secret / credential exfiltration
  • Dangerous shell & filesystem operations
  • Untrusted network calls
  • Known-malicious package signatures
  • high Pipes remote content directly into a shell (remote code execution).

What it can access

  • Network access Used
  • Filesystem access Used
  • Shell / process execution Used
  • Environment & secrets Used
  • Dynamic code execution No

From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.

View the full security report →

Reliability & compatibility

Not yet reviewed
0 installs to date
no reviews yet
9mo ago

Declared compatibility

Claude CodeClaude DesktopCursorWindsurf

Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.

Preview Execution monitoring

We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.

How agent discovery & health will work →
Are you the author of Mcp2py? Claim this listing to set pricing, connect Stripe payouts, and keep 70% of every sale.
Sign up to claim

About

mcp2py: Turn any MCP server into a python module

MCP (Model Context Protocol) is an emerging standard for AI tools and resources. The standard is compatible with normal REST API servers, but adds extra metadata to describe tools, resources, and prompts in a machine-readable way. This provides us with a great opportunity to create Python modules that completely and automatically map to these MCP servers. The biggest advantage of this approach is that we can use any MCP server as if it were a native Python library, with zero configuration. This can be quite a big deal as creating Python software development kits that map to REST APIs is extremely common and was quite a manual process. Now, if the organization hosting the REST API also provides an MCP interface, we can automatically generate a Python SDK for it with zero effort! Don’t worry if this is not all clear to you. You can still leverage the power of mcp2py without knowing all the details of MCP. All you need to know is: if you want to programmatically interact with a website, it is likely that they have an API and as time goes on it is very likely that they have an MCP interface for that API. If they do, you don’t have to learn a whole set of web programming skills, you can just use mcp2py to load the MCP server and start calling functions right away as if it were a native Python library!

Another cool thing to note is that servers don’t have to be running remotely. You can (and have) a lot of servers running on your own personal computer right now. This is useful to have different programs, possibly in different programming languages, talking to each other. As apps that you install will more and more open up a small local server on your machine to let LLMs interact with them, you will also be able to leverage mcp2py to interact with these local servers. That could look like Slack opening a server that lets you query your messages. If so, you could then use mcp2py and have a Python module (a library in essence) that lets you query your Slack messages directly from Python. Super powerful!

Overview

Here is a very simple example of using mcp2py to interact with your local filesystem. That is not very useful as you could just use the built-in Python libraries to do that, but it serves as a very simple example to illustrate how mcp2py works. In this snippet of code we use load to both start the MCP server (which is a Node.js server in this case) and connect to it. Once connected we can call the list_directory tool as if it were a native Python function:

``` python from mcp2py import load fstools = load("npx -y @modelcontextprotocol/server-filesystem /home") fstools.list_directory("/home")


    [DIR] maxime

This is similar to using the os library in Python:

``` python
import os
os.listdir("/home")

['maxime']

The main difference is that instead of going directly from Python to the system, we send commands to a local Node (JavaScript) server and that server has some ‘security’ features. For example, we are not allowed to search outside of /home because that is what we have set as the root. Those features are very useful when you want to expose your file system to an LLM.

------------------------------------------------------------------------

Quick Start

1. Install

You can install mcp2py via pip:

``` bash pip install mcp2py


Python has had the pesky problem of not having a standard way to manage
dependencies for a long time. To avoid dependency conflicts, it is
recommended to use virtual environments. My favorite way to do this is
with `uv` (see here:
https://docs.astral.sh/uv/getting-started/installation/). Then you can
create a new environment and install mcp2py like this:

``` bash
# Install uv (if you haven't already)
curl -LsSf https://astral.sh/uv/install.sh | sh

# Create a new project with a virtual environment
uv init my-mcp-project
cd my-mcp-project

# Install mcp2py
uv add mcp2py

# Activate the environment and start coding
uv run python

2. Use it

``` python from mcp2py import load

Load any MCP server with OAuth authentication

notion = load("https://mcp.notion.com/mcp", auth="oauth")

Browser opens automatically for OAuth login

Once authenticated, you can use the tools

notion.notiongetself()


**3. That’s it!**

The server runs as a subprocess, tools are Python methods, everything
just works.

## What is MCP?

MCP servers expose **tools**, **resources**, and **prompts** via a
protocol. mcp2py turns them into {python}:

- 🔧 **Tools** → {python} functions
- 📦 **Resources** → {python} constants/attributes
- 📝 **Prompts** → Template functions/strings

## Philosophy

**It Just Works™ - But You Can Customize Everything**

mcp2py is designed for **researchers, data analysts, and {python}
beginners** who want to try MCP servers without complexity. At the same
time, it provides **full control** for developers building production
applications.

**Zero configuration by default:** - OAuth login? Browser opens
automatically - Need user input? Terminal prompts appear - Server needs
an LLM? We handle it - Everything “just works” out of the box

**No ceiling for advanced users:** - Override any default behavior -
Customize auth flows - Build production apps - Full control when you
need it

**Your {python} REPL/code becomes an MCP client.** The server is a
separate process (Node.js, {python}, whatever) that mcp2py communicates
with via JSON-RPC. Your {python} code can: - Call tools (server
functions) as if they’re local {python} functions - Access resources
(server data) as {python} attributes - Handle server requests (sampling,
elicitation) automatically or via custom callbacks - Work seamlessly
with any AI SDK (Anthropic, OpenAI, DSPy, etc.)

## Getting Started

### For Beginners & Researchers: It Just Works

``` python
from mcp2py import load

# Load any MCP server - that's it!
server = load("https://api.example.com/mcp")

# If it needs login:
#   → Browser opens automatically
#   → You log in once
#   → Browser closes
#   → Done!

# If it needs your input:
#   → Nice terminal prompts appear
#   → You answer
#   → Code continues!

# If it needs AI help (sampling):
#   → Uses your ANTHROPIC_API_KEY or OPENAI_API_KEY
#   → Handles it automatically
#   → You don't even notice!

# Just use the tools!
result = server.analyze_data(dataset="sales_2024.csv")
print(result)

That’s it. No configuration. No setup. It just works.

------------------------------------------------------------------------

Interface Design

Basic Usage

``` python from mcp2py import load

Load an MCP server - simple and clean

weather = load("npx -y @h1deya/mcp-server-weather")

Or from a remote HTTP server (SSE/HTTP Stream transport)

api = load("https://api.example.com/mcp")

With authentication

api = load("https://api.example.com/mcp", headers={"Authorization": "Bearer YOUR_TOKEN"})

Or from a {python} script

travel = load("{python} mymcpserver.py")

Tools become functions

alerts = weather.getalerts(state="CA") forecast = weather.getforecast(latitude=37.7749, longitude=-122.4194) print(forecast)

Resources become attributes

print(weather.APIDOCUMENTATION) # Constant resource print(weather.currentconfig) # Dynamic resource

Prompts become template functions

prompt = weather.createweatherreport(location="NYC", style="casual")


### Use with AI Frameworks (DSPy, Claudette, etc.)

**The `.tools` attribute gives you a list of callable {python}
functions**:

``` python
from mcp2py import load

server = load("npx -y @modelcontextprotocol/server-filesystem /tmp")

# Get tools as callable functions
tools = server.tools
# [, , ...]

# Each function has __name__ and __doc__
print(tools[0].__name__)  # "read_file"
print(tools[0].__doc__)   # "Read a file from the filesystem"

# And they're callable!
result = tools[0](path="/tmp/test.txt")

Working with AI Frameworks

The .tools attribute gives you callable functions ready for frameworks like DSPy and Claudette:

``` python from mcp2py import load import dspy

Load MCP server

travel = load("{python} airline_server.py")

Use with DSPy - pass callable functions directly

class CustomerService(dspy.Signature): user_request: str = dspy.InputField() result: str = dspy.OutputField()

dspy.configure(lm=dspy.LM("openai/gpt-4o-mini"))

Pass tools directly to DSPy (it expects callables)

react = dspy.ReAct(CustomerService, tools=travel.tools)

result = react(user_request="Book a flight from SFO to JFK on 09/01/2025") print(result)


``` python
# Also works with Claudette
from mcp2py import load
from claudette import Chat

weather = load("npx -y @h1deya/mcp-server-weather")

# Claudette expects callable functions
chat = Chat(model="claude-3-5-sonnet-20241022", tools=weather.tools)

response = chat("What's the weather in Tokyo?")
# Claudette automatically calls the tools as needed
print(response)

Note: For SDKs that have native MCP support (Anthropic, OpenAI, Google Gemini), use their built-in MCP integration directly. The .tools attribute is for frameworks like DSPy and Claudette that expect {python} callables.

Type Safety & IDE Support

Auto-generated stubs for perfect autocomplete:

``` python from mcp2py import load

Stubs auto-generated to ~/.cache/mcp2py/stubs/

server = load("npx my-server")

IDE now has full autocomplete and type hints!

server.searchfiles( pattern="*.py", # type: str - IDE knows this! maxresults=10 # type: int, optional - IDE suggests this! ) # Returns: dict[str, Any] - IDE shows return type!


**Manual stub generation:**

``` python
# Generate stub to specific location for your project
server = load("npx weather-server")
server.generate_stubs("./stubs/weather.pyi")

# Or let it auto-cache (default behavior)
# Stubs saved to: ~/.cache/mcp2py/stubs/.pyi

How it works: - load() returns a dynamically typed class with all methods pre-defined - Your IDE sees proper type hints immediately - no configuration needed! - Type hints include parameter names, types, defaults, and return types - Works in VS Code, PyCharm, Jupyter notebooks, and any {python} IDE - Also generates .pyi stub files to ~/.cache/mcp2py/stubs/ for reference

Zero configuration required - autocomplete just works! ✨

MCP Client Features

When your {python} code acts as an MCP client, servers may request these capabilities:

Sampling

When a server needs LLM completions, mcp2py handles it automatically.

Default: Works Out of the Box

``` python from mcp2py import load

Just works! Uses your default LLM

server = load("npx travel-server")

If server needs LLM help, mcp2py:

1. Checks for ANTHROPICAPIKEY or OPENAIAPIKEY in environment

2. Calls the LLM automatically

3. Returns result to server

4. Your code continues!

result = server.book_flight(destination="Tokyo")


**Configure your preferred LLM:**

``` python
# Set via environment (recommended)
import os
os.environ["ANTHROPIC_API_KEY"] = "sk-..."

# Or configure globally using LiteLLM model strings
from mcp2py import configure

configure(
    model="claude-3-5-sonnet-20241022"  # or "gpt-4o", "gemini/gemini-pro", etc.
)

# LiteLLM automatically detects the right API based on model name
# Uses standard env vars: ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.

# Now all servers use this LLM for sampling
server = load("npx travel-server")

Advanced: Custom Sampling Handler

``` python from mcp2py import load

def mysamplinghandler(messages, modelprefs, systemprompt, maxtokens): """Full control over LLM calls.""" import anthropic client = anthropic.Anthropic() response = client.messages.create( model="claude-3-5-sonnet-20241022", messages=messages, maxtokens=max_tokens ) return response.content[0].text

server = load( "npx travel-server", onsampling=mysampling_handler # Override default )


**Disable sampling (for security/cost control):**

``` python
server = load(
    "npx travel-server",
    allow_sampling=False  # Raises error if server requests LLM
)

Elicitation

When a server needs user input, mcp2py prompts automatically.

Default: Terminal Prompts

``` python from mcp2py import load

Just works! Terminal prompts appear automatically

server = load("npx travel-server")

Server asks: "Confirm booking for $500?"

Terminal shows:

#

Server asks: Confirm booking for $500?

confirm_booking (boolean): y/n

#

You type: y

Code continues!

result = server.book_flight(destination="Paris")


**What you see:**

    Calling book_flight...

    ┌─────────────────────────────────────────┐
    │ 🔔 Server needs your input              │
    ├─────────────────────────────────────────┤
    │ Confirm booking for $500?               │
    │                                         │
    │ confirm_booking (boolean): y/n          │
    │ seat_preference (window/aisle/middle):  │
    │ meal_preference (optional):             │
    └─────────────────────────────────────────┘

    > y
    > window
    > vegetarian

    Booking confirmed!

**Advanced: Custom Elicitation Handler**

``` python
from mcp2py import load

def my_input_handler(message, schema):
    """Custom UI for user input."""
    # Build a GUI, web form, voice input, etc.
    from tkinter import simpledialog
    return simpledialog.askstring("Server Request", message)

server = load(
    "npx travel-server",
    on_elicitation=my_input_handler
)

Disable elicitation (for automated scripts):

``` python server = load( "npx travel-server", allow_elicitation=False # Raises error if server asks for input )

Or provide pre-filled answers

server = load( "npx travel-server", elicitationdefaults={ "confirmbooking": True, "seat_preference": "window" } )


### **Roots**

Servers can ask which directories to focus on. Optional, simple:

``` python
# Single directory
server = load("npx filesystem-server", roots="/home/user/projects")

# Multiple directories
server = load(
    "npx filesystem-server",
    roots=["/home/user/projects", "/tmp/workspace"]
)

# Update roots dynamically
server.set_roots(["/home/user/new-project"])

Design Rules

1. Tools → Functions

MCP tools map to {python} functions with full support for:

  • Arguments: Both required and optional parameters
  • Type hints: Generated from JSON Schema inputSchema
  • Docstrings: Built from tool description
  • Return types: Typed as dict[str, Any] (MCP tools return JSON)

Naming convention: Snake_case (MCP getWeather → {python} get_weather)

``` python

MCP Tool Definition:

{

"name": "searchFiles",

"description": "Search for files matching a pattern",

"inputSchema": {

"type": "object",

"properties": {

"pattern": {"type": "string", "description": "Glob pattern"},

"maxResults": {"type": "integer", "default": 100}

},

"required": ["pattern"]

}

}

Generated {python}:

def searchfiles(pattern: str, maxresults: int = 100) -> dict[str, Any]: """Search for files matching a pattern.

Args: pattern: Glob pattern max_results: Maximum results to return (default: 100) """ ...


### 2. **Resources → Constants or Properties**

Resources map differently based on their nature:

- **Static resources** (like documentation, schemas): Module-level
  constants (UPPER_CASE)
- **Dynamic resources** (may change): Properties with getters
  (lowercase)

``` python
# Static resource (cached)
API_DOCS: str = server._get_resource("api://docs")

# Dynamic resource (fetched on access)
@property
def current_status() -> dict[str, Any]:
    """Current server status."""
    return server._get_resource("status://current")

Naming convention: - Static: UPPER_SNAKE_CASE - Dynamic: lower_snake_case properties

3. **Prompts → Template

Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

Install and usage instructions live in the source repository linked above.

Reviews

No reviews yet, be the first.

Versions

  • v0.1.0 Imported from the upstream source.