Skip to content

feat(mcp): add mcp endpoint for whole openlist#2485

Open
jyxjjj wants to merge 13 commits into
mainfrom
feat/mcp-endpoint
Open

feat(mcp): add mcp endpoint for whole openlist#2485
jyxjjj wants to merge 13 commits into
mainfrom
feat/mcp-endpoint

Conversation

@jyxjjj
Copy link
Copy Markdown
Member

@jyxjjj jyxjjj commented May 18, 2026

Description / 描述

Add an initial MCP endpoint implementation for OpenList.

This PR started from an empty draft commit to reserve the branch and discussion space for MCP integration work. It now includes the first usable MCP server skeleton and the first OpenList tool.

Motivation and Context / 背景

OpenList already exposes a relatively complete API surface for file operations, tasks, sharing, authentication, and admin actions.

This PR establishes the first MCP integration layer on top of the existing backend so OpenList can be consumed through MCP-compatible clients in a structured way.

Current scope in this PR:

  • Add the /mcp route
  • Implement MCP session initialization flow
  • Implement tools/list
  • Implement tools/call
  • Expose the first tool: openlist.fs.list
  • Reorganize MCP implementation into server/mcp to align with the existing server layout
  • Added: openlist.fs.get
  • Added: openlist.fs.link

How Has This Been Tested? / 测试

  • I did not run the full test suite under production environment.
  • All go test passed.

Checklist / 检查清单

  • I have read the CONTRIBUTING document.
    我已阅读 CONTRIBUTING 文档。
  • I have formatted my code with go fmt or prettier.
    我已使用 go fmtprettier 格式化提交的代码。
  • I have added appropriate labels to this PR (or mentioned needed labels in the description if lacking permissions).
    我已为此 PR 添加了适当的标签(如无权限或需要的标签不存在,请在描述中说明,管理员将后续处理)。
  • I have requested review from relevant code authors using the "Request review" feature when applicable.
    我已在适当情况下使用"Request review"功能请求相关代码作者进行审查。
  • I have updated the repository accordingly (If it’s needed).
    我已相应更新了相关仓库(若适用)。

jyxjjj and others added 2 commits May 18, 2026 23:35
- 新增 MCP 路由与 session 初始化流程
- 接入 tools/list 与 tools/call,并开放 openlist.fs.list
- 补充 MCP 相关协议与路由测试

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
- 将 MCP 实现与测试迁移到 server/mcp 目录
- 保留 server/mcp.go 作为路由接入包装入口
- 对齐 webdav、s3、ftp、sftp 的目录组织风格

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces an initial MCP (Model Context Protocol) server skeleton, mounted at /mcp and restricted to admin users, exposing a single openlist.fs.list tool that mirrors the existing FsList REST handler.

Changes:

  • Add MCP HTTP transport handler (initialize, notifications/initialized, ping, tools/list, tools/call, session lifecycle, origin/Accept checks).
  • Implement the first MCP tool openlist.fs.list reusing the existing access-control and listing logic.
  • Wire the new MCP route into server/router.go via a small server/mcp.go shim and add unit tests for handler and tool flows.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
server/router.go Registers the new MCP route on the root group.
server/mcp.go Tiny shim delegating registration to the mcp package.
server/mcp/handler.go JSON-RPC dispatcher, session store, origin/Accept validation, initialize/delete handling.
server/mcp/tools.go Tool catalog definitions and tools/list handler.
server/mcp/call.go tools/call dispatcher producing MCP-style result content.
server/mcp/fs_list.go Implementation of openlist.fs.list, duplicating several helpers from handles/fsread.go.
server/mcp/handler_test.go Tests for initialize/delete/GET flows.
server/mcp/call_test.go Tests for tools/list and tools/call error paths.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread server/mcp/handler.go
Comment thread server/mcp/handler.go Outdated
Comment thread server/mcp/fs_list.go Outdated
Comment thread server/mcp/call_test.go Outdated
Comment thread server/mcp/fs_list.go Outdated
Comment thread server/mcp/fs_list.go
Comment thread server/mcp/fs_list.go
- 收紧 Streamable HTTP Accept 头校验
- 为 MCP session 增加过期清理和数量上限
- 简化 fs.list 参数解析并修复分页边界
- 使用独立 Server 实例隔离 MCP 测试状态

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
@jyxjjj jyxjjj force-pushed the feat/mcp-endpoint branch from b9968d7 to 06e1e9b Compare May 18, 2026 16:05
@jyxjjj jyxjjj added enhancement go Module: Server API and protocol changes labels May 18, 2026
@jyxjjj jyxjjj marked this pull request as ready for review May 18, 2026 16:07
- 新增 openlist.fs.get 和 openlist.fs.link 工具
- 复用文件详情、代理链接和权限校验逻辑
- 补充工具列表和参数解析测试

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 6 comments.

Comment thread server/mcp/tools.go
Comment thread server/mcp/handler.go Outdated
Comment thread server/mcp/fs_link.go
Comment thread server/mcp/handler.go
Comment thread server/mcp/handler.go
Comment thread server/mcp/handler.go Outdated
- Remove WebDAV proxy URL policy from MCP proxy link detection
- Return server protocol version during initialize negotiation
- Return JSON-RPC error body for invalid MCP Accept header
- Add tests for MCP proxy and HTTP negotiation behavior

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
PIKACHUIM
PIKACHUIM previously approved these changes May 19, 2026
Copy link
Copy Markdown
Member

@PIKACHUIM PIKACHUIM left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. getSession 返回值是 session 副本,但 markSessionInitialized/sessionInitialized 是用真实指针;调用者错把副本当事实
    getSession 返回 session{} 值类型(按值),但同一个会话又通过 ID 在 markSessionInitialized 里被改写。这本身不算 bug,但有两个隐患:

getSession 在读路径里也加了写锁 s.mu.Lock()(第 269 行),表面一致,但与 mu sync.RWMutex 的设计意图相违:读路径都没用 RLock,RWMutex 退化成 Mutex,这个锁名/字段类型可以直接换成 sync.Mutex,否则容易让后续维护者误以为读路径不阻塞。
handler.goL265-L282

func (s *Server) getSession(id string) (session, bool) {
	if id == "" {
		return session{}, false
	}
	s.mu.Lock()             // ← RWMutex 但全用写锁
	defer s.mu.Unlock()
	...
}

建议:把 mu sync.RWMutex 改成 sync.Mutex(更诚实),或在能放宽的地方换成 RLock(但要小心 lastUsedAt 的写入需要写锁)。

  1. handleInitialize 不校验也不协商客户端的 protocolVersion
    按 MCP 规范,服务端应在 initialize 时返回双方都支持的协议版本;客户端会拿这个版本来决定后续行为。当前实现忽略 params.ProtocolVersion,无论客户端发什么都直接回 2025-06-18。TestInitializeNegotiatesUnsupportedProtocolVersion 实际只断言"返回服务端版本",掩盖了应当校验/拒绝的语义。

建议:

至少在 params.ProtocolVersion != ProtocolVersion 时记录一行日志;
更好是维护一个 supportedProtocolVersions 列表,能命中就回客户端版本,不能命中就回服务端最新版本(规范允许)。

  1. handleInitialize 的会话泄漏风险
    每次 initialize 都会无条件 createSession:

handler.goL204-L205

currentSession := s.createSession(c.Request.Context().Value(conf.UserKey).(*model.User).ID)
c.Header(SessionHeader, currentSession.id)

但 MCP 客户端在协商失败/重连时会反复发 initialize。配合没有按用户限流,单个管理员客户端就能 30 分钟内积累几百个会话——虽然 LRU 会兜底到 1024,但代价是把别人的会话挤掉。

建议:

如请求 Header 中已有合法 Mcp-Session-Id 且属于当前用户,复用之并重置 initialized=false;或者
在 createSession 里加按 userID 维度的上限(例如每用户最多 32 个会话),避免单用户挤占全局。

  1. handleGet 的 GET 始终 405,但 MCP 规范规定 GET 必须支持以打开服务端 SSE 流(即使用于 server→client 通知)
    当前服务端没有任何 server-initiated 通知(tools/listChanged: false),直接 405 不是大问题,但有些客户端(如部分 SDK)会在 initialize 后主动 GET 探测 SSE 通道,得到 405 会报警告或直接断连。规范允许返回 405,但建议同时加上 Allow: POST, DELETE 头,或者返回一个空 SSE 流(200 + text/event-stream,无事件)。

建议:至少 c.Header("Allow", "POST, DELETE") 再 c.Status(405)。

@jyxjjj
Copy link
Copy Markdown
Member Author

jyxjjj commented May 19, 2026

第一个我改下 第二个我记得修了 还是修的不对吗 第三个暂时风险不是很大 但是既然你有方案了我也可以修一下 第四个我觉得没问题啊 上面说了 暂时用不到这个功能

@PIKACHUIM
Copy link
Copy Markdown
Member

第二个如果暂时不考虑版本兼容性可以不修
第四个看不懂,是我我就直接注释这个接口了
(都是AI评审的)

jyxjjj and others added 5 commits May 20, 2026 09:09
- 为 MCP GET 405 响应添加 Allow 头
- 补充 GET 405 响应头断言

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
- 将 MCP session 锁改为 Mutex
- 让锁类型匹配会更新 lastUsedAt 的访问路径

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
- 添加 MCP 协议版本协商函数
- 不支持客户端版本时返回服务端支持版本

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
- 撤回 MCP 协议版本协商包装函数
- 恢复 initialize 直接返回服务端协议版本

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
- 将 MCP 全局 session 上限调整为 128
- 添加单用户 16 个 session 上限
- initialize 复用同用户已有 session 标识
- 补充 session 复用和上限裁剪测试

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
@jyxjjj
Copy link
Copy Markdown
Member Author

jyxjjj commented May 20, 2026

第二个又修了一下发现没问题就撤回了
故意留了提交记录
image
其他的也都修了 再来个review

@jyxjjj
Copy link
Copy Markdown
Member Author

jyxjjj commented May 20, 2026

@codex review

@jyxjjj jyxjjj requested a review from Copilot May 20, 2026 01:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.

Comment thread server/mcp/handler.go
Comment thread server/mcp/tools.go
Comment thread server/mcp/fs_list.go Outdated
Comment thread server/mcp/link_test.go
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5ba832affb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread server/mcp/handler.go
Comment thread server/mcp/handler.go
PIKACHUIM
PIKACHUIM previously approved these changes May 20, 2026
- 拒绝 openlist.fs.list 的空参数和 null 参数
- 校验 fs.list 缺失 path 时返回 -32602
- 添加 fs.list 参数解析测试覆盖错误文案

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
jyxjjj and others added 2 commits May 20, 2026 11:41
- 校验非 initialize 请求的 MCP-Protocol-Version 头
- 拒绝缺失或不支持协议版本的后续 POST 请求
- 添加协议版本头缺失和不匹配测试

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
- 为修改全局设置缓存的测试添加包级互斥锁
- 保留 ClearAll 清理逻辑,避免并发测试互相影响

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
Signed-off-by: jyxjjj <16695261+jyxjjj@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement go Module: Server API and protocol changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants