@sylphx/mcp服务器sdk
Bun的纯功能MCP(模型上下文协议)服务器SDK。
](https://www.npmjs.com/package/@sylphx/mcp-server-sdk) 
特性
- 纯函数式:不可变数据,可组合处理程序
- 类型安全:具有Vex模式集成的第一类TypeScript
- 生成器模式:流利的API,用于定义工具、资源和提示
- 快速:为Bun构建,依赖性最小
- 流式HTTP:MCP 2025-03-26规范,带有SSE通知
- 完成:工具、资源、提示、通知、采样、启发
安装
bun add @sylphx/mcp-server-sdk快速开始
import { createServer, tool, text, stdio } from "@sylphx/mcp-server-sdk"
import { object, str } from "@sylphx/vex"
// Define tools using builder pattern
const greet = tool()
.description("Greet someone")
.input(object({ name: str() }))
.handler(({ input }) => text(`Hello, ${input.name}!`))
const ping = tool()
.handler(() => text("pong"))
// Create and start server
const server = createServer({
name: "my-server",
version: "1.0.0",
tools: { greet, ping },
transport: stdio()
})
await server.start()工具
工具是暴露给AI的可调用函数。
import { tool, text, image, audio, json, toolError } from "@sylphx/mcp-server-sdk"
import { description, enum_, num, object, str } from "@sylphx/vex"
// Simple tool (no input)
const ping = tool()
.description("Health check")
.handler(() => text("pong"))
// Tool with typed input
const calculator = tool()
.description("Perform arithmetic")
.input(object({
a: num(description("First number")),
b: num(description("Second number")),
op: enum_(["+", "-", "*", "/"] as const),
}))
.handler(({ input }) => {
const { a, b, op } = input
const result = op === "+" ? a + b
: op === "-" ? a - b
: op === "*" ? a * b
: a / b
return text(`${a} ${op} ${b} = ${result}`)
})
// Multiple content items
const systemInfo = tool()
.description("Get system information")
.handler(() => [
text("CPU: 8 cores"),
text("Memory: 16GB")
])
// Mixed content types
const screenshot = tool()
.description("Take screenshot with description")
.handler(() => [
text("Here's the screenshot:"),
image(base64Data, "image/png")
])
// Return JSON data
const getUser = tool()
.description("Get user data")
.input(object({ id: str() }))
.handler(({ input }) => json({ id: input.id, name: "Alice" }))
// Return error
const riskyOperation = tool()
.description("May fail")
.handler(() => toolError("Something went wrong"))资源
资源为AI提供数据。
import { resource, resourceTemplate, resourceText, resourceBlob } from "@sylphx/mcp-server-sdk"
// Static resource with fixed URI
const readme = resource()
.uri("file:///readme.md")
.description("Project readme")
.mimeType("text/markdown")
.handler(({ uri }) => resourceText(uri, "# My Project\n\nWelcome!"))
// Resource template for dynamic URIs
const fileReader = resourceTemplate()
.uriTemplate("file:///{path}")
.description("Read any file")
.handler(async ({ uri, params }) => {
const content = await Bun.file(`/${params.path}`).text()
return resourceText(uri, content)
})
// Binary resource
const logo = resource()
.uri("image:///logo.png")
.mimeType("image/png")
.handler(async ({ uri }) => {
const data = await Bun.file("./logo.png").bytes()
const base64 = Buffer.from(data).toString("base64")
return resourceBlob(uri, base64, "image/png")
})鼓励
提示是可重复使用的对话模板。
import { prompt, user, assistant, messages, promptResult } from "@sylphx/mcp-server-sdk"
import { description, object, optional, str, withDefault } from "@sylphx/vex"
// Simple prompt (no arguments)
const greeting = prompt()
.description("A friendly greeting")
.handler(() => messages(
user("Hello!"),
assistant("Hi there! How can I help you today?")
))
// Prompt with typed arguments
const codeReview = prompt()
.description("Review code for issues")
.args(object({
code: str(description("Code to review")),
language: optional(str(description("Programming language"))),
}))
.handler(({ args }) => messages(
user(`Please review this ${args.language ?? "code"}:\n\`\`\`\n${args.code}\n\`\`\``),
assistant("I'll analyze this code for potential issues, best practices, and improvements.")
))
// Prompt with description in result
const translate = prompt()
.description("Translate text between languages")
.args(object({
text: str(),
from: withDefault(str(), "auto"),
to: str(),
}))
.handler(({ args }) => promptResult(
`Translation from ${args.from} to ${args.to}`,
messages(user(`Translate "${args.text}" from ${args.from} to ${args.to}`))
))服务器配置
import { createServer, stdio, http } from "@sylphx/mcp-server-sdk"
const server = createServer({
// Server identity
name: "my-server",
version: "1.0.0",
instructions: "This server provides...",
// Handlers (names from object keys)
tools: { greet, ping, calculator },
resources: { readme, config },
resourceTemplates: { file: fileReader },
prompts: { codeReview, translate },
// Transport
transport: stdio() // or http({ port: 3000 })
})
await server.start()运输
标准运输
用于CLI工具和子流程通信。
import { stdio } from "@sylphx/mcp-server-sdk"
const server = createServer({
tools: { ping },
transport: stdio()
})
await server.start()HTTP传输
实现MCP流式HTTP(2025-03-26规范),支持SSE实时通知。
import { http } from "@sylphx/mcp-server-sdk"
const server = createServer({
tools: { ping },
transport: http({
port: 3000,
cors: "*" // Enable CORS for web clients
})
})
await server.start()
// Server running at http://localhost:3000/mcp终点:
POST /mcp-JSON-RPC消息(根据Accept标头返回JSON或SSE)GET /mcp/health-健康检查
SSE流媒体:
当客户端发送 Accept: text/event-stream,服务器以SSE格式响应,在请求处理过程中启用实时通知:
event: message
data: {"jsonrpc":"2.0","method":"notifications/progress","params":{...}}
event: message
data: {"jsonrpc":"2.0","id":1,"result":{...}}通知
使用简化的上下文API发送服务器到客户端的进度和日志通知。
import { array, object, str } from "@sylphx/vex"
const processFiles = tool()
.description("Process multiple files")
.input(object({ files: array(str()) }))
.handler(async ({ input, ctx }) => {
const total = input.files.length
for (let i = 0; i {
const sampling = createSamplingClient(ctx.requestSampling)
const result = await sampling.createMessage({
messages: [
{ role: "user", content: { type: "text", text: `Summarize: ${input.text}` } }
],
maxTokens: 500,
// Optional parameters
systemPrompt: "You are a helpful summarizer",
temperature: 0.7,
stopSequences: ["END"],
modelPreferences: {
hints: [{ name: "claude-3" }],
costPriority: 0.5,
speedPriority: 0.5,
intelligencePriority: 0.8,
},
})
// result.content is the response content
// result.model is the model used
// result.stopReason is why generation stopped
return text(result.content.text)
})引出
向客户端请求用户输入。
import { createElicitationClient } from "@sylphx/mcp-server-sdk"
import { object, str } from "@sylphx/vex"
const confirmAction = tool()
.description("Confirm before proceeding")
.input(object({ action: str() }))
.handler(async ({ input, ctx }) => {
const elicit = createElicitationClient(ctx.requestElicitation)
const result = await elicit.elicit(
`Are you sure you want to ${input.action}?`,
{
type: "object",
properties: {
confirm: {
type: "boolean",
description: "Confirm action",
},
reason: {
type: "string",
description: "Optional reason",
},
},
required: ["confirm"],
}
)
// result.action: "accept" | "decline" | "cancel"
// result.content: { confirm: boolean, reason?: string } (when action is "accept")
if (result.action === "accept" && result.content?.confirm) {
return text(`Proceeding with ${input.action}`)
}
return text("Action cancelled")
})激励模式属性
interface ElicitationProperty {
type: "string" | "number" | "integer" | "boolean"
description?: string
default?: string | number | boolean
enum?: (string | number)[] // Constrain to specific values
enumNames?: string[] // Display names for enum values
// String-specific
format?: "email" | "uri" | "date" | "date-time"
minLength?: number
maxLength?: number
// Number-specific
minimum?: number
maximum?: number
}分页
分页大型结果集。
import { paginate } from "@sylphx/mcp-server-sdk"
import { object, optional, str } from "@sylphx/vex"
const listItems = tool()
.description("List items with pagination")
.input(object({ cursor: optional(str()) }))
.handler(async ({ input }) => {
const allItems = await fetchAllItems()
const result = paginate(allItems, input.cursor, {
defaultPageSize: 10,
maxPageSize: 100,
})
// result.items: current page items
// result.nextCursor: cursor for next page (undefined if last page)
return json({
items: result.items,
nextCursor: result.nextCursor,
})
})api参考
服务器
createServer(config: ServerConfig): Server
interface ServerConfig {
name?: string // Default: "mcp-server"
version?: string // Default: "1.0.0"
instructions?: string // Instructions for the LLM
tools?: Record
resources?: Record
resourceTemplates?: Record
prompts?: Record
transport: TransportFactory
}工具生成器
tool()
.description(string) // Optional description
.input(VexSchema) // Optional input schema
.handler(fn: HandlerFn) -> ToolDefinition
// Handler signature
({ input, ctx }) => ToolResult | Promise
// Handler can return:
// - Single content: text("hello")
// - Array: [text("hi"), image(data, "image/png")]
// - Full result: { content: [...], isError: true }全功能资源编辑器
resource()
.uri(string) // Required URI
.description(string) // Optional description
.mimeType(string) // Optional MIME type
.handler(fn) -> ResourceDefinition
resourceTemplate()
.uriTemplate(string) // Required URI template (RFC 6570)
.description(string) // Optional description
.mimeType(string) // Optional MIME type
.handler(fn) -> ResourceTemplateDefinition
// Handler receives { uri, ctx } or { uri, params, ctx }快速构建器
prompt()
.description(string) // Optional description
.args(VexSchema) // Optional arguments schema
.handler(fn) -> PromptDefinition
// Handler receives { args, ctx } or { ctx }内容助手
// Tool content
text(content: string, annotations?): TextContent
image(data: string, mimeType: string, annotations?): ImageContent
audio(data: string, mimeType: string, annotations?): AudioContent
embedded(resource: EmbeddedResource, annotations?): ResourceContent
json(data: unknown): TextContent
toolError(message: string): ToolsCallResult
// Resources
resourceText(uri: string, text: string, mimeType?: string): ResourcesReadResult
resourceBlob(uri: string, blob: string, mimeType: string): ResourcesReadResult
resourceContents(...items: EmbeddedResource[]): ResourcesReadResult
// Prompts
user(content: string): PromptMessage
assistant(content: string): PromptMessage
messages(...msgs: PromptMessage[]): PromptsGetResult
promptResult(description: string, result: PromptsGetResult): PromptsGetResult运输
stdio(options?: StdioOptions): TransportFactory
http(options?: HttpOptions): TransportFactory
interface HttpOptions {
port?: number // Default: 3000
hostname?: string // Default: "localhost"
}通知
progress(token, current, options?): ProgressNotification
log(level, data, logger?): LogNotification
resourcesListChanged(): Notification
toolsListChanged(): Notification
promptsListChanged(): Notification
resourceUpdated(uri): Notification
cancelled(requestId, reason?): Notification采样
createSamplingClient(sender: SamplingRequestSender): SamplingClient
interface SamplingClient {
createMessage(params: SamplingCreateParams): Promise
}引出
createElicitationClient(sender: ElicitationRequestSender): ElicitationClient
interface ElicitationClient {
elicit(message: string, schema: ElicitationSchema): Promise
}分页
paginate(items: T[], cursor?: string, options?: PaginationOptions): PageResult
interface PaginationOptions {
defaultPageSize?: number // Default: 50
maxPageSize?: number // Default: 100
}
interface PageResult {
items: T[]
nextCursor?: string
}由Sylphx提供技术支持
- @sylphx/vex -超快速模式验证
- @sylphx/阵风 -Bun的轻量级HTTP框架
- @sylphx/biome配置 -共享生物特征配置
- @sylphx/tsconfig -共享TypeScript配置
- @sylphx/医生 -项目健康检查器
- @sylphx/bump -版本管理
许可证
麻省理工学院
