chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:36:40 +08:00
commit a6fa58bf2b
24 changed files with 1169 additions and 0 deletions
+3
View File
@@ -0,0 +1,3 @@
[install.lockfile]
save = false
+1
View File
@@ -0,0 +1 @@
module.exports = require('@lobehub/lint').changelog;
+1
View File
@@ -0,0 +1 @@
module.exports = require('@lobehub/lint').commitlint;
+16
View File
@@ -0,0 +1,16 @@
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[Makefile]
indent_style = tab
+30
View File
@@ -0,0 +1,30 @@
# Eslintignore for LobeHub
################################################################
# dependencies
node_modules
# ci
coverage
.coverage
# test
jest*
_test_
__test__
# umi
.umi
.umi-production
.umi-test
.dumi/tmp*
!.dumirc.ts
# production
dist
es
lib
logs
# misc
# add other ignore file below
+14
View File
@@ -0,0 +1,14 @@
const config = require('@lobehub/lint').eslint;
module.exports = {
...config,
globals: {
HeadersInit: false,
},
rules: {
...config.rules,
'unicorn/no-useless-undefined': 0,
'unicorn/prefer-string-replace-all': 0,
'unicorn/switch-case-braces': 0,
},
};
+28
View File
@@ -0,0 +1,28 @@
name: Release CI
on:
push:
branches:
- master
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
token: ${{ secrets.GH_TOKEN }}
- name: Install bun
uses: oven-sh/setup-bun@v2
- name: Install deps
run: bun i
- name: Build
run: bun run build
- name: Release
run: bun run release
env:
GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
+53
View File
@@ -0,0 +1,53 @@
# Gitignore for LobeHub
################################################################
# general
.DS_Store
.idea
.vscode
.history
.temp
.env.local
venv
temp
tmp
# dependencies
node_modules
*.log
*.lock
package-lock.json
# ci
coverage
.coverage
.eslintcache
.stylelintcache
# production
dist
es
lib
logs
test-output
# umi
.umi
.umi-production
.umi-test
.dumi
# husky
.husky/prepare-commit-msg
# misc
# add other ignore file below
client.d.ts
client.js
openapi.d.ts
openapi.js
bun.lockb
schema.json
build
+11
View File
@@ -0,0 +1,11 @@
lockfile=false
resolution-mode=highest
public-hoist-pattern[]=*@umijs/lint*
public-hoist-pattern[]=*changelog*
public-hoist-pattern[]=*commitlint*
public-hoist-pattern[]=*eslint*
public-hoist-pattern[]=*postcss*
public-hoist-pattern[]=*prettier*
public-hoist-pattern[]=*remark*
public-hoist-pattern[]=*semantic-release*
public-hoist-pattern[]=*stylelint*
+61
View File
@@ -0,0 +1,61 @@
# Prettierignore for LobeHub
################################################################
# general
.DS_Store
.editorconfig
.idea
.vscode
.history
.temp
.env.local
.husky
.npmrc
.gitkeep
venv
temp
tmp
LICENSE
# dependencies
node_modules
*.log
*.lock
package-lock.json
# ci
coverage
.coverage
.eslintcache
.stylelintcache
test-output
tests/__snapshots__
*.snap
# production
dist
es
lib
logs
# umi
.umi
.umi-production
.umi-test
.dumi/tmp*
# ignore files
.*ignore
# docker
docker
Dockerfile*
# image
*.webp
*.gif
*.png
*.jpg
# misc
# add other ignore file below
+3
View File
@@ -0,0 +1,3 @@
const {prettier}= require('@lobehub/lint');
export default prettier;
+1
View File
@@ -0,0 +1 @@
module.exports = require('@lobehub/lint').semanticRelease;
+9
View File
@@ -0,0 +1,9 @@
const config = require('@lobehub/lint').stylelint;
module.exports = {
...config,
rules: {
'custom-property-pattern': null,
'selector-pseudo-element-no-unknown': null,
},
};
+127
View File
@@ -0,0 +1,127 @@
<a name="readme-top"></a>
# Changelog
### [Version&nbsp;1.1.2](https://github.com/lobehub/mcp-hello-world/compare/v1.1.1...v1.1.2)
<sup>Released on **2025-04-20**</sup>
#### 💄 Styles
- **misc**: Improve output.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### Styles
* **misc**: Improve output ([3dd383c](https://github.com/lobehub/mcp-hello-world/commit/3dd383c))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
### [Version&nbsp;1.1.1](https://github.com/lobehub/mcp-hello-world/compare/v1.1.0...v1.1.1)
<sup>Released on **2025-04-20**</sup>
#### 🐛 Bug Fixes
- **misc**: Fix output files.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### What's fixed
* **misc**: Fix output files ([fe5c9d8](https://github.com/lobehub/mcp-hello-world/commit/fe5c9d8))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
## [Version&nbsp;1.1.0](https://github.com/lobehub/mcp-hello-world/compare/v1.0.0...v1.1.0)
<sup>Released on **2025-04-20**</sup>
#### ✨ Features
- **misc**: Bump version.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### What's improved
* **misc**: Bump version ([fa7bdd5](https://github.com/lobehub/mcp-hello-world/commit/fa7bdd5))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
## Version&nbsp;1.0.0
<sup>Released on **2025-04-20**</sup>
#### ✨ Features
- **misc**: Init mcp hello word.
<br/>
<details>
<summary><kbd>Improvements and Fixes</kbd></summary>
#### What's improved
* **misc**: Init mcp hello word ([8a8f5c9](https://github.com/lobehub/mcp-hello-world/commit/8a8f5c9))
</details>
<div align="right">
[![](https://img.shields.io/badge/-BACK_TO_TOP-151515?style=flat-square)](#readme-top)
</div>
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 LobeHub
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+221
View File
@@ -0,0 +1,221 @@
# MCP Hello World - MCP Server Mock for Testing
[![][npm-release-shield]][npm-release-link]
[![][npm-downloads-shield]][npm-downloads-link]
[![][github-action-test-shield]][github-action-test-link]
[![][github-action-release-shield]][github-action-release-link]
[github-action-release-link]: https://github.com/lobehub/mcp-hello-world/actions/workflows/release.yml
[github-action-release-shield]: https://img.shields.io/github/actions/workflow/status/lobehub/mcp-hello-world/release.yml?label=Release&logo=githubactions&logoColor=white&style=flat-square
[github-action-test-link]: https://github.com/lobehub/mcp-hello-world/actions/workflows/test.yml
[github-action-test-shield]: https://img.shields.io/github/actions/workflow/status/lobehub/mcp-hello-world/test.yml?label=Test&logo=githubactions&logoColor=white&style=flat-square
[npm-downloads-link]: https://www.npmjs.com/package/mcp-hello-world
[npm-downloads-shield]: https://img.shields.io/npm/dt/mcp-hello-world?label=Downloads&logo=npm&style=flat-square
[npm-release-link]: https://www.npmjs.com/package/mcp-hello-world
[npm-release-shield]: https://img.shields.io/npm/v/mcp-hello-world?logo=npm&style=flat-square
This is a **minimal Model Context Protocol (MCP) server** implemented in TypeScript, primarily intended to serve as a **Test Double / Mock Server**.
**Core Purpose**: To provide a lightweight, controllable, and predictable MCP server environment for **unit testing** or **integration testing** client code that needs to interact with an MCP server.
**Note:** This project is **not suitable for production environments** or deployment as a general-purpose MCP server.
[![MCP Badge](https://lobehub.com/badge/mcp-full/lobehub-mcp-hello-world)](https://lobehub.com/mcp/lobehub-mcp-hello-world)
## Why Use `mcp-hello-world` in Tests?
When testing code related to MCP clients, you usually don't want to depend on a real, potentially complex, and unpredictably responsive AI backend service. Using `mcp-hello-world` as a test double offers several advantages:
1. **Isolation**: Focus your tests on client logic without worrying about network issues or the availability of the real server.
2. **Predictability**: The provided `echo` and `debug` tools have simple, fixed behaviors, making it easy to write assertions.
3. **Speed**: Fast startup and response times, suitable for frequent use in unit tests.
4. **Lightweight**: Few dependencies, easy to integrate into test environments.
5. **Protocol Coverage**: Supports both `STDIO` and `HTTP/SSE` MCP transport protocols, allowing you to test client behavior under different connection methods.
## Installation
Add this package as a **dev dependency** to your project:
```bash
# Using pnpm
pnpm add --save-dev mcp-hello-world
# Or using bun
bun add --dev mcp-hello-world
```
## Manual Execution (for Debugging Tests)
You might want to run the server manually sometimes to debug your tests or client behavior.
### STDIO Mode
This is the simplest way to run, especially during local development and debugging.
```bash
# Ensure it's installed (globally or in the project)
# Using npx (universal)
npx mcp-hello-world
# Or using pnpm dlx
pnpm dlx mcp-hello-world
# Or using bunx
bunx mcp-hello-world
```
The server will listen on standard input and output MCP responses to standard output. You can use tools like [MCP Inspector](https://github.com/lobehub/mcp-inspector) to connect to the process.
To configure this server in your MCP client, add the following to your configuration:
```json
{
"mcpServers": {
"mcp-hello-world": {
"command": "npx",
"args": ["mcp-hello-world"]
}
}
}
```
### HTTP/SSE Mode
If you need to debug via a network interface or test HTTP-based MCP clients.
```bash
# 1. Clone the repository (if not already installed in the project)
# git clone https://github.com/lobehub/mcp-hello-world.git
# cd mcp-hello-world
# pnpm install / bun install
# 2. Build the project
# Using pnpm
pnpm build
# Or using bun
bun run build
# 3. Start the HTTP server
# Using pnpm
pnpm start:http
# Or using bun
bun run start:http
```
The server will start on `http://localhost:3000` and provide:
- SSE endpoint: `/sse`
- Message endpoint: `/messages`
## Usage in Tests
You can programmatically start and stop the `mcp-hello-world` server within your test framework (like Jest, Vitest, Mocha, etc.) for automated testing.
### Example: Testing with STDIO Mode (Node.js)
```typescript
// test/my-mcp-client.test.ts (Example using Jest)
import { spawn } from 'child_process';
import { MCPClient } from '../src/my-mcp-client'; // Assuming this is your client code
describe('My MCP Client (STDIO)', () => {
let mcpServerProcess;
let client: MCPClient;
beforeAll(() => {
// Start the mcp-hello-world process before tests
// Using npx (or pnpm dlx / bunx) ensures the command is found and executed
mcpServerProcess = spawn('npx', ['mcp-hello-world']);
// Instantiate your client and connect to the subprocess's stdio
client = new MCPClient(mcpServerProcess.stdin, mcpServerProcess.stdout);
});
afterAll(() => {
// Shut down the mcp-hello-world process after tests
mcpServerProcess.kill();
});
it('should receive echo response', async () => {
const request = {
jsonrpc: '2.0',
id: 1,
method: 'tools/invoke',
params: { name: 'echo', parameters: { message: 'test message' } },
};
const response = await client.sendRequest(request); // Assuming your client has this method
expect(response).toEqual({
jsonrpc: '2.0',
id: 1,
result: { content: [{ type: 'text', text: 'Hello test message' }] },
});
});
it('should get greeting resource', async () => {
const request = {
jsonrpc: '2.0',
id: 2,
method: 'resources/get',
params: { uri: 'greeting://Alice' },
};
const response = await client.sendRequest(request);
expect(response).toEqual({
jsonrpc: '2.0',
id: 2,
result: { data: 'Hello Alice!' }, // Confirm return format based on actual implementation
});
});
// ... other test cases
});
```
### Example: Testing with HTTP/SSE Mode
For HTTP/SSE, you might need to:
1. Use `exec` or `spawn` in `beforeAll` to start `pnpm start:http` or `bun run start:http`.
2. Use an HTTP client (like `axios`, `node-fetch`, or your test framework's built-in client) to connect to `http://localhost:3000/sse` and `/messages` for testing.
3. Ensure you shut down the started server process in `afterAll`.
## Provided MCP Capabilities (for Test Assertions)
`mcp-hello-world` provides the following fixed capabilities for interaction and assertion in your tests:
### Resources
- **`hello://world`**
- Description: A static Hello World resource.
- Method: `resources/get`
- Parameters: None
- Returns: `{ data: 'Hello World!' }`
- **`greeting://{name}`**
- Description: A dynamic greeting resource.
- Method: `resources/get`
- Parameters: `name` included in the URI, e.g., `greeting://Bob`.
- Returns: `{ data: 'Hello {name}!' }` (e.g., `{ data: 'Hello Bob!' }`)
### Tools
- **`echo`**
- Description: Echoes the input message, prefixed with "Hello ".
- Method: `tools/invoke`
- Parameters: `{ name: 'echo', parameters: { message: string } }`
- Returns: `{ content: [{ type: 'text', text: 'Hello {message}' }] }` (e.g., `{ content: [{ type: 'text', text: 'Hello test' }] }`)
- **`debug`**
- Description: Lists all available MCP method definitions on the server.
- Method: `tools/invoke`
- Parameters: `{ name: 'debug', parameters: {} }`
- Returns: A JSON structure containing definitions for all registered resources, tools, and prompts.
### Prompts
- **`helpful-assistant`**
- Description: A basic assistant prompt definition.
- Method: `prompts/get`
- Parameters: None
- Returns: A JSON structure for the prompt with predefined `system` and `user` roles.
## License
MIT
+7
View File
@@ -0,0 +1,7 @@
# WeHub 来源说明
- 原始项目:`lobehub/mcp-hello-world`
- 原始仓库:https://github.com/lobehub/mcp-hello-world
- 导入方式:上游默认分支的最新快照
- 原作者、版权和许可证信息以原始仓库及本仓库 LICENSE 为准
- 本文件仅用于记录来源,不代表 WeHub 是原项目作者
+206
View File
@@ -0,0 +1,206 @@
# MCP Hello World - 用于测试的 MCP 服务端模拟
[![][npm-release-shield]][npm-release-link]
[![][npm-downloads-shield]][npm-downloads-link]
[![][github-action-test-shield]][github-action-test-link]
[![][github-action-release-shield]][github-action-release-link]
[github-action-release-link]: https://github.com/lobehub/mcp-hello-world/actions/workflows/release.yml
[github-action-release-shield]: https://img.shields.io/github/actions/workflow/status/lobehub/mcp-hello-world/release.yml?label=Release&logo=githubactions&logoColor=white&style=flat-square
[github-action-test-link]: https://github.com/lobehub/mcp-hello-world/actions/workflows/test.yml
[github-action-test-shield]: https://img.shields.io/github/actions/workflow/status/lobehub/mcp-hello-world/test.yml?label=Test&logo=githubactions&logoColor=white&style=flat-square
[npm-downloads-link]: https://www.npmjs.com/package/mcp-hello-world
[npm-downloads-shield]: https://img.shields.io/npm/dt/mcp-hello-world?label=Downloads&logo=npm&style=flat-square
[npm-release-link]: https://www.npmjs.com/package/mcp-hello-world
[npm-release-shield]: https://img.shields.io/npm/v/mcp-hello-world?logo=npm&style=flat-square
这是一个基于 TypeScript 实现的 **极简模型上下文协议 (MCP) 服务端**,其**主要目的是作为测试替身 (Test Double) / 模拟服务器 (Mock Server)**。
**核心用途**:在针对需要与 MCP 服务端交互的客户端代码进行**单元测试**或**集成测试**时,提供一个轻量级、可控且行为可预测的 MCP 服务端环境。
**注意:** 本项目**不适用于生产环境**或作为通用的 MCP 服务端部署。
## 为什么在测试中使用 `mcp-hello-world`
在测试与 MCP 客户端相关的代码时,你通常不希望依赖一个真实的、可能复杂的、响应不确定的 AI 后端服务。使用 `mcp-hello-world` 作为测试替身有以下好处:
1. **隔离性 (Isolation)**:让你的测试专注于客户端逻辑,而无需关心网络问题或真实服务端的可用性。
2. **可预测性 (Predictability)**:提供的 `echo``debug` 工具行为简单且固定,方便编写断言。
3. **速度 (Speed)**:启动和响应速度快,适合在单元测试中频繁使用。
4. **轻量级 (Lightweight)**:依赖少,易于在测试环境中集成。
5. **协议覆盖 (Protocol Coverage)**:同时支持 `STDIO``HTTP/SSE` 两种 MCP 传输协议,可以测试客户端在不同连接方式下的表现。
## 安装
将此包作为**开发依赖**添加到你的项目中:
```bash
# 使用 pnpm
pnpm add --save-dev mcp-hello-world
# 或者使用 bun
bun add --dev mcp-hello-world
```
## 手动运行 (用于调试测试)
有时你可能想手动运行服务来调试你的测试或客户端行为。
### STDIO 模式
这是最简单的运行方式,尤其是在本地开发和调试时。
```bash
# 确保已安装
# 使用 npx (通用)
npx mcp-hello-world
# 或者使用 pnpm dlx
pnpm dlx mcp-hello-world
# 或者使用 bunx
bunx mcp-hello-world
```
服务将监听标准输入,并将 MCP 响应输出到标准输出。你可以使用 [MCP Inspector](https://github.com/lobehub/mcp-inspector) 等工具连接到该进程。
### HTTP/SSE 模式
如果你需要通过网络接口进行调试,或者测试基于 HTTP 的 MCP 客户端。
```bash
# 1. 克隆仓库 (如果尚未在项目中安装)
# git clone https://github.com/lobehub/mcp-hello-world.git
# cd mcp-hello-world
# pnpm install / bun install
# 2. 构建项目
# 使用 pnpm
pnpm build
# 或者使用 bun
bun run build
# 3. 启动 HTTP 服务
# 使用 pnpm
pnpm start:http
# 或者使用 bun
bun run start:http
```
服务将在 `http://localhost:3000` 启动,并提供:
- SSE 端点: `/sse`
- 消息端点: `/messages`
## 在测试中使用
你可以在你的测试框架(如 Jest, Vitest, Mocha 等)中,通过编程方式启动和停止 `mcp-hello-world` 服务,以便在自动化测试中使用。
### 示例:使用 STDIO 模式进行测试 (Node.js)
```typescript
// test/my-mcp-client.test.ts (示例使用 Jest)
import { spawn } from 'child_process';
import { MCPClient } from '../src/my-mcp-client'; // 假设这是你要测试的客户端
describe('My MCP Client (STDIO)', () => {
let mcpServerProcess;
let client: MCPClient;
beforeAll(() => {
// 在测试开始前启动 mcp-hello-world 进程
// 使用 npx (或 pnpm dlx / bunx) 确保能找到并执行命令
mcpServerProcess = spawn('npx', ['mcp-hello-world']);
// 实例化你的客户端,并连接到子进程的 stdio
client = new MCPClient(mcpServerProcess.stdin, mcpServerProcess.stdout);
});
afterAll(() => {
// 测试结束后关闭 mcp-hello-world 进程
mcpServerProcess.kill();
});
it('should receive echo response', async () => {
const request = {
jsonrpc: '2.0',
id: 1,
method: 'tools/invoke',
params: { name: 'echo', parameters: { message: 'test message' } },
};
const response = await client.sendRequest(request); // 假设你的客户端有此方法
expect(response).toEqual({
jsonrpc: '2.0',
id: 1,
result: { content: [{ type: 'text', text: 'Hello test message' }] },
});
});
it('should get greeting resource', async () => {
const request = {
jsonrpc: '2.0',
id: 2,
method: 'resources/get',
params: { uri: 'greeting://Alice' },
};
const response = await client.sendRequest(request);
expect(response).toEqual({
jsonrpc: '2.0',
id: 2,
result: { data: 'Hello Alice!' }, // 根据实际实现确认返回格式
});
});
// ... 其他测试用例
});
```
### 示例:使用 HTTP/SSE 模式进行测试
对于 HTTP/SSE,你可能需要:
1.`beforeAll` 中使用 `exec``spawn` 启动 `pnpm start:http``bun run start:http`
2. 使用 HTTP 客户端 (如 `axios`, `node-fetch`, 或测试框架内置的) 连接到 `http://localhost:3000/sse``/messages` 端点进行测试。
3.`afterAll` 中确保关闭启动的服务器进程。
## 提供的 MCP 能力 (用于测试断言)
`mcp-hello-world` 提供以下固定的能力,供你在测试中进行交互和断言:
### 资源 (Resources)
- **`hello://world`**
- 描述: 一个静态的 Hello World 资源。
- 方法: `resources/get`
- 参数: 无
- 返回: `{ data: 'Hello World!' }`
- **`greeting://{name}`**
- 描述: 一个动态的问候资源。
- 方法: `resources/get`
- 参数: URI 中包含 `name`,例如 `greeting://Bob`
- 返回: `{ data: 'Hello {name}!' }` (例如: `{ data: 'Hello Bob!' }`)
### 工具 (Tools)
- **`echo`**
- 描述: 回显输入的消息,并添加 "Hello " 前缀。
- 方法: `tools/invoke`
- 参数: `{ name: 'echo', parameters: { message: string } }`
- 返回: `{ content: [{ type: 'text', text: 'Hello {message}' }] }` (例如: `{ content: [{ type: 'text', text: 'Hello test' }] }`)
- **`debug`**
- 描述: 列出服务端所有可用的 MCP 方法定义。
- 方法: `tools/invoke`
- 参数: `{ name: 'debug', parameters: {} }`
- 返回: 包含所有已注册的 resources, tools, prompts 定义的 JSON 结构。
### 提示词 (Prompts)
- **`helpful-assistant`**
- 描述: 一个基础的助手提示词定义。
- 方法: `prompts/get`
- 参数: 无
- 返回: 一个包含预定义 `system``user` 角色的提示词结构 JSON。
## 许可证
MIT
+107
View File
@@ -0,0 +1,107 @@
{
"name": "mcp-hello-world",
"version": "1.1.2",
"description": "A simple Hello World MCP server",
"keywords": [
"lobehub",
"model-context-protocol",
"sdk"
],
"homepage": "https://github.com/lobehub/mcp-hello-world",
"bugs": {
"url": "https://github.com/lobehub/mcp-hello-world/issues/new"
},
"repository": {
"type": "git",
"url": "https://github.com/lobehub/mcp-hello-world.git"
},
"license": "MIT",
"type": "module",
"author": "LobeHub <i@lobehub.com>",
"bin": {
"mcp-hello-world": "./build/stdio.js"
},
"sideEffects": false,
"main": "./build/index.js",
"types": "./build/index.d.ts",
"files": [
"build"
],
"scripts": {
"build": "tsc",
"ci": "npm run lint && npm run type-check",
"start": "node build/stdio.js",
"start:http": "node build/http.js",
"lint": "eslint \"{src,example}/**/*.{js,jsx,ts,tsx}\" --fix",
"lint:style": "stylelint \"{src,example}/**/*.{js,jsx,ts,tsx}\" --fix",
"prepack": "npm run build && clean-pkg-json",
"prepare": "husky install",
"prepublishOnly": "npm run build",
"prettier": "prettier -c --write --no-error-on-unmatched-pattern \"**/**\"",
"release": "semantic-release",
"test": "vitest --passWithNoTests",
"test:coverage": "vitest run --coverage --passWithNoTests",
"test:update": "vitest -u",
"type-check": "tsc -p tsconfig-check.json"
},
"lint-staged": {
"*.json": [
"prettier --write --no-error-on-unmatched-pattern"
],
"*.{js,jsx}": [
"prettier --write",
"stylelint --fix",
"eslint --fix"
],
"*.{ts,tsx}": [
"prettier --parser=typescript --write",
"stylelint --fix",
"eslint --fix"
]
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.7.0",
"express": "^4.18.2",
"zod": "^3.22.4"
},
"devDependencies": {
"@commitlint/cli": "^18",
"@lobehub/i18n-cli": "^1.10.0",
"@lobehub/lint": "latest",
"@testing-library/react": "^14.1.2",
"@types/lodash-es": "^4",
"@types/node": "^22",
"@types/react": "^18",
"@types/react-dom": "^18",
"@vitest/coverage-v8": "^1",
"clean-pkg-json": "^1",
"commitlint": "^18",
"dumi": "^2",
"dumi-theme-lobehub": "latest",
"eslint": "^8",
"husky": "^8",
"jsdom": "^22",
"leva": "^0",
"lint-staged": "^15",
"prettier": "^3",
"react": "^18",
"react-dom": "^18",
"remark": "^14",
"remark-cli": "^11",
"semantic-release": "^21",
"@types/express": "^4.17.21",
"rimraf": "^5.0.5",
"stylelint": "^15",
"ts-json-schema-generator": "^1.4.0",
"typescript": "^5",
"vitest": "^1"
},
"peerDependencies": {
"react": ">=18",
"react-dom": ">=18"
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org"
}
}
+94
View File
@@ -0,0 +1,94 @@
#!/usr/bin/env node
import express from "express";
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
import { createServer } from "./server.js";
async function main() {
// Create the server
const server = createServer();
// Create Express app
const app = express();
const port = process.env.PORT || 3000;
// Server-side connections
const connections = new Map();
// Handle SSE connections
app.get("/sse", async (req, res) => {
// Generate a unique connection ID (UUID format)
const sessionId = req.query.sessionId as string ||
`${Math.random().toString(36).substring(2, 15)}-${Date.now().toString(36)}`;
try {
// Create a new SSE transport
const transport = new SSEServerTransport(`/messages?sessionId=${sessionId}`, res);
connections.set(sessionId, transport);
// Connect the server to this transport
await server.connect(transport);
} catch (error: any) {
console.error('Error establishing SSE connection:', error);
// If headers already sent due to transport.start(), don't try to set them again
if (!res.headersSent) {
res.status(500).end(`Server error: ${error.message || 'Unknown error'}`);
}
}
// Handle client disconnect
req.on("close", () => {
if (connections.has(sessionId)) {
connections.delete(sessionId);
console.error(`Client ${sessionId} disconnected`);
}
});
});
// Handle messages from client
app.post("/messages", express.json(), async (req, res) => {
try {
// Extract sessionId from query parameters
const sessionId = req.query.sessionId as string;
console.log(`Received message for session ${sessionId}, body:`, req.body);
if (!sessionId || !connections.has(sessionId)) {
// If no sessionId or connection not found, try the first connection
if (connections.size === 0) {
return res.status(400).json({ error: "No active connections" });
}
console.log('Using first available connection');
const transport = connections.values().next().value;
await transport.handlePostMessage(req, res, req.body);
} else {
// Use the specific connection for this session
console.log(`Using connection for session ${sessionId}`);
const transport = connections.get(sessionId);
await transport.handlePostMessage(req, res, req.body);
}
} catch (error: any) {
console.error('Error handling message:', error);
if (!res.headersSent) {
res.status(500).json({ error: `Internal server error: ${error.message || 'Unknown error'}` });
}
}
});
// Debug: log available methods
console.error('Available methods in the MCP server:');
console.error('Server object keys:', Object.keys(server));
console.error('Server constructor:', server.constructor.name);
// Start the server
app.listen(port, () => {
console.error(`Hello World MCP Server running on http://localhost:${port}`);
console.error(`- Connect to /sse for server-sent events`);
console.error(`- Send messages to /messages endpoint`);
});
}
main().catch((error) => {
console.error("Fatal error in main():", error);
process.exit(1);
});
+1
View File
@@ -0,0 +1 @@
export { createServer } from './server.js';
+117
View File
@@ -0,0 +1,117 @@
import {
McpServer,
ResourceTemplate,
} from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
/**
* Creates and configures a Hello World MCP server
* with one resource, one prompt, and one tool
*/
export function createServer() {
// Create an MCP server
const server = new McpServer({
name: "hello-world",
version: "1.0.0",
// Debug handler for incoming method calls
debug: true,
});
// Add a static resource
server.resource("hello", "hello://world", async (uri) => ({
contents: [
{
uri: uri.href,
text: "Hello, World from the resource!",
},
],
}));
// Add a dynamic resource with parameters
server.resource(
"greeting",
new ResourceTemplate("greeting://{name}", { list: undefined }),
async (uri, { name }) => ({
contents: [
{
uri: uri.href,
text: `Hello, ${name} from the resource!`,
},
],
})
);
// Add a prompt
server.prompt(
"helpful-assistant",
"A helpful assistant prompt", // Add description as second parameter
() => ({
messages: [
{
role: "assistant",
content: {
type: "text",
text: "You are a helpful assistant.",
},
},
],
})
);
// Add an echo tool
server.tool(
"echo",
"Echoes back a message with 'Hello' prefix",
{ message: z.string().describe("The message to echo") },
async ({ message }) => ({
content: [
{
type: "text",
text: `You said: ${message}`,
},
],
})
);
// Add a debug tool to list available tools
server.tool(
"debug",
"Lists all available tools and methods",
{},
async () => ({
content: [
{
type: "text",
text: JSON.stringify({
tools: Object.keys(server),
methods: ["tools/invoke", "mcp/capabilities", "debug/info"]
}, null, 2),
},
],
})
);
server.tool(
'add',
'Adds two numbers',
{
a: z.number().describe('The first number'),
b: z.number().describe('The second number'),
},
async ({ a, b }) => {
console.log(`[Mock SDK Server] Executing add tool with a=${a}, b=${b}`);
const sum = a + b;
return {
content: [
{
text: `The sum is: ${sum}`,
type: 'text',
},
],
};
},
);
return server;
}
+22
View File
@@ -0,0 +1,22 @@
#!/usr/bin/env node
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import { createServer } from "./server.js";
async function main() {
// Create the server
const server = createServer();
// Create stdio transport
const transport = new StdioServerTransport();
// Connect the server to the transport
await server.connect(transport);
console.error("Hello World MCP Server running on stdio");
}
main().catch((error) => {
console.error("Fatal error in main():", error);
process.exit(1);
});
+15
View File
@@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./build",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
}