@rhofkens/mcp-quotes-server-claude-code
Version:
Model Context Protocol (MCP) server for managing and serving quotes
528 lines (426 loc) • 11.5 kB
Markdown
# MCP Quotes Server - Usage Examples
This document provides comprehensive examples of using the MCP Quotes Server in various scenarios.
## Table of Contents
- [Basic Usage](#basic-usage)
- [Advanced Features](#advanced-features)
- [Error Handling](#error-handling)
- [Integration Patterns](#integration-patterns)
- [Troubleshooting](#troubleshooting)
## Basic Usage
### Getting Started
First, ensure your server is running with the correct environment variables:
```bash
export SERPER_API_KEY="your-api-key-here"
npx mcp-quotes-server
```
### Simple Quote Request
The most basic usage is requesting quotes from a person:
```json
{
"tool": "getQuotes",
"arguments": {
"person": "Albert Einstein",
"numberOfQuotes": 3
}
}
```
**Expected Response:**
```json
{
"quotes": [
{
"text": "Imagination is more important than knowledge.",
"author": "Albert Einstein",
"source": "https://example.com/einstein-quotes"
},
{
"text": "Life is like riding a bicycle. To keep your balance, you must keep moving.",
"author": "Albert Einstein",
"source": "https://example.com/einstein-bicycle"
},
{
"text": "The important thing is not to stop questioning.",
"author": "Albert Einstein",
"source": "https://example.com/einstein-curiosity"
}
]
}
```
### Topic-Specific Quotes
Filter quotes by a specific topic:
```json
{
"tool": "getQuotes",
"arguments": {
"person": "Maya Angelou",
"numberOfQuotes": 2,
"topic": "courage"
}
}
```
### Using the Prompt Template
First, retrieve the prompt template:
```json
{
"resource": "quotes://prompt-template"
}
```
This returns a structured template:
```json
{
"template": "Find {numberOfQuotes} quotes from {person} {topic}. Return them in a structured format with proper attribution.",
"variables": {
"person": {
"description": "The person whose quotes you want to retrieve. Can be any famous or notable individual.",
"required": true,
"examples": ["Albert Einstein", "Maya Angelou", "Steve Jobs", "Marie Curie"]
},
"numberOfQuotes": {
"description": "The number of quotes to retrieve. Must be between 1 and 10.",
"required": true,
"default": 3,
"minimum": 1,
"maximum": 10
},
"topic": {
"description": "Optional topic to filter quotes. When provided, quotes will be related to this subject.",
"required": false,
"examples": ["success", "innovation", "life", "education", "happiness"]
}
},
"instructions": "To use this template, replace the variables in curly braces with your desired values.",
"exampleUsage": {
"request": "Find 3 quotes from Albert Einstein about imagination.",
"expectedFormat": "1. \"Imagination is more important than knowledge.\" - Albert Einstein\n..."
}
}
```
## Advanced Features
### Handling Different Person Names
The tool handles various name formats:
```json
// Full names with titles
{
"person": "Dr. Martin Luther King Jr.",
"numberOfQuotes": 3
}
// Names with special characters
{
"person": "Jean-Paul Sartre",
"numberOfQuotes": 2
}
// Single names
{
"person": "Plato",
"numberOfQuotes": 4
}
// Contemporary figures
{
"person": "Elon Musk",
"numberOfQuotes": 2,
"topic": "innovation"
}
```
### Multiple Topic Searches
For broader searches, you can make multiple requests with different topics:
```javascript
const topics = ["success", "failure", "perseverance"];
const allQuotes = [];
for (const topic of topics) {
const result = await mcpClient.callTool("getQuotes", {
person: "Winston Churchill",
numberOfQuotes: 2,
topic: topic
});
allQuotes.push(...result.quotes);
}
```
## Error Handling
### Missing API Key
If the SERPER_API_KEY is not set:
```json
{
"error": {
"code": "CONFIG_ERROR",
"message": "Configuration error: Missing or invalid SERPER_API_KEY. Please set the SERPER_API_KEY environment variable with your API key from https://serper.dev. You can export it in your terminal or add it to a .env file."
}
}
```
**Solution:**
```bash
# Set the API key before starting the server
export SERPER_API_KEY="your-api-key"
# Or add to .env file
echo "SERPER_API_KEY=your-api-key" >> .env
```
### Invalid Parameters
Request with invalid numberOfQuotes:
```json
{
"tool": "getQuotes",
"arguments": {
"person": "Albert Einstein",
"numberOfQuotes": 20
}
}
```
**Error Response:**
```json
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid value for field 'numberOfQuotes': Value must be between 1 and 10. The numberOfQuotes field must be a number between 1 and 10."
}
}
```
### Rate Limiting
When you exceed the API rate limits:
```json
{
"error": {
"code": "API_RATE_LIMIT",
"message": "Rate limit exceeded for serper. To avoid this:\n1. Wait a few minutes before retrying\n2. Reduce the number of quotes requested\n3. Space out your requests over time\n4. Consider upgrading your API plan if this happens frequently"
}
}
```
### Network Issues
When the server cannot reach the API:
```json
{
"error": {
"code": "API_TIMEOUT",
"message": "The request timed out (serper). This may be due to network issues or server load. Please try again in a few moments."
}
}
```
## Integration Patterns
### With Claude Desktop
Add to your Claude Desktop configuration (`~/.claude/config.json`):
```json
{
"mcpServers": {
"quotes": {
"command": "npx",
"args": ["mcp-quotes-server"],
"env": {
"SERPER_API_KEY": "your-api-key",
"LOG_LEVEL": "info"
}
}
}
}
```
Usage in Claude:
```
"Can you find me 5 inspirational quotes from Nelson Mandela about freedom?"
```
### Programmatic Usage with MCP Client
```typescript
import { McpClient } from '@modelcontextprotocol/sdk';
const client = new McpClient();
// Connect to the server
await client.connect({
command: 'npx',
args: ['mcp-quotes-server'],
env: { SERPER_API_KEY: process.env.SERPER_API_KEY }
});
// Get quotes
const result = await client.callTool('getQuotes', {
person: 'Steve Jobs',
numberOfQuotes: 3,
topic: 'innovation'
});
console.log(result.quotes);
```
### Building a Quote Collection
```typescript
// Function to collect quotes from multiple people on a topic
async function collectQuotesOnTopic(topic: string, people: string[]) {
const collection = [];
for (const person of people) {
try {
const result = await client.callTool('getQuotes', {
person,
numberOfQuotes: 2,
topic
});
collection.push({
person,
quotes: result.quotes
});
} catch (error) {
console.error(`Failed to get quotes from ${person}:`, error.message);
}
}
return collection;
}
// Usage
const wisdomCollection = await collectQuotesOnTopic('wisdom', [
'Socrates',
'Confucius',
'Buddha',
'Marcus Aurelius'
]);
```
### Error Recovery Pattern
```typescript
async function getQuotesWithRetry(params, maxRetries = 3) {
let lastError;
for (let i = 0; i < maxRetries; i++) {
try {
return await client.callTool('getQuotes', params);
} catch (error) {
lastError = error;
// Handle specific error types
if (error.code === 'API_RATE_LIMIT') {
// Wait longer for rate limits
await new Promise(resolve => setTimeout(resolve, 60000));
} else if (error.code === 'API_TIMEOUT') {
// Shorter wait for timeouts
await new Promise(resolve => setTimeout(resolve, 5000));
} else if (error.code === 'VALIDATION_ERROR') {
// Don't retry validation errors
throw error;
}
}
}
throw lastError;
}
```
## Troubleshooting
### Common Issues and Solutions
#### 1. Server Won't Start
**Issue:** Server fails to start with configuration error
**Solution:**
```bash
# Check if API key is set
echo $SERPER_API_KEY
# If empty, set it
export SERPER_API_KEY="your-api-key"
# Or use a .env file
echo "SERPER_API_KEY=your-api-key" > .env
```
#### 2. No Quotes Found
**Issue:** Server returns empty quotes array
**Possible Causes:**
- Person name is misspelled
- Person is not well-known enough
- Topic is too specific
**Solutions:**
```json
// Try without topic first
{
"person": "Albert Einstein",
"numberOfQuotes": 3
}
// Try different name variations
{
"person": "Einstein",
"numberOfQuotes": 3
}
// Try broader topics
{
"person": "Albert Einstein",
"numberOfQuotes": 3,
"topic": "science" // instead of "quantum mechanics"
}
```
#### 3. Authentication Failures
**Issue:** Consistent authentication errors
**Debugging Steps:**
```bash
# Test your API key directly
curl -X POST https://google.serper.dev/search \
-H 'X-API-KEY: your-api-key' \
-H 'Content-Type: application/json' \
-d '{"q": "test"}'
# Check API key status at https://serper.dev/dashboard
```
#### 4. Slow Response Times
**Issue:** Quotes take too long to retrieve
**Solutions:**
- Reduce numberOfQuotes
- Remove topic filter for faster searches
- Check network connectivity
- Consider caching frequently requested quotes
### Debug Mode
Enable debug logging for troubleshooting:
```bash
export LOG_LEVEL=debug
export NODE_ENV=development
npx mcp-quotes-server
```
This will show detailed logs including:
- API request/response details
- Search query construction
- Quote extraction process
- Error stack traces
## Best Practices
1. **Start Simple**: Begin with basic requests before adding topics
2. **Handle Errors Gracefully**: Always wrap tool calls in try-catch blocks
3. **Respect Rate Limits**: Space out requests when making multiple calls
4. **Cache When Possible**: Store frequently requested quotes locally
5. **Validate Input**: Check parameters before sending to avoid validation errors
6. **Use the Template**: Reference the prompt template for correct formatting
7. **Monitor Usage**: Keep track of API calls to stay within limits
## Example Applications
### Daily Quote Widget
```typescript
async function getDailyQuote() {
const people = [
'Marcus Aurelius', 'Lao Tzu', 'Rumi',
'Maya Angelou', 'Nelson Mandela'
];
const person = people[Math.floor(Math.random() * people.length)];
const result = await client.callTool('getQuotes', {
person,
numberOfQuotes: 1,
topic: 'wisdom'
});
return result.quotes[0];
}
```
### Quote Search API
```typescript
app.get('/api/quotes', async (req, res) => {
try {
const { person, count = 5, topic } = req.query;
if (!person) {
return res.status(400).json({ error: 'Person parameter required' });
}
const result = await client.callTool('getQuotes', {
person,
numberOfQuotes: Math.min(parseInt(count), 10),
topic
});
res.json(result);
} catch (error) {
res.status(500).json({
error: error.message,
guidance: error.getUserMessage?.() || 'Please try again'
});
}
});
```
### Educational Quote Collector
```typescript
async function collectEducationalQuotes() {
const educators = [
'John Dewey', 'Maria Montessori', 'Paulo Freire',
'bell hooks', 'Howard Gardner'
];
const quotes = await Promise.allSettled(
educators.map(person =>
client.callTool('getQuotes', {
person,
numberOfQuotes: 3,
topic: 'education'
})
)
);
return quotes
.filter(result => result.status === 'fulfilled')
.map(result => result.value.quotes)
.flat();
}
```