> ## Documentation Index
> Fetch the complete documentation index at: https://docs.skybridge.tech/llms.txt
> Use this file to discover all available pages before exploring further.

# McpServer

> The main class for building MCP servers with Skybridge, supporting tools, views, and type inference.

The main class for building MCP servers with Skybridge.

## Import

```typescript theme={null}
import { McpServer } from "skybridge/server";
```

## Constructor

```typescript theme={null}
const server = new McpServer(
  serverInfo: { name: string; version: string },
  options: McpServerOptions
);
```

### Parameters

| Parameter            | Type               | Description             |
| -------------------- | ------------------ | ----------------------- |
| `serverInfo.name`    | `string`           | Name of your MCP server |
| `serverInfo.version` | `string`           | Version of your server  |
| `options`            | `McpServerOptions` | Configuration options   |

### Options

```typescript theme={null}
type McpServerOptions = {
  // Additional options as needed
};
```

## Methods

### registerTool

Register a tool. Provide `view` to bind the tool to a view. See [registerTool](/api-reference/register-tool) for the full API.

```typescript theme={null}
server.registerTool(config, handler);
```

### use

Register Express middleware on the underlying HTTP server. Supports optional path filtering.

```typescript theme={null}
// Global middleware
server.use(cors());

// Path-scoped middleware
server.use("/api", authMiddleware);
```

### useOnError

Register [Express error handler](https://expressjs.com/en/guide/error-handling.html) on the underlying HTTP server. Supports optional path filtering.

```typescript theme={null}
// Global error handler
server.useOnError((err, req, res, next) => {
  console.error(err);
  res.status(500).send('Something broke!');
})

// Path-scoped error handler
server.useOnError('/api', (err, req, res, next) => {
  console.error(err);
  res.status(500).send('Something broke!');
})
```

There is a default error handler already registered, defined as:

```typescript theme={null}
function defaultErrorHandler(
  err: unknown,
  _req: express.Request,
  res: express.Response,
  _next: express.NextFunction,
) {
  console.error("Error handling MCP request:", err);
  if (!res.headersSent) {
    res.status(500).json({
      jsonrpc: "2.0",
      error: { code: -32603, message: "Internal server error" },
      id: null,
    });
  }
}
```

### mcpMiddleware

Register MCP protocol-level middleware using an onion model. Middleware wraps request/notification handlers and can inspect, modify, or short-circuit them.

Must be registered **before** calling `server.run()` or `server.connect()`.

```typescript theme={null}
server.mcpMiddleware(handler);
server.mcpMiddleware(filter, handler);
```

#### Parameters

| Parameter | Type                  | Description                                                                       |
| --------- | --------------------- | --------------------------------------------------------------------------------- |
| `filter`  | `McpMiddlewareFilter` | Optional. Determines which methods the middleware applies to. Omit for catch-all. |
| `handler` | `McpMiddlewareFn`     | The middleware function. Call `next()` to continue the chain.                     |

#### Filter patterns

| Pattern      | Example                            | Matches                                    |
| ------------ | ---------------------------------- | ------------------------------------------ |
| Exact method | `"tools/call"`                     | Only `tools/call`                          |
| Wildcard     | `"tools/*"`                        | Any method starting with `tools/`          |
| Category     | `"request"`                        | All requests (with `extra` context)        |
| Category     | `"notification"`                   | All notifications (`extra` is `undefined`) |
| Array        | `["tools/call", "resources/read"]` | Multiple patterns (OR logic)               |

#### Middleware signature

```typescript theme={null}
type McpMiddlewareFn = (
  request: { method: string; params: Record<string, unknown> },
  extra: McpExtra | undefined,
  next: () => Promise<unknown>,
) => Promise<unknown> | unknown;
```

* `request` — the incoming MCP request with `method` and `params`
* `extra` — SDK context (`McpExtra`) for requests, `undefined` for notifications
* `next()` — invoke the next middleware or original handler. Can only be called once per middleware.

#### Type-safe filters

When using an exact method string, both `params` and `extra` are narrowed automatically:

```typescript theme={null}
server.mcpMiddleware("tools/call", (request, extra, next) => {
  // request.params is typed as CallToolRequest["params"]
  // extra is typed as McpExtra (not undefined)
  console.log(`Tool called: ${request.params.name}`);
  return next();
});
```

#### Examples

**Logging all requests:**

```typescript theme={null}
server.mcpMiddleware("request", (request, extra, next) => {
  console.log(`[MCP] ${request.method}`, request.params);
  return next();
});
```

**Auth guard on tool calls:**

```typescript theme={null}
server.mcpMiddleware("tools/call", async (request, extra, next) => {
  const token = extra.requestInfo?.headers?.["authorization"];
  if (!token) {
    throw new Error("Unauthorized");
  }
  return next();
});
```

**Modifying params:**

```typescript theme={null}
server.mcpMiddleware("tools/call", (request, extra, next) => {
  request.params = { ...request.params, injectedAt: Date.now() };
  return next();
});
```

**Multiple middleware (onion order):**

```typescript theme={null}
const server = new McpServer({ name: "my-app", version: "1.0" }, {})
  .mcpMiddleware((request, extra, next) => {
    console.log("outer: before");
    const result = await next();
    console.log("outer: after");
    return result;
  })
  .mcpMiddleware((request, extra, next) => {
    console.log("inner: before");
    return next();
  });
// Logs: outer: before → inner: before → handler → outer: after
```

## Type Export Pattern

Export the server type for client-side type inference:

```typescript theme={null}
const server = new McpServer({ name: "my-app", version: "1.0" }, {})
  .registerTool(
    {
      name: "search",
      inputSchema: { query: z.string() },
      view: { component: "search" },
    },
    async ({ query }) => {
      return { structuredContent: { results: [] } };
    },
  );

// Export for generateHelpers
export type AppType = typeof server;
```

## Exported Types

The following middleware types are available from `skybridge/server`:

```typescript theme={null}
import type {
  McpExtra,
  McpMiddlewareFn,
  McpMiddlewareFilter,
  McpTypedMiddlewareFn,
  McpMethodString,
} from "skybridge/server";
```

## Related

* [registerTool](/api-reference/register-tool) - View registration details
* [generateHelpers](/api-reference/generate-helpers) - Client-side type inference
* [Type Safety concept](/concepts/type-safety) - Understanding the type system
