返回市场
阿多尼斯-mcp

阿多尼斯-mcp

作者:batosai8 星标更新:2025-11-21

项目介绍

@jrmc/adonis-mcp

npm 版本 许可证: MIT

AdonisJS MCP - 适用于您的 AdonisJS 应用程序的 MCP 服务器。

发展路线图

  • 支持 MCP 提示
  • 支持 MCP 资源
  • 支持 MCP 提示
  • 支持替代传输 SSE
  • 支持替代传输 stdio
  • 高级分页支持
  • 自动使用 Vine 进行模式验证
  • 假传输
  • 文档

安装与配置

node ace add @jrmc/adonis-mcp

这将创建一个配置文件 config/mcp.ts

import { defineConfig } from '@jrmc/adonis-mcp'

export default defineConfig({
  name: 'adonis-mcp-server',
  version: '1.0.0',
  path: 'app/mcp', // 存储工具的位置
})

使用方法

创建工具

要创建一个新的工具,请使用 Ace 命令:

node ace make:mcp-tool my_tool

此命令将在 app/mcp/tools/my_tool.ts 中创建一个带有基础模板的文件:

import type { McpContext } from '@jrmc/adonis-mcp/types/context'
import type { BaseSchema, InferJSONSchema } from '@jrmc/adonis-mcp/types/method'

import { Tool } from '@jrmc/adonis-mcp'

type Schema = BaseSchema<{
  text: { type: "string" }
}>

type Context = McpContext & { args: InferJSONSchema<Schema> }

export default class MyToolTool implements Tool<Schema> {
  name = 'tool_name'
  title = 'Tool title'
  description = 'Tool description'

  async handle({ args }: Context) {
    console.log(args.text)
  }

  schema() {
    return {
      type: "object",
      properties: {
        text: {
          type: "string",
          description: "描述文本参数"
        },
      },
      required: ["text"]
    } as Schema
  }
}

模式定义

模式定义了工具的输入参数。它遵循 JSON Schema 规范:

schema() {
  return {
    type: "object",
    properties: {
      title: {
        type: "string",
        description: "书签标题"
      },
      url: {
        type: "string",
        description: "书签 URL"
      }
    },
    required: ["title", "url"]
  } as Schema
}

您也可以使用 Zod 来定义模式:

import * as z from 'zod'

const zodSchema = z.object({
  page: z.number().optional(),
  perPage: z.number().optional()
})

schema() {
  return z.toJSONSchema(
    zodSchema,
    { io: "input" }
  ) as Schema
}

处理程序实现

handle 方法包含工具的逻辑。它接收一个带有已验证参数的类型化上下文:

async handle({ args, response, auth, bouncer }: Context) {
  // 您的逻辑在这里
  const result = await SomeModel.query().where('id', args.id)
  
  return response.text(JSON.stringify({ result }))
}

设置身份验证和 Bouncer

要在您的 MCP 工具中使用 authbouncer,请在中间件(例如,在您的 Bouncer 初始化中间件中)添加以下 TypeScript 声明:

declare module '@jrmc/adonis-mcp/types/context' {
  export interface McpContext {
    auth?: {
      user?: HttpContext['auth']['user']
    }
    bouncer?: Bouncer<
      Exclude<HttpContext['auth']['user'], undefined>,
      typeof abilities,
      typeof policies
    >
  }
}

MCP 上下文会自动绑定 authbouncerHttpContext,如果它们可用的话,因此请确保您的中间件首先在 HttpContext 上初始化它们。

注册 MCP 路由

在您的 start/routes.ts 文件中,注册 MCP 路由并应用中间件:

import { middleware } from '#start/kernel'
import router from '@adonisjs/core/services/router'

// 注册 MCP 路由(默认为 /mcp,或指定自定义路径)
router.mcp().use(middleware.auth())

您还可以指定自定义路径:

router.mcp('/custom-mcp-path').use(middleware.auth())

使用身份验证

MCP 上下文会自动包含来自 HttpContextauth 实例(如果可用)。您可以使用它来访问经过身份验证的用户:

async handle({ args, auth }: Context) {
  const user = auth?.user
  
  if (!user) {
    throw new Error('用户未经过身份验证')
  }
  
  // 使用经过身份验证的用户
  const bookmark = await Bookmark.create({
    title: args.title,
    userId: user.id,
  })
  
  return response.text(JSON.stringify({ bookmark }))
}

使用 Bouncer

MCP 上下文会自动包含来自 HttpContextbouncer 实例(如果可用)。您可以使用它来检查权限:

async handle({ args, bouncer }: Context) {
  // 检查权限
  await bouncer.authorize('viewUsers')
  
  // 或使用策略
  const user = await User.findOrFail(args.userId)
  await bouncer.with(UserPolicy).authorize('view', user)
  
  return response.text(JSON.stringify({ user }))
}

返回响应

上下文包括一个 response 实例来格式化您的响应。最常用的方法是 text()

async handle({ args, response }: Context) {
  const data = { success: true, message: '操作完成' }
  
  return response.text(JSON.stringify(data))
}

完整示例

这是一个创建书签的工具的完整示例:

import type { McpContext } from '@jrmc/adonis-mcp/types/context'
import type { BaseSchema, InferJSONSchema } from '@jrmc/adonis-mcp/types/method'

import { Tool } from '@jrmc/adonis-mcp'
import Bookmark from '#models/bookmark'

type Schema = BaseSchema<{
  title: { type: "string" }
  url: { type: "string" }
}>

type Context = McpContext & { args: InferJSONSchema<Schema> }

export default class AddBookmarkTool implements Tool<Schema> {
  name = 'create_bookmark'
  title = '创建书签'
  description = '创建新的书签'

  async handle({ args, response, auth }: Context) {
    const bookmark = await Bookmark.create({
      title: args.title,
      text: args.url,
      userId: auth?.user?.id,
    })

    return response.text(JSON.stringify({ bookmark }))
  }

  schema() {
    return {
      type: "object",
      properties: {
        title: {
          type: "string",
          description: "书签标题"
        },
        url: {
          type: "string",
          description: "书签 URL"
        }
      },
      required: ["title", "url"]
    } as Schema
  }
}

分页

tools/list 方法支持基于游标的分页,以高效处理大量工具。当您在应用程序中注册了许多工具时,这一点特别有用。更多信息

支持

对于任何问题或问题,请在 GitHub 仓库 上打开一个问题。

启发

此包受到 laravel/mcp 的启发。