AI & Agents

How to Build MCP Servers with Deno

Building MCP servers with Deno provides a secure way to expose tools for AI agents. The Model Context Protocol (MCP) allows streamable tool calls over HTTP or SSE. Deno's permission system handles untrusted agents safely. This tutorial shows how to set up a server, implement core endpoints, add security, integrate Fresh, and deploy.

Fast.io Editorial Team 6 min read
Deno MCP server running locally

What is an MCP Server?

An MCP server implements the Model Context Protocol, a streaming protocol for AI agent tools. It handles requests like tool discovery, execution, and state management.

Fast.io runs a production MCP server at mcp.fast.io with multiple tools for file storage and collaboration. Building your own lets you expose custom tools securely.

Key features include:

  • Streamable HTTP at /mcp
  • SSE fallback at /sse
  • Session state for auth tokens
  • Dynamic resource listing for files

Deno fits perfectly. It runs TypeScript natively and bundles to a single executable binary. Permissions like --deny-net protect against malicious agents.

Helpful references: Fast.io Workspaces, Fast.io Collaboration, and Fast.io AI.

Practical execution note for building-mcp-servers-deno: define a baseline process, assign ownership, and document fallback behavior when dependencies fail. Run a pilot with a small team, collect concrete metrics, and compare throughput, error rate, and review time before broad rollout. After rollout, keep a living checklist so future contributors can repeat the workflow without re-learning critical constraints.

AI agent connecting to MCP server

Why Deno for MCP Servers?

Deno emphasizes security for untrusted code, ideal for agent tools.

Advantages:

  • Built-in TypeScript support, no config needed
  • Permission flags (--allow-net, --deny-all) for fine-grained control
  • Bundles to single binary with deno compile
  • Fast runtime with V8 isolates
  • Native HTTP server APIs

Compared to Node.js, Deno avoids npm vulnerabilities and package.json hell.

Practical execution note for building-mcp-servers-deno: define a baseline process, assign ownership, and document fallback behavior when dependencies fail. Run a pilot with a small team, collect concrete metrics, and compare throughput, error rate, and review time before broad rollout. After rollout, keep a living checklist so future contributors can repeat the workflow without re-learning critical constraints.

Deno security permissions diagram

Prerequisites

Install Deno 2.0+:

curl -fsSL https://deno.land/install.sh | sh

Verify:

deno --version

Create project:

mkdir mcp-server-deno
cd mcp-server-deno
deno init

Practical execution note for building-mcp-servers-deno: define a baseline process, assign ownership, and document fallback behavior when dependencies fail. Run a pilot with a small team, collect concrete metrics, and compare throughput, error rate, and review time before broad rollout. After rollout, keep a living checklist so future contributors can repeat the workflow without re-learning critical constraints.

Add one practical example, one implementation constraint, and one measurable outcome so the section is concrete and useful for execution.

Teams should validate this approach in a small test path first, then standardize it across environments once metrics and outcomes are stable.

Set Up Fresh Framework

Fresh provides file-based routing and islands for agent UIs.

Add Fresh:

deno add @fresh/core @preact/signals-react fresh

main.ts:

import manifest from "./fresh.gen.ts";

import { start } from "@fresh/server";
import { type Plugin } from "$fresh/server.ts";

const plugins: Plugin[] = [];

await start(manifest, { plugins });

routes/api/mcp.ts for MCP endpoint.

Practical execution note for building-mcp-servers-deno: define a baseline process, assign ownership, and document fallback behavior when dependencies fail. Run a pilot with a small team, collect concrete metrics, and compare throughput, error rate, and review time before broad rollout. After rollout, keep a living checklist so future contributors can repeat the workflow without re-learning critical constraints.

Implement MCP Endpoints

Create /api/mcp POST handler for streamable calls.

Example handler:

import { HandlerContext } from "$fresh/server.ts";

export const handler = {
  async POST(req: Request, ctx: HandlerContext) {
    const sessionId = ctx.state.sessionId || crypto.randomUUID();
    // Parse MCP request
    const body = await req.json();
    const { tool, action, params } = body;

// Route to tool action
    let result;
    if (tool === "storage") {
      result = await handleStorage(action, params, sessionId);
    } // etc

// Stream response
    const stream = new ReadableStream({
      start(controller) {
        controller.enqueue(JSON.stringify({ result }));
        controller.close();
      }
    });

return new Response(stream, {
      headers: { "Content-Type": "application/json-stream" }
    });
  }
};

Add session state with Deno KV for persistence.

Practical execution note for building-mcp-servers-deno: define a baseline process, assign ownership, and document fallback behavior when dependencies fail. Run a pilot with a small team, collect concrete metrics, and compare throughput, error rate, and review time before broad rollout. After rollout, keep a living checklist so future contributors can repeat the workflow without re-learning critical constraints.

Agent Permissions and Security

Deno permissions protect against untrusted agents.

Run with:

deno run --allow-net --allow-env --deny-all main.ts

Explicitly allow only needed perms.

In code, validate agent requests:

if (!isTrustedAgent(req.headers.get("User-Agent"))) {
  return new Response("Unauthorized", { status: 401 });
}

Use Deno's secure defaults: no file access unless allowed.

For production, add rate limiting and auth tokens per agent.

Practical execution note for building-mcp-servers-deno: define a baseline process, assign ownership, and document fallback behavior when dependencies fail. Run a pilot with a small team, collect concrete metrics, and compare throughput, error rate, and review time before broad rollout. After rollout, keep a living checklist so future contributors can repeat the workflow without re-learning critical constraints.

Security audit log for MCP calls

Deploy to Deno Deploy

Bundle and deploy.

deno.json:

{
  "compilerOptions": {
    "lib": ["deno.unstable"]
  },
  "tasks": {
    "deploy": "deno task start"
  },
  "deploy": "./main.ts"
}

Deploy:

deployctl deploy --project=my-mcp

Flags: --allow-net for HTTP, Deno Deploy handles scaling.

Practical execution note for building-mcp-servers-deno: define a baseline process, assign ownership, and document fallback behavior when dependencies fail. Run a pilot with a small team, collect concrete metrics, and compare throughput, error rate, and review time before broad rollout. After rollout, keep a living checklist so future contributors can repeat the workflow without re-learning critical constraints.

Add one practical example, one implementation constraint, and one measurable outcome so the section is concrete and useful for execution.

Testing Your MCP Server

Test with curl:

curl -X POST http://localhost:8000/api/mcp \\
  -H "Content-Type: application/json" \\
  -d '{"tool":"storage","action":"list"}'

works alongside agents using MCP clients.

Define clear tool contracts and fallback behavior so agents fail safely when dependencies are unavailable. This improves reliability in production workflows.

Teams should validate this approach in a small test path first, then standardize it across environments once metrics and outcomes are stable.

Document decisions, ownership, and rollback steps so implementation remains repeatable as the workflow scales.

Teams should validate this approach in a small test path first, then standardize it across environments once metrics and outcomes are stable.

Document decisions, ownership, and rollback steps so implementation remains repeatable as the workflow scales.

Frequently Asked Questions

What are Deno MCP permissions?

Deno uses runtime flags like --allow-net, --deny-read to restrict access. For MCP, deny all then allow specific for agent tools. This prevents untrusted agents from accessing files or network.

How does Fresh framework works alongside MCP?

Fresh handles routing to /mcp endpoints. Use islands for agent dashboards. Combine with Preact for reactive UIs serving MCP data.

Can I bundle MCP server to a binary?

Yes, `deno compile --allow-net main.ts` creates a single executable. Distribute easily without Deno install.

What Deno Deploy flags for production?

Use deployctl with --allow-net, --allow-env=DENO_KV. Deno Deploy provides global edge runtime.

How to handle sessions in MCP?

Use Deno KV for persistent sessions. Store auth tokens by sessionId from headers.

Related Resources

Fast.io features

Ready for Agentic Workspaces?

Build custom MCP tools or use Fast.io's hosted MCP server with 251 tools, 50GB free storage, no credit card. Perfect for Deno developers. Built for building mcp servers deno workflows.