Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,18 @@ BlockVectra provides two Streamable HTTP MCP endpoints. Use `https://docs.blockv
https://docs.blockvectra.com/mcp
```

### Read documentation from a Python agent

Python 3.11+ can connect directly with the [official MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk). With [uv](https://docs.astral.sh/uv/) installed, run this from the cloned repository:

```bash
uv run examples/mcp_docs.py
```

The example pins `mcp==2.3.0` in its script metadata, lists the two documentation tools, then reads the English `quickstart` page. It prints JSON containing the tool names, page path, language and complete Markdown text, so an agent can consume the result. It uses the documentation-only endpoint: no BlockVectra key, wallet, model API or chain RPC is involved. Errors exit non-zero; the example has a 40-second overall deadline. Dependency installation occurs before that deadline.

The separate standard-library RPC example above still needs no third-party Python packages.

### 1. Claude Code Configuration

#### Keyless Documentation MCP
Expand Down
12 changes: 12 additions & 0 deletions README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,18 @@ BlockVectra 提供两个基于 Streamable HTTP 的 MCP 入口:文档专用入
https://docs.blockvectra.com/mcp
```

### 从 Python Agent 读取文档

Python 3.11+ 可通过[官方 MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk)直接连接。安装 [uv](https://docs.astral.sh/uv/) 后,在克隆的仓库中执行:

```bash
uv run examples/mcp_docs.py
```

示例在脚本元数据中固定 `mcp==2.3.0`,先列出两个文档工具,再读取英文 `quickstart` 页。输出 JSON 包含工具名、页面路径、语言和完整 Markdown,Agent 可直接消费。它只连接文档专用入口,不需要 BlockVectra key、钱包或模型 API,也不调用链上 RPC。出错时非零退出;示例运行总时限为 40 秒,依赖安装不包含在该时限内。

前面的独立标准库 RPC 示例仍无需第三方 Python 包。

### 1. Claude Code 配置

#### 免 Key 文档服务
Expand Down
48 changes: 48 additions & 0 deletions examples/mcp_docs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# /// script
# requires-python = ">=3.11"
# dependencies = ["mcp==2.3.0"]
# ///
"""Read BlockVectra documentation with the official Python MCP SDK."""

import asyncio
import json
import os

import httpx2
from mcp import ClientSession
from mcp.client.streamable_http import streamable_http_client

ENDPOINT = "https://docs.blockvectra.com/mcp/docs"


async def read_quickstart(http_client: httpx2.AsyncClient) -> dict:
async with streamable_http_client(ENDPOINT, http_client=http_client) as (read, write):
async with ClientSession(read, write, read_timeout_seconds=15) as session:
await session.initialize()
available = await session.list_tools()
names = sorted(tool.name for tool in available.tools)
if names != ["read_doc", "search_docs"]:
raise RuntimeError("The endpoint did not expose the two documentation tools.")
result = await session.call_tool("read_doc", {"path": "quickstart", "lang": "en"})
payload = result.model_dump(mode="json", by_alias=True)
if payload.get("isError", False):
raise RuntimeError("read_doc returned a tool error.")
texts = [item["text"] for item in payload.get("content", []) if item.get("type") == "text"]
if not texts or not any(text.strip() for text in texts):
raise RuntimeError("read_doc returned no documentation text.")
return {"tools": names, "path": "quickstart", "lang": "en", "text": "\n".join(texts)}


async def main() -> None:
user_agent = "BlockVectraDocsPython/1"
if os.environ.get("BLOCKVECTRA_INTERNAL_QA") == "1":
user_agent += " BlockVectraQA/1"
async with httpx2.AsyncClient(
timeout=15, follow_redirects=False, headers={"User-Agent": user_agent}
) as http_client:
result = await read_quickstart(http_client)
print(json.dumps(result, ensure_ascii=False, indent=2))


if __name__ == "__main__":
asyncio.run(asyncio.wait_for(main(), timeout=40))
Loading