nest-mcp-learning-server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@nest-mcp-learning-serverget post 42"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
NestJS MCP Learning Server
A deliberately small Model Context Protocol (MCP) server built with NestJS. It teaches how a remote MCP server exposes documentation as a resource and safe operations as tools.
The server documents and reads from JSONPlaceholder. Codex is the AI/MCP client, so this project needs no model SDK, API key, frontend, or database.
Architecture
flowchart LR
Codex["Codex MCP client"] -->|"Streamable HTTP + bearer token"| Nest["NestJS /mcp"]
Nest --> Resource["API documentation resource"]
Nest --> Tools["Three read-only tools"]
Tools --> API["JSONPlaceholder REST API"]One MCP request follows this path:
Codex sends an MCP JSON-RPC request to
POST /mcp.McpAccessGuardchecks the bearer token and any suppliedOrigin.McpControllercreates a fresh server and Streamable HTTP transport.McpServerFactoryregisters the resource and tools.A selected tool calls
JsonPlaceholderService.The controller returns the MCP response and closes the server and transport.
Creating a fresh transport per request makes the server stateless. It does not issue session IDs or require sticky sessions.
What the server exposes
Resource
jsonplaceholder://api-docs is a short Markdown reference for the supported JSONPlaceholder endpoints. Resources provide context that a client can list and read without pretending the documentation is an action.
Tools
Tool | Input | Purpose |
|
| Lists at most 10 posts, optionally filtered by user. |
|
| Gets one post. |
|
| Gets one user. |
Every tool has a Zod input schema, structured output, a five-second upstream timeout, and MCP annotations marking it read-only, non-destructive, and idempotent. There is intentionally no generic URL caller and no write tool.
Code map
src/
├── main.ts # Starts Nest on PORT
├── app.module.ts # Wires configuration and providers
├── health.controller.ts # Render/local health check
├── json-placeholder/
│ └── json-placeholder.service.ts # Typed REST calls and timeout
└── mcp/
├── mcp-access.guard.ts # Token and Origin checks
├── mcp.controller.ts # Streamable HTTP transport
└── mcp-server.factory.ts # Resource and tool definitionsThe official SDK is pinned to @modelcontextprotocol/sdk@1.29.0. Version 1 remains the stable production line while the SDK's version 2 is pre-release.
Run locally
Requirements: Node.js 22 or newer and npm.
npm install
cp .env.example .env
openssl rand -hex 32Copy the generated token into MCP_AUTH_TOKEN in .env, then start Nest:
npm run start:devThe endpoints are:
http://localhost:3000/healthhttp://localhost:3000/mcp
Check health:
curl http://localhost:3000/healthOpening /mcp in a browser is not a valid test: MCP uses JSON-RPC over HTTP and this stateless server intentionally rejects GET. Use an MCP client.
Test with MCP Inspector
Run the official Inspector without installing it globally:
npx @modelcontextprotocol/inspectorIn the Inspector UI:
Select Streamable HTTP.
Enter
http://localhost:3000/mcp.Add header
Authorization: Bearer <your MCP_AUTH_TOKEN>.Connect and open the Resources and Tools tabs.
Read
jsonplaceholder://api-docs, then call each tool.
If the Inspector sends an Origin header, add that exact origin to the comma-separated MCP_ALLOWED_ORIGINS value. The example allows http://localhost:6274.
Automated verification
npm run lint
npm test
npm run buildThe end-to-end test starts Nest on a random port and connects with the official Client and StreamableHTTPClientTransport. It verifies real MCP initialization, resources, tools, structured responses, input validation, authentication, and independent stateless clients. JSONPlaceholder is mocked only in automated tests so tests stay deterministic.
Deploy free on Render
This repository includes a Render Blueprint. Render runs the normal Nest HTTP server; MCP does not require a special hosting product.
Push this repository to GitHub.
Open Render's Blueprint page.
Create a Blueprint from the GitHub repository.
Choose the Free instance when prompted.
Set
MCP_AUTH_TOKENto a random 32-byte hex token. Do not commit it.Deploy and copy the resulting
https://<service>.onrender.comURL.
render.yaml configures:
npm ci && npm run buildas the build command;npm run start:prodas the start command;/healthas the health check;Node.js 22;
MCP_AUTH_TOKENas a dashboard-supplied secret.
Render Free services sleep after 15 idle minutes. Wake the service before an MCP test:
until curl -fsS https://<service>.onrender.com/health; do sleep 5; doneThen repeat the Inspector steps with https://<service>.onrender.com/mcp.
Connect the deployed server to Codex
Keep the token out of config.toml. Codex can read it from an environment variable:
read -s NEST_MCP_DEMO_TOKEN
export NEST_MCP_DEMO_TOKEN
launchctl setenv NEST_MCP_DEMO_TOKEN "$NEST_MCP_DEMO_TOKEN"
codex mcp add jsonplaceholder-learning \
--url https://<service>.onrender.com/mcp \
--bearer-token-env-var NEST_MCP_DEMO_TOKENThe launchctl step makes the variable available to GUI applications started on macOS. Fully quit and reopen Codex after setting it.
Because Render can cold start slowly, add these non-secret settings to the generated server table in ~/.codex/config.toml:
[mcp_servers.jsonplaceholder-learning]
url = "https://<service>.onrender.com/mcp"
bearer_token_env_var = "NEST_MCP_DEMO_TOKEN"
startup_timeout_sec = 90
tool_timeout_sec = 30After restarting Codex, check Settings → MCP servers or type /mcp. Try:
“Read the API documentation exposed by the JSONPlaceholder learning server.”
“List the first three posts and summarize them.”
“Get post 1, then find its author.”
“Show only two posts belonging to user 3.”
“Create a new post.” The correct response is that no write tool exists.
Security boundaries
This is a temporary read-only learning server:
Every
/mcprequest requires the shared bearer token.Requests with an
Originare accepted only when explicitly allowed.Tool inputs cannot supply arbitrary URLs.
Result sizes and IDs are bounded.
Upstream errors are replaced by a safe tool error.
Secrets are excluded from Git and from MCP results.
A shared token is intentionally simpler than production authorization. For user-specific or sensitive data, implement the MCP OAuth 2.1 authorization model, per-user authorization, auditing, rate limiting, and secret rotation.
Troubleshooting
401 Unauthorized: Codex/Inspector is missing the token or it differs from Render.403 Forbidden: add the exact supplied Origin toMCP_ALLOWED_ORIGINS.Codex says the server timed out: wake
/health, wait for200, and keepstartup_timeout_sec = 90.Browser shows 405 on
/mcp: expected; use Inspector or Codex instead of browser navigation.Tool returns a retry message: JSONPlaceholder timed out or returned an error.
Server does not appear in Codex: fully restart Codex after adding the server and environment variable.
Remove the experiment
codex mcp remove jsonplaceholder-learning
launchctl unsetenv NEST_MCP_DEMO_TOKEN
unset NEST_MCP_DEMO_TOKENThen suspend or delete the Render service. Rotating or deleting MCP_AUTH_TOKEN immediately prevents further MCP access.
Primary references
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/mohamedalalwan-penny/nest-mcp-learning-server'
If you have feedback or need assistance with the MCP directory API, please join our Discord server