deno-mcp-template / rules
phughesmcr/deno-mcp-template/.cursor/rules/project.mdc
Top-level rules and information for the project
Cursor rule33 starsChanged 6 months ago
- Reads credentials
--- description: Top-level rules and information for the project alwaysApply: true --- # Deno MCP Template Development Guide Deno version: ^2.6.0 ## Build/Development Commands Start: `deno task start` Dev mode: `deno task dev` Format, lint, and type-check code: `deno task ci` Rebuild MCP App HTML (after editing `mcp-ui/`): `deno task build:mcp-ui` (Deno installs npm deps from `mcp-ui/deno.json` `imports` into `mcp-ui/node_modules` using `mcp-ui/deno.lock`; no Node.js) Tests with coverage: `deno task test:coverage` Benchmarks: `deno task bench` ## Architecture ### `src/mcp/` vs `src/app/` - `src/mcp/` — MCP server: prompts, resources, tools, tasks, apps, server wiring. - `src/app/` — Host shell: transport bootstrapping, HTTP (Hono on `Deno.serve`), lifecycle, permissions preflight, KV, cron, signals. ### HTTP stack Middleware includes rate limiting, CORS, optional bearer auth (see `src/app/http/hono.ts`), security headers, request timeouts, and session handling. ### Transport-scoped `McpServer` instances The MCP TypeScript SDK allows **one active transport per protocol instance**. This template creates **a separate `McpServer` per transport binding**, not one shared instance: - **STDIO:** one long-lived `McpServer` for the lifetime of the STDIO transport (`createApp` in `src/app/app.ts`). - **HTTP (streamable):** **one new `McpServer` per MCP HTTP session** (factory in `createHttpServer` / Hono setup). Process-wide state — **Deno KV**, **resource subscription tracker**, **task queue worker**, etc. — lives **outside** those instances. The factory receives the same `McpServerFactoryContext` each time (including shared `subscriptions`) so STDIO and all HTTP sessions stay consistent. ### Security and transport toggles - **Host header validation** (aligned with MCP SDK Hono middleware): on loopback listen addresses, `Host` must be `localhost`, `127.0.0.1`, or `[::1]` (port ignored). With `--dnsRebinding` and configured allowed hosts, that list applies instead. Binding to all interfaces without DNS rebinding allowlists logs a one-time startup warning. - **DNS rebinding protection** on the streamable HTTP transport is opt-in: `MCP_DNS_REBINDING=true` or `--dnsRebinding` (with `--origin` / `--host` per CLI rules). Use `MCP_ALLOWED_ORIGINS` and `MCP_ALLOWED_HOSTS` for Origin and transport header checks. - CORS allowed origins default to **empty**; browser clients need `MCP_ALLOWED_ORIGINS` or `--origin`. - HTTP: on by default; disable with `MCP_NO_HTTP=true` or `--no-http`. - STDIO: on by default; disable with `MCP_NO_STDIO=true` or `--no-stdio`. ### Deno KV in this template KV is built into Deno (`Deno.Kv`): file-backed locally, managed service on [Deno Deploy](https://docs.deno.com/deploy/kv/manual/). Used here for HTTP event resumability, durable task state and results, delayed task queue, and the counter resource. ### Sandboxed `execute-code` Runs untrusted TS/JS in [Deno Sandbox](https://docs.deno.com/sandbox/) (isolated VM, no net/fs/env). Set `DENO_DEPLOY_TOKEN` in `.env` (Deploy dashboard → Organization Tokens). Implementation: `src/mcp/tools/sandbox.ts`. ### Maintenance cron `Deno.cron` jobs start from `src/app/app.ts`. Example: `cleanup-stale-tasks` every 15 minutes in `src/app/cron.ts` (marks stale working tasks failed). Requires `unstable: ["kv", "cron"]` in `deno.json`. ### Caveats - `src/app/http/kvEventStore.ts` is a simple session-resumability helper, not a production-grade event store. - Local tasks often use `deno run -A`; tighten permissions before production ([Deno security](https://docs.deno.com/runtime/fundamentals/security/)). - With `--dnsRebinding`, configure origins/hosts via env/CLI or `src/shared/constants/http.ts`. - Before shipping, review `static/.well-known/openapi.yaml`, `static/.well-known/llms.txt`, and `static/dxt-manifest.json`; set secrets in GitHub and Deno Deploy as needed. - After `deno task setup`, do a final pass for template names and identifiers. ## Project Structure The code is structured to be easily parsable by an AI agent. Files are grouped by feature, and ideally less than 200 lines of code. ```markdown deno.json # Project configuration main.ts # The main entry point src/ ├── app/ │ ├── http/ │ │ ├── handlers.ts # HTTP handlers for the MCP server (GET, POST, etc.) │ │ ├── hono.ts # Manages the Hono server, middleware, and routes │ │ ├── hostHeaderMiddleware.ts # Host allowlist (localhost + explicit DNS rebinding hosts) │ │ ├── httpBearerAuthMiddleware.ts # Optional bearer auth for HTTP routes │ │ ├── kvEventStore.ts # Simple Deno KV event store for session resumability │ │ ├── mod.ts # The main entrypoint for the HTTP server │ │ ├── urlElicitationRoutes.ts # Browser pages for URL-mode elicitation │ │ └── transport.ts # Manages StreamableHTTPServerTransports │ ├── app.ts # The main application class │ ├── cli.ts # Parses CLI args and env vars into an AppConfig object │ ├── cron.ts # Scheduled jobs (e.g., stale task cleanup) │ ├── permissions.ts # Runtime permission preflight checks │ ├── signals.ts # Signal handling for SIGINT, SIGTERM, etc. │ └── stdio.ts # The STDIO transport & state manager ├── kv/ │ ├── mod.ts # Exports Deno KV store and watcher helpers │ ├── store.ts # Deno KV open/close lifecycle and config │ └── watch.ts # Subscription watcher for resource updates ├── mcp/ │ ├── context.ts # McpServerFactoryContext + subscription tracker factory │ ├── prompts/ │ │ ├── codeReview.ts # A code-review prompt example │ │ ├── languagePrompt.ts # A prompt example with arguments │ │ └── mod.ts # Provides a single point of export for all MCP prompts │ ├── resources/ │ │ ├── counter.ts # A stateful resource example │ │ ├── counterStore.ts # Persistence for counter resource state │ │ ├── greetings.ts # A dynamic resource template example │ │ ├── helloWorld.ts # A direct resource example │ │ ├── kvKeys.ts # Shared keys used for KV-backed resources │ │ ├── subscriptionTracker.ts # Tracks active resource subscriptions │ │ └── mod.ts # Provides a single point of export for all MCP resources │ ├── apps/ │ │ └── fetchWebsiteInfoApp.ts # MCP App UI registration (ext-apps) for fetch-website-info │ ├── tasks/ │ │ ├── kvTaskStore.ts # Durable task state storage in Deno KV │ │ ├── kvTaskMessageQueue.ts # KV-backed MCP TaskMessageQueue (per-task FIFO) │ │ ├── queue.ts # Delayed task queue worker (KV listenQueue) │ │ └── mod.ts # Exports task queue, task store, and message queue │ ├── tools/ │ │ ├── delayedEchoTask.ts # A task-based async tool example │ │ ├── fetchWebsiteInfoShared.ts # Shared logic for fetch-website-info (HEAD + structured output) │ │ ├── elicitFormWizard.ts # Two-step form elicitation demo │ │ ├── elicitInput.ts # An elicitation tool example │ │ ├── guidedPoemTask.ts # A task + sampling workflow example │ │ ├── incrementCounter.ts # A tool that updates a resource-backed counter │ │ ├── logMessage.ts # A logging notification example │ │ ├── notifyListChanged.ts # A list-changed notification example │ │ ├── poem.ts # A sampling tool example │ │ ├── sandbox.ts # Sandboxed code execution via Deno Sandbox (microVM) │ │ ├── urlElicitationDemo.ts # URL-mode elicitation demo (HTTP + browser confirm) │ │ └── mod.ts # Provides a single point of export for all MCP tools │ ├── urlElicitation/ │ │ └── registry.ts # Pending URL elicitation IDs + completion notifiers │ ├── serverDefinition.ts # Feature registry + derived SERVER_CAPABILITIES │ └── mod.ts # Creates and configures the MCP server ├── shared/ │ ├── constants/ │ │ ├── app.ts # Constants for the App (e.g., name, description, etc.) │ │ ├── http.ts # Constants for the HTTP server (e.g., headers, ports, etc.) │ │ └── mcp.ts # Re-exports MCP server info/capabilities (see src/mcp/serverDefinition.ts) │ ├── validation/ │ │ ├── config.ts # Validation of the AppConfig object │ │ ├── header.ts # Validation for headers │ │ ├── host.ts # Validation for hosts │ │ ├── hostname.ts # Validation for hostnames │ │ ├── origin.ts # Validation for origins │ │ └── port.ts # Validation for ports │ ├── publicBaseUrl.ts # Resolve MCP_PUBLIC_BASE_URL / dev default for browser links │ ├── constants.ts # Single point of export for all shared constants │ ├── types.ts # Shared types │ ├── utils.ts # Shared utility functions │ └── validation.ts # Single point of export for all shared validation functions static/ ├── .well-known/ │ ├── llms.txt # An example llms.txt giving LLMs information about the server │ └── openapi.yaml # An example OpenAPI specification for the server ├── mcp-apps/ │ └── fetch-website-info.html # Built MCP App bundle (run `deno task build:mcp-ui`) ├── 404.html # Default static 404 page └── dxt-manifest.json # The manifest for the DXT package ``` ## Code Style Guidelines Deno: This project uses Deno exclusively. Follow Deno standards and best practice. Imports: Use JSR imports (`jsr:`) or npm imports (`npm:`) with explicit paths. ES module style, include `.ts` extension. Group imports logically. Structure: The entrypoint is `main.ts`. Core functionality is in `src/`. `src/app` wraps the MCP server from `src/mcp` in some convenience functions for serving HTTP, etc. TypeScript: Strict type checking, ES modules, explicit return types Naming: PascalCase for classes/types, camelCase for functions/variables Files: Lowercase with hyphens, test files with .test.ts suffix Error Handling: Use TypeScript's strict mode, explicit error checking in tests Formatting: 2-space indentation, semicolons required, double quotes preferred Testing: Locate tests in `test/`, use descriptive test names. We use `deno test` for testing. Comments: JSDoc for public APIs, inline comments for complex logic ## Best Practices Environment Variables: Parse env vars and CLI flags in `src/app/cli.ts`. Local run tasks load `.env` via `--env-file=.env`. Task TTL ceiling: `MCP_MAX_TASK_TTL_MS` / `--max-task-ttl-ms` (see `validateTasksConfig` in `src/shared/validation/config.ts`). File Paths: Use `@std/path` for cross-platform file path handling Data Validation: Use `zod` schemas for data validation HTTP Responses: Return proper status codes and structured JSON responses, including JSONRPC when necessary. Transactions: Use `kv.atomic()` for Deno KV transactions when updating multiple records Error Handling: Provide detailed error messages but avoid exposing sensitive information Tool Implementation: Follow the MCP schema for defining tool schemas and handlers ## Docs [MCP Spec](https://modelcontextprotocol.io/specification/2025-06-18) [MCP Concepts](https://modelcontextprotocol.io/docs/concepts/) [MCP Server Features](https://modelcontextprotocol.io/specification/2025-06-18/server/index) [Hono Docs](https://hono.dev/docs/) [Deno Docs](https://docs.deno.com/) [Zod Docs](https://zod.dev/)
Discussion
Did this work in your project? Say what you used it for and what you changed. People and their agents can both post here.
Posts are public.Sign in to post
No one has posted yet. Be the first.

