Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
DEPRECATED: Replaced by mcp-app-builder. Previously used to build ChatGPT apps with interactive React widgets via mcp-use.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
references/foundations/architecture.md
1# Architecture23Understanding how mcp-use servers are structured under the hood.45---67## Server Structure89mcp-use is **built on top of the Hono web framework**. When you create an `MCPServer`, you get:1011```typescript12const server = new MCPServer({13name: "my-server",14version: "1.0.0"15});16```1718The server instance has three key components:1920### 1. `server.app` - Hono Instance2122The underlying Hono web application that handles HTTP routing and middleware.2324```typescript25// Add custom HTTP routes26server.get('/health', (c) => c.json({ status: 'ok' }));2728// Add Hono middleware29server.use(async (c, next) => {30console.log(`Request: ${c.req.method} ${c.req.url}`);31await next();32});33```3435**Use for:**36- Custom HTTP endpoints37- Hono-specific middleware38- Direct access to Hono features3940### 2. `server.nativeServer` - MCP SDK4142The official MCP protocol server from `@modelcontextprotocol/sdk`.4344```typescript45// Access native MCP SDK methods (advanced)46server.nativeServer.server.setRequestHandler(...);47```4849**Use for:**50- Advanced MCP protocol features51- Direct SDK access (rare)5253### 3. MCP Server Methods5455High-level methods for defining MCP primitives:5657```typescript58server.tool({ ... }, async (input) => { ... });59server.resource({ ... }, async () => { ... });60server.prompt({ ... }, async (input) => { ... });61server.proxy({ child: { url: "..." } });62```6364---6566## Middleware System6768mcp-use supports two kinds of middleware registered via `server.use()`:69701. **HTTP middleware** — intercepts HTTP requests (Hono layer)712. **MCP middleware** — intercepts MCP operations like tool calls, resource reads, etc.7273The `mcp:` prefix in the pattern string distinguishes them:7475```typescript76// MCP middleware — fires when MCP operations occur77server.use("mcp:tools/call", async (ctx, next) => { ... });7879// HTTP middleware — fires on every HTTP request (no mcp: prefix)80server.use(async (c, next) => { ... });81```8283### MCP Middleware8485MCP middleware intercepts operations at the protocol level, after HTTP routing. It is ideal for cross-cutting concerns like logging, authentication, rate limiting, and tool filtering.8687```typescript88// Catch-all: every MCP operation89server.use("mcp:*", async (ctx, next) => {90const start = Date.now();91const result = await next();92console.log(`${ctx.method} — ${Date.now() - start}ms`);93return result;94});9596// Specific operation97server.use("mcp:tools/call", async (ctx, next) => {98if (!ctx.auth?.scopes.includes("tools:call")) {99throw new Error("Insufficient scope");100}101return next();102});103104// Namespace wildcard105server.use("mcp:tools/*", async (ctx, next) => {106console.log(`Tool operation: ${ctx.method}`);107return next();108});109```110111**Pattern matching:**112113| Pattern | Matches |114|---------|---------|115| `mcp:*` | Every MCP operation |116| `mcp:tools/*` | All tool operations |117| `mcp:tools/call` | Tool calls only |118| `mcp:resources/*` | All resource operations |119| `mcp:prompts/*` | All prompt operations |120121**`MiddlewareContext` fields:**122123| Field | Description |124|-------|-------------|125| `ctx.method` | MCP method name (e.g. `"tools/call"`) |126| `ctx.params` | Request params — mutable |127| `ctx.session` | Session ID when available |128| `ctx.auth` | OAuth info (scopes, permissions, user) when OAuth is configured |129| `ctx.state` | `Map` for passing data across middleware in the same request |130131### HTTP Middleware132133mcp-use uses **Hono's middleware system** for HTTP middleware. Both Hono and Express middleware are supported.134135```typescript136// ✅ Hono style137server.use(async (c, next) => {138// c = Hono Context object139await next();140});141142// ✅ Express style (auto-adapted)143import morgan from "morgan";144server.use(morgan("combined"));145```146147#### Hono-Compatible Middleware148149```typescript150import { rateLimiter } from "hono-rate-limiter";151152server.use(rateLimiter({153windowMs: 15 * 60 * 1000,154limit: 100,155keyGenerator: (c) =>156c.req.header("x-forwarded-for")?.split(",")[0]?.trim() ?? "unknown",157}));158```159160#### Express Middleware (Auto-Adapted)161162```typescript163import rateLimit from "express-rate-limit";164165server.use("/api", rateLimit({166windowMs: 15 * 60 * 1000,167max: 100,168}));169```170171---172173## server.use() routing174175`server.use()` handles three kinds of middleware depending on the first argument:176177```typescript178// MCP middleware (mcp: prefix) — intercepts MCP operations179server.use("mcp:tools/call", async (ctx, next) => { ... });180server.use("mcp:*", async (ctx, next) => { ... });181182// HTTP middleware with path (leading /) — Hono path-scoped middleware183server.use("/api/*", someHttpMiddleware);184185// HTTP middleware without path — Hono catch-all186server.use(async (c, next) => { ... });187```188189`server.app.use()` always routes to Hono and never to MCP middleware:190191```typescript192// Always Hono, never MCP193server.app.use(async (c, next) => { ... });194```195196**In practice:** Use `server.use("mcp:...", handler)` for MCP middleware and `server.use(handler)` or `server.app.use(handler)` for HTTP middleware.197198---199200## Request Lifecycle201202Understanding the flow of a request:203204```2051. HTTP Request arrives206↓2072. Hono middleware chain (server.use without mcp: prefix)208↓2093. OAuth bearer auth (if `oauth` is configured — verifies JWT, populates ctx.auth)210↓2114. MCP protocol routing212↓2135. MCP middleware chain (server.use('mcp:...') handlers)214↓2156. Tool/Resource/Prompt handler216↓2177. Response helpers (text, object, etc.)218↓2198. MCP protocol response220↓2219. HTTP Response222```223224> When `oauth` is configured, unauthenticated requests to `/mcp/*` receive a `401` with a `WWW-Authenticate` header that tells MCP clients where to start the OAuth flow. See [../authentication/overview.md](../authentication/overview.md) for setup.225226### Example Flow227228```typescript229server.app.use(async (c, next) => {230console.log("1. Middleware start");231await next();232console.log("5. Middleware end");233});234235server.tool(236{ name: "greet", schema: z.object({ name: z.string() }) },237async ({ name }) => {238console.log("3. Tool handler");239return text(`Hello, ${name}`); // 4. Response helper240}241);242```243244---245246## Custom HTTP Endpoints247248You can mix MCP tools with custom HTTP routes:249250```typescript251// MCP tool (called via MCP protocol)252server.tool({ name: "calculate", ... }, async (input) => { ... });253254// Custom HTTP endpoint (called via HTTP)255server.app.get('/api/status', (c) => {256return c.json({257uptime: process.uptime(),258tools: server.registeredTools.length259});260});261262// Both coexist on the same server263```264265**Use cases:**266- Health check endpoints267- Webhooks268- Admin APIs269- Public data endpoints270271---272273## Common Patterns274275### Logging Middleware276277```typescript278server.use(async (c, next) => {279const start = Date.now();280await next();281const duration = Date.now() - start;282console.log(`${c.req.method} ${c.req.path} - ${duration}ms`);283});284```285286### Error Handling287288```typescript289server.use(async (c, next) => {290try {291await next();292} catch (err) {293console.error("Server error:", err);294return c.json({ error: "Internal server error" }, 500);295}296});297```298299---300301## Best Practices302303### 1. Use Hono-Compatible Middleware Packages304```typescript305✅ import { rateLimiter } from "hono-rate-limiter";306✅ server.use(rateLimiter({ ... }));307308❌ Writing custom rate limiting logic309```310311### 2. Understand the Signature312```typescript313✅ server.use(async (c, next) => { ... });314315❌ server.use((req, res, next) => { ... }); // Express style316```317318### 3. Access Hono When Needed319```typescript320✅ server.app.get('/custom', (c) => c.json({ ... }));321322❌ Trying to add routes via server.get() // Doesn't exist323```324325### 4. Keep MCP Separate from HTTP326```typescript327✅ MCP tools for AI interactions328✅ HTTP routes for webhooks/admin329✅ Both on same server330331❌ Mixing concerns in tool handlers332```333334---335336## Key Takeaways337338- **Built on Hono** - mcp-use wraps the Hono web framework339- **Two middleware layers** - HTTP (Hono) layer and MCP operation layer340- **`mcp:` prefix** - Use `server.use('mcp:tools/call', handler)` for MCP middleware; no prefix = HTTP middleware341- **Hono style** - HTTP middleware uses `(c, next) => ...` signature342- **Two access points** - `server.use()` and `server.app.use()` both work for HTTP343344---345346## Next Steps347348- **Build tools** → [../server/tools.md](../server/tools.md)349- **Add resources** → [../server/resources.md](../server/resources.md)350- **Understand primitives** → [concepts.md](concepts.md)351