MCP服务器构建工具

一个用于构建MCP服务器的Node.js库,允许AI发现并调用域、功能和模型CRUD操作,支持自动组织工具和优化系统。

  • by Node-In-Layers
  • TypeScript
  • 本地部署
  • 更新于
在 GitHub 查看 Node-In-Layers/mcp-server

使用说明

MCP服务器-用于构建MCP服务器的分层节点包

用于构建MCP服务器的Node In Layers包。它将您的域、功能和模型CRUD作为MCP工具公开,以便AI可以发现和调用它们。配套图书馆: @node-in-layers/mcp-client (功能、模型和工具的共享协议)。

该系统是 self-describing 并自动将工具组织成一个优化和高效的系统,从而减少工具的总数。该系统还自动包含提示和示例,大大提高了系统中AI工具的选择和格式化精度,即使不是数千个工具,也可以包含在具有数百个工具的系统中。

API文件


如何使用这个

1.安装

npm install @node-in-layers/mcp-server

2.配置

// /config.base.mts
import { CoreNamespace } from '@node-in-layers/core'
import { McpNamespace, HttpConnection } from '@node-in-layers/mcp-server'

export default () => ({
  systemName: 'your-system-name',
  [CoreNamespace.root]: {
    /* 1. Add to the Apps List */
    apps: await Promise.all([
      // Other Very Early Modules
      //import('@node-in-layers/data/index.js'),

      // Insert Here
      import('@node-in-layers/mcp-server/index.js'),

      // Insert Your Domains Here
    ]),
    /* 2. Add mcp layer. NOTE: You must have entries between features and mcp */
    layerOrder: ['services', 'features', ['entries', 'mcp']], // can also be ['entries', 'express', 'mcp']
  },
  /* 3. Add Mcp Server Configurations */
  [McpNamespace]: {
    // Required: The configuration of the server itself.
    server: {
      connection: {
        type: 'http',
        url: 'http://localhost',
        port: 4000,
      } as HttpConnection,
    },
    // Optional arguments go here.
  },
})

3.现在有什么可用的

  1. 功能会自动显示(除非特别隐藏)
  2. 模型CRUD会自动公开(除非特别隐藏)
  3. 一 mcp 层现在可用于功能,并在名称空间中包含其他功能: McpNamespace(稍后解释)

4.运行服务器

通过执行以下操作,您可以很容易地在一个简单的脚本中运行服务器:

import { McpNamespace } from '@node-in-layers/mcp-server'
const system: System = (await core.loadSystem<SystemConfig>({
  environment,
})) as any // "System" is your typed System object.
await system.mcp[McpNamespace].start(context)

示例。/bin/mcp_server.mts文件(可以随意复制粘贴)

#!/usr/bin/env tsx

import esMain from 'es-main'
import { ArgumentParser } from 'argparse'
import * as core from '@node-in-layers/core'
import { McpNamespace } from '@node-in-layers/mcp-server'
import { SystemConfig } from '../src/types.js'
import { System } from '../src/system/types.js'

const _parseArguments = () => {
  const parser = new ArgumentParser({
    description: 'Starts the MCP server.',
  })
  parser.add_argument('environment', {
    help: 'The environment for the service.',
  })
  return parser.parse_args()
}

const startServer = async (environment: string) => {
  const system = (await core.loadSystem<SystemConfig>({
    environment,
  })) as unknown as System
  if (system.config[McpNamespace].server.connection.type === 'http') {
    console.info(
      `Starting MCP server on ${system.config[McpNamespace].server.connection.port}...`
    )
  }
  process.on('SIGINT', async function () {
    await system.services['@node-in-layers/data'].cleanup()
    process.exit()
  })

  await system.mcp[McpNamespace].start(system)
}

if (esMain(import.meta)) {
  const args = _parseArguments()
  startServer(args.environment).catch((error: any) => {
    console.error('Failed to start the server:', error)
    process.exit(1)
  })
}

背景及其工作原理

MCP接口(域、功能、模型)

MCP工具表面为 按领域组织,然后是特征和模型:

  • 领域 --AI可以列出域名(list_domains),然后针对每个域列表功能(list_features)以及(如果存在)列出型号。仅显示具有公开功能或模型的域。
  • 特性 --对于给定的域/特征,AI可以获得模式(describe_feature)并运行它(execute_feature).
  • 模型 --对于给定的域/模型,AI可以获取模式并运行保存、检索、删除、搜索、bulkInsert、bulkDelete。

这 文件返回给AI (包括START_HERE返回的内容) 可配置的默认情况下,服务器提供指令,因此AI将:

  1. 列出域。
  2. 列出域中的功能(和模型)。
  3. 当需要模式时,描述一个特征或模型。
  4. 使用正确的参数执行功能和建模CRUD操作。

因此,人工智能从可配置的“从这里开始”和默认系统条目中学习系统的形状,然后根据需要使用工具列出/描述/执行。

平面模式(仅功能工具)

如果你想要一个非常小的“前端和中心”工具表面(例如:一个具有单一功能的系统),你可以在中运行MCP服务器 扁平模式.

在平面模式下,服务器:

  • 暴露 每个功能都是自己的MCP工具 命名 domain_featureName.
  • 不 显示图层中的节点导航工具(START_HERE, list_domains, list_features, describe_feature, execute_feature).
  • 不 公开任何模型CRUD工具(list_models, describe_model, save, retrieve, delete, search, bulkInsert, bulkDelete).
  • 仍然公开您通过显式注册的任何工具 addTool() / addAnnotatedFunction().

通过以下方式启用它:

// /config.base.mts
import { McpNamespace } from '@node-in-layers/mcp-server'

export default () => ({
  // ...
  [McpNamespace]: {
    mode: 'flat',
    server: { connection: { type: 'cli' } },
  },
})

隐藏组件

您可以限制调用者可见的内容(以及可执行的内容)(例如某些域、功能或所有模型CRUD),以便只暴露预期的表面。

配置 hideComponents 在MCP配置下:

  • 路径 --点分隔路径以隐藏,例如。 myDomain, myDomain.myFeature, myDomain.cruds, myDomain.cruds.MyModel.
  • 领域 --域名完全隐藏(它们不会出现在 list_domains).
  • 所有模型 --如果 true,没有公开模型CRUD工具。

所有没有隐藏的东西都是可用的。看 配置详情 对于完整的形状。

示例(部分配置):

// /config.base.mts
import { McpNamespace } from '@node-in-layers/mcp-server'

export default () => ({
  // ...
  [McpNamespace]: {
    // ...
    hideComponents: {
      // Completely hide these domains from the MCP surface
      domains: ['internalAdmin', 'experimental'],

      // Hide specific paths (domains, features, or models)
      paths: [
        'billing.cruds', // hide all models in the billing domain
        'users.cruds.ApiKeys', // hide a single model. (The ApiKeys table located in the users domain)
        'debug.internalFeature', // hide a specific feature
      ],

      // Or hide all models everywhere. Good for "feature" oriented systems.
      allModels: false, // set true to hide all model CRUD tools
    },
  },
})

系统描述

在...之下 systemDescription 你设置 静态元数据 对于starthere响应中包含的系统:

  • 描述 --AI的简短系统描述。
  • 版本 --系统版本字符串。

这是“这个系统是什么”和版本的正确位置;它不控制存在哪些工具,也不控制START_HERE工具包括什么(即 startHere).

示例(部分配置):

// /config.base.mts
import { McpNamespace } from '@node-in-layers/mcp-server'

export default () => ({
  // ...
  [McpNamespace]: {
    // ...
    systemDescription: {
      description: 'Order management and billing system for ACME Corp.',
      version: '2.3.0',
    },
  },
})

从这里开始

这 开始_此处 该工具使系统可导航:AI被指示先调用它(或当用户寻求帮助时)。其响应基于以下内容:

  1. 系统元数据 — systemName, systemDescription, systemVersion 从配置。
  2. 默认系统条目 --内置文档(例如“这是一个域分层系统”、“MCP导航工作流”、“跨层道具”)。你可以通过以下方式关闭它们 startHere.hideDefaultSystemEntries.
  3. 可选:包括域/包括功能 --如果 startHere.includeDomains 如果为true,则响应包括当前域列表(就像 list_domains 已被召唤)。如果 startHere.includeFeatures 如果为真,它还包括每个域的功能列表(就像 list_features 每个人都被要求)。因此,AI获得了域和/或特征 没有 进行额外的工具调用。
  4. 使用示例 --您在下面添加的自定义条目 startHere.examplesOfUse。这些是你记录的地方 更高级别的流量 (例如“运行特征A,然后是B,然后是C”)。内置文档解释了域、功能和模型;他们确实如此 不 解释你的应用程序特定的序列。把那些放进去 examplesOfUse,如 JSON对象示例,简洁明了 因此AI可以直接应用它们。

包含域/包含功能
启用这些就像预运行 list_domains 和 list_features 并将结果嵌入START_HERE中。缺点是 上下文长度:对于大型系统(许多工具),这可能会消耗大量上下文并增加噪声。对于 小型系统(约1-10个工具) 通常都很好。对于较大的系统,首选 使用示例 让AI呼叫 list_domains / list_features 必要时。

示例(部分配置):

// /config.base.mts
import { McpNamespace } from '@node-in-layers/mcp-server'

export default () => ({
  // ...
  [McpNamespace]: {
    // ...
    startHere: {
      // Optional: override tool identity
      name: 'START_HERE',
      description:
        'BEFORE YOU DO ANYTHING, call this first to learn how to navigate the system.',

      // What to include in the start-here response
      hideDefaultSystemEntries: false, // do we want the ones that come by default? Usually this is yes.
      includeDomains: true, // Should we go ahead and tell it the domains? Commonly this should be true.
      includeFeatures: false, // Should we tell them all the features on the first go? In most cases this should be FALSE. Unless its a small system with few functions.

      // Higher-level flows through your system
      examplesOfUse: [
        {
          name: 'Create order then fetch it',
          description: 'Typical flow that creates an order and then retrieves it.',
          // Giving ACTUAL examples (json data, + small annotations) works amazingly.
          example: `
```markdown
// 1. Create an order
{ "tool": "execute_feature", "args": { "domain": "orders", "featureName": "createOrder" } }
// 2. Get the order by id (using the id from step 1)
{ "tool": "execute_feature", "args": { "domain": "orders", "featureName": "getOrderById" } }
      `,
      tags: ['orders', 'flow'],
    },
  ],
},

}, })


---

## Extending with custom tools

You can add your own MCP tools via the MCP layer using `addTool`. Use this from a layer that has access to `mcp[McpNamespace]` (e.g. after the MCP layer in the stack).

Example (conceptual):

```typescript
// In a layer that runs after the MCP layer and has context.mcp[McpNamespace]
const mcp = context.mcp[McpNamespace]
mcp.addTool({
  name: 'my_custom_tool',
  description: 'Does something custom',
  inputSchema: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'] },
  outputSchema: { type: 'object' },
  execute: async (input) => ({ result: input.id }),
})

然后,您的工具将与内置的域/功能/模型工具一起公开。


如何运行服务器

  • 开始 --启动MCP服务器(监听配置中定义的连接)。
    mcp[McpNamespace].start(systemContext, options?)
  • getApp --获取Express应用程序(用于HTTP/SSE),以便您可以将其挂载到自己的服务器中。
    mcp[McpNamespace].getApp(options?)

使用 开始 当MCP服务器是主进程时。使用 getApp 当您使用现有的Express应用程序进行组合时(例如,在路径上挂载MCP应用程序)。


中间件和路由

  • addPreRouteMiddleware(中间件) --添加在MCP路由处理之前运行的Express中间件。
  • addCrossLayerPropMiddleware(中间件) --添加中间件以提取和传递请求级数据(例如,经过身份验证的 user)转换为跨层属性,供下游函数使用。
  • addAdditional route(路线) --在同一应用程序上注册额外的Express路线(例如健康或管理员)。

在设置过程中调用这些(例如,从有权访问的层调用 mcp[McpNamespace])在服务器启动或应用程序使用之前。


更改日志记录配置

日志记录配置在 logging MCP配置的一部分。您可以控制日志级别,并可选择向每个请求/响应日志条目添加结构化数据。

  • requestLogLevel / responseLogLevel:覆盖默认日志级别(info)用于传入请求和传出响应。
  • requestLogGetData(输入):将原始请求输入映射到日志中的额外数据的函数。
  • responseLogGetData(结果):将原始工具结果映射到日志中的额外数据的函数。

示例(部分配置):

// /config.base.mts
import { McpNamespace } from '@node-in-layers/mcp-server'

export default () => ({
  // ...
  [McpNamespace]: {
    // ...
    logging: {
      // Adjust verbosity
      requestLogLevel: 'debug',
      responseLogLevel: 'info',

      // Attach additional request information to the log.
      requestLogGetData: (input: Request) => ({
        something: input.something,
      }),
      responseLogGetData: (input: Request) => ({
        // Shape this to your needs; example:
        truncated: true,
      }),
    },
  },
})