使用说明
MCP服务器-用于构建MCP服务器的分层节点包
用于构建MCP服务器的Node In Layers包。它将您的域、功能和模型CRUD作为MCP工具公开,以便AI可以发现和调用它们。配套图书馆: @node-in-layers/mcp-client (功能、模型和工具的共享协议)。
该系统是 self-describing 并自动将工具组织成一个优化和高效的系统,从而减少工具的总数。该系统还自动包含提示和示例,大大提高了系统中AI工具的选择和格式化精度,即使不是数千个工具,也可以包含在具有数百个工具的系统中。
如何使用这个
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.现在有什么可用的
- 功能会自动显示(除非特别隐藏)
- 模型CRUD会自动公开(除非特别隐藏)
- 一
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将:
- 列出域。
- 列出域中的功能(和模型)。
- 当需要模式时,描述一个特征或模型。
- 使用正确的参数执行功能和建模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被指示先调用它(或当用户寻求帮助时)。其响应基于以下内容:
- 系统元数据 —
systemName,systemDescription,systemVersion从配置。 - 默认系统条目 --内置文档(例如“这是一个域分层系统”、“MCP导航工作流”、“跨层道具”)。你可以通过以下方式关闭它们
startHere.hideDefaultSystemEntries. - 可选:包括域/包括功能 --如果
startHere.includeDomains如果为true,则响应包括当前域列表(就像list_domains已被召唤)。如果startHere.includeFeatures如果为真,它还包括每个域的功能列表(就像list_features每个人都被要求)。因此,AI获得了域和/或特征 没有 进行额外的工具调用。 - 使用示例 --您在下面添加的自定义条目
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,
}),
},
},
})
