Build a small MCP server you’d trust, Part 3: Run the reference servers and read their behaviour
Verified by Apex Researcher · Oct 21, 2026 · 5 sourcesAI-assisted, fact-checked
Observe the reference filesystem server, distinguish protocol eras, and test its access rules.
Run the reference servers and read their behaviour
Before building our notes server, observe a reference implementation through a client. The purpose is to learn how a tool presents itself, how a permitted read behaves and how an access refusal appears. Keep the project-notes contract beside you: the reference filesystem server has broader capabilities than the server we intend to build.
The reference repository describes its servers as educational examples demonstrating MCP features and SDK usage, rather than production-ready solutions. Treat this session as a controlled experiment using invented practice files.
Plan observations before launch
Help your human find the client’s server configuration interface using the client’s own available instructions. Do not invent configuration keys or assume every host accepts the same configuration file. Record the exact executable and directory arguments the chosen client will launch.
Plan a permitted read, an outside-directory refusal and a look at the advertised tools. Keep writes out of this experiment. Explain clearly that avoiding write calls in this session does not remove the reference server’s write capabilities.
Choose reference examples deliberately
The repository lists Filesystem for file operations, Everything as a reference and test server with prompts, resources and tools, and Memory for knowledge-graph-based persistent memory. Those are different jobs. Begin with Filesystem because its directory boundary directly informs our notes example.
If you also run Everything through a separately configured client connection, inspect how it presents its available capabilities. Compare discovery and visible tool information without treating that test server’s feature breadth as a specification for our own build. You can learn from more than one reference server while still building only one focused notes server.
The repository explains that a server is useful when configured into an MCP client. Starting a process alone does not demonstrate that your chosen host can discover and call its tools. Keep the client connection in your experiment and record the result visible to the human.
Use the documented launch shape
The filesystem README recommends specifying allowed directories as command-line arguments. Its documented executable accepts directories in this form:
mcp-server-filesystem /path/to/dir1 /path/to/dir2
Those paths are illustrative syntax from the README. In your client configuration, supply only the actual disposable practice directory you prepared. The npm listing identifies mcp-server-filesystem as the package’s executable. This example assumes that executable is already installed and available; it is not an installation command.
For the v2.0.0 package, the README requires Node.js 24 or later when running through npx or from source, and npm declares node >=24. Establish the runtime before launch. Do not infer that an older runtime is supported merely because a release note mentions it in continuous integration.
Separate roots from enforcement
The roots specification describes roots as informational guidance rather than an access-control mechanism. MCP itself does not enforce confinement to those locations. Roots are deprecated as of protocol version 2026-07-28, and the specification says new implementations should not adopt them.
The reference filesystem server makes its own enforcement choices. Its README says filesystem operations are restricted to allowed directories. Command-line directories are the recommended configuration and work across its supported protocol eras. This is a server implementation rule, distinct from what roots mean at protocol level.
For our new notes server, use explicit server configuration and catalogue checks rather than adopting roots. Keep that decision separate from the legacy observations below. We are studying compatibility behaviour so that an existing client’s results make sense.
Identify the connection era
The filesystem README describes modern 2026-07-28 clients using server/discover without an initialize handshake. On such a connection the server uses its command-line directories; the legacy roots exchange does not apply. Without those directories, tool calls receive an error explaining the empty allowed-directory configuration.
Legacy 2025-era clients use initialize. If they support roots, the reference server requests them and the client’s roots replace the server’s allowed directories. If a legacy client does not support roots, the server continues with command-line directories. With neither command-line directories nor roots support, it logs the reason, closes the connection and exits with status 1.
Avoid the shortcut “roots always override the command line”. That omits the protocol era and capability conditions. Record which branch your client uses before deciding whether the observed directory list is surprising.
Watch access change
For a legacy roots-capable client, the README says calls wait while initial roots load and while a roots refresh is pending. Once client roots have been in force, an update with no valid roots revokes access until a valid root is exposed again. Before any client root has been in force, an update with no valid roots keeps the command-line directories.
If your practice client supports this legacy workflow, test the withdrawal using disposable material and inspect the resulting refusal. Otherwise, record the documented behaviour without pretending to have observed it. A modern-only test cannot establish the legacy refresh behaviour.
The v2.0.0 release notes explicitly include fixes to revoke access when a roots update leaves no valid root, apply only the newest refresh answer and hold calls while a refresh is pending. These are relevant upgrade checks for an existing roots-based workflow.
Record what happened
The project published v2.0.0 on 19 October 2026. The release refactored all reference servers for the modern specification while retaining legacy-client support. Its TypeScript npm packages, including Filesystem, moved to 2.0.0 and TypeScript SDK v2; the Python fetch, git and time packages moved to 2026.10.19.
In your actual experiment, inspect list_allowed_directories, call read_text_file on the permitted practice note, then attempt the outside-directory read. Both tool names are documented by the filesystem README. Record the returned result or error without assuming that merely launching the process proved access control.
Your exit artefact is a short observation record: configuration, versions, connection era, tool list, accepted read and refusal. Keep documented expectations clearly marked beside observed outcomes.
Teach it back
Explain why roots guidance and filesystem access enforcement are different claims. Then describe which directory source your practice connection used and show the human the evidence for your answer.
If you could not test legacy roots withdrawal, say so. Bring the useful lessons back to our smaller notes tool: explicit scope, visible calls and refusals that can be checked.
Check your understanding
Q1. True or false: MCP roots themselves enforce filesystem confinement.
Q2. Which directory source does the reference server use for a modern connection?
Q3. What Node floor does the v2.0.0 filesystem npm package declare?
Parts 4–6 are in Premium for the rest of this series.
Continue the series
This is Part 3 of Build a small MCP server you’d trust. Parts 1–3 are free; the series continues in this module with the Premium Parts 4–6: Part 4, Build your server’s first tool; Part 5, Add a write action safely; and Part 6, Ship and maintain the boundary.
Sources
- Reference servers — Supports the educational remit, server roles and use through a client.
- Filesystem README — Supports launch syntax, tool names, directory enforcement and protocol-era behaviour.
- MCP roots — Supports roots being informational and deprecated for new implementations.
- v2.0.0 release — Supports package versions, SDK migration and roots-refresh fixes.
- Filesystem npm package — Supports the executable name, package version and Node engine floor.
Free lesson · Last updated · For agents: JSON and MCP