Skip to content

feat(unstable): Deno.McpServer API for writing MCP servers#35178

Draft
bartlomieju wants to merge 1 commit into
mainfrom
experiment/native-mcp
Draft

feat(unstable): Deno.McpServer API for writing MCP servers#35178
bartlomieju wants to merge 1 commit into
mainfrom
experiment/native-mcp

Conversation

@bartlomieju

Copy link
Copy Markdown
Member

Experiment: a built-in API for writing Model Context Protocol servers in
Deno with zero dependencies, behind --unstable-mcp.

const server = new Deno.McpServer({ name: "calculator", version: "1.0.0" });

server.tool("add", {
  description: "Add two numbers",
  inputSchema: {
    type: "object",
    properties: { a: { type: "number" }, b: { type: "number" } },
    required: ["a", "b"],
  },
}, ({ a, b }) => a + b);

await server.serve();            // stdio transport
// or: Deno.serve(server.fetch)  // streamable HTTP transport

It is implemented as a JS-only lazy-loaded extension (ext/mcp, no ops)
that handles the MCP JSON-RPC lifecycle (initialize handshake with
protocol version negotiation, ping, tools, resources, prompts), reports
tool execution errors in-band per spec, and supports the stdio transport
(newline-delimited JSON-RPC) plus a stateless streamable HTTP transport.
Handlers can return plain values, which are auto-wrapped into MCP result
shapes, or full spec-shaped result objects. Verified against the official
MCP Inspector client over stdio and with raw JSON-RPC on both transports.

Not implemented yet (follow-ups if this is pursued): server-initiated
notifications (listChanged), SSE streaming and sessions for the HTTP
transport, resource templates, argument completion, schema validation of
tool arguments, and spec tests.

Adds an unstable Deno.McpServer API behind --unstable-mcp that makes it
easy to write Model Context Protocol servers in Deno without any
dependencies:

  const server = new Deno.McpServer({ name: "demo", version: "1.0.0" });
  server.tool("add", { inputSchema }, ({ a, b }) => a + b);
  server.resource("file:///greeting.txt", () => "hello");
  server.prompt("review", ({ code }) => "Review this: " + code);
  await server.serve();           // stdio transport
  // or: Deno.serve(server.fetch) // streamable HTTP transport

Implemented as a new lazy loaded JS-only extension (ext/mcp) that
handles the MCP JSON-RPC lifecycle (initialize, ping, tools, resources,
prompts), reports tool errors in-band per spec, and supports both the
stdio transport (newline delimited JSON-RPC) and a stateless streamable
HTTP transport.

Verified against the official MCP Inspector client (initialize
handshake, tools/list, tools/call) and with raw JSON-RPC over both
transports.
@sigmaSd

sigmaSd commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Seems like this is going the bun way of adding everything under the main scope , maybe another global variable called Extra that have all this and S3 and what not should be considered and if something is truly used frequently with time it will be upgraded to deno scooe

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants