# ABOUTME: MCP server providing a 'think' tool for structured reasoning
# ABOUTME: Allows Claude to add thinking steps during complex tool use
from datetime import datetime
import json
from typing import Any
from mcp.server import Server
from mcp.server.stdio import stdio_server
from mcp.types import Tool, TextContent, Resource, Prompt, PromptArgument
from pydantic import BaseModel
# Store thoughts in memory (could be persisted to file if needed)
thoughts_log = []
class ThinkInput(BaseModel):
thought: str
async def serve():
"""Serve the MCP server using stdio transport."""
server = Server("mcp-server-scratchpad")
@server.list_tools()
async def list_tools() -> list[Tool]:
"""List available tools."""
return [
Tool(
name="think",
description="Use this tool to think about something. It will not obtain new information or change any database, but just append the thought to the log.",
inputSchema={
"type": "object",
"properties": {
"thought": {
"type": "string",
"description": "A thought to think about"
}
},
"required": ["thought"]
}
),
Tool(
name="clear_thoughts",
description="Clear all thoughts from the log",
inputSchema={
"type": "object",
"properties": {}
}
)
]
@server.call_tool()
async def call_tool(name: str, arguments: dict[str, Any]) -> list[TextContent]:
"""Handle tool calls."""
if name == "think":
thought = arguments["thought"]
timestamp = datetime.now().isoformat()
thought_entry = {
"timestamp": timestamp,
"thought": thought
}
thoughts_log.append(thought_entry)
return [TextContent(type="text", text=f"Thought logged at {timestamp}")]
elif name == "clear_thoughts":
thoughts_log.clear()
return [TextContent(type="text", text="Thinking log cleared")]
else:
raise ValueError(f"Unknown tool: {name}")
@server.list_resources()
async def list_resources() -> list[Resource]:
"""List available resources."""
return [
Resource(
uri="log://thoughts",
title="Thinking Log",
description="View all logged thoughts"
)
]
@server.read_resource()
async def read_resource(uri: str) -> str:
"""Read a resource."""
if uri == "log://thoughts":
if not thoughts_log:
return "No thoughts logged yet."
return json.dumps(thoughts_log, indent=2)
else:
raise ValueError(f"Unknown resource: {uri}")
@server.list_prompts()
async def list_prompts() -> list[Prompt]:
"""List available prompts."""
return [
Prompt(
name="structured_thinking",
title="Structured Thinking",
description="Template for systematic problem-solving using the think tool",
arguments=[
PromptArgument(
name="topic",
description="The topic or problem to think through",
required=True
)
]
)
]
@server.get_prompt()
async def get_prompt(name: str, arguments: dict[str, str] | None) -> list[dict]:
"""Get a prompt."""
if name == "structured_thinking":
if not arguments or "topic" not in arguments:
raise ValueError("Topic argument is required")
topic = arguments["topic"]
return [{
"role": "user",
"content": {
"type": "text",
"text": f"""Please use the 'think' tool to work through this topic step by step: {topic}
Remember to:
1. Break down the problem into smaller parts
2. Consider different angles and approaches
3. Validate your reasoning at each step
4. Summarize your conclusions"""
}
}]
else:
raise ValueError(f"Unknown prompt: {name}")
options = server.create_initialization_options()
async with stdio_server() as (read_stream, write_stream):
await server.run(read_stream, write_stream, options)