Skip to Content

Server

Most should use ArcadeMCP — it handles transport and provides a simpler API. This page covers MCPServer, the low-level core for advanced use cases.

When to Use MCPServer

  • Embedding — Add endpoints to an existing HTTP server
  • Custom transports — WebSocket, IPC, or other non-standard transports
  • Multi- — Isolated server instances with different /auth
  • Testing — Instantiate without starting a transport

MCPServer

arcade-mcp-server.MCPServer

Low-level server with middleware and support.

This server provides:

  • Middleware chain for request/response processing
  • injection for
  • Component managers for , resources, and prompts
  • Direct control over server lifecycle
  • Bidirectional communication with clients

Constructor

TypeScript
new MCPServer(options: MCPServerOptions)
TypeScript
interface MCPServerOptions { /** Collection of tools to serve */ catalog: ToolCatalog; /** Server name */ name?: string; /** Server version */ version?: string; /** Human-readable title */ title?: string; /** Usage instructions for AI clients */ instructions?: string; /** Configuration object */ settings?: MCPSettings; /** Request/response middleware */ middleware?: Middleware[]; /** Lifecycle manager for startup/shutdown */ lifespan?: LifespanManager; /** Disable auth (development only, never in production) */ authDisabled?: boolean; /** Arcade API key */ arcadeApiKey?: string; /** Arcade API URL */ arcadeApiUrl?: string; }

Defaults:

OptionDefaultNotes
name'ArcadeMCP'
version'1.0.0'
arcadeApiKeyprocess.env.ARCADE_API_KEY
arcadeApiUrl'https://api.arcade.dev'
authDisabledfalse⚠️ Never enable in production

Methods

start()

TypeScript
async start(): Promise<void>

Initialize the server. Call before running a transport.

stop()

TypeScript
async stop(): Promise<void>

Gracefully shut down the server. Waits for in-flight requests to complete.

handleMessage()

TypeScript
async handleMessage( message: MCPMessage, session?: ServerSession ): Promise<MCPMessage | undefined>

Handle a single message. Used internally by transports.

runConnection()

TypeScript
async runConnection( readStream: ReadableStream, writeStream: WritableStream, initOptions?: Record<string, unknown> ): Promise<void>

Run a single connection using WHATWG Streams  (not Node.js streams).

Properties

PropertyTypeDescription
toolsToolManagerRuntime tool operations (add, remove, list)
resourcesResourceManagerRuntime resource operations
promptsPromptManagerRuntime prompt operations

Examples

stdio Transport

TypeScript
import { MCPServer, ToolCatalog, StdioTransport } from 'arcade-mcp-server'; import { z } from 'zod'; const catalog = new ToolCatalog(); catalog.add('ping', { description: 'Health check', input: z.object({}), handler: () => 'pong', }); const server = new MCPServer({ catalog, name: 'example', version: '1.0.0', }); await server.start(); try { const transport = new StdioTransport(); await transport.run(server); } finally { await server.stop(); }

catalog.add() is the low-level API for MCPServer. It’s equivalent to app.tool() on ArcadeMCP — both use name as first argument, options second.

HTTP Transport

TypeScript
import { MCPServer, ToolCatalog, HTTPTransport } from 'arcade-mcp-server'; import { z } from 'zod'; const catalog = new ToolCatalog(); catalog.add('ping', { description: 'Health check', input: z.object({}), handler: () => 'pong', }); const server = new MCPServer({ catalog, name: 'example', version: '1.0.0', }); await server.start(); try { const transport = new HTTPTransport({ host: '0.0.0.0', port: 8000 }); await transport.run(server); } finally { await server.stop(); }

With Middleware

TypeScript
import { MCPServer, ToolCatalog, LoggingMiddleware, ErrorHandlingMiddleware, } from 'arcade-mcp-server'; const server = new MCPServer({ catalog: new ToolCatalog(), middleware: [ new ErrorHandlingMiddleware({ maskErrorDetails: true }), new LoggingMiddleware({ logLevel: 'DEBUG' }), ], });

Middleware runs in order. ErrorHandlingMiddleware first means it catches errors from all subsequent middleware.

With Lifespan Manager

TypeScript
import { MCPServer, ToolCatalog, createLifespan } from 'arcade-mcp-server'; const lifespan = createLifespan({ async onStart(server) { await db.connect(); }, async onStop(server) { await db.disconnect(); }, }); const server = new MCPServer({ catalog: new ToolCatalog(), lifespan, });

Runtime Tool Management

Add and remove from a running server:

TypeScript
import { MCPServer, ToolCatalog, tool } from 'arcade-mcp-server'; import { z } from 'zod'; const server = new MCPServer({ catalog: new ToolCatalog() }); await server.start(); // Create a tool object (tool() provides type inference) const dynamicTool = tool({ description: 'Added at runtime', input: z.object({ value: z.string() }), handler: ({ input }) => `Got: ${input.value}`, }); // Add it to the running server — name is first arg await server.tools.add('dynamic-tool', dynamicTool); // List all tools const tools = await server.tools.list(); console.error(`Server has ${tools.length} tools`); // Remove a tool by name await server.tools.remove('dynamic-tool');

Custom Transport

For WebSocket or other custom transports, implement a class that calls server.runConnection() with readable/writable Web Streams:

TypeScript
import { MCPServer } from 'arcade-mcp-server'; class CustomTransport { async run(server: MCPServer) { // Your transport creates read/write streams for each connection // then passes them to the server: // // await server.runConnection(readableStream, writableStream); // // The server handles MCP message parsing and routing. // Your transport handles I/O (WebSocket frames, TCP packets, etc.) } }

See the SDK source for StdioTransport and HTTPTransport as complete reference implementations.

Last updated on

Server - Arcade MCP TypeScript Reference | Arcade Docs