feat: mcp (#31)

* feat: add mcp connections table and related crud api

* feat: mcp-stdio api
This commit is contained in:
Acbox Liu
2026-02-09 20:07:40 +08:00
committed by GitHub
parent 92838ef8da
commit 8ea779779e
17 changed files with 2486 additions and 32 deletions
+458
View File
@@ -887,6 +887,362 @@ const docTemplate = `{
}
}
},
"/bots/{bot_id}/mcp": {
"get": {
"description": "List MCP connections for a bot",
"tags": [
"mcp"
],
"summary": "List MCP connections",
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/mcp.ListResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"403": {
"description": "Forbidden",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
}
}
},
"post": {
"description": "Create a MCP connection for a bot",
"tags": [
"mcp"
],
"summary": "Create MCP connection",
"parameters": [
{
"description": "MCP payload",
"name": "payload",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/mcp.UpsertRequest"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/github_com_memohai_memoh_internal_mcp.Connection"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"403": {
"description": "Forbidden",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
}
}
}
},
"/bots/{bot_id}/mcp-stdio": {
"post": {
"description": "Start a stdio MCP process in the bot container and expose it as MCP HTTP endpoint.",
"tags": [
"containerd"
],
"summary": "Create MCP stdio proxy",
"parameters": [
{
"type": "string",
"description": "Bot ID",
"name": "bot_id",
"in": "path",
"required": true
},
{
"description": "Stdio MCP payload",
"name": "payload",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/handlers.MCPStdioRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/handlers.MCPStdioResponse"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
}
}
}
},
"/bots/{bot_id}/mcp-stdio/{session_id}": {
"post": {
"description": "Proxies MCP JSON-RPC requests to a stdio MCP process in the container.",
"tags": [
"containerd"
],
"summary": "MCP stdio proxy (JSON-RPC)",
"parameters": [
{
"type": "string",
"description": "Bot ID",
"name": "bot_id",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Session ID",
"name": "session_id",
"in": "path",
"required": true
},
{
"description": "JSON-RPC request",
"name": "payload",
"in": "body",
"required": true,
"schema": {
"type": "object"
}
}
],
"responses": {
"200": {
"description": "JSON-RPC response: {jsonrpc,id,result|error}",
"schema": {
"type": "object"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
}
}
}
},
"/bots/{bot_id}/mcp/{id}": {
"get": {
"description": "Get a MCP connection by ID",
"tags": [
"mcp"
],
"summary": "Get MCP connection",
"parameters": [
{
"type": "string",
"description": "MCP ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/github_com_memohai_memoh_internal_mcp.Connection"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"403": {
"description": "Forbidden",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
}
}
},
"put": {
"description": "Update a MCP connection by ID",
"tags": [
"mcp"
],
"summary": "Update MCP connection",
"parameters": [
{
"type": "string",
"description": "MCP ID",
"name": "id",
"in": "path",
"required": true
},
{
"description": "MCP payload",
"name": "payload",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/mcp.UpsertRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/github_com_memohai_memoh_internal_mcp.Connection"
}
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"403": {
"description": "Forbidden",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
}
}
},
"delete": {
"description": "Delete a MCP connection by ID",
"tags": [
"mcp"
],
"summary": "Delete MCP connection",
"parameters": [
{
"type": "string",
"description": "MCP ID",
"name": "id",
"in": "path",
"required": true
}
],
"responses": {
"204": {
"description": "No Content"
},
"400": {
"description": "Bad Request",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"403": {
"description": "Forbidden",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"404": {
"description": "Not Found",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
},
"500": {
"description": "Internal Server Error",
"schema": {
"$ref": "#/definitions/handlers.ErrorResponse"
}
}
}
}
},
"/bots/{bot_id}/memory/add": {
"post": {
"description": "Add memory for a user via memory. Auth: Bearer JWT determines user_id (sub or user_id).",
@@ -4678,6 +5034,36 @@ const docTemplate = `{
}
}
},
"github_com_memohai_memoh_internal_mcp.Connection": {
"type": "object",
"properties": {
"active": {
"type": "boolean"
},
"bot_id": {
"type": "string"
},
"config": {
"type": "object",
"additionalProperties": {}
},
"created_at": {
"type": "string"
},
"id": {
"type": "string"
},
"name": {
"type": "string"
},
"type": {
"type": "string"
},
"updated_at": {
"type": "string"
}
}
},
"handlers.ChannelMeta": {
"type": "object",
"properties": {
@@ -4933,6 +5319,49 @@ const docTemplate = `{
}
}
},
"handlers.MCPStdioRequest": {
"type": "object",
"properties": {
"args": {
"type": "array",
"items": {
"type": "string"
}
},
"command": {
"type": "string"
},
"cwd": {
"type": "string"
},
"env": {
"type": "object",
"additionalProperties": {
"type": "string"
}
},
"name": {
"type": "string"
}
}
},
"handlers.MCPStdioResponse": {
"type": "object",
"properties": {
"session_id": {
"type": "string"
},
"tools": {
"type": "array",
"items": {
"type": "string"
}
},
"url": {
"type": "string"
}
}
},
"handlers.SkillItem": {
"type": "object",
"properties": {
@@ -5185,6 +5614,35 @@ const docTemplate = `{
}
}
},
"mcp.ListResponse": {
"type": "object",
"properties": {
"items": {
"type": "array",
"items": {
"$ref": "#/definitions/github_com_memohai_memoh_internal_mcp.Connection"
}
}
}
},
"mcp.UpsertRequest": {
"type": "object",
"properties": {
"active": {
"type": "boolean"
},
"config": {
"type": "object",
"additionalProperties": {}
},
"name": {
"type": "string"
},
"type": {
"type": "string"
}
}
},
"memory.DeleteResponse": {
"type": "object",
"properties": {