Organize your MCP server and tools
Outcomes
Learn best practices for organizing your server and , how to import tools from other packages and how to use them together. Jump to Example Code to see the complete code.
You will Learn
- How to define in separate files and import them
- How to import from other Arcade packages
- How to use
@app.tool
decorators and imported together
Prerequisites
Project Structure
We recommend keeping your server file at the root of your and keeping your in separate files in a tools
directory like so:
my_server/
├── .env
├── server.py # Main MCPApp
├── tools/
│ ├── __init__.py
│ ├── math_tools.py # @tool decorated functions
│ └── text_tools.py # @tool decorated functions
├── pyproject.toml
└── README.md
Defining tools
You can use the @app.tool
decorator to define your tools in your server file directly on the app object (MCPApp
) like this:
@app.tool
def server_info() -> Annotated[dict, "Information about this server"]:
"""Return information about this MCP server."""
return {
"name": "Organized Server",
"version": "1.0.0",
"description": "Demonstrates modular tool organization",
"total_tools": 6, # 4 imported + 2 defined here
}
However, if you need to define more than a few tools, this can make your server file longer and harder to read and maintain. Instead, you can define your in separate files and import them.
Importing tools
You can import from separate files like this:
from tools.math_tools import add, multiply
from tools.text_tools import capitalize_string, word_count
You could also import from Arcade PyPI packages:
from arcade_gmail.tools import list_emails
Add imported tools explicitly to the server app object like this:
app.add_tool(add)
app.add_tool(list_emails)
Key takeaways
- Keep your server file clean and readable by defining in separate files
- Store your in a
tools
directory in your project root alongside your server file - You can import from other Arcade packages and your own files
- Add imported tools explicitly to the server app object
Example Code
#!/usr/bin/env python3
import sys
from typing import Annotated
from arcade_mcp_server import MCPApp
# Import tools from our 'mock' other_files module
# In a real project, these could come from actual separate files
from tools_math import add, multiply
from tools_text import capitalize_string, word_count
# In a real project, you could also import from Arcade PyPI packages:
# from arcade_gmail.tools import list_emails
# Create the MCP application
app = MCPApp(
name="organized_server",
version="1.0.0",
instructions="Example server demonstrating modular tool organization",
)
# Method 1: Add imported tools explicitly
app.add_tool(add)
app.add_tool(multiply)
app.add_tool(capitalize_string)
app.add_tool(word_count)
# Method 2: Define tools directly on the app
@app.tool
def server_info() -> Annotated[dict, "Information about this server"]:
"""Return information about this MCP server."""
return {
"name": "Organized Server",
"version": "1.0.0",
"description": "Demonstrates modular tool organization",
"total_tools": 6, # 4 imported + 2 defined here
}
@app.tool
def combine_results(
text: Annotated[str, "Text to process"],
add_num: Annotated[int, "Number to add"],
multiply_num: Annotated[int, "Number to multiply"],
) -> Annotated[dict, "Combined results from multiple tools"]:
"""Demonstrate using multiple tools together."""
return {
"original_text": text,
"capitalized": capitalize_string(text),
"word_count": word_count(text),
"math_result": multiply(add(5, add_num), multiply_num),
}
if __name__ == "__main__":
# Check if stdio transport was requested
transport = "stdio" if len(sys.argv) > 1 and sys.argv[1] == "stdio" else "http"
print(f"Starting {app.name} v{app.version}")
print(f"Transport: {transport}")
print("Setting up database...")
# simulate a database setup
print("Database setup complete")
# Run the server
app.run(transport=transport, host="127.0.0.1", port=8000)
Run your MCP server
HTTP transport (default)
uv run server.py http
For HTTP transport, view your server’s API docs at http://127.0.0.1:8000/docs .