futuresearch-mcp 0.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- futuresearch_mcp-0.6.0/.gitignore +232 -0
- futuresearch_mcp-0.6.0/.mcpbignore +13 -0
- futuresearch_mcp-0.6.0/PKG-INFO +200 -0
- futuresearch_mcp-0.6.0/README.md +181 -0
- futuresearch_mcp-0.6.0/deploy/.dockerignore +15 -0
- futuresearch_mcp-0.6.0/deploy/.env.example +8 -0
- futuresearch_mcp-0.6.0/deploy/Dockerfile +36 -0
- futuresearch_mcp-0.6.0/deploy/chart/.gitignore +4 -0
- futuresearch_mcp-0.6.0/deploy/chart/.sops.yaml +2 -0
- futuresearch_mcp-0.6.0/deploy/chart/Chart.yaml +6 -0
- futuresearch_mcp-0.6.0/deploy/chart/secrets.enc.yaml +15 -0
- futuresearch_mcp-0.6.0/deploy/chart/secrets.staging.enc.yaml +14 -0
- futuresearch_mcp-0.6.0/deploy/chart/templates/deployment.yaml +96 -0
- futuresearch_mcp-0.6.0/deploy/chart/templates/gcpbackendpolicy.yaml +15 -0
- futuresearch_mcp-0.6.0/deploy/chart/templates/httproute.yaml +19 -0
- futuresearch_mcp-0.6.0/deploy/chart/templates/networkpolicy.yaml +90 -0
- futuresearch_mcp-0.6.0/deploy/chart/templates/secrets.yaml +13 -0
- futuresearch_mcp-0.6.0/deploy/chart/templates/service.yaml +17 -0
- futuresearch_mcp-0.6.0/deploy/chart/templates/serviceaccount.yaml +5 -0
- futuresearch_mcp-0.6.0/deploy/chart/values.staging.yaml +16 -0
- futuresearch_mcp-0.6.0/deploy/chart/values.yaml +91 -0
- futuresearch_mcp-0.6.0/deploy/docker-compose.local.yaml +12 -0
- futuresearch_mcp-0.6.0/deploy/docker-compose.multi.yaml +22 -0
- futuresearch_mcp-0.6.0/deploy/docker-compose.yaml +62 -0
- futuresearch_mcp-0.6.0/deploy/nginx.conf +13 -0
- futuresearch_mcp-0.6.0/images/future-search-logo-128.png +3 -0
- futuresearch_mcp-0.6.0/manifest.json +115 -0
- futuresearch_mcp-0.6.0/pyproject.toml +69 -0
- futuresearch_mcp-0.6.0/server.json +33 -0
- futuresearch_mcp-0.6.0/src/futuresearch_mcp/__init__.py +1 -0
- futuresearch_mcp-0.6.0/src/futuresearch_mcp/app.py +183 -0
- futuresearch_mcp-0.6.0/src/futuresearch_mcp/auth.py +712 -0
- futuresearch_mcp-0.6.0/src/futuresearch_mcp/config.py +193 -0
- futuresearch_mcp-0.6.0/src/futuresearch_mcp/http_config.py +264 -0
- futuresearch_mcp-0.6.0/src/futuresearch_mcp/middleware.py +189 -0
- futuresearch_mcp-0.6.0/src/futuresearch_mcp/models.py +792 -0
- futuresearch_mcp-0.6.0/src/futuresearch_mcp/redis_store.py +322 -0
- futuresearch_mcp-0.6.0/src/futuresearch_mcp/result_store.py +425 -0
- futuresearch_mcp-0.6.0/src/futuresearch_mcp/routes.py +326 -0
- futuresearch_mcp-0.6.0/src/futuresearch_mcp/server.py +160 -0
- futuresearch_mcp-0.6.0/src/futuresearch_mcp/templates.py +898 -0
- futuresearch_mcp-0.6.0/src/futuresearch_mcp/tool_helpers.py +570 -0
- futuresearch_mcp-0.6.0/src/futuresearch_mcp/tools.py +1433 -0
- futuresearch_mcp-0.6.0/src/futuresearch_mcp/uploads.py +274 -0
- futuresearch_mcp-0.6.0/src/futuresearch_mcp/utils.py +457 -0
- futuresearch_mcp-0.6.0/tests/__init__.py +1 -0
- futuresearch_mcp-0.6.0/tests/conftest.py +284 -0
- futuresearch_mcp-0.6.0/tests/test_auth.py +904 -0
- futuresearch_mcp-0.6.0/tests/test_http_integration.py +599 -0
- futuresearch_mcp-0.6.0/tests/test_http_real.py +255 -0
- futuresearch_mcp-0.6.0/tests/test_http_transport.py +353 -0
- futuresearch_mcp-0.6.0/tests/test_integration.py +559 -0
- futuresearch_mcp-0.6.0/tests/test_manifest_sync.py +66 -0
- futuresearch_mcp-0.6.0/tests/test_mcp_e2e.py +469 -0
- futuresearch_mcp-0.6.0/tests/test_middleware.py +239 -0
- futuresearch_mcp-0.6.0/tests/test_redis_utils.py +77 -0
- futuresearch_mcp-0.6.0/tests/test_result_store.py +1112 -0
- futuresearch_mcp-0.6.0/tests/test_routes.py +498 -0
- futuresearch_mcp-0.6.0/tests/test_security_hardening.py +100 -0
- futuresearch_mcp-0.6.0/tests/test_server.py +2152 -0
- futuresearch_mcp-0.6.0/tests/test_state_redis.py +126 -0
- futuresearch_mcp-0.6.0/tests/test_stdio_content.py +829 -0
- futuresearch_mcp-0.6.0/tests/test_tool_helpers.py +162 -0
- futuresearch_mcp-0.6.0/tests/test_ua_detection.py +72 -0
- futuresearch_mcp-0.6.0/tests/test_uploads.py +404 -0
- futuresearch_mcp-0.6.0/tests/test_utils.py +504 -0
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
# Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
# uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
# poetry.lock
|
|
109
|
+
# poetry.toml
|
|
110
|
+
|
|
111
|
+
# pdm
|
|
112
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
113
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
114
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
115
|
+
# pdm.lock
|
|
116
|
+
# pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# pixi
|
|
121
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
122
|
+
# pixi.lock
|
|
123
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
124
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
125
|
+
.pixi
|
|
126
|
+
|
|
127
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
128
|
+
__pypackages__/
|
|
129
|
+
|
|
130
|
+
# Celery stuff
|
|
131
|
+
celerybeat-schedule
|
|
132
|
+
celerybeat.pid
|
|
133
|
+
|
|
134
|
+
# Redis
|
|
135
|
+
*.rdb
|
|
136
|
+
*.aof
|
|
137
|
+
*.pid
|
|
138
|
+
|
|
139
|
+
# RabbitMQ
|
|
140
|
+
mnesia/
|
|
141
|
+
rabbitmq/
|
|
142
|
+
rabbitmq-data/
|
|
143
|
+
|
|
144
|
+
# ActiveMQ
|
|
145
|
+
activemq-data/
|
|
146
|
+
|
|
147
|
+
# SageMath parsed files
|
|
148
|
+
*.sage.py
|
|
149
|
+
|
|
150
|
+
# Environments
|
|
151
|
+
.env
|
|
152
|
+
.envrc
|
|
153
|
+
.venv
|
|
154
|
+
env/
|
|
155
|
+
venv/
|
|
156
|
+
ENV/
|
|
157
|
+
env.bak/
|
|
158
|
+
venv.bak/
|
|
159
|
+
|
|
160
|
+
# Spyder project settings
|
|
161
|
+
.spyderproject
|
|
162
|
+
.spyproject
|
|
163
|
+
|
|
164
|
+
# Rope project settings
|
|
165
|
+
.ropeproject
|
|
166
|
+
|
|
167
|
+
# mkdocs documentation
|
|
168
|
+
/site
|
|
169
|
+
|
|
170
|
+
# mypy
|
|
171
|
+
.mypy_cache/
|
|
172
|
+
.dmypy.json
|
|
173
|
+
dmypy.json
|
|
174
|
+
|
|
175
|
+
# Pyre type checker
|
|
176
|
+
.pyre/
|
|
177
|
+
|
|
178
|
+
# pytype static type analyzer
|
|
179
|
+
.pytype/
|
|
180
|
+
|
|
181
|
+
# Cython debug symbols
|
|
182
|
+
cython_debug/
|
|
183
|
+
|
|
184
|
+
# PyCharm
|
|
185
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
186
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
187
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
188
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
189
|
+
.idea/
|
|
190
|
+
|
|
191
|
+
# Abstra
|
|
192
|
+
# Abstra is an AI-powered process automation framework.
|
|
193
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
194
|
+
# Learn more at https://abstra.io/docs
|
|
195
|
+
.abstra/
|
|
196
|
+
|
|
197
|
+
# Visual Studio Code
|
|
198
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
199
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
200
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
201
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
202
|
+
.vscode/
|
|
203
|
+
|
|
204
|
+
# MacOS
|
|
205
|
+
.DS_Store
|
|
206
|
+
|
|
207
|
+
# Ruff stuff:
|
|
208
|
+
.ruff_cache/
|
|
209
|
+
|
|
210
|
+
# PyPI configuration file
|
|
211
|
+
.pypirc
|
|
212
|
+
|
|
213
|
+
# Marimo
|
|
214
|
+
marimo/_static/
|
|
215
|
+
marimo/_lsp/
|
|
216
|
+
__marimo__/
|
|
217
|
+
|
|
218
|
+
# Streamlit
|
|
219
|
+
.streamlit/secrets.toml
|
|
220
|
+
|
|
221
|
+
.history/
|
|
222
|
+
.python-version
|
|
223
|
+
|
|
224
|
+
# MCPB bundles
|
|
225
|
+
*.mcpb
|
|
226
|
+
|
|
227
|
+
# MCP registry tokens
|
|
228
|
+
.mcpregistry_*
|
|
229
|
+
|
|
230
|
+
# Claude Code local instructions
|
|
231
|
+
CLAUDE.local.md
|
|
232
|
+
worktrees/
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: futuresearch-mcp
|
|
3
|
+
Version: 0.6.0
|
|
4
|
+
Summary: MCP server for futuresearch: a researcher for every row
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
|
+
Requires-Dist: futuresearch>=0.6.0
|
|
7
|
+
Requires-Dist: httpx>=0.27.0
|
|
8
|
+
Requires-Dist: jsonschema>=4.0.0
|
|
9
|
+
Requires-Dist: litellm>=1.50.0
|
|
10
|
+
Requires-Dist: mcp[cli]>=1.0.0
|
|
11
|
+
Requires-Dist: pandas>=2.0.0
|
|
12
|
+
Requires-Dist: pydantic-settings>=2.0.0
|
|
13
|
+
Requires-Dist: pydantic<3.0.0,>=2.0.0
|
|
14
|
+
Requires-Dist: pyjwt[crypto]>=2.8.0
|
|
15
|
+
Requires-Dist: redis[hiredis]>=5.0.0
|
|
16
|
+
Requires-Dist: sentry-sdk[starlette]>=2.0.0
|
|
17
|
+
Requires-Dist: tabulate>=0.9.0
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# FutureSearch MCP Server
|
|
21
|
+
|
|
22
|
+
> Most users don't need to run the MCP server locally. Use the hosted remote server at `https://mcp.futuresearch.ai/mcp` — it authenticates via OAuth, no API key needed. See the [setup guide](https://futuresearch.ai/docs). The instructions below are for self-hosted or advanced use cases where an API key is required.
|
|
23
|
+
|
|
24
|
+
MCP (Model Context Protocol) server for [FutureSearch](https://futuresearch.ai): agent ops at spreadsheet scale.
|
|
25
|
+
|
|
26
|
+
This server exposes FutureSearch's core operations as MCP tools, allowing LLM applications to classify, rank, dedupe, merge, forecast, and run agents on CSV files.
|
|
27
|
+
|
|
28
|
+
**All tools operate on local CSV files.** Provide absolute file paths as input, and transformed results are written to new CSV files at your specified output path.
|
|
29
|
+
|
|
30
|
+
## Installation
|
|
31
|
+
|
|
32
|
+
The server requires a FutureSearch API key. Get one at [futuresearch.ai/api-key](https://futuresearch.ai/api-key) ($20 free credit).
|
|
33
|
+
|
|
34
|
+
### Claude Desktop
|
|
35
|
+
|
|
36
|
+
Download the latest `.mcpb` bundle from the [GitHub Releases](https://github.com/futuresearch/futuresearch-python/releases) page and double-click to install in Claude Desktop. You'll be prompted to enter your FutureSearch API key during setup. After installing the bundle, you can use FutureSearch from Chat, Cowork and Code within Claude Desktop.
|
|
37
|
+
|
|
38
|
+
### Cursor
|
|
39
|
+
Set the environment variable in your terminal shell before opening cursor. You may need to re-open cursor from your shell after this. Alternatively, hardcode the api key within cursor settings instead of the hard-coded `${env:FUTURESEARCH_API_KEY}`
|
|
40
|
+
```bash
|
|
41
|
+
export FUTURESEARCH_API_KEY=your_key_here
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Manual Config
|
|
45
|
+
|
|
46
|
+
Either set the API key in your shell environment as mentioned above, or hardcode it directly in the config below. Environment variable interpolation may differ between MCP clients.
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
export FUTURESEARCH_API_KEY=your_key_here
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Add this to your MCP config. If you have [uv](https://docs.astral.sh/uv/) installed:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"mcpServers": {
|
|
57
|
+
"futuresearch": {
|
|
58
|
+
"command": "uvx",
|
|
59
|
+
"args": ["futuresearch-mcp"],
|
|
60
|
+
"env": {
|
|
61
|
+
"FUTURESEARCH_API_KEY": "${FUTURESEARCH_API_KEY}"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Alternatively, install with pip (ideally in a venv) and use `"command": "futuresearch-mcp"` instead of uvx.
|
|
69
|
+
|
|
70
|
+
## Workflow
|
|
71
|
+
|
|
72
|
+
All operations follow an async pattern:
|
|
73
|
+
|
|
74
|
+
1. **Start** - Call an operation tool (e.g., `futuresearch_agent`) to start a task. Returns immediately with a task ID and session URL.
|
|
75
|
+
2. **Monitor** - Call `futuresearch_progress(task_id)` repeatedly to check status. The tool blocks ~12s to limit the polling rate.
|
|
76
|
+
3. **Retrieve** - Once complete, call `futuresearch_results(task_id, output_path)` to save results to CSV.
|
|
77
|
+
|
|
78
|
+
## Available Tools
|
|
79
|
+
|
|
80
|
+
### futuresearch_rank
|
|
81
|
+
|
|
82
|
+
Score and sort CSV rows based on qualitative criteria.
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
Parameters:
|
|
86
|
+
- task: Natural language instructions for scoring a single row
|
|
87
|
+
- input_csv: Absolute path to input CSV
|
|
88
|
+
- field_name: Name of the score field to add
|
|
89
|
+
- field_type: Type of the score field (float, int, str, bool)
|
|
90
|
+
- ascending_order: Sort direction (default: true)
|
|
91
|
+
- response_schema: (optional) JSON schema for custom response fields
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Example: Rank leads by "likelihood to need data integration solutions"
|
|
95
|
+
|
|
96
|
+
### futuresearch_dedupe
|
|
97
|
+
|
|
98
|
+
Remove duplicate rows using semantic equivalence.
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
Parameters:
|
|
102
|
+
- equivalence_relation: Natural language description of what makes rows duplicates
|
|
103
|
+
- input_csv: Absolute path to input CSV
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Example: Dedupe contacts where "same person even with name abbreviations or career changes"
|
|
107
|
+
|
|
108
|
+
### futuresearch_merge
|
|
109
|
+
|
|
110
|
+
Join two CSV files using intelligent entity matching (LEFT JOIN semantics).
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
Parameters:
|
|
114
|
+
- task: Natural language description of how to match rows
|
|
115
|
+
- left_csv: The table being enriched — all its rows are kept in the output
|
|
116
|
+
- right_csv: The lookup/reference table — its columns are appended to matches; unmatched left rows get nulls
|
|
117
|
+
- merge_on_left: (optional) Only set if you expect exact string matches on this column or want to draw agent attention to it. Fine to omit.
|
|
118
|
+
- merge_on_right: (optional) Only set if you expect exact string matches on this column or want to draw agent attention to it. Fine to omit.
|
|
119
|
+
- use_web_search: (optional) "auto" (default), "yes", or "no"
|
|
120
|
+
- relationship_type: (optional) "many_to_one" (default) if multiple left rows can match one right row, "one_to_one" matches must be unique, "one_to_many" one left row can match multiple right rows, "many_to_many" multiple left rows can match multiple right rows. For one_to_many and many_to_many, multiple matches are joined with " | " in each added column.
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Example: Match software products (left, enriched) to parent companies (right, lookup): Photoshop -> Adobe
|
|
124
|
+
|
|
125
|
+
### futuresearch_classify
|
|
126
|
+
|
|
127
|
+
Classify each row into one of the provided categories.
|
|
128
|
+
|
|
129
|
+
```
|
|
130
|
+
Parameters:
|
|
131
|
+
- task: Natural language classification instructions
|
|
132
|
+
- categories: Allowed categories (minimum 2)
|
|
133
|
+
- classification_field: (optional) Output column name (default: "classification")
|
|
134
|
+
- include_reasoning: (optional) Include reasoning column (default: false)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Example: Classify companies by GICS sector with categories ["Energy", "Financials", "Information Technology", ...]
|
|
138
|
+
|
|
139
|
+
### futuresearch_forecast
|
|
140
|
+
|
|
141
|
+
Forecast the probability of binary questions.
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
Parameters:
|
|
145
|
+
- context: (optional) Batch-level context for all questions
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
Example: "Will the US Federal Reserve cut rates before July 2027?"
|
|
149
|
+
|
|
150
|
+
### futuresearch_agent
|
|
151
|
+
|
|
152
|
+
Run web research agents on each row of a CSV.
|
|
153
|
+
|
|
154
|
+
```
|
|
155
|
+
Parameters:
|
|
156
|
+
- task: Natural language description of research task
|
|
157
|
+
- input_csv: Absolute path to input CSV
|
|
158
|
+
- response_schema: (optional) JSON schema for custom response fields
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Example: "Find this company's latest funding round and lead investors"
|
|
162
|
+
|
|
163
|
+
### futuresearch_progress
|
|
164
|
+
|
|
165
|
+
Check progress of a running task.
|
|
166
|
+
|
|
167
|
+
```
|
|
168
|
+
Parameters:
|
|
169
|
+
- task_id: The task ID returned by an operation tool
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Blocks ~12s before returning status. Call repeatedly until task completes.
|
|
173
|
+
|
|
174
|
+
### futuresearch_results
|
|
175
|
+
|
|
176
|
+
Retrieve and save results from a completed task.
|
|
177
|
+
|
|
178
|
+
```
|
|
179
|
+
Parameters:
|
|
180
|
+
- task_id: The task ID of the completed task
|
|
181
|
+
- output_path: Full absolute path to output CSV file (must end in .csv)
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Only call after `futuresearch_progress` reports status "completed".
|
|
185
|
+
|
|
186
|
+
## Development
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
cd futuresearch-mcp
|
|
190
|
+
uv sync
|
|
191
|
+
uv run pytest
|
|
192
|
+
```
|
|
193
|
+
For MCP [registry publishing](https://modelcontextprotocol.info/tools/registry/publishing/#package-deployment):
|
|
194
|
+
|
|
195
|
+
mcp-name: io.github.futuresearch/futuresearch-mcp
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
## License
|
|
199
|
+
|
|
200
|
+
MIT - See [LICENSE.txt](../LICENSE.txt)
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# FutureSearch MCP Server
|
|
2
|
+
|
|
3
|
+
> Most users don't need to run the MCP server locally. Use the hosted remote server at `https://mcp.futuresearch.ai/mcp` — it authenticates via OAuth, no API key needed. See the [setup guide](https://futuresearch.ai/docs). The instructions below are for self-hosted or advanced use cases where an API key is required.
|
|
4
|
+
|
|
5
|
+
MCP (Model Context Protocol) server for [FutureSearch](https://futuresearch.ai): agent ops at spreadsheet scale.
|
|
6
|
+
|
|
7
|
+
This server exposes FutureSearch's core operations as MCP tools, allowing LLM applications to classify, rank, dedupe, merge, forecast, and run agents on CSV files.
|
|
8
|
+
|
|
9
|
+
**All tools operate on local CSV files.** Provide absolute file paths as input, and transformed results are written to new CSV files at your specified output path.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
The server requires a FutureSearch API key. Get one at [futuresearch.ai/api-key](https://futuresearch.ai/api-key) ($20 free credit).
|
|
14
|
+
|
|
15
|
+
### Claude Desktop
|
|
16
|
+
|
|
17
|
+
Download the latest `.mcpb` bundle from the [GitHub Releases](https://github.com/futuresearch/futuresearch-python/releases) page and double-click to install in Claude Desktop. You'll be prompted to enter your FutureSearch API key during setup. After installing the bundle, you can use FutureSearch from Chat, Cowork and Code within Claude Desktop.
|
|
18
|
+
|
|
19
|
+
### Cursor
|
|
20
|
+
Set the environment variable in your terminal shell before opening cursor. You may need to re-open cursor from your shell after this. Alternatively, hardcode the api key within cursor settings instead of the hard-coded `${env:FUTURESEARCH_API_KEY}`
|
|
21
|
+
```bash
|
|
22
|
+
export FUTURESEARCH_API_KEY=your_key_here
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Manual Config
|
|
26
|
+
|
|
27
|
+
Either set the API key in your shell environment as mentioned above, or hardcode it directly in the config below. Environment variable interpolation may differ between MCP clients.
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
export FUTURESEARCH_API_KEY=your_key_here
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Add this to your MCP config. If you have [uv](https://docs.astral.sh/uv/) installed:
|
|
34
|
+
|
|
35
|
+
```json
|
|
36
|
+
{
|
|
37
|
+
"mcpServers": {
|
|
38
|
+
"futuresearch": {
|
|
39
|
+
"command": "uvx",
|
|
40
|
+
"args": ["futuresearch-mcp"],
|
|
41
|
+
"env": {
|
|
42
|
+
"FUTURESEARCH_API_KEY": "${FUTURESEARCH_API_KEY}"
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Alternatively, install with pip (ideally in a venv) and use `"command": "futuresearch-mcp"` instead of uvx.
|
|
50
|
+
|
|
51
|
+
## Workflow
|
|
52
|
+
|
|
53
|
+
All operations follow an async pattern:
|
|
54
|
+
|
|
55
|
+
1. **Start** - Call an operation tool (e.g., `futuresearch_agent`) to start a task. Returns immediately with a task ID and session URL.
|
|
56
|
+
2. **Monitor** - Call `futuresearch_progress(task_id)` repeatedly to check status. The tool blocks ~12s to limit the polling rate.
|
|
57
|
+
3. **Retrieve** - Once complete, call `futuresearch_results(task_id, output_path)` to save results to CSV.
|
|
58
|
+
|
|
59
|
+
## Available Tools
|
|
60
|
+
|
|
61
|
+
### futuresearch_rank
|
|
62
|
+
|
|
63
|
+
Score and sort CSV rows based on qualitative criteria.
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
Parameters:
|
|
67
|
+
- task: Natural language instructions for scoring a single row
|
|
68
|
+
- input_csv: Absolute path to input CSV
|
|
69
|
+
- field_name: Name of the score field to add
|
|
70
|
+
- field_type: Type of the score field (float, int, str, bool)
|
|
71
|
+
- ascending_order: Sort direction (default: true)
|
|
72
|
+
- response_schema: (optional) JSON schema for custom response fields
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Example: Rank leads by "likelihood to need data integration solutions"
|
|
76
|
+
|
|
77
|
+
### futuresearch_dedupe
|
|
78
|
+
|
|
79
|
+
Remove duplicate rows using semantic equivalence.
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
Parameters:
|
|
83
|
+
- equivalence_relation: Natural language description of what makes rows duplicates
|
|
84
|
+
- input_csv: Absolute path to input CSV
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
Example: Dedupe contacts where "same person even with name abbreviations or career changes"
|
|
88
|
+
|
|
89
|
+
### futuresearch_merge
|
|
90
|
+
|
|
91
|
+
Join two CSV files using intelligent entity matching (LEFT JOIN semantics).
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
Parameters:
|
|
95
|
+
- task: Natural language description of how to match rows
|
|
96
|
+
- left_csv: The table being enriched — all its rows are kept in the output
|
|
97
|
+
- right_csv: The lookup/reference table — its columns are appended to matches; unmatched left rows get nulls
|
|
98
|
+
- merge_on_left: (optional) Only set if you expect exact string matches on this column or want to draw agent attention to it. Fine to omit.
|
|
99
|
+
- merge_on_right: (optional) Only set if you expect exact string matches on this column or want to draw agent attention to it. Fine to omit.
|
|
100
|
+
- use_web_search: (optional) "auto" (default), "yes", or "no"
|
|
101
|
+
- relationship_type: (optional) "many_to_one" (default) if multiple left rows can match one right row, "one_to_one" matches must be unique, "one_to_many" one left row can match multiple right rows, "many_to_many" multiple left rows can match multiple right rows. For one_to_many and many_to_many, multiple matches are joined with " | " in each added column.
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Example: Match software products (left, enriched) to parent companies (right, lookup): Photoshop -> Adobe
|
|
105
|
+
|
|
106
|
+
### futuresearch_classify
|
|
107
|
+
|
|
108
|
+
Classify each row into one of the provided categories.
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
Parameters:
|
|
112
|
+
- task: Natural language classification instructions
|
|
113
|
+
- categories: Allowed categories (minimum 2)
|
|
114
|
+
- classification_field: (optional) Output column name (default: "classification")
|
|
115
|
+
- include_reasoning: (optional) Include reasoning column (default: false)
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
Example: Classify companies by GICS sector with categories ["Energy", "Financials", "Information Technology", ...]
|
|
119
|
+
|
|
120
|
+
### futuresearch_forecast
|
|
121
|
+
|
|
122
|
+
Forecast the probability of binary questions.
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
Parameters:
|
|
126
|
+
- context: (optional) Batch-level context for all questions
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Example: "Will the US Federal Reserve cut rates before July 2027?"
|
|
130
|
+
|
|
131
|
+
### futuresearch_agent
|
|
132
|
+
|
|
133
|
+
Run web research agents on each row of a CSV.
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
Parameters:
|
|
137
|
+
- task: Natural language description of research task
|
|
138
|
+
- input_csv: Absolute path to input CSV
|
|
139
|
+
- response_schema: (optional) JSON schema for custom response fields
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Example: "Find this company's latest funding round and lead investors"
|
|
143
|
+
|
|
144
|
+
### futuresearch_progress
|
|
145
|
+
|
|
146
|
+
Check progress of a running task.
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
Parameters:
|
|
150
|
+
- task_id: The task ID returned by an operation tool
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Blocks ~12s before returning status. Call repeatedly until task completes.
|
|
154
|
+
|
|
155
|
+
### futuresearch_results
|
|
156
|
+
|
|
157
|
+
Retrieve and save results from a completed task.
|
|
158
|
+
|
|
159
|
+
```
|
|
160
|
+
Parameters:
|
|
161
|
+
- task_id: The task ID of the completed task
|
|
162
|
+
- output_path: Full absolute path to output CSV file (must end in .csv)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Only call after `futuresearch_progress` reports status "completed".
|
|
166
|
+
|
|
167
|
+
## Development
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
cd futuresearch-mcp
|
|
171
|
+
uv sync
|
|
172
|
+
uv run pytest
|
|
173
|
+
```
|
|
174
|
+
For MCP [registry publishing](https://modelcontextprotocol.info/tools/registry/publishing/#package-deployment):
|
|
175
|
+
|
|
176
|
+
mcp-name: io.github.futuresearch/futuresearch-mcp
|
|
177
|
+
|
|
178
|
+
|
|
179
|
+
## License
|
|
180
|
+
|
|
181
|
+
MIT - See [LICENSE.txt](../LICENSE.txt)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
FUTURESEARCH_API_KEY=sk-cho-your-api-key-here
|
|
2
|
+
SUPABASE_URL=https://your-project.supabase.co
|
|
3
|
+
SUPABASE_ANON_KEY=sb_publishable_your-anon-key-here
|
|
4
|
+
MCP_SERVER_URL=https://your-tunnel-url.example.com
|
|
5
|
+
REDIS_PASSWORD=change-me-to-a-strong-random-password
|
|
6
|
+
|
|
7
|
+
# Legacy env vars (still supported for backwards compatibility):
|
|
8
|
+
# EVERYROW_API_KEY=sk-cho-your-api-key-here
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Stage 1: Build Python environment with uv
|
|
2
|
+
FROM ghcr.io/astral-sh/uv:python3.13-bookworm-slim AS build
|
|
3
|
+
ENV PYTHONDONTWRITEBYTECODE=1
|
|
4
|
+
ENV PYTHONUNBUFFERED=1
|
|
5
|
+
WORKDIR /app
|
|
6
|
+
|
|
7
|
+
# Copy workspace root pyproject + lock + README, then each package
|
|
8
|
+
COPY --link pyproject.toml uv.lock README.md ./
|
|
9
|
+
COPY --link src/ ./src/
|
|
10
|
+
COPY --link everyrow-mcp/pyproject.toml everyrow-mcp/README.md ./everyrow-mcp/
|
|
11
|
+
COPY --link everyrow-mcp/src/ ./everyrow-mcp/src/
|
|
12
|
+
|
|
13
|
+
# Install everyrow-mcp and its dependencies (includes workspace everyrow package)
|
|
14
|
+
RUN uv sync --package everyrow-mcp --no-dev --no-sources --no-editable
|
|
15
|
+
|
|
16
|
+
# Stage 2: Slim runtime
|
|
17
|
+
FROM python:3.13-slim
|
|
18
|
+
|
|
19
|
+
ENV PYTHONDONTWRITEBYTECODE=1
|
|
20
|
+
ENV PYTHONUNBUFFERED=1
|
|
21
|
+
|
|
22
|
+
RUN groupadd -r -g 10000 mcp && useradd -r -u 10000 -g mcp -d /app -s /sbin/nologin mcp
|
|
23
|
+
|
|
24
|
+
ENV PATH="/app/.venv/bin:$PATH"
|
|
25
|
+
EXPOSE 8000
|
|
26
|
+
|
|
27
|
+
WORKDIR /app
|
|
28
|
+
COPY --link --from=build /app/.venv .venv
|
|
29
|
+
RUN chown -R mcp:mcp /app
|
|
30
|
+
|
|
31
|
+
USER mcp
|
|
32
|
+
|
|
33
|
+
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
|
|
34
|
+
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')"
|
|
35
|
+
|
|
36
|
+
CMD ["everyrow-mcp", "--http", "--port", "8000", "--host", "0.0.0.0"]
|