Skip to content

Commit da9dde5

Browse files
committed
[minimcp][examples] Add math_mcp example server
- Add math_mcp.py with tools, prompts, and resources - Add server implementations for all three transports - Demonstrate MiniMCP features with mathematical operations
1 parent 64eb983 commit da9dde5

File tree

4 files changed

+144
-0
lines changed

4 files changed

+144
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from mcp.server.minimcp import HTTPTransport
2+
3+
from .math_mcp import math_mcp
4+
5+
transport = HTTPTransport[None](math_mcp)
6+
app = transport.as_starlette("/mcp")
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
"""
2+
A simple MCP server for mathematical operations.
3+
"""
4+
5+
from typing import Any
6+
7+
import anyio
8+
from pydantic import Field
9+
10+
from mcp.server.minimcp import MiniMCP
11+
12+
math_mcp = MiniMCP[Any](
13+
name="MathServer", version="0.1.0", instructions="This is a simple MCP server for mathematical operations."
14+
)
15+
16+
17+
# -- Prompts --
18+
@math_mcp.prompt()
19+
def problem_solving(problem_description: str = Field(description="Description of the problem to solve")) -> str:
20+
"General prompt to systematically solve math problems."
21+
22+
return f"""You are a math problem solver.
23+
Solve the following problem step by step and provide the final simplified answer.
24+
25+
Problem: {problem_description}
26+
27+
Output:
28+
1. Step-by-step reasoning
29+
2. Final answer in simplest form
30+
"""
31+
32+
33+
# -- Resources --
34+
GEOMETRY_FORMULAS = {
35+
"Area": {
36+
"rectangle": "A = length * width",
37+
"triangle": "A = (1/2) * base * height",
38+
"circle": "A = πr²",
39+
"trapezoid": "A = (1/2)(b₁ + b₂)h",
40+
},
41+
"Volume": {
42+
"cube": "V = s³",
43+
"rectangular_prism": "V = length * width * height",
44+
"cylinder": "V = πr²h",
45+
"sphere": "V = (4/3)πr³",
46+
},
47+
}
48+
49+
50+
@math_mcp.resource("math://formulas/geometry")
51+
def get_geometry_formulas() -> dict[str, dict[str, str]]:
52+
"""Geometry formulas reference for all types"""
53+
return GEOMETRY_FORMULAS
54+
55+
56+
@math_mcp.resource("math://formulas/geometry/{formula_type}")
57+
def get_geometry_formula(formula_type: str) -> dict[str, str]:
58+
"Get a geometry formula by type (Area, Volume, etc.)"
59+
if formula_type not in GEOMETRY_FORMULAS:
60+
raise ValueError(f"Invalid formula type: {formula_type}")
61+
return GEOMETRY_FORMULAS[formula_type]
62+
63+
64+
# -- Tools --
65+
@math_mcp.tool()
66+
def add(
67+
a: float = Field(description="The first float number"), b: float = Field(description="The second float number")
68+
) -> float:
69+
"Add two numbers"
70+
return a + b
71+
72+
73+
@math_mcp.tool(description="Add two numbers with progress reporting")
74+
async def add_with_progress(
75+
a: float = Field(description="The first float number"), b: float = Field(description="The second float number")
76+
) -> float:
77+
responder = math_mcp.context.get_responder()
78+
await responder.report_progress(0.1, message="Adding numbers")
79+
await anyio.sleep(1)
80+
await responder.report_progress(0.4, message="Adding numbers")
81+
await anyio.sleep(1)
82+
await responder.report_progress(0.7, message="Adding numbers")
83+
await anyio.sleep(1)
84+
return a + b
85+
86+
87+
@math_mcp.tool(description="Subtract two numbers")
88+
def subtract(
89+
a: float = Field(description="The first float number"), b: float = Field(description="The second float number")
90+
) -> float:
91+
return a - b
92+
93+
94+
@math_mcp.tool(name="multiply") # Different name from function name
95+
def product(
96+
a: float = Field(description="The first float number"), b: float = Field(description="The second float number")
97+
) -> float:
98+
"Multiply two numbers"
99+
100+
return a * b
101+
102+
103+
@math_mcp.tool(description="Divide two numbers")
104+
def divide(
105+
a: float = Field(description="The first float number"), b: float = Field(description="The second float number")
106+
) -> float:
107+
return a / b
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import logging
2+
import os
3+
4+
import anyio
5+
6+
from mcp.server.minimcp import StdioTransport
7+
8+
from .math_mcp import math_mcp
9+
10+
# Configure logging globally for the demo server
11+
logging.basicConfig(
12+
level=logging.DEBUG,
13+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
14+
handlers=[
15+
logging.FileHandler(os.environ.get("MCP_SERVER_LOG_FILE", "mcp_server.log")),
16+
logging.StreamHandler(), # Also log to stderr
17+
],
18+
)
19+
logger = logging.getLogger(__name__)
20+
21+
22+
if __name__ == "__main__":
23+
logger.info("MiniMCP: Started stdio server, listening for messages...")
24+
transport = StdioTransport[None](math_mcp)
25+
anyio.run(transport.run)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from mcp.server.minimcp import StreamableHTTPTransport
2+
3+
from .math_mcp import math_mcp
4+
5+
transport = StreamableHTTPTransport[None](math_mcp)
6+
app = transport.as_starlette("/mcp")

0 commit comments

Comments
 (0)