This commit is contained in:
George Pickett 2026-10-10 16:49:17 +00:00 • committed by GitHub
commit 527dea89ab
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 108 additions and 0 deletions

View file

@ -0,0 +1,43 @@
# Parallel web search and page fetching
Use [Parallel Search MCP](https://docs.parallel.ai/integrations/mcp/search-mcp)
through OpenSpace's existing MCP provider for free web search and page fetching,
with no account or API key. Anonymous searches use Fast mode. The free endpoint
is rate limited and intended for exploration and light use.
## Run the example
From the repository root, with Python 3.12 or newer:
```bash
python -m venv .venv-parallel
source .venv-parallel/bin/activate
cd examples/parallel-search
python -m pip install -r requirements.txt
OPENSPACE_SKIP_DOTENV=1 python search.py
```
On Windows, activate with `.venv-parallel\Scripts\activate` and set
`OPENSPACE_SKIP_DOTENV=1` in your shell before running `python search.py`.
The example constrains the MCP SDK to 1.x, which the current OpenSpace
connectors require.
The script loads `config_mcp.json`, discovers the live tools through
`MCPProvider`, calls `web_search` and `web_fetch`, prints their results, and
closes its sessions. It makes direct tool calls without invoking an LLM or
requiring LLM credentials. Customize the search and the page to fetch:
```bash
OPENSPACE_SKIP_DOTENV=1 python search.py \
--query "Python asyncio TaskGroup cancellation" \
--url https://docs.python.org/3/library/asyncio-task.html
```
## Add the server to your OpenSpace configuration
Merge the `parallel` entry from this example's `mcpServers` into your
`openspace/config/config_mcp.json`, retaining any existing entries. OpenSpace's
HTTP connector negotiates Streamable HTTP with `https://search.parallel.ai/mcp`;
the entry includes an OpenSpace User-Agent and no authentication header.
The example does not change the built-in `web_search` provider. Parallel's
`web_search` and `web_fetch` are external MCP tools.

View file

@ -0,0 +1,10 @@
{
"mcpServers": {
"parallel": {
"url": "https://search.parallel.ai/mcp",
"headers": {
"User-Agent": "OpenSpace/2.0 (+https://github.com/HKUDS/OpenSpace)"
}
}
}
}

View file

@ -0,0 +1,3 @@
# Install from this directory. OpenSpace's MCP connectors use the 1.x SDK.
-e ../..
mcp>=1.0.0,<2

View file

@ -0,0 +1,48 @@
"""Search and fetch through OpenSpace's MCP provider, without an LLM call."""
import argparse
import asyncio
import json
from pathlib import Path
from uuid import uuid4
from openspace.grounding.backends.mcp import MCPProvider
from openspace.grounding.core.types import ToolStatus
async def search_and_fetch(query: str, url: str) -> None:
config = json.loads(Path(__file__).with_name("config_mcp.json").read_text())
provider = MCPProvider(config)
session_id = uuid4().hex
try:
tools = {tool.name for tool in await provider.list_tools(use_cache=False)}
if not {"web_search", "web_fetch"}.issubset(tools):
raise RuntimeError("Parallel search and fetch tools are unavailable")
calls = [
("web_search", {"objective": query, "search_queries": [query]}),
("web_fetch", {"urls": [url], "objective": query[:200]}),
]
for name, parameters in calls:
result = await provider.call_tool(
"mcp-parallel", name, {**parameters, "session_id": session_id}
)
if result.status != ToolStatus.SUCCESS:
raise RuntimeError(f"{name} failed: {result.error or result.content}")
if not result.content:
raise RuntimeError(f"{name} returned no content")
print(f"\n{name}:\n{result.content}")
finally:
await provider.close_all_sessions()
def main() -> None:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument("--query", default="Python asyncio task cancellation")
parser.add_argument("--url", default="https://docs.python.org/3/library/asyncio-task.html")
args = parser.parse_args()
asyncio.run(search_and_fetch(args.query, args.url))
if __name__ == "__main__":
main()

View file

@ -200,6 +200,10 @@ cp openspace/config/config_mcp.json.example openspace/config/config_mcp.json
}
```
For an HTTP MCP server with free, keyless web search and page fetching, see the
[runnable Parallel Search example](../../examples/parallel-search/README.md).
Merge its server entry into your configuration to keep existing MCP servers.
## 5. Execution Mode
The shell backend supports only local execution. This keeps Bash sandbox