mcp-agent-tools
by zyay
README.md
# π€ mcp-agent-tools
A custom **MCP (Model Context Protocol) server** that gives AI agents real-world tools: file access, **read-only MySQL queries**, web summarization, calculations, and system info. Built to understand how agentic tool calling works end-to-end β server side *and* client side.
## Architecture
```
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β MCP Client (AI Agent) β
β Claude Code / Qwen Code / Claude Desktop β
βββββββββββββββββββββββββ¬ββββββββββββββββββββββββββββββββββ
β stdio (JSON-RPC)
βββββββββββββββββββββββββΌββββββββββββββββββββββββββββββββββ
β MCP Server (this) β
β β
β ββββββββββββ ββββββββββββ ββββββββββββ βββββββββββββ β
β βread_file β βquery_ β βsummarize_β βcalculator β β
β βlist_dir β βmysql β βurl β βget_datetimeβ β
β β β β(SELECT β β β βsysinfo β β
β β β β only) β β β βword_count β β
β ββββββββββββ ββββββββββββ ββββββββββββ βββββββββββββ β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
```
## Tools (8)
| Tool | What it does | Safety |
|---|---|---|
| `read_file` | Read a text file (first 5000 chars) | read-only, path validation |
| `list_dir` | List directory contents with type indicators | read-only |
| `query_mysql` | Query MySQL database | **SELECT-only guardrail** |
| `summarize_url` | Fetch & summarize a webpage | no writes, timeout protected |
| `calculator` | Evaluate math expressions safely | AST-based (no eval) |
| `get_datetime` | Current date/time (UTC + local) | read-only |
| `sysinfo` | System information (OS, Python, arch) | read-only |
| `word_count` | Count words, chars, lines, sentences | read-only |
## Quick start
```bash
# 1. Clone and set up
git clone https://github.com/zyay/mcp-agent-tools.git
cd mcp-agent-tools
python -m venv venv && venv\Scripts\activate # Windows
# source venv/bin/activate # macOS/Linux
# 2. Install dependencies
pip install -r requirements.txt
# 3. Set up MySQL (optional β for query_mysql tool)
mysql -u root -p < setup.sql
# 4. Test the server
python client_test.py
```
## Connecting an MCP client
### Option 1: Qwen Code
```bash
qwen mcp add agent-tools -- python /full/path/to/server.py
```
Or add to `.qwen/settings.json`:
```json
{
"mcpServers": {
"agent-tools": {
"command": "python",
"args": ["/full/path/to/mcp-agent-tools/server.py"]
}
}
}
```
### Option 2: Claude Code
```bash
claude mcp add agent-tools -- python /full/path/to/server.py
```
### Option 3: Claude Desktop
Edit `claude_desktop_config.json`:
```json
{
"mcpServers": {
"agent-tools": {
"command": "python",
"args": ["/full/path/to/mcp-agent-tools/server.py"]
}
}
}
```
Location:
- **Windows**: `%APPDATA%\Claude\claude_desktop_config.json`
- **macOS**: `~/Library/Application Support/Claude/claude_desktop_config.json`
### Option 4: Any MCP client
The server uses **stdio transport** (JSON-RPC over stdin/stdout). Any MCP-compatible client can connect.
## Usage examples
Once connected, the AI agent can use these tools naturally:
### File operations
```
User: "What's in the config file at ./settings.json?"
Agent: [calls read_file("./settings.json")]
```
### Database queries
```
User: "Show me all clients with projects over $1000"
Agent: [calls query_mysql("SELECT * FROM clients WHERE price > 1000")]
```
### Web research
```
User: "What does the Python docs say about async generators?"
Agent: [calls summarize_url("https://docs.python.org/3/reference/expressions.html")]
```
### Calculations
```
User: "If I have 150 items at $12.99 each with 15% discount, what's the total?"
Agent: [calls calculator("150 * 12.99 * 0.85")]
```
### System debugging
```
User: "What Python version am I running and what OS?"
Agent: [calls sysinfo()]
```
## MySQL setup
The `query_mysql` tool connects to a demo database. Set up:
```bash
# Load demo data
mysql -u root -p < setup.sql
# Verify
mysql -u root -p -e "SELECT * FROM demo.clients;"
```
### Environment variables
| Variable | Default | Description |
|---|---|---|
| `MYSQL_HOST` | `localhost` | MySQL server host |
| `MYSQL_USER` | `root` | MySQL username |
| `MYSQL_PASS` | *(empty)* | MySQL password |
| `MYSQL_DB` | `demo` | Database name |
Example with custom credentials:
```bash
set MYSQL_HOST=localhost
set MYSQL_USER=myuser
set MYSQL_PASS=mypassword
python server.py
```
## Design decisions
| Decision | Why |
|---|---|
| **SELECT-only guardrail** | An agent with DROP TABLE access is a bug waiting to happen. Least-privilege by default. |
| **AST calculator** | No `eval()` β the calculator uses Python AST parsing to safely evaluate math expressions only. |
| **stdio transport** | Simplest, works with any MCP client. No HTTP server needed. |
| **Docstrings = tool descriptions** | The `@mcp.tool()` decorator uses the function's docstring as the tool description the LLM reads. Good docstrings = better tool selection. |
| **Error messages, not exceptions** | Tools return error strings instead of raising β the agent can read the error and adapt. |
| **No state between calls** | Each tool call is independent. No shared state = no race conditions. |
## Testing
```bash
# Run the test client β lists all tools and calls each one
python client_test.py
# Expected output:
# π§ Tools (8): ['read_file', 'list_dir', 'query_mysql', 'summarize_url', ...]
# β
query_mysql: [{'id': 1, 'name': 'Firma A', ...}, ...]
# β
calculator: 100.0
# β
get_datetime: UTC: 2026-08-11 ...
# ...
```
## Adding your own tools
```python
@mcp.tool()
def my_tool(param: str) -> str:
"""Describe what this tool does β the LLM reads this description.
Be specific about:
- What it does
- What parameters it takes
- What it returns
- Any safety considerations
"""
# Your implementation
return f"Result for {param}"
```
Then restart the server. The new tool appears automatically.
## Production upgrade path
1. **Human-in-the-loop** β add confirmation prompts for destructive operations
2. **Auth / permissions** β per-tool access control, API keys
3. **HTTP transport** β deploy as a remote MCP server (streamable-http)
4. **Rate limiting** β prevent abuse of web fetching / database queries
5. **Logging** β structured logs for debugging and auditing
6. **More databases** β PostgreSQL, SQLite, MongoDB adapters
## What I learned
- MCP protocol: JSON-RPC over stdio, tool schema from docstrings
- Why guardrails matter: agents are powerful but need boundaries
- AST-based evaluation: safe math without `eval()` security risks
- Tool description quality directly affects agent behavior
- The MCP ecosystem is growing fast β Claude, Qwen Code, Cursor all support it
## Security
| Check | Status |
|---|---|
| No `eval()` anywhere | β
AST-based calculator only |
| SELECT-only MySQL guardrail | β
All non-SELECT queries rejected |
| Path traversal protection | β
Sandbox with allowed_paths + blocked_paths |
| Timeout on network calls | β
All HTTP calls have timeouts |
| Rate limiting | β
Configurable per-tool rate limits |
| Human-in-the-loop writes | β
2-step prepare β confirm flow |
| Tool-call logging | β
Every call logged to JSONL |
| Config-driven tool enable/disable | β
Toggle tools in config.yaml |
## License
MIT
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues