aaabulkhair/Tiny-Tools-Agent
If you are the rightful owner of Tiny-Tools-Agent and would like to certify it and/or have it hosted online, please leave a comment on the right or send an email to henry@mcphub.com.
This document provides a comprehensive overview of a Model Context Protocol (MCP) server, detailing its architecture, features, and usage.
clock.now
Get current time
clock.shift
Calculate time with offset
Tiny Tools MCP Showcase: A Complete LangGraph Agent System
A production-ready demonstration of a 4-node LangGraph agent with Model Context Protocol (MCP) tool integration, Redis-backed memory, and local LLM support.
Table of Contents
- Overview
- Architecture
- Features
- Installation
- Quick Start
- Configuration
- Usage Guide
- API Reference
- Development
- Testing
- Deployment
- Troubleshooting
- Contributing
Overview
This project demonstrates a complete AI agent system built with LangGraph that showcases modern patterns for tool-based AI interactions. The system consists of two main components:
- MCP Server: A secure FastAPI-based server that provides tool capabilities
- LangGraph Agent: A 4-node workflow that intelligently selects and executes tools
The project serves as both a working demonstration and a reference implementation for building production-ready AI agent systems with proper memory management, error handling, and observability.
Architecture
System Components
graph TB
User[π€ User] --> Agent[π€ LangGraph Agent]
Agent --> LLM[π§ Local LLM Server]
Agent --> MCP[π§ MCP Tool Server]
Agent --> Redis[πΎ Redis Memory]
MCP --> Tools[βοΈ Tool Implementations]
subgraph "Agent Workflow"
P[π Planner] --> E[β‘ Executor]
E --> M[πΎ Memory]
M --> R[π¬ Responder]
R --> P
end
4-Node LangGraph Workflow
The agent follows a linear pipeline with conditional looping:
-
Planner Node (
planner_node
)- Analyzes user requests using local LLM
- Creates structured tool execution plans
- Handles JSON parsing failures with intelligent fallbacks
- Integrates conversation memory for context-aware planning
-
Tool Executor Node (
tool_executor_node
)- Validates and executes planned tool calls via HTTP
- Supports parallel tool execution and result chaining
- Comprehensive error handling and retry logic
- Real-time progress indicators
-
Memory Updater Node (
memory_updater_node
)- Persists conversation state to Redis
- Extracts entities and key facts automatically
- Maintains conversation history and context
- Graceful degradation to in-memory storage
-
Responder Node (
responder_node
)- Generates natural language responses using LLM
- Integrates tool results seamlessly
- Detects follow-up intents for conversation flow
- Provides user-friendly error messages
Project Structure
tiny-tools-mcp-showcase/
βββ app/ # MCP Server (FastAPI)
β βββ main.py # FastAPI app with security & rate limiting
β βββ manifest.py # Tool capability discovery
β βββ tools/
β β βββ schemas.py # Pydantic validation models
β β βββ impl.py # Tool implementation engine
β βββ tests/
β βββ test_tools.py # Comprehensive MCP server tests
βββ agent/ # LangGraph Agent
β βββ workflow.py # Main orchestrator & CLI interface
β βββ nodes.py # 4-node implementation
β βββ edges.py # Conditional routing logic
β βββ memory.py # Redis-backed conversation memory
β βββ prompt_fragments.py # LLM prompt templates
β βββ tests/
β βββ test_agent.py # Agent workflow tests
βββ logs/ # Execution traces & debugging
βββ docker-compose.yml # Multi-service orchestration
βββ Dockerfile # MCP server containerization
βββ Makefile # Development automation
βββ pyproject.toml # Project configuration & dependencies
Features
π Core Capabilities
- Intelligent Tool Selection: LLM-powered planning with efficiency optimization
- Conversation Memory: Redis-backed persistent state with automatic fallback
- Local LLM Integration: Compatible with LM Studio, Ollama, and OpenAI-compatible servers
- Secure MCP Server: Rate limiting, CORS, authentication, and input validation
- Rich Terminal UI: Clean progress indicators and error handling
- Comprehensive Logging: JSON execution traces for debugging and monitoring
π οΈ Available Tools
Tool | Description | Usage Example |
---|---|---|
clock.now | Get current time | "What time is it?" |
clock.shift | Calculate time with offset | "What time will it be in 2 hours?" |
π§ Technical Features
- Type Safety: Full Pydantic validation throughout the stack
- Async/Await: Non-blocking operations for optimal performance
- Error Recovery: Graceful handling of LLM, tool, and network failures
- Session Management: Isolated conversations with reset capability
- Extensible Design: Easy addition of new tools and capabilities
- Production Ready: Docker support, health checks, and monitoring
Installation
Prerequisites
- Python 3.10+ with pip
- Local LLM Server (LM Studio, Ollama, or OpenAI-compatible)
- Docker (optional, for Redis and containerized deployment)
- Redis (optional, for persistent memory)
Method 1: Local Development (Recommended)
-
Clone the repository:
git clone <repository-url> cd tiny-tools-mcp-showcase
-
Install dependencies:
pip install -e .
-
Start Redis (optional but recommended):
# Using Docker docker run -d --name redis -p 6379:6379 redis:alpine # Or using Docker Compose docker-compose up -d redis
Method 2: Docker Development
- Clone and start services:
git clone <repository-url> cd tiny-tools-mcp-showcase docker-compose up -d
Quick Start
1. Start Your Local LLM
Ensure you have a local LLM server running on http://127.0.0.1:1234
:
- LM Studio: Download and start a model server
- Ollama:
ollama serve
with your preferred model - Other: Any OpenAI-compatible API server
2. Start the MCP Server
# Local development
python -m uvicorn app.main:app --host 0.0.0.0 --port 7443 --reload
# Or using Make
make start-server
# Or using Docker
docker-compose up -d mcp
3. Test the MCP Server (Optional)
# Health check
curl http://localhost:7443/health
# Get tool manifest
curl http://localhost:7443/mcp/manifest
# Execute a tool
curl -X POST http://localhost:7443/mcp/tool.execute \
-H "Content-Type: application/json" \
-d '{"capability": "clock.now", "args": {}}'
4. Run the Agent
# Interactive terminal interface
python agent/workflow.py
# Or using Make
make demo
# Or programmatically
python -c "
import asyncio
from agent.workflow import run_agent
result = asyncio.run(run_agent('What time is it?'))
print(result)
"
5. Try Example Queries
π¬ What time is it?
π§ π§ β 1 tools
π€ It's currently 2:30 PM.
π¬ What time will it be in 90 minutes?
π§ π§πΎπ¬ β 2 tools
π€ In 90 minutes, it will be 4:00 PM.
π¬ I have a meeting after 2 hours when will it be
π§ π§πΎπ¬ β 2 tools
π€ Your meeting will be at 4:30 PM.
π¬ quit
π Goodbye!
Configuration
Environment Variables
Variable | Default | Description |
---|---|---|
LLM_URL | http://127.0.0.1:1234 | Local LLM server endpoint |
REDIS_URL | redis://localhost:6379 | Redis connection string |
MCP_API_KEY | demo-key-change-in-production | Optional API key for MCP server |
PYTHONPATH | /app | Python module path (for Docker) |
Local LLM Configuration
The agent is tested with various local LLM providers:
- LM Studio: Use any chat model with OpenAI-compatible API
- Ollama: Models like
llama2
,mistral
,codellama
- Text Generation WebUI: With OpenAI extension enabled
- vLLM: High-performance inference server
Redis Configuration
Redis is used for conversation memory with automatic fallback:
- With Redis: Persistent conversations across restarts
- Without Redis: In-memory storage (warnings are normal)
- TTL: 24-hour automatic session cleanup
Usage Guide
Interactive Terminal Interface
The primary interface is a clean terminal conversation:
python agent/workflow.py
Commands:
- Type your questions naturally
!reset
- Clear conversation memoryquit
,exit
,bye
- End conversation
Programmatic Usage
import asyncio
from agent.workflow import TinyToolsAgent, run_agent
# Single interaction
async def example():
result = await run_agent("What time is it?", session_id="user123")
print(result["bot_response"])
# Agent instance
async def conversation():
agent = TinyToolsAgent()
# Single message
result = await agent.run_single("What time is it?", "session123")
# Interactive conversation
await agent.run_conversation("session123")
asyncio.run(example())
Tool Usage Patterns
Time Queries
"What time is it?" β Uses clock.now (1 tool)
"What time will it be in 2 hours?" β Uses clock.now + clock.shift (2 tools)
"I have a meeting in 45 minutes when will it be" β Uses both tools
Conversation Flow
User: What time is it?
π§ π§ β 1 tools
Bot: It's 2:30 PM.
User: What about in 30 minutes?
π§ π§πΎπ¬ β 2 tools
Bot: In 30 minutes, it will be 3:00 PM.
API Reference
MCP Server Endpoints
Endpoint | Method | Description |
---|---|---|
/ | GET | Server information and endpoint list |
/health | GET | Health check for monitoring |
/mcp/manifest | GET | Complete tool capability manifest |
/mcp/capabilities/summary | GET | Brief capability summary for prompts |
/mcp/tool.execute | POST | Execute tools with validation |
Agent API
# Main classes
from agent.workflow import TinyToolsAgent
from agent.nodes import AgentState
from agent.memory import ConversationMemory
# Convenience functions
from agent.workflow import run_agent, start_conversation
Tool Execution Response Format
{
"success": true,
"result": {
"current_time": "2:30 PM",
"timestamp": "2024-01-15T14:30:00"
},
"error": null,
"execution_time_ms": 5.2
}
Development
Setting Up Development Environment
# Install in development mode
make dev
# Or manually
pip install -e ".[dev]"
Running Tests
# Run all tests
make test
# Run with coverage
make test-coverage
# Run specific test files
pytest app/tests/test_tools.py -v
pytest agent/tests/test_agent.py -v
Code Quality
# Format code
make format
# Lint code
make lint
# Type checking
mypy app/ agent/
Adding New Tools
-
Define schemas in
app/tools/schemas.py
:class NewToolArgs(BaseModel): param: str = Field(description="Tool parameter") class NewToolResult(BaseModel): result: str = Field(description="Tool result")
-
Implement function in
app/tools/impl.py
:def execute_new_tool(args: NewToolArgs) -> NewToolResult: return NewToolResult(result=f"Processed: {args.param}")
-
Register tool in schemas registry:
TOOL_SCHEMAS["new.tool"] = { "args": NewToolArgs, "result": NewToolResult, "description": "Description of new tool", "cost_estimate": 0.1, "avg_latency_ms": 10.0 }
-
Add implementation to registry:
TOOL_IMPLEMENTATIONS["new.tool"] = execute_new_tool
-
Write tests in
app/tests/test_tools.py
Development Commands
# Start MCP server in development mode
make start-mcp
# Start agent in development mode
make start-agent
# Clean build artifacts
make clean
# Build Docker images
make docker-build
# Start full stack with Docker
make docker-up
Testing
Test Structure
tests/
βββ app/tests/
β βββ test_tools.py # MCP server tests
βββ agent/tests/
βββ test_agent.py # Agent workflow tests
Running Tests
# All tests
pytest
# Specific test file
pytest app/tests/test_tools.py::TestToolImplementations::test_clock_now_tool
# With coverage
pytest --cov=app --cov=agent --cov-report=html
# Async tests
pytest -v -s agent/tests/test_agent.py
Test Categories
- Unit Tests: Individual component testing
- Integration Tests: Component interaction testing
- API Tests: HTTP endpoint testing
- Workflow Tests: End-to-end agent testing
Deployment
Docker Deployment
# Build and start all services
docker-compose up -d
# Scale services
docker-compose up -d --scale mcp=2
# View logs
docker-compose logs -f mcp
Production Considerations
-
Security:
- Change default API keys
- Configure proper CORS origins
- Use HTTPS in production
- Set up proper authentication
-
Monitoring:
- Health check endpoints
- Execution trace logging
- Performance metrics collection
- Error rate monitoring
-
Scaling:
- Redis cluster for high availability
- Load balancing for MCP servers
- Horizontal scaling of agent instances
Environment-Specific Configuration
# Development
export LLM_URL="http://localhost:1234"
export REDIS_URL="redis://localhost:6379"
# Production
export LLM_URL="https://your-llm-server.com"
export REDIS_URL="redis://your-redis-cluster:6379"
export MCP_API_KEY="your-secure-api-key"
Troubleshooting
Common Issues
1. LLM Connection Issues
Error: Error calling local LLM: Connection refused
Solution: Ensure your local LLM server is running on the correct port.
2. MCP Server Not Responding
Warning: Could not fetch tool manifest
Solution: Start the MCP server and check port 7443 is available.
3. Redis Connection Warnings
Warning: Redis not available, using in-memory storage
Solution: Start Redis or ignore (in-memory fallback works fine).
4. Tool Execution Failures
β 0/1 tools
Solution: Check MCP server logs and ensure tools are properly registered.
5. JSON Parsing Errors
Planning failed: Invalid JSON response
Solution: The agent has built-in fallback logic for this. Check LLM configuration.
Debug Mode
Enable verbose logging:
import logging
logging.basicConfig(level=logging.DEBUG)
Log Analysis
Execution traces are saved in logs/trace-{session}-{timestamp}.json
:
{
"session_id": "abc123",
"timestamp": "2024-01-15T14:30:00",
"user_message": "What time is it?",
"bot_response": "It's 2:30 PM",
"execution_summary": {
"planning_success": true,
"execution_success": true,
"tools_executed": 1
},
"plan": [...],
"tool_results": [...]
}
Performance Tuning
-
LLM Settings:
- Adjust temperature (0.1 for consistent results)
- Optimize max_tokens for your use case
- Consider model size vs. speed tradeoffs
-
Redis Optimization:
- Adjust TTL based on conversation patterns
- Monitor memory usage
- Consider Redis clustering for scale
-
Tool Execution:
- Implement parallel execution for independent tools
- Add caching for expensive operations
- Monitor execution times and optimize slow tools
Contributing
We welcome contributions! Please see our contributing guidelines:
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-feature
- Make your changes with proper tests and documentation
- Run the test suite:
make test
- Submit a pull request
Development Workflow
- Issues: Report bugs or request features via GitHub issues
- Pull Requests: Follow the PR template and ensure tests pass
- Code Review: All changes require review before merging
- Documentation: Update documentation for any new features
Code Style
- Follow PEP 8 for Python code
- Use type hints throughout
- Write comprehensive docstrings
- Add tests for new functionality
- Keep functions focused and small
License
This project is licensed under the MIT License - see the file for details.
Acknowledgments
- LangGraph for the workflow framework
- FastAPI for the web framework
- Pydantic for data validation
- Redis for memory persistence
- Rich for terminal UI
Built with β€οΈ for the AI agent community