# Directory Structure
```
├── .gitignore
├── LICENSE
├── pyproject.toml
├── README.md
├── tau_bench.png
├── think_mcp
│ ├── __init__.py
│ └── __main__.py
└── uv.lock
```
# Files
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# UV
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
#uv.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/latest/usage/project/#working-with-version-control
.pdm.toml
.pdm-python
.pdm-build/
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/
# Ruff stuff:
.ruff_cache/
# PyPI configuration file
.pypirc
.vscode/
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
# Think MCP Tool
Think MCP is an implementation of an MCP (Model Context Protocol) server that provides a "think" tool for structured reasoning in agentic AI workflows. This project is inspired by the Anthropic engineering article: [The "think" tool: Enabling Claude to stop and think in complex tool use situations](https://www.anthropic.com/engineering/claude-think-tool).
According to the referenced article, adding the think tool can lead to improved evaluation metrics by enabling reasoning capabilities even in models that do not natively possess advanced reasoning skills.

## What is the "think" tool?
The "think" tool allows an AI agent to pause and record an explicit thought during complex reasoning or multi-step tool use. It does not change the environment or database, but appends the thought to the log, helping the agent process information, backtrack, or comply with detailed policies.
This approach is especially useful for:
- Tool output analysis (processing results of previous tool calls)
- Policy-heavy environments (verifying compliance with guidelines)
- Sequential decision making (where each step builds on previous ones)
## Features
- Implements the "think" tool as described in Anthropic's research
- Minimal, standards-based MCP server using [mcp[cli]](https://pypi.org/project/mcp/)
- Ready for integration with Claude or other agentic LLMs
## Usage
### MCP server configuration
Add this MCP server to your facorite agent.
```
"mcpServers": {
"think-mcp": {
"command": "uvx",
"args": ["think-mcp"],
"enabled": true
}
}
```
## Tool definition
The "think" tool is defined as:
- **Input:** `thought` (string) — A thought to think about.
- **Behavior:** Appends the thought to the log for structured reasoning.
## Advanced mode
Adds aditional tools for your agent:
- criticize
- plan
- search
```
"mcpServers": {
"think-mcp": {
"command": "uvx",
"args": ["think-mcp", "--advanced"],
"enabled": true,
"env": {
"TAVILY_API_KEY": ... YOUR TAVILY API KEY HERE ...
}
}
}
```
## Reference
- Based on: [Anthropic Engineering Blog — The "think" tool](https://www.anthropic.com/engineering/claude-think-tool)
## License
MIT License — see [LICENSE](LICENSE)
```
--------------------------------------------------------------------------------
/think_mcp/__init__.py:
--------------------------------------------------------------------------------
```python
```
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
```toml
[project]
name = "think_mcp"
version = "0.1.16"
description = "MCP server providing a 'think' tool for structured reasoning, inspired by Anthropic's Claude 'think' tool. Enables agentic LLMs to pause, log thoughts, and improve multi-step tool use."
readme = "README.md"
requires-python = ">=3.10"
dependencies = [
"mcp[cli]>=1.6.0",
"python-dotenv>=1.1.0",
"tavily-python>=0.5.4",
]
authors = [
{ name = "Konstantin Krestnikov", email = "[email protected]" }
]
license = { text = "MIT" }
keywords = [
"mcp",
"think",
"agentic",
"llm",
"structured reasoning",
"anthropic",
"claude",
]
[project.urls]
Homepage = "https://github.com/Rai220/think-mcp"
[tool.setuptools.packages.find]
where = ["."]
[project.scripts]
think_mcp = "think_mcp.__main__:main"
think-mcp = "think_mcp.__main__:main"
```
--------------------------------------------------------------------------------
/think_mcp/__main__.py:
--------------------------------------------------------------------------------
```python
from mcp.server.fastmcp import FastMCP
from pydantic import Field
from dotenv import load_dotenv, find_dotenv
import argparse
import json
load_dotenv(find_dotenv())
mcp = FastMCP("think_mcp")
tavily_client = None
advanced_mode = False # default, may be set in main()
@mcp.prompt()
def system() -> str:
return """## Using the think tool
Before taking any action or responding to the user after receiving tool results, use the think tool as a scratchpad to:
- List the specific rules that apply to the current request
- Check if all required information is collected
- Verify that the planned action complies with all policies
- Iterate over tool results for correctness
Here are some examples of what to iterate over inside the think tool:
<think_tool_example_1>
User wants to cancel flight ABC123
- Need to verify: user ID, reservation ID, reason
- Check cancellation rules:
* Is it within 24h of booking?
* If not, check ticket class and insurance
- Verify no segments flown or are in the past
- Plan: collect missing info, verify rules, get confirmation
</think_tool_example_1>
<think_tool_example_2>
User wants to book 3 tickets to NYC with 2 checked bags each
- Need user ID to check:
* Membership tier for baggage allowance
* Which payments methods exist in profile
- Baggage calculation:
* Economy class × 3 passengers
* If regular member: 1 free bag each → 3 extra bags = $150
* If silver member: 2 free bags each → 0 extra bags = $0
* If gold member: 3 free bags each → 0 extra bags = $0
- Payment rules to verify:
* Max 1 travel certificate, 1 credit card, 3 gift cards
* All payment methods must be in profile
* Travel certificate remainder goes to waste
- Plan:
1. Get user ID
2. Verify membership level for bag fees
3. Check which payment methods in profile and if their combination is allowed
4. Calculate total: ticket price + any bag fees
5. Get explicit confirmation for booking
</think_tool_example_2>"""
@mcp.tool()
async def think(thought: str = Field(..., description="A thought to think about.")) -> str:
"""Use the tool to think about something.
It will not obtain new information or change the database, but just append the thought to the log.
Use it when complex reasoning or some cache memory is needed."""
return thought
parser = argparse.ArgumentParser(description="Think MCP server")
parser.add_argument('--advanced', action='store_true', help='Enable advanced mode (plan, search, criticize tools)')
args = parser.parse_args()
if args.advanced:
print("Advanced mode enabled. Loading advanced tools...")
@mcp.tool()
async def criticize(criticism: str = Field(..., description="Сonstructive criticism")) -> str:
"""Use the tool to critic your steps.
It will not obtain new information or change the database, but just append the thought to the log.
Use it when complex reasoning or some cache memory is needed."""
return criticism
@mcp.tool()
async def plan(plan: str = Field(..., description="A plan of next steps")) -> str:
"""Use the tool to plan your steps.
It will not obtain new information or change the database, but just append the thought to the log.
Use it when complex reasoning or some cache memory is needed."""
return plan
@mcp.tool()
async def search(query: str = Field(..., description="Search query")) -> str:
"""Search the web for a given query."""
from tavily import TavilyClient
tavily_client = TavilyClient()
context = tavily_client.get_search_context(query=query)
return json.dumps(context, ensure_ascii=False)
def main():
mcp.run(transport='stdio')
if __name__ == "__main__":
main()
```