For tools where we seek to get some response from the server, renamed as an action, e.g., "Get Sum" rather than "Add" or "Get Annotated Message" rather than "Annotated Message", so that it's clear what the intent of the tool is in a quick review. * Updated architecture.md * Refactor/renamed add.ts to get-sum.ts * Refactor/renamed annotated-message.ts to get-annotated-message.ts * In tools/index.ts - sorted presentation order
18 KiB
Everything Server – Architecture and Layout
This document 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 a simple tool, several prompts, and both static and dynamic 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.
-
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. Simulated logging and resource‑update notifications are opt‑in and controlled by tools.
-
Two server implementations exist:
server/index.ts: The lightweight, modular server used by transports in this package.server/everything.ts: A comprehensive reference server (much larger, many tools/prompts/resources) kept for reference/testing but not wired up by default in the entry points.
-
Multi‑client subscriptions: The server supports multiple concurrent clients. Each client manages its own resource subscriptions and receives notifications only for the URIs it subscribed to, independent of other clients.
Directory Layout
src/everything
├── index.ts
├── docs
│ ├── architecture.md
│ └── server-instructions.md
├── prompts
│ ├── index.ts
│ ├── args.ts
│ ├── completions.ts
│ ├── simple.ts
│ └── resource.ts
├── resources
│ ├── index.ts
│ ├── files.ts
│ ├── subscriptions.ts
│ └── templates.ts
├── server
│ ├── index.ts
│ ├── logging.ts
│ └── everything.ts
├── transports
│ ├── sse.ts
│ ├── stdio.ts
│ └── streamableHttp.ts
├── tools
│ ├── index.ts
│ ├── echo.ts
│ ├── get-annotated-message.ts
│ ├── get-env.ts
│ ├── get-tiny-image.ts
│ ├── get-resource-links.ts
│ ├── get-resource-reference.ts
│ ├── get-structured-content.ts
│ ├── get-sum.ts
│ ├── long-running-operation.ts
│ ├── sampling-request.ts
│ ├── toggle-logging.ts
│ └── toggle-subscriber-updates.ts
└── package.json
At src/everything:
-
index.ts
- CLI entry that selects and runs a specific transport module based on the first CLI argument:
stdio,sse, orstreamableHttp.
- CLI entry that selects and runs a specific transport module based on the first CLI argument:
-
server/
- index.ts
- Server factory that creates an
McpServerwith 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 disconencts.
- Server factory that creates an
- 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.
- everything.ts
- A full “reference/monolith” implementation demonstrating most MCP features. Not the default path used by the transports in this package.
- index.ts
-
transports/
- stdio.ts
- Starts a
StdioServerTransport, created the server viacreateServer(), and connects it. HandlesSIGINTto close cleanly and callscleanup()to remove any live intervals.
- Starts a
- sse.ts
- Express server exposing:
GET /sseto establish an SSE connection per session.POST /messagefor client messages.
- Manages multiple connected clients via a transport map.
- Starts an
SSEServerTransport, created the server viacreateServer(), and connects it to a new transport. - On server disconnect, calls
cleanup()to remove any live intervals.
- Express server exposing:
- streamableHttp.ts
- Express server exposing a single
/mcpendpoint for POST (JSON‑RPC), GET (SSE stream), and DELETE (session termination) usingStreamableHTTPServerTransport. - Uses an
InMemoryEventStorefor resumable sessions and tracks transports bysessionId. Connects a fresh server instance on initialization POST and reuses the transport for subsequent requests.
- Express server exposing a single
- stdio.ts
-
tools/
-
index.ts
registerTools(server)orchestrator; delegates to basic tools and control tools.- echo.ts
- Registers an
echotool that takes a message and returnsEcho: {message}.
- Registers an
- get-annotated-message.ts
- Registers an
annotated-messagetool which demonstrates annotated content items by emitting a primarytextmessage withannotationsthat vary bymessageType("error" | "success" | "debug"), and optionally includes an annotatedimage(tiny PNG) whenincludeImageis true.
- Registers an
- get-env.ts
- Registers a
get-envtool that returns the current process environment variables as formatted JSON text; useful for debugging configuration.
- Registers a
- get-tiny-image.ts
- Registers a
get-tiny-imagetool, which returns a tiny PNG MCP logo as animagecontent item, along with surrounding descriptivetextitems.
- Registers a
- get-sum.ts
- Registers an
get-sumtool with a Zod input schema that sums two numbersaandband returns the result.
- Registers an
- long-running-operation.ts
- Registers a
long-running-operationtool that simulates a long-running task over a specifiedduration(seconds) and number ofsteps; emitsnotifications/progressupdates when the client supplies aprogressToken.
- Registers a
- sampling-request.ts
- Registers a
sampling-requesttool that sends asampling/createMessagerequest to the client/LLM and returns the sampling result.
- Registers a
- toggle-logging.ts
- Registers a
toggle-loggingtool, which starts or stops simulated logging for the invoking session.
- Registers a
- toggle-subscriber-updates.ts
- Registers a
toggle-subscriber-updatestool, which starts or stops simulated resource subscription update checks for the invoking session.
- Registers a
-
-
prompts/
- index.ts
registerPrompts(server)orchestrator; delegates to individual prompt registrations.
- simple.ts
- Registers
simple-prompt: a prompt with no arguments that returns a single user message.
- Registers
- args.ts
- Registers
args-prompt: a prompt with two arguments (cityrequired,stateoptional) used to compose a message.
- Registers
- completions.ts
- Registers
completable-prompt: a prompt whose arguments support server-driven completions using the SDK’scompletable(...)helper (e.g., completingdepartmentand context-awarename).
- Registers
- resource.ts
- Exposes
registerEmbeddedResourcePrompt(server)which registersresource-prompt— a prompt that acceptsresourceType("Text" or "Blob") andresourceId(integer), and embeds a dynamically generated resource of the requested type within the returned messages. Internally reuses helpers fromresources/templates.ts.
- Exposes
- index.ts
-
resources/
- index.ts
registerResources(server)orchestrator; delegates to template‑based dynamic resources and static file-based resources by callingregisterResourceTemplates(server)andregisterFileResources(server).
- 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)
- Text:
- 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), andblobResourceUri(index)so other modules can construct and embed dynamic resources directly (e.g., from prompts).
- Registers two dynamic, template‑driven resources using
- 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,.txtastext/plain,.jsonasapplication/json, others default totext/plain.
- Registers static file-based resources for each file in the
- index.ts
-
docs/
- server-instructions.md
- Human‑readable instructions intended to be passed to the client/LLM as MCP server instructions. Loaded by the server at startup.
- architecture.md (this document)
- server-instructions.md
-
package.json
- Package metadata and scripts:
build: TypeScript compile todist/, copiesdocs/intodist/and marks the compiled entry scripts as executable.start:stdio,start:sse,start:streamableHttp: Run built transports fromdist/.
- Declares dependencies on
@modelcontextprotocol/sdk,express,cors,zod, etc.
- Package metadata and scripts:
Startup and Runtime Flow
-
A transport is chosen via the CLI entry
index.ts:node dist/index.js stdio→ loadstransports/stdio.jsnode dist/index.js sse→ loadstransports/sse.jsnode dist/index.js streamableHttp→ loadstransports/streamableHttp.js
-
The transport creates the server via
createServer()fromserver/index.tsand connects it to the chosen transport type from the MCP SDK. -
The server factory (
server/index.ts) does the following:- Creates
new McpServer({ name, title, version }, { capabilities, instructions }). - Capabilities:
tools: {}logging: {}prompts: {}resources: { subscribe: true }
- Loads human‑readable “server instructions” from the docs folder (
server-instructions.md). - Registers tools via
registerTools(server). - Registers resources via
registerResources(server). - Registers prompts via
registerPrompts(server). - Sets up resource subscription handlers via
setSubscriptionHandlers(server). - Returns the server and a
cleanup(sessionId?)hook that stops any active intervals and removes any session‑scoped state.
- Creates
-
Each transport is responsible for network/session lifecycle:
- STDIO: simple process‑bound connection; closes on
SIGINTand callscleanup(). - SSE: maintains a session map keyed by
sessionId; hooks server’soncloseto clean and remove session; exposes/sse(GET) and/message(POST) endpoints. - Streamable HTTP: exposes
/mcpfor POST (JSON‑RPC messages), GET (SSE stream), and DELETE (termination). Uses an event store for resumability and stores transports bysessionId. Does not auto‑start simulated features; callscleanup(sessionId)on DELETE.
- STDIO: simple process‑bound connection; closes on
Registered Features (current minimal set)
-
Tools
echo(tools/echo.ts): Echoes the providedmessage: string. Uses Zod to validate inputs.get-annotated-message(tools/get-annotated-message.ts): Returns atextmessage annotated withpriorityandaudiencebased onmessageType(error,success, ordebug); can optionally include an annotatedimage.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 introtextblock followed by multipleresource_linkitems. For a requestedcount(1–10), alternates between dynamic Text and Blob resources using URIs fromresources/templates.ts.get-resource-reference(tools/get-resource-reference.ts): AcceptsresourceType(textorblob) andresourceId(positive integer). Returns a concreteresourcecontent block (with itsuri,mimeType, and data) with surrounding explanatorytext.get-structured-content(tools/get-structured-content.ts): Demonstrates structured responses. Acceptslocationinput and returns both backward‑compatiblecontent(atextblock containing JSON) andstructuredContentvalidated by anoutputSchema(temperature, conditions, humidity).get-sum(tools/get-sum.ts): For two numbersaandbcalculates and returns their sum. Uses Zod to validate inputs.get-tiny-image(tools/get-tiny-image.ts): Returns a tiny PNG MCP logo as animagecontent item with brief descriptive text before and after.long-running-operation(tools/long-running-operation.ts): Simulates a multi-step operation over a givendurationand number ofsteps; reports progress vianotifications/progresswhen aprogressTokenis provided by the client.sampling-request(tools/sampling-request.ts): Issues asampling/createMessagerequest to the client/LLM using providedpromptand optional generation controls; returns the LLM’s response payload.toggle-logging(tools/toggle-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.
-
Prompts
simple-prompt(prompts/simple.ts): No-argument prompt that returns a static user message.args-prompt(prompts/args.ts): Two-argument prompt withcity(required) andstate(optional) used to compose a question.completable-prompt(prompts/completions.ts): Demonstrates argument auto-completions with the SDK’scompletablehelper;departmentcompletions drive context-awarenamesuggestions.resource-prompt(prompts/resource.ts): AcceptsresourceType("Text" or "Blob") andresourceId(string convertible to integer) and returns messages that include an embedded dynamic resource of the selected type generated viaresources/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 Docs:
demo://resource/static/document/<filename>(serves files fromsrc/everything/docs/as static file-based resources)
- Dynamic Text:
-
Resource Subscriptions and Notifications
- Clients may subscribe/unsubscribe to resource URIs using the MCP
resources/subscribeandresources/unsubscriberequests. - Simulated update notifications are opt‑in and off by default. Use the
toggle-subscriber-updatestool to start/stop a per‑session interval that emitsnotifications/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.
- Clients may subscribe/unsubscribe to resource URIs using the MCP
-
Logging
- Simulated logging is available but off by default. Use the
toggle-loggingtool 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 MCPlogging/setLevelrequest.
- Simulated logging is available but off by default. Use the
Extension Points
-
Adding Tools
- Create a new file under
tools/with yourregisterXTool(server)function that registers the tool viaserver.registerTool(...). - Export and call it from
tools/index.tsinsideregisterTools(server).
- Create a new file under
-
Adding Prompts
- Create a new file under
prompts/with yourregisterXPrompt(server)function that registers the prompt viaserver.registerPrompt(...). - Export and call it from
prompts/index.tsinsideregisterPrompts(server).
- Create a new file under
-
Adding Resources
- Create a new file under
resources/with yourregisterXResources(server)function usingserver.registerResource(...)(optionally withResourceTemplate). - Export and call it from
resources/index.tsinsideregisterResources(server).
- Create a new file under
Resource Subscriptions – How It Works
-
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-updatestool, which callsbeginSimulatedResourceUpdates(server, sessionId)andstopSimulatedResourceUpdates(sessionId). cleanup(sessionId?)callsstopSimulatedResourceUpdates(sessionId)to clear intervals and remove session‑scoped state.
- Tracks subscribers per URI:
-
Design note: Each client session has its own
McpServerinstance; periodic checks run per session and invokeserver.notification(...)on that instance, so messages are delivered only to the intended client.
Simulated Logging – How It Works
-
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-loggingtool, which callsbeginSimulatedLogging(server, sessionId?)andstopSimulatedLogging(sessionId?). Note that transport disconnect triggerscleanup()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.
-
Adding Transports
- Implement a new transport module under
transports/. - Add a case to
index.tsso the CLI can select it.
- Implement a new transport module under
Build and Distribution
- TypeScript sources are compiled into
dist/vianpm run build. - The
buildscript copiesdocs/intodist/so instruction files ship alongside the compiled server. - The CLI bin is configured in
package.jsonasmcp-server-everything→dist/index.js.
Relationship to the Full Reference Server
The large server/everything.ts shows a comprehensive MCP server showcasing many features (tools with schemas, prompts, resource operations, notifications, etc.). The current transports in this package use the lean factory from server/index.ts instead, keeping the runtime small and focused while preserving the reference implementation for learning and experimentation.