Merge pull request #3121 from cliffhall/new-everything-server
New everything server
This commit is contained in:
commit
dcb47d2d94
52 changed files with 3412 additions and 1651 deletions
62
package-lock.json
generated
62
package-lock.json
generated
|
|
@ -1862,7 +1862,6 @@
|
|||
"resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
|
||||
"integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"accepts": "^2.0.0",
|
||||
"body-parser": "^2.2.1",
|
||||
|
|
@ -2675,6 +2674,22 @@
|
|||
"node": "^10 || ^12 || >=14"
|
||||
}
|
||||
},
|
||||
"node_modules/prettier": {
|
||||
"version": "2.8.8",
|
||||
"resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
|
||||
"integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"prettier": "bin-prettier.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10.13.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/prettier/prettier?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/process-nextick-args": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
|
||||
|
|
@ -3390,7 +3405,6 @@
|
|||
"integrity": "sha512-j3lYzGC3P+B5Yfy/pfKNgVEg4+UtcIJcVRt2cDjIOmhLourAqPqf8P7acgxeiSgUB7E3p2P8/3gNIgDLpwzs4g==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.21.3",
|
||||
"postcss": "^8.4.43",
|
||||
|
|
@ -3474,7 +3488,6 @@
|
|||
"integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@vitest/expect": "2.1.9",
|
||||
"@vitest/mocker": "2.1.9",
|
||||
|
|
@ -3644,7 +3657,6 @@
|
|||
"resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
|
||||
"integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
|
|
@ -3735,10 +3747,10 @@
|
|||
},
|
||||
"src/everything": {
|
||||
"name": "@modelcontextprotocol/server-everything",
|
||||
"version": "0.6.2",
|
||||
"version": "2.0.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.24.0",
|
||||
"@modelcontextprotocol/sdk": "^1.24.3",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^5.2.1",
|
||||
"jszip": "^3.10.1",
|
||||
|
|
@ -3751,10 +3763,48 @@
|
|||
"devDependencies": {
|
||||
"@types/cors": "^2.8.19",
|
||||
"@types/express": "^5.0.6",
|
||||
"prettier": "^2.8.8",
|
||||
"shx": "^0.3.4",
|
||||
"typescript": "^5.6.2"
|
||||
}
|
||||
},
|
||||
"src/everything/node_modules/@modelcontextprotocol/sdk": {
|
||||
"version": "1.24.3",
|
||||
"resolved": "https://registry.npmjs.org/@modelcontextprotocol/sdk/-/sdk-1.24.3.tgz",
|
||||
"integrity": "sha512-YgSHW29fuzKKAHTGe9zjNoo+yF8KaQPzDC2W9Pv41E7/57IfY+AMGJ/aDFlgTLcVVELoggKE4syABCE75u3NCw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"ajv": "^8.17.1",
|
||||
"ajv-formats": "^3.0.1",
|
||||
"content-type": "^1.0.5",
|
||||
"cors": "^2.8.5",
|
||||
"cross-spawn": "^7.0.5",
|
||||
"eventsource": "^3.0.2",
|
||||
"eventsource-parser": "^3.0.0",
|
||||
"express": "^5.0.1",
|
||||
"express-rate-limit": "^7.5.0",
|
||||
"jose": "^6.1.1",
|
||||
"pkce-challenge": "^5.0.0",
|
||||
"raw-body": "^3.0.0",
|
||||
"zod": "^3.25 || ^4.0",
|
||||
"zod-to-json-schema": "^3.25.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@cfworker/json-schema": "^4.1.1",
|
||||
"zod": "^3.25 || ^4.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@cfworker/json-schema": {
|
||||
"optional": true
|
||||
},
|
||||
"zod": {
|
||||
"optional": false
|
||||
}
|
||||
}
|
||||
},
|
||||
"src/filesystem": {
|
||||
"name": "@modelcontextprotocol/server-filesystem",
|
||||
"version": "0.6.3",
|
||||
|
|
|
|||
4
src/everything/.prettierignore
Normal file
4
src/everything/.prettierignore
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
packages
|
||||
dist
|
||||
README.md
|
||||
node_modules
|
||||
52
src/everything/AGENTS.md
Normal file
52
src/everything/AGENTS.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# MCP "Everything" Server - Development Guidelines
|
||||
|
||||
## Build, Test & Run Commands
|
||||
|
||||
- Build: `npm run build` - Compiles TypeScript to JavaScript
|
||||
- Watch mode: `npm run watch` - Watches for changes and rebuilds automatically
|
||||
- Run STDIO server: `npm run start:stdio` - Starts the MCP server using stdio transport
|
||||
- Run SSE server: `npm run start:sse` - Starts the MCP server with SSE transport
|
||||
- Run StreamableHttp server: `npm run start:stremableHttp` - Starts the MCP server with StreamableHttp transport
|
||||
- Prepare release: `npm run prepare` - Builds the project for publishing
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
- Use ES modules with `.js` extension in import paths
|
||||
- Strictly type all functions and variables with TypeScript
|
||||
- Follow zod schema patterns for tool input validation
|
||||
- Prefer async/await over callbacks and Promise chains
|
||||
- Place all imports at top of file, grouped by external then internal
|
||||
- Use descriptive variable names that clearly indicate purpose
|
||||
- Implement proper cleanup for timers and resources in server shutdown
|
||||
- Handle errors with try/catch blocks and provide clear error messages
|
||||
- Use consistent indentation (2 spaces) and trailing commas in multi-line objects
|
||||
- Match existing code style, import order, and module layout in the respective folder.
|
||||
- Use camelCase for variables/functions,
|
||||
- Use PascalCase for types/classes,
|
||||
- Use UPPER_CASE for constants
|
||||
- Use kebab-case for file names and registered tools, prompts, and resources.
|
||||
- Use verbs for tool names, e.g., `get-annotated-message` instead of `annotated-message`
|
||||
|
||||
## Extending the Server
|
||||
|
||||
The Everything Server is designed to be extended at well-defined points.
|
||||
See [Extension Points](docs/extension.md) and [Project Structure](docs/structure.md).
|
||||
The server factory is `src/everything/server/index.ts` and registers all features during startup as well as handling post-connection setup.
|
||||
|
||||
### High-level
|
||||
|
||||
- Tools live under `src/everything/tools/` and are registered via `registerTools(server)`.
|
||||
- Resources live under `src/everything/resources/` and are registered via `registerResources(server)`.
|
||||
- Prompts live under `src/everything/prompts/` and are registered via `registerPrompts(server)`.
|
||||
- Subscriptions and simulated update routines are under `src/everything/resources/subscriptions.ts`.
|
||||
- Logging helpers are under `src/everything/server/logging.ts`.
|
||||
- Transport managers are under `src/everything/transports/`.
|
||||
|
||||
### When adding a new feature
|
||||
|
||||
- Follow the existing file/module pattern in its folder (naming, exports, and registration function).
|
||||
- Export a `registerX(server)` function that registers new items with the MCP SDK in the same style as existing ones.
|
||||
- Wire your new module into the central index (e.g., update `tools/index.ts`, `resources/index.ts`, or `prompts/index.ts`).
|
||||
- Ensure schemas (for tools) are accurate JSON Schema and include helpful descriptions and examples.
|
||||
`server/index.ts` and usages in `logging.ts` and `subscriptions.ts`.
|
||||
- Keep the docs in `src/everything/docs/` up to date if you add or modify noteworthy features.
|
||||
|
|
@ -1,20 +0,0 @@
|
|||
# MCP "Everything" Server - Development Guidelines
|
||||
|
||||
## Build, Test & Run Commands
|
||||
- Build: `npm run build` - Compiles TypeScript to JavaScript
|
||||
- Watch mode: `npm run watch` - Watches for changes and rebuilds automatically
|
||||
- Run server: `npm run start` - Starts the MCP server using stdio transport
|
||||
- Run SSE server: `npm run start:sse` - Starts the MCP server with SSE transport
|
||||
- Prepare release: `npm run prepare` - Builds the project for publishing
|
||||
|
||||
## Code Style Guidelines
|
||||
- Use ES modules with `.js` extension in import paths
|
||||
- Strictly type all functions and variables with TypeScript
|
||||
- Follow zod schema patterns for tool input validation
|
||||
- Prefer async/await over callbacks and Promise chains
|
||||
- Place all imports at top of file, grouped by external then internal
|
||||
- Use descriptive variable names that clearly indicate purpose
|
||||
- Implement proper cleanup for timers and resources in server shutdown
|
||||
- Follow camelCase for variables/functions, PascalCase for types/classes, UPPER_CASE for constants
|
||||
- Handle errors with try/catch blocks and provide clear error messages
|
||||
- Use consistent indentation (2 spaces) and trailing commas in multi-line objects
|
||||
|
|
@ -1,166 +1,17 @@
|
|||
# Everything MCP Server
|
||||
**[Architecture](docs/architecture.md)
|
||||
| [Project Structure](docs/structure.md)
|
||||
| [Startup Process](docs/startup.md)
|
||||
| [Server Features](docs/features.md)
|
||||
| [Extension Points](docs/extension.md)
|
||||
| [How It Works](docs/how-it-works.md)**
|
||||
|
||||
|
||||
This MCP server attempts to exercise all the features of the MCP protocol. It is not intended to be a useful server, but rather a test server for builders of MCP clients. It implements prompts, tools, resources, sampling, and more to showcase MCP capabilities.
|
||||
|
||||
## Components
|
||||
## Tools, Resources, Prompts, and Other Features
|
||||
|
||||
### Tools
|
||||
|
||||
1. `echo`
|
||||
- Simple tool to echo back input messages
|
||||
- Input:
|
||||
- `message` (string): Message to echo back
|
||||
- Returns: Text content with echoed message
|
||||
|
||||
2. `add`
|
||||
- Adds two numbers together
|
||||
- Inputs:
|
||||
- `a` (number): First number
|
||||
- `b` (number): Second number
|
||||
- Returns: Text result of the addition
|
||||
|
||||
3. `longRunningOperation`
|
||||
- Demonstrates progress notifications for long operations
|
||||
- Inputs:
|
||||
- `duration` (number, default: 10): Duration in seconds
|
||||
- `steps` (number, default: 5): Number of progress steps
|
||||
- Returns: Completion message with duration and steps
|
||||
- Sends progress notifications during execution
|
||||
|
||||
4. `printEnv`
|
||||
- Prints all environment variables
|
||||
- Useful for debugging MCP server configuration
|
||||
- No inputs required
|
||||
- Returns: JSON string of all environment variables
|
||||
|
||||
5. `sampleLLM`
|
||||
- Demonstrates LLM sampling capability using MCP sampling feature
|
||||
- Inputs:
|
||||
- `prompt` (string): The prompt to send to the LLM
|
||||
- `maxTokens` (number, default: 100): Maximum tokens to generate
|
||||
- Returns: Generated LLM response
|
||||
|
||||
6. `getTinyImage`
|
||||
- Returns a small test image
|
||||
- No inputs required
|
||||
- Returns: Base64 encoded PNG image data
|
||||
|
||||
7. `annotatedMessage`
|
||||
- Demonstrates how annotations can be used to provide metadata about content
|
||||
- Inputs:
|
||||
- `messageType` (enum: "error" | "success" | "debug"): Type of message to demonstrate different annotation patterns
|
||||
- `includeImage` (boolean, default: false): Whether to include an example image
|
||||
- Returns: Content with varying annotations:
|
||||
- Error messages: High priority (1.0), visible to both user and assistant
|
||||
- Success messages: Medium priority (0.7), user-focused
|
||||
- Debug messages: Low priority (0.3), assistant-focused
|
||||
- Optional image: Medium priority (0.5), user-focused
|
||||
- Example annotations:
|
||||
```json
|
||||
{
|
||||
"priority": 1.0,
|
||||
"audience": ["user", "assistant"]
|
||||
}
|
||||
```
|
||||
|
||||
8. `getResourceReference`
|
||||
- Returns a resource reference that can be used by MCP clients
|
||||
- Inputs:
|
||||
- `resourceId` (number, 1-100): ID of the resource to reference
|
||||
- Returns: A resource reference with:
|
||||
- Text introduction
|
||||
- Embedded resource with `type: "resource"`
|
||||
- Text instruction for using the resource URI
|
||||
|
||||
9. `startElicitation`
|
||||
- Initiates an elicitation (interaction) within the MCP client.
|
||||
- Inputs:
|
||||
- `color` (string): Favorite color
|
||||
- `number` (number, 1-100): Favorite number
|
||||
- `pets` (enum): Favorite pet
|
||||
- Returns: Confirmation of the elicitation demo with selection summary.
|
||||
|
||||
10. `structuredContent`
|
||||
- Demonstrates a tool returning structured content using the example in the specification
|
||||
- Provides an output schema to allow testing of client SHOULD advisory to validate the result using the schema
|
||||
- Inputs:
|
||||
- `location` (string): A location or ZIP code, mock data is returned regardless of value
|
||||
- Returns: a response with
|
||||
- `structuredContent` field conformant to the output schema
|
||||
- A backward compatible Text Content field, a SHOULD advisory in the specification
|
||||
|
||||
11. `listRoots`
|
||||
- Lists the current MCP roots provided by the client
|
||||
- Demonstrates the roots protocol capability even though this server doesn't access files
|
||||
- No inputs required
|
||||
- Returns: List of current roots with their URIs and names, or a message if no roots are set
|
||||
- Shows how servers can interact with the MCP roots protocol
|
||||
|
||||
### Resources
|
||||
|
||||
The server provides 100 test resources in two formats:
|
||||
- Even numbered resources:
|
||||
- Plaintext format
|
||||
- URI pattern: `test://static/resource/{even_number}`
|
||||
- Content: Simple text description
|
||||
|
||||
- Odd numbered resources:
|
||||
- Binary blob format
|
||||
- URI pattern: `test://static/resource/{odd_number}`
|
||||
- Content: Base64 encoded binary data
|
||||
|
||||
Resource features:
|
||||
- Supports pagination (10 items per page)
|
||||
- Allows subscribing to resource updates
|
||||
- Demonstrates resource templates
|
||||
- Auto-updates subscribed resources every 5 seconds
|
||||
|
||||
### Prompts
|
||||
|
||||
1. `simple_prompt`
|
||||
- Basic prompt without arguments
|
||||
- Returns: Single message exchange
|
||||
|
||||
2. `complex_prompt`
|
||||
- Advanced prompt demonstrating argument handling
|
||||
- Required arguments:
|
||||
- `temperature` (string): Temperature setting
|
||||
- Optional arguments:
|
||||
- `style` (string): Output style preference
|
||||
- Returns: Multi-turn conversation with images
|
||||
|
||||
3. `resource_prompt`
|
||||
- Demonstrates embedding resource references in prompts
|
||||
- Required arguments:
|
||||
- `resourceId` (number): ID of the resource to embed (1-100)
|
||||
- Returns: Multi-turn conversation with an embedded resource reference
|
||||
- Shows how to include resources directly in prompt messages
|
||||
|
||||
### Roots
|
||||
|
||||
The server demonstrates the MCP roots protocol capability:
|
||||
|
||||
- Declares `roots: { listChanged: true }` capability to indicate support for roots
|
||||
- Handles `roots/list_changed` notifications from clients
|
||||
- Requests initial roots during server initialization
|
||||
- Provides a `listRoots` tool to display current roots
|
||||
- Logs roots-related events for demonstration purposes
|
||||
|
||||
Note: This server doesn't actually access files, but demonstrates how servers can interact with the roots protocol for clients that need to understand which directories are available for file operations.
|
||||
|
||||
### Logging
|
||||
|
||||
The server sends random-leveled log messages every 15 seconds, e.g.:
|
||||
|
||||
```json
|
||||
{
|
||||
"method": "notifications/message",
|
||||
"params": {
|
||||
"level": "info",
|
||||
"data": "Info-level message"
|
||||
}
|
||||
}
|
||||
```
|
||||
A complete list of the registered MCP primitives and other protocol features demonstrated can be found in the [Server Features](docs/features.md) document.
|
||||
|
||||
## Usage with Claude Desktop (uses [stdio Transport](https://modelcontextprotocol.io/specification/2025-03-26/basic/transports#stdio))
|
||||
|
||||
|
|
|
|||
44
src/everything/docs/architecture.md
Normal file
44
src/everything/docs/architecture.md
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
# Everything Server – Architecture
|
||||
|
||||
**Architecture
|
||||
| [Project Structure](structure.md)
|
||||
| [Startup Process](startup.md)
|
||||
| [Server Features](features.md)
|
||||
| [Extension Points](extension.md)
|
||||
| [How It Works](how-it-works.md)**
|
||||
|
||||
This documentation summarizes the current layout and runtime architecture of the `src/everything` package.
|
||||
It explains how the server starts, how transports are wired, where tools, prompts, and resources are registered, and how to extend the system.
|
||||
|
||||
## High‑level Overview
|
||||
|
||||
### Purpose
|
||||
|
||||
A minimal, modular MCP server showcasing core Model Context Protocol features. It exposes simple tools, prompts, and resources, and can be run over multiple transports (STDIO, SSE, and Streamable HTTP).
|
||||
|
||||
### Design
|
||||
|
||||
A small “server factory” constructs the MCP server and registers features.
|
||||
Transports are separate entry points that create/connect the server and handle network concerns.
|
||||
Tools, prompts, and resources are organized in their own submodules.
|
||||
|
||||
### Multi‑client
|
||||
|
||||
The server supports multiple concurrent clients. Tracking per session data is demonstrated with
|
||||
resource subscriptions and simulated logging.
|
||||
|
||||
## Build and Distribution
|
||||
|
||||
- TypeScript sources are compiled into `dist/` via `npm run build`.
|
||||
- The `build` script copies `docs/` into `dist/` so instruction files ship alongside the compiled server.
|
||||
- The CLI bin is configured in `package.json` as `mcp-server-everything` → `dist/index.js`.
|
||||
|
||||
## [Project Structure](structure.md)
|
||||
|
||||
## [Startup Process](startup.md)
|
||||
|
||||
## [Server Features](features.md)
|
||||
|
||||
## [Extension Points](extension.md)
|
||||
|
||||
## [How It Works](how-it-works.md)
|
||||
23
src/everything/docs/extension.md
Normal file
23
src/everything/docs/extension.md
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
# Everything Server - Extension Points
|
||||
|
||||
**[Architecture](architecture.md)
|
||||
| [Project Structure](structure.md)
|
||||
| [Startup Process](startup.md)
|
||||
| [Server Features](features.md)
|
||||
| Extension Points
|
||||
| [How It Works](how-it-works.md)**
|
||||
|
||||
## Adding Tools
|
||||
|
||||
- Create a new file under `tools/` with your `registerXTool(server)` function that registers the tool via `server.registerTool(...)`.
|
||||
- Export and call it from `tools/index.ts` inside `registerTools(server)`.
|
||||
|
||||
## Adding Prompts
|
||||
|
||||
- Create a new file under `prompts/` with your `registerXPrompt(server)` function that registers the prompt via `server.registerPrompt(...)`.
|
||||
- Export and call it from `prompts/index.ts` inside `registerPrompts(server)`.
|
||||
|
||||
## Adding Resources
|
||||
|
||||
- Create a new file under `resources/` with your `registerXResources(server)` function using `server.registerResource(...)` (optionally with `ResourceTemplate`).
|
||||
- Export and call it from `resources/index.ts` inside `registerResources(server)`.
|
||||
52
src/everything/docs/features.md
Normal file
52
src/everything/docs/features.md
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# Everything Server - Features
|
||||
|
||||
**[Architecture](architecture.md)
|
||||
| [Project Structure](structure.md)
|
||||
| [Startup Process](startup.md)
|
||||
| Server Features
|
||||
| [Extension Points](extension.md)
|
||||
| [How It Works](how-it-works.md)**
|
||||
|
||||
## Tools
|
||||
|
||||
- `echo` (tools/echo.ts): Echoes the provided `message: string`. Uses Zod to validate inputs.
|
||||
- `get-annotated-message` (tools/get-annotated-message.ts): Returns a `text` message annotated with `priority` and `audience` based on `messageType` (`error`, `success`, or `debug`); can optionally include an annotated `image`.
|
||||
- `get-env` (tools/get-env.ts): Returns all environment variables from the running process as pretty-printed JSON text.
|
||||
- `get-resource-links` (tools/get-resource-links.ts): Returns an intro `text` block followed by multiple `resource_link` items. For a requested `count` (1–10), alternates between dynamic Text and Blob resources using URIs from `resources/templates.ts`.
|
||||
- `get-resource-reference` (tools/get-resource-reference.ts): Accepts `resourceType` (`text` or `blob`) and `resourceId` (positive integer). Returns a concrete `resource` content block (with its `uri`, `mimeType`, and data) with surrounding explanatory `text`.
|
||||
- `get-roots-list` (tools/get-roots-list.ts): Returns the last list of roots sent by the client.
|
||||
- `gzip-file-as-resource` (tools/gzip-file-as-resource.ts): Accepts a `name` and `data` (URL or data URI), fetches the data subject to size/time/domain constraints, compresses it, registers it as a session resource at `demo://resource/session/<name>` with `mimeType: application/gzip`, and returns either a `resource_link` (default) or an inline `resource` depending on `outputType`.
|
||||
- `get-structured-content` (tools/get-structured-content.ts): Demonstrates structured responses. Accepts `location` input and returns both backward‑compatible `content` (a `text` block containing JSON) and `structuredContent` validated by an `outputSchema` (temperature, conditions, humidity).
|
||||
- `get-sum` (tools/get-sum.ts): For two numbers `a` and `b` calculates and returns their sum. Uses Zod to validate inputs.
|
||||
- `get-tiny-image` (tools/get-tiny-image.ts): Returns a tiny PNG MCP logo as an `image` content item with brief descriptive text before and after.
|
||||
- `trigger-long-running-operation` (tools/trigger-trigger-long-running-operation.ts): Simulates a multi-step operation over a given `duration` and number of `steps`; reports progress via `notifications/progress` when a `progressToken` is provided by the client.
|
||||
- `toggle-simulated-logging` (tools/toggle-simulated-logging.ts): Starts or stops simulated, random‑leveled logging for the invoking session. Respects the client’s selected minimum logging level.
|
||||
- `toggle-subscriber-updates` (tools/toggle-subscriber-updates.ts): Starts or stops simulated resource update notifications for URIs the invoking session has subscribed to.
|
||||
- `trigger-sampling-request` (tools/trigger-sampling-request.ts): Issues a `sampling/createMessage` request to the client/LLM using provided `prompt` and optional generation controls; returns the LLM’s response payload.
|
||||
|
||||
## Prompts
|
||||
|
||||
- `simple-prompt` (prompts/simple.ts): No-argument prompt that returns a static user message.
|
||||
- `args-prompt` (prompts/args.ts): Two-argument prompt with `city` (required) and `state` (optional) used to compose a question.
|
||||
- `completable-prompt` (prompts/completions.ts): Demonstrates argument auto-completions with the SDK’s `completable` helper; `department` completions drive context-aware `name` suggestions.
|
||||
- `resource-prompt` (prompts/resource.ts): Accepts `resourceType` ("Text" or "Blob") and `resourceId` (string convertible to integer) and returns messages that include an embedded dynamic resource of the selected type generated via `resources/templates.ts`.
|
||||
|
||||
## Resources
|
||||
|
||||
- Dynamic Text: `demo://resource/dynamic/text/{index}` (content generated on the fly)
|
||||
- Dynamic Blob: `demo://resource/dynamic/blob/{index}` (base64 payload generated on the fly)
|
||||
- Static Documents: `demo://resource/static/document/<filename>` (serves files from `src/everything/docs/` as static file-based resources)
|
||||
- Session Scoped: `demo://resource/session/<name>` (per-session resources registered dynamically; available only for the lifetime of the session)
|
||||
|
||||
## Resource Subscriptions and Notifications
|
||||
|
||||
- Simulated update notifications are opt‑in and off by default.
|
||||
- Clients may subscribe/unsubscribe to resource URIs using the MCP `resources/subscribe` and `resources/unsubscribe` requests.
|
||||
- Use the `toggle-subscriber-updates` tool to start/stop a per‑session interval that emits `notifications/resources/updated { uri }` only for URIs that session has subscribed to.
|
||||
- Multiple concurrent clients are supported; each client’s subscriptions are tracked per session and notifications are delivered independently via the server instance associated with that session.
|
||||
|
||||
## Simulated Logging
|
||||
|
||||
- Simulated logging is available but off by default.
|
||||
- Use the `toggle-simulated-logging` tool to start/stop periodic log messages of varying levels (debug, info, notice, warning, error, critical, alert, emergency) per session.
|
||||
- Clients can control the minimum level they receive via the standard MCP `logging/setLevel` request.
|
||||
45
src/everything/docs/how-it-works.md
Normal file
45
src/everything/docs/how-it-works.md
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
# Everything Server - How It Works
|
||||
|
||||
**[Architecture](architecture.md)
|
||||
| [Project Structure](structure.md)
|
||||
| [Startup Process](startup.md)
|
||||
| [Server Features](features.md)
|
||||
| [Extension Points](extension.md)
|
||||
| How It Works**
|
||||
|
||||
# Conditional Tool Registration
|
||||
|
||||
### Module: `server/index.ts`
|
||||
|
||||
- Some tools require client support for the capability they demonstrate. These are:
|
||||
- `get-roots-list`
|
||||
- `trigger-elicitation-request`
|
||||
- `trigger-sampling-request`
|
||||
- Client capabilities aren't known until after initilization handshake is complete.
|
||||
- Most tools are registered immediately during the Server Factory execution, prior to client connection.
|
||||
- To defer registration of these commands until client capabilities are known, a `registerConditionalTools(server)` function is invoked from an `onintitialized` handler.
|
||||
|
||||
## Resource Subscriptions
|
||||
|
||||
### Module: `resources/subscriptions.ts`
|
||||
|
||||
- Tracks subscribers per URI: `Map<uri, Set<sessionId>>`.
|
||||
- Installs handlers via `setSubscriptionHandlers(server)` to process subscribe/unsubscribe requests and keep the map updated.
|
||||
- Updates are started/stopped on demand by the `toggle-subscriber-updates` tool, which calls `beginSimulatedResourceUpdates(server, sessionId)` and `stopSimulatedResourceUpdates(sessionId)`.
|
||||
- `cleanup(sessionId?)` calls `stopSimulatedResourceUpdates(sessionId)` to clear intervals and remove session‑scoped state.
|
||||
|
||||
## Session‑scoped Resources
|
||||
|
||||
### Module: `resources/session.ts`
|
||||
|
||||
- `getSessionResourceURI(name: string)`: Builds a session resource URI: `demo://resource/session/<name>`.
|
||||
- `registerSessionResource(server, resource, type, payload)`: Registers a resource with the given `uri`, `name`, and `mimeType`, returning a `resource_link`. The content is served from memory for the life of the session only. Supports `type: "text" | "blob"` and returns data in the corresponding field.
|
||||
- Intended usage: tools can create and expose per-session artifacts without persisting them. For example, `tools/gzip-file-as-resource.ts` compresses fetched content, registers it as a session resource with `mimeType: application/gzip`, and returns either a `resource_link` or an inline `resource` based on `outputType`.
|
||||
|
||||
## Simulated Logging
|
||||
|
||||
### Module: `server/logging.ts`
|
||||
|
||||
- Periodically sends randomized log messages at different levels. Messages can include the session ID for clarity during demos.
|
||||
- Started/stopped on demand via the `toggle-simulated-logging` tool, which calls `beginSimulatedLogging(server, sessionId?)` and `stopSimulatedLogging(sessionId?)`. Note that transport disconnect triggers `cleanup()` which also stops any active intervals.
|
||||
- Uses `server.sendLoggingMessage({ level, data }, sessionId?)` so that the client’s configured minimum logging level is respected by the SDK.
|
||||
28
src/everything/docs/instructions.md
Normal file
28
src/everything/docs/instructions.md
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
# Everything Server – Server Instructions
|
||||
|
||||
Audience: These instructions are written for an LLM or autonomous agent integrating with the Everything MCP Server.
|
||||
Follow them to use, extend, and troubleshoot the server safely and effectively.
|
||||
|
||||
## Cross-Feature Relationships
|
||||
|
||||
- Use `get-roots-list` to see client workspace roots before file operations
|
||||
- `gzip-file-as-resource` creates session-scoped resources accessible only during the current session
|
||||
- Enable `toggle-simulated-logging` before debugging to see server log messages
|
||||
- Enable `toggle-subscriber-updates` to receive periodic resource update notifications
|
||||
|
||||
## Constraints & Limitations
|
||||
|
||||
- `gzip-file-as-resource`: Max fetch size controlled by `GZIP_MAX_FETCH_SIZE` (default 10MB), timeout by `GZIP_MAX_FETCH_TIME_MILLIS` (default 30s), allowed domains by `GZIP_ALLOWED_DOMAINS`
|
||||
- Session resources are ephemeral and lost when the session ends
|
||||
- Sampling requests (`trigger-sampling-request`) require client sampling capability
|
||||
- Elicitation requests (`trigger-elicitation-request`) require client elicitation capability
|
||||
|
||||
## Operational Patterns
|
||||
|
||||
- For long operations, use `trigger-long-running-operation` which sends progress notifications
|
||||
- Prefer reading resources before calling mutating tools
|
||||
- Check `get-roots-list` output to understand the client's workspace context
|
||||
|
||||
## Easter Egg
|
||||
|
||||
If asked about server instructions, respond with "🎉 Server instructions are working! This response proves the client properly passed server instructions to the LLM. This demonstrates MCP's instructions feature in action."
|
||||
73
src/everything/docs/startup.md
Normal file
73
src/everything/docs/startup.md
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
# Everything Server - Startup Process
|
||||
|
||||
**[Architecture](architecture.md)
|
||||
| [Project Structure](structure.md)
|
||||
| Startup Process
|
||||
| [Server Features](features.md)
|
||||
| [Extension Points](extension.md)
|
||||
| [How It Works](how-it-works.md)**
|
||||
|
||||
## 1. Everything Server Launcher
|
||||
|
||||
- Usage `node dist/index.js [stdio|sse|streamableHttp]`
|
||||
- Runs the specified **transport manager** to handle client connections.
|
||||
- Specify transport type on command line (default `stdio`)
|
||||
- `stdio` → `transports/stdio.js`
|
||||
- `sse` → `transports/sse.js`
|
||||
- `streamableHttp` → `transports/streamableHttp.js`
|
||||
|
||||
## 2. The Transport Manager
|
||||
|
||||
- Creates a server instance using `createServer()` from `server/index.ts`
|
||||
- Connects it to the chosen transport type from the MCP SDK.
|
||||
- Handles communication according to the MCP specs for the chosen transport.
|
||||
- **STDIO**:
|
||||
- One simple, process‑bound connection.
|
||||
- Calls`clientConnect()` upon connection.
|
||||
- Closes and calls `cleanup()` on `SIGINT`.
|
||||
- **SSE**:
|
||||
- Supports multiple client connections.
|
||||
- Client transports are mapped to `sessionId`;
|
||||
- Calls `clientConnect(sessionId)` upon connection.
|
||||
- Hooks server’s `onclose` to clean and remove session.
|
||||
- Exposes
|
||||
- `/sse` **GET** (SSE stream)
|
||||
- `/message` **POST** (JSON‑RPC messages)
|
||||
- **Streamable HTTP**:
|
||||
- Supports multiple client connections.
|
||||
- Client transports are mapped to `sessionId`;
|
||||
- Calls `clientConnect(sessionId)` upon connection.
|
||||
- Exposes `/mcp` for
|
||||
- **POST** (JSON‑RPC messages)
|
||||
- **GET** (SSE stream)
|
||||
- **DELETE** (termination)
|
||||
- Uses an event store for resumability and stores transports by `sessionId`.
|
||||
- Calls `cleanup(sessionId)` on **DELETE**.
|
||||
|
||||
## 3. The Server Factory
|
||||
|
||||
- Invoke `createServer()` from `server/index.ts`
|
||||
- Creates a new `McpServer` instance with
|
||||
- **Capabilities**:
|
||||
- `tools: {}`
|
||||
- `logging: {}`
|
||||
- `prompts: {}`
|
||||
- `resources: { subscribe: true }`
|
||||
- **Server Instructions**
|
||||
- Loaded from the docs folder (`server-instructions.md`).
|
||||
- **Registrations**
|
||||
- Registers **tools** via `registerTools(server)`.
|
||||
- Registers **resources** via `registerResources(server)`.
|
||||
- Registers **prompts** via `registerPrompts(server)`.
|
||||
- **Other Request Handlers**
|
||||
- Sets up resource subscription handlers via `setSubscriptionHandlers(server)`.
|
||||
- Roots list change handler is added post-connection via
|
||||
- **Returns**
|
||||
- The `McpServer` instance
|
||||
- A `clientConnect(sessionId)` callback that enables post-connection setup
|
||||
- A `cleanup(sessionId?)` callback that stops any active intervals and removes any session‑scoped state
|
||||
|
||||
## Enabling Multiple Clients
|
||||
|
||||
Some of the transport managers defined in the `transports` folder can support multiple clients.
|
||||
In order to do so, they must map certain data to a session identifier.
|
||||
182
src/everything/docs/structure.md
Normal file
182
src/everything/docs/structure.md
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
# Everything Server - Project Structure
|
||||
|
||||
**[Architecture](architecture.md)
|
||||
| Project Structure
|
||||
| [Startup Process](startup.md)
|
||||
| [Server Features](features.md)
|
||||
| [Extension Points](extension.md)
|
||||
| [How It Works](how-it-works.md)**
|
||||
|
||||
```
|
||||
src/everything
|
||||
├── index.ts
|
||||
├── AGENTS.md
|
||||
├── package.json
|
||||
├── docs
|
||||
│ ├── architecture.md
|
||||
│ ├── extension.md
|
||||
│ ├── features.md
|
||||
│ ├── how-it-works.md
|
||||
│ ├── instructions.md
|
||||
│ ├── startup.md
|
||||
│ └── structure.md
|
||||
├── prompts
|
||||
│ ├── index.ts
|
||||
│ ├── args.ts
|
||||
│ ├── completions.ts
|
||||
│ ├── simple.ts
|
||||
│ └── resource.ts
|
||||
├── resources
|
||||
│ ├── index.ts
|
||||
│ ├── files.ts
|
||||
│ ├── session.ts
|
||||
│ ├── subscriptions.ts
|
||||
│ └── templates.ts
|
||||
├── server
|
||||
│ ├── index.ts
|
||||
│ ├── logging.ts
|
||||
│ └── roots.ts
|
||||
├── tools
|
||||
│ ├── index.ts
|
||||
│ ├── echo.ts
|
||||
│ ├── get-annotated-message.ts
|
||||
│ ├── get-env.ts
|
||||
│ ├── get-resource-links.ts
|
||||
│ ├── get-resource-reference.ts
|
||||
│ ├── get-roots-list.ts
|
||||
│ ├── get-structured-content.ts
|
||||
│ ├── get-sum.ts
|
||||
│ ├── get-tiny-image.ts
|
||||
│ ├── gzip-file-as-resource.ts
|
||||
│ ├── toggle-simulated-logging.ts
|
||||
│ ├── toggle-subscriber-updates.ts
|
||||
│ ├── trigger-elicitation-request.ts
|
||||
│ ├── trigger-long-running-operation.ts
|
||||
│ └── trigger-sampling-request.ts
|
||||
└── transports
|
||||
├── sse.ts
|
||||
├── stdio.ts
|
||||
└── streamableHttp.ts
|
||||
```
|
||||
|
||||
# Project Contents
|
||||
|
||||
## `src/everything`:
|
||||
|
||||
### `index.ts`
|
||||
|
||||
- CLI entry point that selects and runs a specific transport module based on the first CLI argument: `stdio`, `sse`, or `streamableHttp`.
|
||||
|
||||
### `AGENTS.md`
|
||||
|
||||
- Directions for Agents/LLMs explaining coding guidelines and how to appropriately extend the server.
|
||||
|
||||
### `package.json`
|
||||
|
||||
- Package metadata and scripts:
|
||||
- `build`: TypeScript compile to `dist/`, copies `docs/` into `dist/` and marks the compiled entry scripts as executable.
|
||||
- `start:stdio`, `start:sse`, `start:streamableHttp`: Run built transports from `dist/`.
|
||||
- Declares dependencies on `@modelcontextprotocol/sdk`, `express`, `cors`, `zod`, etc.
|
||||
|
||||
### `docs/`
|
||||
|
||||
- `architecture.md`
|
||||
- This document.
|
||||
- `server-instructions.md`
|
||||
- Human‑readable instructions intended to be passed to the client/LLM as for guidance on server use. Loaded by the server at startup and returned in the "initialize" exchange.
|
||||
|
||||
### `prompts/`
|
||||
|
||||
- `index.ts`
|
||||
- `registerPrompts(server)` orchestrator; delegates to prompt factory/registration methods from in individual prompt files.
|
||||
- `simple.ts`
|
||||
- Registers `simple-prompt`: a prompt with no arguments that returns a single user message.
|
||||
- `args.ts`
|
||||
- Registers `args-prompt`: a prompt with two arguments (`city` required, `state` optional) used to compose a message.
|
||||
- `completions.ts`
|
||||
- Registers `completable-prompt`: a prompt whose arguments support server-driven completions using the SDK’s `completable(...)` helper (e.g., completing `department` and context-aware `name`).
|
||||
- `resource.ts`
|
||||
- Exposes `registerEmbeddedResourcePrompt(server)` which registers `resource-prompt` — a prompt that accepts `resourceType` ("Text" or "Blob") and `resourceId` (integer), and embeds a dynamically generated resource of the requested type within the returned messages. Internally reuses helpers from `resources/templates.ts`.
|
||||
|
||||
### `resources/`
|
||||
|
||||
- `index.ts`
|
||||
- `registerResources(server)` orchestrator; delegates to resource factory/registration methods from individual resource files.
|
||||
- `templates.ts`
|
||||
- Registers two dynamic, template‑driven resources using `ResourceTemplate`:
|
||||
- Text: `demo://resource/dynamic/text/{index}` (MIME: `text/plain`)
|
||||
- Blob: `demo://resource/dynamic/blob/{index}` (MIME: `application/octet-stream`, Base64 payload)
|
||||
- The `{index}` path variable must be a finite positive integer. Content is generated on demand with a timestamp.
|
||||
- Exposes helpers `textResource(uri, index)`, `textResourceUri(index)`, `blobResource(uri, index)`, and `blobResourceUri(index)` so other modules can construct and embed dynamic resources directly (e.g., from prompts).
|
||||
- `files.ts`
|
||||
- Registers static file-based resources for each file in the `docs/` folder.
|
||||
- URIs follow the pattern: `demo://resource/static/document/<filename>`.
|
||||
- Serves markdown files as `text/markdown`, `.txt` as `text/plain`, `.json` as `application/json`, others default to `text/plain`.
|
||||
|
||||
### `server/`
|
||||
|
||||
- `index.ts`
|
||||
- Server factory that creates an `McpServer` with declared capabilities, loads server instructions, and registers tools, prompts, and resources.
|
||||
- Sets resource subscription handlers via `setSubscriptionHandlers(server)`.
|
||||
- Exposes `{ server, cleanup }` to the chosen transport. Cleanup stops any running intervals in the server when the transport disconnects.
|
||||
- `logging.ts`
|
||||
- Implements simulated logging. Periodically sends randomized log messages at various levels to the connected client session. Started/stopped on demand via a dedicated tool.
|
||||
|
||||
### `tools/`
|
||||
|
||||
- `index.ts`
|
||||
- `registerTools(server)` orchestrator; delegates to tool factory/registration methods in individual tool files.
|
||||
- `echo.ts`
|
||||
- Registers an `echo` tool that takes a message and returns `Echo: {message}`.
|
||||
- `get-annotated-message.ts`
|
||||
- Registers an `annotated-message` tool which demonstrates annotated content items by emitting a primary `text` message with `annotations` that vary by `messageType` (`"error" | "success" | "debug"`), and optionally includes an annotated `image` (tiny PNG) when `includeImage` is true.
|
||||
- `get-env.ts`
|
||||
- Registers a `get-env` tool that returns the current process environment variables as formatted JSON text; useful for debugging configuration.
|
||||
- `get-resource-links.ts`
|
||||
- Registers a `get-resource-links` tool that returns an intro `text` block followed by multiple `resource_link` items.
|
||||
- `get-resource-reference.ts`
|
||||
- Registers a `get-resource-reference` tool that returns a reference for a selected dynamic resource.
|
||||
- `get-roots-list.ts`
|
||||
- Registers a `get-roots-list` tool that returns the last list of roots sent by the client.
|
||||
- `gzip-file-as-resource.ts`
|
||||
- Registers a `gzip-file-as-resource` tool that fetches content from a URL or data URI, compresses it, and then either:
|
||||
- returns a `resource_link` to a session-scoped resource (default), or
|
||||
- returns an inline `resource` with the gzipped data. The resource will be still discoverable for the duration of the session via `resources/list`.
|
||||
- Uses `resources/session.ts` to register the gzipped blob as a per-session resource at a URI like `demo://resource/session/<name>` with `mimeType: application/gzip`.
|
||||
- Environment controls:
|
||||
- `GZIP_MAX_FETCH_SIZE` (bytes, default 10 MiB)
|
||||
- `GZIP_MAX_FETCH_TIME_MILLIS` (ms, default 30000)
|
||||
- `GZIP_ALLOWED_DOMAINS` (comma-separated allowlist; empty means all domains allowed)
|
||||
- `trigger-elicitation-request.ts`
|
||||
- Registers a `trigger-elicitation-request` tool that sends an `elicitation/create` request to the client/LLM and returns the elicitation result.
|
||||
- `trigger-sampling-request.ts`
|
||||
- Registers a `trigger-sampling-request` tool that sends a `sampling/createMessage` request to the client/LLM and returns the sampling result.
|
||||
- `get-structured-content.ts`
|
||||
- Registers a `get-structured-content` tool that demonstrates structuredContent block responses.
|
||||
- `get-sum.ts`
|
||||
- Registers an `get-sum` tool with a Zod input schema that sums two numbers `a` and `b` and returns the result.
|
||||
- `get-tiny-image.ts`
|
||||
- Registers a `get-tiny-image` tool, which returns a tiny PNG MCP logo as an `image` content item, along with surrounding descriptive `text` items.
|
||||
- `trigger-long-running-operation.ts`
|
||||
- Registers a `long-running-operation` tool that simulates a long-running task over a specified `duration` (seconds) and number of `steps`; emits `notifications/progress` updates when the client supplies a `progressToken`.
|
||||
- `toggle-simulated-logging.ts`
|
||||
- Registers a `toggle-simulated-logging` tool, which starts or stops simulated logging for the invoking session.
|
||||
- `toggle-subscriber-updates.ts`
|
||||
- Registers a `toggle-subscriber-updates` tool, which starts or stops simulated resource subscription update checks for the invoking session.
|
||||
|
||||
### `transports/`
|
||||
|
||||
- `stdio.ts`
|
||||
- Starts a `StdioServerTransport`, created the server via `createServer()`, and connects it.
|
||||
- Handles `SIGINT` to close cleanly and calls `cleanup()` to remove any live intervals.
|
||||
- `sse.ts`
|
||||
- Express server exposing:
|
||||
- `GET /sse` to establish an SSE connection per session.
|
||||
- `POST /message` for client messages.
|
||||
- Manages multiple connected clients via a transport map.
|
||||
- Starts an `SSEServerTransport`, created the server via `createServer()`, and connects it to a new transport.
|
||||
- On server disconnect, calls `cleanup()` to remove any live intervals.
|
||||
- `streamableHttp.ts`
|
||||
- Express server exposing a single `/mcp` endpoint for POST (JSON‑RPC), GET (SSE stream), and DELETE (session termination) using `StreamableHTTPServerTransport`.
|
||||
- Uses an `InMemoryEventStore` for resumable sessions and tracks transports by `sessionId`.
|
||||
- Connects a fresh server instance on initialization POST and reuses the transport for subsequent requests.
|
||||
File diff suppressed because one or more lines are too long
|
|
@ -2,36 +2,41 @@
|
|||
|
||||
// Parse command line arguments first
|
||||
const args = process.argv.slice(2);
|
||||
const scriptName = args[0] || 'stdio';
|
||||
const scriptName = args[0] || "stdio";
|
||||
|
||||
async function run() {
|
||||
try {
|
||||
// Dynamically import only the requested module to prevent all modules from initializing
|
||||
switch (scriptName) {
|
||||
case 'stdio':
|
||||
// Import and run the default server
|
||||
await import('./stdio.js');
|
||||
break;
|
||||
case 'sse':
|
||||
// Import and run the SSE server
|
||||
await import('./sse.js');
|
||||
break;
|
||||
case 'streamableHttp':
|
||||
// Import and run the streamable HTTP server
|
||||
await import('./streamableHttp.js');
|
||||
break;
|
||||
default:
|
||||
console.error(`Unknown script: ${scriptName}`);
|
||||
console.log('Available scripts:');
|
||||
console.log('- stdio');
|
||||
console.log('- sse');
|
||||
console.log('- streamableHttp');
|
||||
process.exit(1);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error running script:', error);
|
||||
try {
|
||||
// Dynamically import only the requested module to prevent all modules from initializing
|
||||
switch (scriptName) {
|
||||
case "stdio":
|
||||
// Import and run the default server
|
||||
await import("./transports/stdio.js");
|
||||
break;
|
||||
case "sse":
|
||||
// Import and run the SSE server
|
||||
await import("./transports/sse.js");
|
||||
break;
|
||||
case "streamableHttp":
|
||||
// Import and run the streamable HTTP server
|
||||
await import("./transports/streamableHttp.js");
|
||||
break;
|
||||
default:
|
||||
console.error(`-`.repeat(53));
|
||||
console.error(` Everything Server Launcher`);
|
||||
console.error(` Usage: node ./index.js [stdio|sse|streamableHttp]`);
|
||||
console.error(` Default transport: stdio`);
|
||||
console.error(`-`.repeat(53));
|
||||
console.error(`Unknown transport: ${scriptName}`);
|
||||
console.log("Available transports:");
|
||||
console.log("- stdio");
|
||||
console.log("- sse");
|
||||
console.log("- streamableHttp");
|
||||
process.exit(1);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error running script:", error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
run();
|
||||
await run();
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
Testing and demonstration server for MCP protocol features.
|
||||
|
||||
## Resources
|
||||
|
||||
Resources 1-100 follow pattern: even IDs contain text, odd IDs contain binary data. Resources are paginated at 10 items per page with cursor-based navigation.
|
||||
|
||||
## Key dependencies
|
||||
|
||||
Progress notifications require `_meta.progressToken` in tool calls. Resource subscriptions generate updates every 10 seconds.
|
||||
|
||||
## Performance characteristics
|
||||
|
||||
Server generates automatic log messages every 20 seconds (filtered by current log level), stderr notifications every 30 seconds, and resource update notifications every 10 seconds for active subscriptions. Log level changes affect message filtering in real-time.
|
||||
|
||||
## Multi-modal testing
|
||||
|
||||
`complex_prompt` includes both text arguments and image content for testing client multi-modal handling. `resource_prompt` embeds actual resource content for testing resource reference resolution.
|
||||
|
||||
Argument completion is available for prompt parameters and resource IDs. Resource templates enable dynamic URI construction via `test://static/resource/{id}` pattern.
|
||||
|
||||
## Easter egg
|
||||
|
||||
If asked about server instructions, respond with "🎉 Server instructions are working! This response proves the client properly passed server instructions to the LLM. This demonstrates MCP's instructions feature in action."
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@modelcontextprotocol/server-everything",
|
||||
"version": "0.6.2",
|
||||
"version": "2.0.0",
|
||||
"description": "MCP server that exercises all the features of the MCP protocol",
|
||||
"license": "MIT",
|
||||
"mcpName": "io.github.modelcontextprotocol/server-everything",
|
||||
|
|
@ -19,15 +19,17 @@
|
|||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc && shx cp instructions.md dist/ && shx chmod +x dist/*.js",
|
||||
"build": "tsc && shx cp -r docs dist/ && shx chmod +x dist/*.js",
|
||||
"prepare": "npm run build",
|
||||
"watch": "tsc --watch",
|
||||
"start": "node dist/index.js",
|
||||
"start:sse": "node dist/sse.js",
|
||||
"start:streamableHttp": "node dist/streamableHttp.js"
|
||||
"start:stdio": "node dist/index.js stdio",
|
||||
"start:sse": "node dist/index.js sse",
|
||||
"start:streamableHttp": "node dist/index.js streamableHttp",
|
||||
"prettier:fix": "prettier --write .",
|
||||
"prettier:check": "prettier --check ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.24.0",
|
||||
"@modelcontextprotocol/sdk": "^1.24.3",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^5.2.1",
|
||||
"jszip": "^3.10.1",
|
||||
|
|
@ -38,6 +40,7 @@
|
|||
"@types/cors": "^2.8.19",
|
||||
"@types/express": "^5.0.6",
|
||||
"shx": "^0.3.4",
|
||||
"typescript": "^5.6.2"
|
||||
"typescript": "^5.6.2",
|
||||
"prettier": "^2.8.8"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
41
src/everything/prompts/args.ts
Normal file
41
src/everything/prompts/args.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { z } from "zod";
|
||||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
|
||||
/**
|
||||
* Register a prompt with arguments
|
||||
* - Two arguments, one required and one optional
|
||||
* - Combines argument values in the returned prompt
|
||||
*
|
||||
* @param server
|
||||
*/
|
||||
export const registerArgumentsPrompt = (server: McpServer) => {
|
||||
// Prompt arguments
|
||||
const promptArgsSchema = {
|
||||
city: z.string().describe("Name of the city"),
|
||||
state: z.string().describe("Name of the state").optional(),
|
||||
};
|
||||
|
||||
// Register the prompt
|
||||
server.registerPrompt(
|
||||
"args-prompt",
|
||||
{
|
||||
title: "Arguments Prompt",
|
||||
description: "A prompt with two arguments, one required and one optional",
|
||||
argsSchema: promptArgsSchema,
|
||||
},
|
||||
(args) => {
|
||||
const location = `${args?.city}${args?.state ? `, ${args?.state}` : ""}`;
|
||||
return {
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: {
|
||||
type: "text",
|
||||
text: `What's weather in ${location}?`,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
64
src/everything/prompts/completions.ts
Normal file
64
src/everything/prompts/completions.ts
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
import { z } from "zod";
|
||||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import { completable } from "@modelcontextprotocol/sdk/server/completable.js";
|
||||
|
||||
/**
|
||||
* Register a prompt with completable arguments
|
||||
* - Two required arguments, both with completion handlers
|
||||
* - First argument value will be included in context for second argument
|
||||
* - Allows second argument to depend on the first argument value
|
||||
*
|
||||
* @param server
|
||||
*/
|
||||
export const registerPromptWithCompletions = (server: McpServer) => {
|
||||
// Prompt arguments
|
||||
const promptArgsSchema = {
|
||||
department: completable(
|
||||
z.string().describe("Choose the department."),
|
||||
(value) => {
|
||||
return ["Engineering", "Sales", "Marketing", "Support"].filter((d) =>
|
||||
d.startsWith(value)
|
||||
);
|
||||
}
|
||||
),
|
||||
name: completable(
|
||||
z
|
||||
.string()
|
||||
.describe("Choose a team member to lead the selected department."),
|
||||
(value, context) => {
|
||||
const department = context?.arguments?.["department"];
|
||||
if (department === "Engineering") {
|
||||
return ["Alice", "Bob", "Charlie"].filter((n) => n.startsWith(value));
|
||||
} else if (department === "Sales") {
|
||||
return ["David", "Eve", "Frank"].filter((n) => n.startsWith(value));
|
||||
} else if (department === "Marketing") {
|
||||
return ["Grace", "Henry", "Iris"].filter((n) => n.startsWith(value));
|
||||
} else if (department === "Support") {
|
||||
return ["John", "Kim", "Lee"].filter((n) => n.startsWith(value));
|
||||
}
|
||||
return [];
|
||||
}
|
||||
),
|
||||
};
|
||||
|
||||
// Register the prompt
|
||||
server.registerPrompt(
|
||||
"completable-prompt",
|
||||
{
|
||||
title: "Team Management",
|
||||
description: "First argument choice narrows values for second argument.",
|
||||
argsSchema: promptArgsSchema,
|
||||
},
|
||||
({ department, name }) => ({
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: {
|
||||
type: "text",
|
||||
text: `Please promote ${name} to the head of the ${department} team.`,
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
);
|
||||
};
|
||||
17
src/everything/prompts/index.ts
Normal file
17
src/everything/prompts/index.ts
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import { registerSimplePrompt } from "./simple.js";
|
||||
import { registerArgumentsPrompt } from "./args.js";
|
||||
import { registerPromptWithCompletions } from "./completions.js";
|
||||
import { registerEmbeddedResourcePrompt } from "./resource.js";
|
||||
|
||||
/**
|
||||
* Register the prompts with the MCP server.
|
||||
*
|
||||
* @param server
|
||||
*/
|
||||
export const registerPrompts = (server: McpServer) => {
|
||||
registerSimplePrompt(server);
|
||||
registerArgumentsPrompt(server);
|
||||
registerPromptWithCompletions(server);
|
||||
registerEmbeddedResourcePrompt(server);
|
||||
};
|
||||
93
src/everything/prompts/resource.ts
Normal file
93
src/everything/prompts/resource.ts
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
||||
import {
|
||||
resourceTypeCompleter,
|
||||
resourceIdForPromptCompleter,
|
||||
} from "../resources/templates.js";
|
||||
import {
|
||||
textResource,
|
||||
textResourceUri,
|
||||
blobResourceUri,
|
||||
blobResource,
|
||||
RESOURCE_TYPE_BLOB,
|
||||
RESOURCE_TYPE_TEXT,
|
||||
RESOURCE_TYPES,
|
||||
} from "../resources/templates.js";
|
||||
|
||||
/**
|
||||
* Register a prompt with an embedded resource reference
|
||||
* - Takes a resource type and id
|
||||
* - Returns the corresponding dynamically created resource
|
||||
*
|
||||
* @param server
|
||||
*/
|
||||
export const registerEmbeddedResourcePrompt = (server: McpServer) => {
|
||||
// Prompt arguments
|
||||
const promptArgsSchema = {
|
||||
resourceType: resourceTypeCompleter,
|
||||
resourceId: resourceIdForPromptCompleter,
|
||||
};
|
||||
|
||||
// Register the prompt
|
||||
server.registerPrompt(
|
||||
"resource-prompt",
|
||||
{
|
||||
title: "Resource Prompt",
|
||||
description: "A prompt that includes an embedded resource reference",
|
||||
argsSchema: promptArgsSchema,
|
||||
},
|
||||
(args) => {
|
||||
// Validate resource type argument
|
||||
const resourceType = args.resourceType;
|
||||
if (
|
||||
!RESOURCE_TYPES.includes(
|
||||
resourceType as typeof RESOURCE_TYPE_TEXT | typeof RESOURCE_TYPE_BLOB
|
||||
)
|
||||
) {
|
||||
throw new Error(
|
||||
`Invalid resourceType: ${args?.resourceType}. Must be ${RESOURCE_TYPE_TEXT} or ${RESOURCE_TYPE_BLOB}.`
|
||||
);
|
||||
}
|
||||
|
||||
// Validate resourceId argument
|
||||
const resourceId = Number(args?.resourceId);
|
||||
if (
|
||||
!Number.isFinite(resourceId) ||
|
||||
!Number.isInteger(resourceId) ||
|
||||
resourceId < 1
|
||||
) {
|
||||
throw new Error(
|
||||
`Invalid resourceId: ${args?.resourceId}. Must be a finite positive integer.`
|
||||
);
|
||||
}
|
||||
|
||||
// Get resource based on the resource type
|
||||
const uri =
|
||||
resourceType === RESOURCE_TYPE_TEXT
|
||||
? textResourceUri(resourceId)
|
||||
: blobResourceUri(resourceId);
|
||||
const resource =
|
||||
resourceType === RESOURCE_TYPE_TEXT
|
||||
? textResource(uri, resourceId)
|
||||
: blobResource(uri, resourceId);
|
||||
|
||||
return {
|
||||
messages: [
|
||||
{
|
||||
role: "user",
|
||||
content: {
|
||||
type: "text",
|
||||
text: `This prompt includes the ${resourceType} resource with id: ${resourceId}. Please analyze the following resource:`,
|
||||
},
|
||||
},
|
||||
{
|
||||
role: "user",
|
||||
content: {
|
||||
type: "resource",
|
||||
resource: resource,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue