Skip to main content
Glama
MichaelGNielsen

dad-jokes-mcp

Agent instructions: See AGENTS.md for architecture, commands, and how to add tools.

Note: Denne MCP server er fuldt kompatibel med MCP-klienter der understøtter HTTP transport, herunder Page Assist, Gemini, og andre moderne AI-værktøjer.

Available Tools

Tool Name

Description

Input

Output

Example

curl

get_random_joke

Fetch a random dad joke and save it

None

Joke text

@dad-jokes-mcp get_random_joke

curl -X POST http://localhost:5000/mcp -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_random_joke","arguments":{}}}'

get_multiple_jokes

Fetch multiple random dad jokes at once

count (1-20, default: 5)

Array of jokes

@dad-jokes-mcp get_multiple_jokes count=10

curl -X POST http://localhost:5000/mcp -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_multiple_jokes","arguments":{"count":10}}}'

server_status

Show server version, sources count, stored jokes, tools

None

JSON status

@dad-jokes-mcp server_status

curl -X POST http://localhost:5000/mcp -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"server_status","arguments":{}}}'

get_all_jokes

View all jokes stored in www/jokes.json

None

All saved jokes

@dad-jokes-mcp get_all_jokes

curl -X POST http://localhost:5000/mcp -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_all_jokes","arguments":{}}}'

clear_jokes

Delete all saved jokes

None

Confirmation

@dad-jokes-mcp clear_jokes

curl -X POST http://localhost:5000/mcp -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"clear_jokes","arguments":{}}}'

get_joke_category

Get joke from category

category (enum)

Joke from category

@dad-jokes-mcp get_joke_category category=Programming

curl -X POST http://localhost:5000/mcp -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_joke_category","arguments":{"category":"Programming"}}}'

fill_jokes_batch

Ensure at least N jokes are stored; fetches if needed

count (1-20, default: 5)

N jokes from pool

@dad-jokes-mcp fill_jokes_batch count=10

curl -X POST http://localhost:5000/mcp -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"fill_jokes_batch","arguments":{"count":10}}}'

add_jokes

Fetch and store N new jokes unconditionally

count (1-20, default: 5)

N new jokes added

@dad-jokes-mcp add_jokes count=10

curl -X POST http://localhost:5000/mcp -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"add_jokes","arguments":{"count":10}}}'

add_joke

Add a custom joke manually

text (string)

Confirmation

@dad-jokes-mcp add_joke text="Why..."

curl -X POST http://localhost:5000/mcp -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"add_joke","arguments":{"text":"Why did the chicken cross the road?"}}}'

clean_jokes

Remove null/empty entries from the pool

None

Cleanup result

@dad-jokes-mcp clean_jokes

curl -X POST http://localhost:5000/mcp -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"clean_jokes","arguments":{}}}'

Related MCP server: Jokes MCP Server

How MCP Tool Routing Works

The Short Answer

Nej, det er ikke hardkodet. Det er dynamisk routing baseret på tool-navn.

Hvad der sker når du skriver:

@dad-jokes-mcp get_multiple_jokes count=10

Step 1: PA parser din besked

  • PA ser @dad-jokes-mcp = server navn

  • PA ser get_multiple_jokes = tool navn

  • PA ser count=10 = argument

Step 2: PA laver en JSON-RPC request

{
  "jsonrpc": "2.0",
  "id": 123,
  "method": "tools/call",
  "params": {
    "name": "get_multiple_jokes",
    "arguments": {
      "count": 10
    }
  }
}

Step 3: MCP Server modtager request

Serveren (dad_jokes_mcp.mjs) modtager JSON via POST /mcp:

if (request.method === "tools/call") {
  const { name, arguments: args } = request.params;

  // name = "get_multiple_jokes"
  // args = { count: 10 }


**Step 4: Server matcher tool-navn og udfører**

Serveren bruger et **handler lookup-objekt** i stedet for if/else:

```javascript
const handlers = {
  get_random_joke: async () => { /* ... */ },
  get_multiple_jokes: async () => { /* ... */ },  // ← MATCH!
  get_all_jokes: async () => { /* ... */ },
  clear_jokes: async () => { /* ... */ },
  get_joke_category: async () => { /* ... */ },
  fill_jokes_batch: async () => { /* ... */ },
  add_jokes: async () => { /* ... */ },
  add_joke: async () => { /* ... */ },
  clean_jokes: async () => { /* ... */ },
};

const handler = handlers[name];
if (handler) {
  toolResponse = await handler(args);
} else {
  toolResponse = { error: { code: -32601, message: `Tool not found: ${name}` } };
}

Step 5: Server returnerer resultat

{
  "jsonrpc": "2.0",
  "id": 123,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "😄 10 Dad Jokes:\n\n1. ...\n2. ..."
      }
    ]
  }
}

Step 6: PA viser resultatet

PA modtager resultatet og viser det for brugeren.

Hvorfor er det ikke hardkodet?

  1. Tool-navne er defineret dynamisk - I tools/list metoden returnerer serveren hvilke tools der findes

  2. Arguments er dynamiske - Hver tool kan have forskellige inputs

  3. Routing er baseret på string matching - if (name === "tool_name") matcher kun hvis navn passer

Hvis du tilføjede en ny tool

Du skulle:

  1. Tilføje den til tools/list response:

{
  name: "my_new_tool",
  description: "What it does",
  inputSchema: { /* ... */ }
}
  1. Tilføje en key i handlers-objektet i tools/call:

my_new_tool: async () => {
  return { content: [{ type: "text", text: "Result" }] };
},
  1. PA ville automatisk detektere den næste gang den kalder tools/list!

MCP Protocol Flow

PA Client                          MCP Server (dad_jokes_mcp.js)
   │                                        │
   ├─ POST /mcp (initialize) ───────────────┤
   │                                        │
   │ ◄──── { serverInfo, capabilities } ────┤
   │                                        │
   ├─ POST /mcp (tools/list) ───────────────┤
   │                                        │
   │ ◄──── { tools: [...] } ────────────────┤
   │                                        │
   ├─ POST /mcp (tools/call) ───────────────┤
   │   { name: "get_multiple_jokes", ... }  │
   │                                        │
   │ ◄──── { result: { content: [...] } } ──┤
   │                                        │

API Details

MCP Endpoint: /mcp

Method: POST

Headers:

  • Content-Type: application/json

  • Mcp-Session-Id (response header - auto-generated)

Request Format: JSON-RPC 2.0

Example request body for calling a tool:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_random_joke",
    "arguments": {}
  }
}

Dad Jokes MCP Server

A Model Context Protocol (MCP) server that fetches and manages dad jokes via Streamable HTTP transport. Jokes are automatically saved to persistent storage.

Features

  • 🎯 Streamable HTTP Transport - Uses MCP 2024-11-05 protocol

  • 💾 Persistent Storage - Jokes automatically saved to www/jokes.json

  • 😄 Multiple Joke Sources - Fetches from 9+ joke APIs

  • 🐳 Docker Ready - Full Docker setup with volume mounts

  • 🔧 10 Tools:

    • get_random_joke - Fetch a random dad joke and save it

    • get_multiple_jokes - Fetch multiple jokes at once

    • server_status - View server status, version, and stats

    • get_all_jokes - View all saved jokes

    • clear_jokes - Clear saved jokes

    • get_joke_category - Get jokes by category (Programming, Knock-knock, General, Chuck Norris)

    • fill_jokes_batch - Ensure at least N jokes are stored

    • add_jokes - Fetch and store N new jokes

    • add_joke - Add a custom joke manually

    • clean_jokes - Remove null/empty entries

Quick Start

Prerequisites

  • Docker & Docker Compose

  • Node.js 20+ (for local development)

Run with Docker

docker compose up -d

The server will start on http://localhost:5000/ (frontend) with MCP endpoint at /mcp

MCP Configuration

Add to your MCP client config (Gemini, Page Assist, etc):

{
  "mcp": {
    "servers": {
      "dad-jokes": {
        "url": "http://localhost:5000/mcp"
      }
    }
  }
}

Testing

See docs/test.md for the full test suite, JSON fixtures, and gotchas.

Test with curl

# Initialize
curl -X POST http://localhost:5000/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'

# List tools
curl -X POST http://localhost:5000/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'

# Get a random joke
curl -X POST http://localhost:5000/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"get_random_joke","arguments":{}}}'

Project Structure

dad-jokes-mcp/
├── dad_jokes_mcp.mjs        # Main server code
├── package.json             # Node.js dependencies
├── Dockerfile               # Docker image definition
├── docker-compose.yml       # Docker Compose config
├── .dockerignore            # Docker build exclusions
├── www/
│   └── jokes.json           # Persistent jokes storage
└── .git/                    # Git repository

Jokes Storage

Jokes are automatically saved to www/jokes.json with the following structure:

[
  "Chuck Norris can understand women.",
  "Why did the scarecrow win an award? He was outstanding in his field.",
  "..."
]

The file persists across container restarts due to Docker volume mounting.

API Details

MCP Endpoint: /mcp

Method: POST

Headers:

  • Content-Type: application/json

  • Mcp-Session-Id (response header - auto-generated)

Request Format: JSON-RPC 2.0

Example request body for calling a tool:

{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "tools/call",
  "params": {
    "name": "get_random_joke",
    "arguments": {}
  }
}

Environment Variables

  • PORT - Server port (default: 5000)

Docker Volumes

  • ./www:/app/www - Mounts local www/ directory for persistent joke storage

Development

Local Development (without Docker)

npm install
PORT=5000 node dad_jokes_mcp.mjs

Build Docker Image

docker compose build

View Logs

docker logs dad-jokes-mcp-server -f

Troubleshooting

MCP Validation Failed

If you see "Legacy MCP SSE endpoints are not supported", ensure your MCP client is configured to use the Streamable HTTP endpoint:

http://localhost:5000/mcp  ✓ Correct
http://localhost:5000/sse  ✗ Deprecated (SSE)

No Jokes Saved

  • Check Docker volume mount: docker compose config | grep volumes

  • Verify www/ directory exists: ls -la www/

  • Check container logs: docker logs dad-jokes-mcp-server

API Connection Issues

  • Ensure server is running: curl http://localhost:5000/

  • Check port availability: netstat -an | grep 5000

  • Verify firewall allows port 5000

Performance

  • Joke fetching: ~1-3 seconds (with retries)

  • JSON parsing: <100ms

  • File I/O: ~50-200ms depending on disk speed

License

MIT

Author

Michael G. Nielsen


Dad jokes duh 😄

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables users to retrieve jokes from various categories including Chuck Norris jokes and dad jokes. Provides a humor-focused tool that can be integrated into Microsoft Copilot Studio agents for delivering appropriate and engaging jokes upon request.
    MIT
  • A
    license
    Not graded
    quality
    C
    maintenance
    Provides access to dad jokes from icanhazdadjoke.com with the ability to get random jokes, search by keyword, and retrieve specific jokes by ID.
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides dad jokes in multiple styles and topics through prompts and tools, including joke generation, rating, category browsing, and statistics to add humor to development workflows.
    8 npm
    3
    MIT