返回市场
哈斯克尔MCP服务器

哈斯克尔MCP服务器

作者:drshade37 星标更新:2025-08-13

项目介绍

mcp-server

一个用于构建模型上下文协议(MCP)服务器的全功能Haskell库。

特性

  • 完整的MCP实现:支持MCP 2025-06-18规范
  • 类型安全API:利用Haskell的类型系统构建健壮的MCP服务器
  • 多种抽象:提供低级细粒度控制和高级派生接口
  • 模板Haskell支持:从数据类型自动派生处理器
  • 多种传输方式:标准输入输出(STDIO)和HTTP流传输(MCP 2025-06-18可流式HTTP)

支持的MCP特性

  • 提示:用户控制的带有参数的提示模板
  • 资源:应用程序控制的可读资源
  • 工具:模型控制的可调用函数
  • 初始化流程:完整的协议生命周期,包括版本协商
  • 错误处理:全面的错误类型和JSON-RPC错误响应

快速开始

在您的cabal文件中添加库mcp-server

build-depends:
  mcp-server

创建一个简单的模块,例如下面的示例:

{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TemplateHaskell #-}

import MCP.Server
import MCP.Server.Derive

-- 定义您的数据类型
data MyPrompt = Recipe { idea :: Text } | Shopping { items :: Text }
data MyResource = Menu | Specials  
data MyTool = Search { query :: Text } | Order { item :: Text }

-- 实现处理器
handlePrompt :: MyPrompt -> IO Content
handlePrompt (Recipe idea) = pure $ ContentText $ "食谱:" <> idea
handlePrompt (Shopping items) = pure $ ContentText $ "购物清单:" <> items

handleResource :: MyResource -> IO Content  
handleResource Menu = pure $ ContentText "今天的菜单..."
handleResource Specials = pure $ ContentText "每日特价..."

handleTool :: MyTool -> IO Content
handleTool (Search query) = pure $ ContentText $ "搜索结果:" <> query
handleTool (Order item) = pure $ ContentText $ "已订购:" <> item

-- 自动派生处理器
main :: IO ()
main = runMcpServerStdio serverInfo handlers
  where
    serverInfo = McpServerInfo
      { serverName = "我的MCP服务器"
      , serverVersion = "1.0.0" 
      , serverInstructions = "一个示例MCP服务器"
      }
    handlers = McpServerHandlers
      { prompts = Just $(derivePromptHandler ''MyPrompt 'handlePrompt)
      , resources = Just $(deriveResourceHandler ''MyResource 'handleResource)  
      , tools = Just $(deriveToolHandler ''MyTool 'handleTool)
      }

高级模板Haskell特性

自动命名约定

构造器名称会自动转换为snake_case以供MCP名称使用:

data MyTool = GetValue | SetValue | SearchItems
-- 转换为: "get_value", "set_value", "search_items"

自动类型转换

派生系统会自动将Text参数转换为适当的Haskell类型:

data MyTool = Calculate { number :: Int, factor :: Double, enabled :: Bool }
-- Text "42" -> Int 42
-- Text "3.14" -> Double .14
-- Text "true" -> Bool True

支持的转换类型:Int, Integer, Double, Float, BoolText(无转换)。

嵌套参数类型

您可以嵌套参数类型,并进行自动解包:

-- 参数记录类型
data GetValueParams = GetValueParams { _gvpKey :: Text }
data SetValueParams = SetValueParams { _svpKey :: Text, _svpValue :: Text }

-- 主工具类型
data SimpleTool
    = GetValue GetValueParams
    | SetValue SetValueParams
    deriving (Show, Eq)

模板Haskell派生会递归地解包单参数构造器,直到达到记录类型,然后提取所有字段以生成MCP模式。

资源URI生成

资源会根据构造器名称自动生成resource:// URI:

data MyResource = Menu | Specials
-- 生成: "resource://menu", "resource://specials"

不支持的模式

我们不支持位置(未命名)参数:

-- ❌ 这不会工作 - 没有字段名称
data SimpleTool
    = GetValue Int
    | SetValue Int Text

所有参数类型最终必须解析为具有命名字段的记录,以便生成正确的MCP模式。

自定义描述

您可以为构造器和字段提供自定义描述,使用*WithDescription变体:

-- 定义构造器和字段的描述
descriptions :: [(String, String)]
descriptions = 
  [ ("Recipe", "为特定菜肴生成食谱")     -- 构造器描述
  , ("Search", "搜索我们的菜单数据库")                  -- 构造器描述
  , ("idea", "您想要食谱的菜肴")              -- 字段描述
  , ("query", "用于查找菜单项的搜索词")            -- 字段描述
  ]

-- 在派生中使用
handlers = McpServerHandlers
  { prompts = Just $(derivePromptHandlerWithDescription ''MyPrompt 'handlePrompt descriptions)
  , tools = Just $(deriveToolHandlerWithDescription ''MyTool 'handleTool descriptions)
  , resources = Just $(deriveResourceHandlerWithDescription ''MyResource 'handleResource descriptions)
  }

手动处理器实现

为了精细控制,可以手动实现处理器:

import MCP.Server

-- 手动处理器实现
promptListHandler :: IO [PromptDefinition]
promptGetHandler :: PromptName -> [(ArgumentName, ArgumentValue)] -> IO (Either Error Content)
-- ... 实现您的自定义逻辑

main :: IO ()
main = runMcpServerStdio serverInfo handlers
  where
    handlers = McpServerHandlers
      { prompts = Just (promptListHandler, promptGetHandler)
      , resources = Nothing  -- 不支持
      , tools = Nothing      -- 不支持  
      }

HTTP传输(新!)

该库现在支持MCP 2025-06-18可流式HTTP传输:

import MCP.Server.Transport.Http

-- 简单的HTTP服务器(localhost:3000/mcp)
main = runMcpServerHttp serverInfo handlers

-- 自定义配置
main = runMcpServerHttpWithConfig customConfig serverInfo handlers
  where
    customConfig = HttpConfig
      { httpPort = 8080
      , httpHost = "0.0.0.0"
      , httpEndpoint = "/api/mcp"
      , httpVerbose = True  -- 启用详细日志
      }

特性:

  • 为Web客户端启用CORS
  • GET /mcp 用于服务器发现
  • POST /mcp 用于JSON-RPC消息
  • 完全符合MCP 2025-06-18规范

示例

该库包含几个示例:

  • examples/Simple/:使用模板Haskell派生的基本键值存储(STDIO)
  • examples/Complete/:带有提示、资源和工具的全功能示例(STDIO)
  • examples/HttpSimple/:HTTP版本的简单键值存储

Docker使用

我喜欢将我的MCP服务器构建并发布到Docker中,这意味着配置像Claude Desktop这样的助手来运行它们会更容易。

# 构建镜像
docker build -t haskell-mcp-server .

# 运行不同的示例
docker run -i --entrypoint="/usr/local/bin/haskell-mcp-server" haskell-mcp-server

然后通过编辑claude_desktop_config.json来配置Claude:

{
    "mcpServers": {
       "haskell-mcp-server-example": {
            "command": "docker",
            "args": [
                "run",
                "-i",
                "--entrypoint=/usr/local/bin/haskell-mcp-server",
                "haskell-mcp-server"
            ]
        }
    }
}

文档

贡献

欢迎贡献!请查看问题跟踪器中的开放问题和功能请求。

免责声明 - AI辅助

我不确定这是否有污名,但Claude帮助我编写了这个库的很多部分。我从一个非常具体的规格开始,与Claude肩并肩地实施和重构这个库,直到我对它感到满意。一些功能,如Derive函数,是我不太愿意手动编写的,因此我很感激有一个专家指导我——然而,我确实怀疑这种实现可能不是最佳的,并且我打算通过定期维护来重构和重写这个库的大片内容。

许可证

BSD-3-Clause