Skip to Content

Server

Most should use MCPApp from the Overview. Use MCPServer only when you need low-level control over the server lifecycle, custom transports, or advanced middleware composition.

MCPServer

arcade-mcp.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'
arcadeApiKeyBun.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. Used for custom transport implementations.

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'; const catalog = new ToolCatalog(); // catalog.add(...) to register tools 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(); }

HTTP Transport

TypeScript
import { MCPServer, ToolCatalog, HTTPTransport } from 'arcade-mcp'; const catalog = new ToolCatalog(); 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'; 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'; 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

Use materializeTool() to create objects for runtime registration:

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

materializeTool() takes the same options as app.tool() and returns a MaterializedTool object suitable for the runtime APIs.

Custom Transport

For WebSocket or other custom transports, implement a class that calls server.runConnection():

TypeScript
import { MCPServer, ToolCatalog } from 'arcade-mcp'; // Pseudocode - implement stream adapters for your transport class CustomTransport { async run(server: MCPServer) { // Accept connections, create readable/writable streams const { readable, writable } = await acceptConnection(); await server.runConnection(readable, writable); } }

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

Last updated on

Server - Arcade MCP TypeScript Reference | Arcade Docs