import textwrap
import gradio as gr
from .config import config
from .tools import execute_python_code, execute_shell_command, export_files
@gr.mcp.prompt()
def py_mcp_system_prompt() -> str:
return textwrap.dedent("""
Usage guidelines for 'execute_python_code,' 'execute_shell_command,' and 'export_files.'
These tools run inside a Docker sandbox. Use the following instructions to utilize them properly:
1. Dependency Management:
- If the task requires system-level libraries, use 'execute_shell_command' to install them (e.g., 'apt-get install -y package').
- If the task requires Python libraries, use the 'required_packages' argument in 'execute_python_code' (e.g., 'required_packages="pandas,numpy"').
2. Code Execution:
- Call 'execute_python_code' to run your logic.
- Each call to 'execute_python_code' runs as a separate process. The execution context (imports, variables, and functions) does not persist to the next call.
- To pass data between steps, you must save it to a file (e.g., as .csv, .json, or .pkl) and then load it in the next step.
3. File Output & Visibility:
- Files created in the sandbox (charts, PDFs, and CSVs) are not available by default to the user.
- To make these files available to the user, use 'export_files' to generate a downloadable URL.
""").strip()
with gr.Blocks() as app:
with gr.Tabs():
with gr.TabItem("⚡️ Quickstart"):
gr.Markdown(
"""
PyMCP
A powerful MCP server for AI agents that uses Docker sandboxing to securely run
Python code.
Unlike other solutions, it allows agents to install both system-level and Python
dependencies and export generated files.
[Open README Documentation](https://huggingface.co/spaces/MCP-1st-Birthday/PyMCP/blob/main/README.md)
# Demo Video
# Quickstart
> Use the following endpoints based on your use case:
>
> - Web Interface: `https://huggingface.co/spaces/MCP-1st-Birthday/PyMCP`
> - Streamable HTTP (MCP): `https://mcp-1st-birthday-pymcp.hf.space/gradio_api/mcp`
> - SSE (MCP): `https://mcp-1st-birthday-pymcp.hf.space/gradio_api/mcp/sse`
## Claude Desktop (Requires npx)
Add/update your `claude_desktop_config.json`:
```json
{
"mcpServers": {
"py-mcp": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://mcp-1st-birthday-pymcp.hf.space/gradio_api/mcp"
]
}
}
}
```
## LangChain
The example below also demonstrates PyMCP's built-in system prompt.
```bash
pip install langchain langchain-mcp-adapters langchain-openai
```
```python
import asyncio
from langchain.agents import create_agent
from langchain_mcp_adapters.client import MultiServerMCPClient
async def main() -> None:
client = MultiServerMCPClient(
{
"py-mcp": {
"transport": "streamable_http",
"url": "https://mcp-1st-birthday-pymcp.hf.space/gradio_api/mcp",
},
}
)
system_prompt = (await client.get_prompt("py-mcp", "system_prompt"))[0].content
tools = await client.get_tools()
agent = create_agent(
model="openai:gpt-5.1",
system_prompt=system_prompt,
tools=tools,
)
query = "Create a simple bar chart using matplotlib."
response = await agent.ainvoke({"messages": query})
print(response["messages"][-1].content)
if __name__ == "__main__":
asyncio.run(main())
```
> When running inside a Jupyter notebook, use `await main()` instead of `asyncio.run(main())` since an event loop is already running.