"""
MCP Calculator Server
A simple calculator server that exposes basic arithmetic operations.
Run with: python calculator_server.py
Or: uv run calculator_server.py
"""
from mcp.server import FastMCP
from mcp.types import PromptMessage, TextContent
from pathlib import Path
import argparse
import sys
# Create an MCP server instance
# Use 'mcp' as the variable name so it's auto-discovered by the CLI
# Note: transport_security is set to None in main() if binding to external IP
mcp = FastMCP("Calculator")
# Register the TypeScript SDK documentation as a markdown resource so clients
# can read it via the MCP resource API. The resource URI is
# `resource://typescriptsdk` and the MIME type is `text/markdown`.
@mcp.resource("resource://typescriptsdk", mime_type="text/markdown", title="MCP TypeScript SDK")
def typescript_sdk_resource() -> str:
"""Return the contents of `typescriptsdk.md` as markdown text.
This uses a relative path (same directory as this file). The file
`typescriptsdk.md` is included in the workspace root alongside this
server module.
"""
path = Path(__file__).resolve().parent / "typescriptsdk.md"
try:
return path.read_text(encoding="utf-8")
except Exception as e:
# Return a helpful error message as the resource content
return f"Error reading typescriptsdk.md: {e}"
@mcp.prompt(name="meeting_analysis", description="Comprehensive meeting analysis template for analyzing meeting transcripts and generating executive summaries, detailed minutes, action items, risk analysis, and individual contributions")
def meeting_analysis_prompt(meeting_date: str, meeting_title: str, transcript: str) -> list[PromptMessage]:
"""Meeting Analysis Prompt Template
Provides a structured framework for analyzing meeting transcripts with
exceptional attention to detail and organizational skills.
Args:
meeting_date: The date when the meeting took place
meeting_title: The title or subject of the meeting
transcript: The full transcript of the meeting
Returns:
A list of PromptMessage objects containing the prompt template and instructions
"""
prompt_text = f"""You are an Executive Assistant working for a global infrastructure consultancy. Your task is to analyze the following meeting transcript with exceptional attention to detail and organizational skills.
Meeting Information:
Date: {meeting_date}
Title: {meeting_title}
Transcript:
{transcript}
Please provide a comprehensive analysis using the following structure:
## 1. Executive Summary
- Provide a concise overview of the meeting's purpose and outcomes
- Highlight the most important strategic decisions
- Include critical insights from the discussion
## 2. Detailed Minutes
- Structure the minutes by topic/agenda item
- Include attendees and their roles
- Summarize key discussions
- Document all decisions made
- List action items with assignees and deadlines
## 3. Key Decisions & Action Items
- Enumerate all decisions made during the meeting
- List action items in a structured format:
* Who is responsible
* What needs to be done
* When it needs to be completed
* Any dependencies or resources needed
## 4. Risk Analysis
- Identify potential risks or challenges mentioned
- Note opportunities discussed
- Highlight areas needing further discussion or clarification
## 5. Individual Contributions
- Summarize key points made by each participant
- Note any commitments or responsibilities taken on
- Highlight expertise or insights shared
Please format your response using clean markdown with appropriate headers and bullet points.
Remember to:
- Be objective and factual
- Capture both explicit and implicit information
- Maintain professional language
- Highlight strategic implications
- Note any follow-up requirements"""
return [
PromptMessage(
role="user",
content=TextContent(
type="text",
text=prompt_text
)
)
]
@mcp.tool()
def add(a: float, b: float) -> float:
"""Add two numbers together.
Args:
a: First number
b: Second number
Returns:
The sum of a and b
"""
return a + b
@mcp.tool()
def subtract(a: float, b: float) -> float:
"""Subtract b from a.
Args:
a: First number (minuend)
b: Second number (subtrahend)
Returns:
The difference (a - b)
"""
return a - b
@mcp.tool()
def multiply(a: float, b: float) -> float:
"""Multiply two numbers.
Args:
a: First number
b: Second number
Returns:
The product of a and b
"""
return a * b
@mcp.tool()
def divide(a: float, b: float) -> float:
"""Divide a by b.
Args:
a: Dividend (numerator)
b: Divisor (denominator)
Returns:
The quotient (a / b)
Raises:
ValueError: If b is zero
"""
if b == 0:
raise ValueError("Cannot divide by zero")
return a / b
def main(argv: list[str] | None = None) -> None:
"""CLI entrypoint to run the MCP server.
Allows choosing the transport (stdio, sse, or streamable-http) and
overriding host/port for HTTP transports.
When binding to a non-localhost IP, DNS rebinding protection is automatically
disabled to allow external MCP clients to connect.
"""
parser = argparse.ArgumentParser(prog="calculator_server")
parser.add_argument("--transport", choices=["stdio", "sse", "streamable-http"], default="stdio", help="Transport to run the MCP server with")
parser.add_argument("--host", default=None, help="Host to bind HTTP transports to (overrides server default)")
parser.add_argument("--port", type=int, default=None, help="Port to bind HTTP transports to (overrides server default)")
args = parser.parse_args(argv)
# If host/port provided, update the FastMCP settings
if args.host is not None:
mcp.settings.host = args.host
if args.port is not None:
mcp.settings.port = args.port
# Disable DNS rebinding protection only when binding to an explicit external IP.
# Treat `None` as the default (local) setting; treat `0.0.0.0` as external (bind-all).
host = mcp.settings.host
is_localhost = host is None or str(host) in ("127.0.0.1", "localhost", "::1")
if not is_localhost:
# Only disable transport security when the user explicitly requests binding
# to a non-local address. Disabling transport security may expose the server
# to DNS rebinding attacks — this is preserved only for explicit user choice.
mcp.settings.transport_security = None
print(f"[INFO] Binding to external IP {mcp.settings.host}:{mcp.settings.port} — DNS rebinding protection disabled.", file=sys.stderr)
try:
mcp.run(transport=args.transport)
except Exception as e:
print(f"Error running MCP server: {e}", file=sys.stderr)
raise
if __name__ == "__main__":
# Run via CLI so users can choose `--transport streamable-http` for HTTP
# access (useful for connecting MCP clients over HTTP).
main()