mcp-connector-pattern
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., "@mcp-connector-patternDraft an order for 2 bikes"
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.
mcp-connector-pattern
A small, complete reference MCP server for a fictional bike shop, Northwind Cycles. It exists to show how we build MCP servers, not to sell bikes: customers, inventory, orders, and outbound messages, backed by an in-memory fake upstream API. Read this in five minutes to see the shape of the pattern; read the source (it's short) to see it's real code, not a sketch.
What this demonstrates
1. One tool registry, two transports. src/server.ts
exports a single createServer() factory. src/transports/stdio.ts
and src/transports/http.ts both call it and hand
the result to a different SDK Transport. MCP_TRANSPORT=stdio or
MCP_TRANSPORT=http picks which one runs -- nothing about the tools changes.
tests/dual-transport.test.ts proves this by
spawning the real stdio process and a real HTTP server side by side and
asserting they list the identical tool set.
2. Tool descriptions are the real interface. Every tool description in
src/tools/ spells out what it does, what it doesn't do, and
an example call -- see draft_order or confirm_order for the clearest
case. A vague description ("place an order") gives a model no way to tell
"draft it" from "commit it, charge the card, ship it" apart, and it will
still answer confidently with the wrong tool -- you find out from a wrong
result, not an exception. Precise descriptions are the cheapest fix
available, and they're free at runtime.
3. Structured, not prose, responses. Every tool declares an
outputSchema and returns matching structuredContent alongside a short
text summary (see src/lib/result.ts). A caller -- model
or code -- reads result.structuredContent.order.status, it doesn't parse a
sentence.
4. Read/write separated, with a human-approval seam. This is the load-bearing
idea. draft_order and draft_customer_message (src/tools/orders.ts,
src/tools/messages.ts) only ever write to our own
draft state -- no stock is touched, nothing is sent. confirm_order and
send_customer_message are the only code paths that reach the outside
world (decrementing stock, dispatching a message), and each requires the
exact draft id from the step before. There is no single call that goes from
"customer wants 2 bikes" to "stock decremented" -- a human has to be in that
gap. tests/approval-seam.test.ts asserts
this directly: it drafts an order, checks inventory hasn't moved, confirms
it, and only then checks the stock changed.
5. Every side-effect tool reports exactly what it changed.
confirm_order returns stockChanges: [{ unitId, before, after }] for every
unit it touched; send_customer_message returns the sentAt timestamp. A
model relaying "done!" to a user is only as honest as what the tool actually
handed back -- so the tool hands back specifics, not a boolean.
6. One audit line per call. src/lib/audit.ts wraps
every handler and writes [audit] {tool, actor, args, ok, durationMs} to
stderr on every call, success or failure. Never stdout -- on the stdio
transport stdout is the JSON-RPC channel, and one stray log line there
corrupts every message after it. no-console is enforced by lint in src/
(console.error only) so this can't regress silently.
7. Secrets stay out of the repo. .env.example documents
every variable; .env is gitignored. The HTTP transport requires
Authorization: Bearer <token> on every request
(src/lib/auth.ts, constant-time compare) and refuses to
start without MCP_BEARER_TOKEN set. src/lib/redact.ts
masks anything shaped like a token/secret/password before it reaches a log
line -- see the audit output in the run below, where the bearer token shows
as cu***23.
8. Registering as a custom connector -- see below.
Related MCP server: clinic-mcp
What this deliberately does not do
Scope is the point. This is a pattern, not a starter kit:
No database -- state is an in-memory array (
src/upstream/) that resets every restart. Swap that module for a real API client; nothing insrc/tools/has to change.No OAuth -- the HTTP transport uses one shared bearer token, not per-user auth. Fine for a demo or an internal tool; a multi-tenant product needs real auth in front of
/mcp.No Docker, no CI, no MCP resources or prompts. Just the tool layer, two transports, and tests that prove both actually run.
Run it
npm install
MCP_TRANSPORT=stdio npm run start:stdioThat's the whole stdio path. In a second terminal, the same registry over HTTP:
cp .env.example .env # edit MCP_BEARER_TOKEN to a real random value
npm run start:httpcurl -s -X POST http://localhost:8787/mcp \
-H 'Content-Type: application/json' \
-H 'Accept: application/json, text/event-stream' \
-H 'Authorization: Bearer <your MCP_BEARER_TOKEN>' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'Requests without a valid bearer token get 401; try the same curl without
the Authorization header to see it.
Register as a custom connector
Both Claude.ai and Claude Desktop can add an MCP server as a custom connector under Settings -> Connectors -> Add custom connector:
Run the server with
MCP_TRANSPORT=http(above). For a connector reachable from claude.ai (not just localhost), put a public HTTPS URL in front of it -- a tunnel likengrok http 8787is enough for a demo; a real deployment needs a real host and TLS.In "Add custom connector", set the URL to
https://<your-host>/mcp.If your client supports a custom header for the connector, set
Authorization: Bearer <your MCP_BEARER_TOKEN>. Clients that only support OAuth will need a real OAuth flow in front of/mcpinstead of the bearer check here -- out of scope for this demo, in scope for a production build.Save. The client calls
initialize, thentools/list; you should see all ten Northwind Cycles tools with their descriptions.
For a local-only client (Claude Desktop, or any stdio-based MCP host), point
it at MCP_TRANSPORT=stdio node --import tsx src/index.ts from this
directory instead -- no network, no token, same tools.
Project layout
src/
server.ts single tool-registry factory (point 1)
index.ts entry point, picks a transport from MCP_TRANSPORT
transports/
stdio.ts StdioServerTransport
http.ts StreamableHTTPServerTransport + bearer auth
tools/
customers.ts read-only
inventory.ts read-only
orders.ts read/write split + approval seam (points 4, 5)
messages.ts read/write split + approval seam (points 4, 5)
lib/
audit.ts per-call audit logging to stderr (point 6)
redact.ts secret masking for log lines (point 7)
auth.ts bearer token check (point 7)
result.ts structuredContent + text summary helper (point 3)
upstream/
db.ts in-memory fake upstream data
client.ts async client over db.ts (swap this for a real API)
tests/
approval-seam.test.ts proves point 4
dual-transport.test.ts proves point 1
scripts/
smoke-stdio.ts manual end-to-end check over stdio
smoke-http.ts manual end-to-end check over HTTPGates
npm run lint # eslint, zero warnings
npm run typecheck # tsc --noEmit, strict
npm test # vitestStack
TypeScript, Node 22, ESM, @modelcontextprotocol/sdk 1.30, Zod 3, Vitest.
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.
Related MCP Servers
- Alicense-qualityDmaintenanceA reference implementation for creating an MCP server supporting Streamable HTTP & SSE Transports with OAuth authorization, allowing developers to build OAuth-authorized MCP servers with minimal configuration.106MIT
- AlicenseAqualityDmaintenanceA reference MCP server for clinic scheduling and intake, demonstrating production patterns like tenant isolation, idempotent writes, and structured errors using synthetic data.5MIT
- Alicense-qualityCmaintenanceA reference MCP server demonstrating authentication, authorization, approval workflows, and audit logging for a notes domain with secure defaults.MIT
- Alicense-qualityBmaintenanceAn MCP server reference implementation adding enterprise layers (identity, authorization, audit) around MCP, with sample shipment status and delayed shipment tools over a stateless transport.Apache 2.0
Related MCP Connectors
MCP server for Vonage API documentation, code snippets, tutorials, and troubleshooting.
MCP Server for agents to onboard, pay, and provision services autonomously with InFlow
MCP server for AI access to Swagger by SmartBear.
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- 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/andrewrozumny/mcp-connector-pattern'
If you have feedback or need assistance with the MCP directory API, please join our Discord server