MCP网络阅读器
用于获取和解析web内容的Swift MCP(模型上下文协议)服务器。
TLDR-快速入门
通过Homebrew安装: (仅限macos) 使用brew来获得 披萨工具包,包含此(和其他工具)。
brew tap mredig/pizza-mcp-tools
brew update
brew install mcp-webreader或者从源代码构建:
# Clone and build
git clone
cd MCP-WebReader
swift build添加到Zed设置 (~/.config/zed/settings.json):(推荐)
(在Zed中, Add Custom Server 并提供以下代码片段)
{
/// The name of your MCP server
"webreader": {
/// The command which runs the MCP server
"command": "mcp-webreader", // if building yourself, you'll need to provide the whole path
/// The arguments to pass to the MCP server
"args": [],
/// The environment variables to set
"env": {}
}
}或克劳德
# Add to Claude Desktop config at:
# ~/Library/Application Support/Claude/claude_desktop_config.json
{
"mcpServers": {
"webreader": {
"command": "/path/to/MCP-WebReader/.build/debug/mcp-webreader"
}
}
}添加您自己的工具
- 创建一个新文件 在
Sources/MCPWebReaderLib/ToolImplementations/ - 扩展
ToolCommand使用您的命令名 - 实施
ToolImplementation协议 - 添加到注册表 在
ToolRegistry.swift
示例:添加计算器工具
// CalculatorTool.swift
import MCP
import Foundation
extension ToolCommand {
static let calculate = ToolCommand(rawValue: "calculate")
}
struct CalculatorTool: ToolImplementation {
static let command: ToolCommand = .calculate
// JSON Schema reference: https://json-schema.org/understanding-json-schema/reference
static let tool = Tool(
name: command.rawValue,
description: "Performs basic arithmetic operations",
inputSchema: .object([
"type": "object",
"properties": .object([
"operation": .object([
"type": "string",
"enum": .array([.string("add"), .string("subtract"), .string("multiply"), .string("divide")]),
"description": "The operation to perform"
]),
"a": .object([
"type": "number",
"description": "First number"
]),
"b": .object([
"type": "number",
"description": "Second number"
])
]),
"required": .array([.string("operation"), .string("a"), .string("b")])
])
)
let operation: String
let a: Double
let b: Double
init(arguments: CallTool.Parameters) throws(ContentError) {
guard let operation = arguments.strings.operation else {
throw .missingArgument("operation")
}
guard let a = arguments.doubles.a else {
throw .missingArgument("a")
}
guard let b = arguments.doubles.b else {
throw .missingArgument("b")
}
self.operation = operation
self.a = a
self.b = b
}
func callAsFunction() async throws(ContentError) -> CallTool.Result {
let result: Double
switch operation {
case "add": result = a + b
case "subtract": result = a - b
case "multiply": result = a * b
case "divide":
guard b != 0 else {
throw .contentError(message: "Division by zero")
}
result = a / b
default:
throw .contentError(message: "Unknown operation: \(operation)")
}
let output = StructuredContentOutput(
inputRequest: "\(operation): \(a) and \(b)",
metaData: nil,
content: [["result": result]])
return output.toResult()
}
}然后添加到 ToolRegistry.swift:
static let registeredTools: [ToolCommand: any ToolImplementation.Type] = [
.echo: EchoTool.self,
.getTimestamp: GetTimestampTool.self,
.calculate: CalculatorTool.self, // ← Add your tool here
]就是这样!重建后,您的工具可用。
项目结构
MCP-WebReader/
├── Sources/MCPWebReaderLib/
│ ├── ToolRegistry.swift ← Register your tools here
│ ├── ToolCommand.swift ← Tool command constants
│ ├── ToolImplementations/ ← Put your tools here
│ │ ├── ToolImplementation.swift ← Protocol definition
│ │ ├── EchoTool.swift ← Example tool
│ │ └── GetTimestampTool.swift ← Example tool
│ └── Support/ ← Implementation details (don't need to modify)
│ ├── ServerHandlers.swift
│ ├── ToolSupport.swift
│ └── ...工具实现模式
每个工具都遵循相同的模式:
- 扩展
ToolCommand-定义您的命令标识符 - 定义
static let tool-使用JSON模式定义MCP工具 - 提取参数
init-验证并转换为类型化属性 - 实施
callAsFunction-您的工具的业务逻辑
参数提取
使用 ParamLookup 用于提取类型化参数的助手:
arguments.strings.myStringParam // String?
arguments.integers.myIntParam // Int?
arguments.doubles.myDoubleParam // Double?
arguments.bools.myBoolParam // Bool?错误处理
扔 ContentError 对于所有工具错误:
throw .missingArgument("paramName")
throw .mismatchedType(argument: "paramName", expected: "string")
throw .initializationFailed("custom message")
throw .contentError(message: "custom error")
throw .other(someError)需求
- Swift 6.0+
- macOS 13.0+
测试
swift test可用工具
Web内容工具
fetch-page
使用URLSession(无JavaScript渲染)获取网页内容。可以在两种模式下运行: 获取模式 (返回分页内容)或 搜索模式 (查找并返回所有与上下文匹配的项)。
参数:
url(必填,字符串)-要获取的URL(必须是http://或https://)query(可选,字符串)-搜索查询。提供时,搜索整个网页并返回与上下文匹配的位置。如果省略,则返回分页内容。offset(可选,整数)-分页的起始字符位置(默认值:0)。 当被忽略时query提供。limit(可选,整数)-要返回的最大字符数(默认值:10000)。 当被忽略时query提供。includeMetadata(可选,布尔值)-包括页面元数据,如标题和描述(默认值:true)
提取模式(无查询): 从网页返回分页内容。
{
"text": "Page content here...",
"title": "Page Title",
"description": "Meta description if available",
"url": "https://example.com",
"contentLength": 12345,
"returnedLength": 500,
"offset": 0,
"hasMore": true,
"nextOffset": 500
}搜索模式(带查询): 搜索整个网页,并返回与周围上下文的所有匹配项。
{
"query": "search term",
"matches": [
{
"position": 1234,
"context": "...text before search term text after..."
},
{
"position": 5678,
"context": "...another match context..."
}
],
"totalMatches": 2,
"title": "Page Title",
"description": "Meta description if available",
"url": "https://example.com",
"webpageLength": 12345
}注: 此工具不执行JavaScript。对于需要JavaScript渲染的页面,请使用 render-page 相反(即将推出)。
示例工具
echo-回传消息(演示参数处理)get-timestamp-返回当前ISO 8601时间戳(演示无参数工具)
资源
webreader://status-服务器状态(JSON)webreader://welcome-欢迎信息(文本)webreader://config-服务器配置(JSON)
使用示例
获取网页
{
"tool": "fetch-page",
"arguments": {
"url": "https://example.com"
}
}分页提取
{
"tool": "fetch-page",
"arguments": {
"url": "https://example.com",
"offset": 500,
"limit": 1000
}
}在网页内搜索
{
"tool": "fetch-page",
"arguments": {
"url": "https://example.com",
"query": "search term"
}
}获取搜索结果周围的内容
搜索后,使用返回的位置获取特定的内容范围:
{
"tool": "fetch-page",
"arguments": {
"url": "https://example.com",
"offset": 1200,
"limit": 500
}
}资源
许可证
MIT许可证
