PyMCP / app /main.py
aniketppanchal's picture
Added PyMCP
3b93525
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(
"""
<div
style="
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
"
>
<div style="display: flex; align-items: center; gap: 15px">
<img
src="https://github.com/aniketppanchal/mcp-1st-birthday-hackathon-assets/raw/refs/heads/main/py-mcp/logo.png"
width="150px"
/>
<h1 style="font-size: 40px; margin: 0">PyMCP</h1>
</div>
<p style="font-size: 16px; margin: 15px 0">
A powerful MCP server for AI agents that uses Docker sandboxing to securely run
Python code.<br />
Unlike other solutions, it allows agents to install both system-level and Python
dependencies and export generated files.
</p>
</div>
[Open README Documentation](https://huggingface.co/spaces/MCP-1st-Birthday/PyMCP/blob/main/README.md)
# Demo Video
<video width="50%" controls>
<source
src="https://github.com/aniketppanchal/mcp-1st-birthday-hackathon-assets/raw/refs/heads/main/py-mcp/demo.mp4"
type="video/mp4"
/>
Your browser does not support the video tag.
</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.
<div align="center">
<strong>
<a href="https://huggingface.co/spaces/MCP-1st-Birthday/PyMCP/blob/main/LICENSE">MIT License</a>
| Built with <a href="https://www.gradio.app" target="_blank">Gradio</a> ❤️
</strong>
</div>
"""
)
with gr.TabItem("🐍 Run Python Code"):
gr.Interface(
fn=execute_python_code,
inputs=[
gr.Code(language="python", label="Code"),
gr.Textbox(label="Required Packages (Comma Seperated)"),
],
outputs=[gr.TextArea(label="Output")],
)
with gr.TabItem("💻 Run Shell Command"):
gr.Interface(
fn=execute_shell_command,
inputs=[gr.Code(language="shell", label="Command")],
outputs=[gr.TextArea(label="Output")],
)
with gr.TabItem("📁 Export Files"):
gr.Interface(
fn=export_files,
inputs=[
gr.Textbox(label="File Paths (Comma Seperated)"),
gr.Checkbox(value=False, label="Bundle as ZIP archive"),
],
outputs=[
gr.File(file_count="multiple", label="Output"),
gr.TextArea(label="Error Message"),
],
)
with gr.TabItem("💬 System Prompt"):
gr.Interface(
fn=py_mcp_system_prompt,
inputs=[],
outputs=[gr.TextArea(label="Output")],
)
if __name__ == "__main__":
config.setup_working_dir()
app.launch(share=config.share_online, server_name="0.0.0.0", mcp_server=True)