
mcp-ts-core
TypeScript framework for building MCP servers with auth, storage, OpenTelemetry, and support for Bun/Node/Cloudflare Wor
Agent-native TypeScript framework for building MCP servers with declarative definitions, auth, multi-backend storage, and observability. Build tools, not infrastructure.
About mcp-ts-core
mcp-ts-core is a community-built MCP server published by cyanheads that provides AI assistants with tools and capabilities via the Model Context Protocol. TypeScript framework for building MCP servers with auth, storage, OpenTelemetry, and support for Bun/Node/Cloudflare Wor It is categorized under search web. This server exposes 1 tool that AI clients can invoke during conversations and coding sessions.
How to install
You can install mcp-ts-core in your AI client of choice. Use the install panel on this page to get one-click setup for Cursor, Claude Desktop, VS Code, and other MCP-compatible clients. This server runs locally on your machine via the stdio transport.
License
mcp-ts-core is released under the Apache-2.0 license. This is a permissive open-source license, meaning you can freely use, modify, and distribute the software.
Tools (1)
Greet someone by name and return a personalized message
@cyanheads/mcp-ts-core
Agent-native TypeScript framework for building MCP servers. Build tools, not infrastructure. Declarative definitions with auth, multi-backend storage, OpenTelemetry, and first-class support for Bun/Node/Cloudflare Workers.
What is this?
@cyanheads/mcp-ts-core is the infrastructure layer for TypeScript MCP servers. Install it as a dependency — don't fork it. You write tools, resources, and prompts; the framework handles transports, auth, storage, config, logging, telemetry, and lifecycle.
import { createApp, tool, z } from '@cyanheads/mcp-ts-core';
const greet = tool('greet', {
description: 'Greet someone by name and return a personalized message.',
annotations: { readOnlyHint: true },
input: z.object({ name: z.string().describe('Name of the person to greet') }),
output: z.object({ message: z.string().describe('The greeting message') }),
handler: async (input) => ({ message: `Hello, ${input.name}!` }),
});
await createApp({ tools: [greet] });
That's a complete MCP server. Every tool call is automatically logged with duration, payload sizes, memory usage, and request correlation — no instrumentation code needed. createApp() handles config parsing, logger init, transport startup, signal handlers, and graceful shutdown.
Features
- Declarative definitions —
tool(),resource(),prompt()builders with Zod schemas.appTool()andappResource()for MCP Apps with interactive HTML UIs. Framework handles registration, validation, and response formatting. - Unified Context — handlers receive a single
ctxobject withctx.log(request-scoped logging),ctx.state(tenant-scoped storage),ctx.elicit(user prompting),ctx.sample(LLM completion), andctx.signal(cancellation). - Inline auth —
auth: ['scope']on definitions. No wrapper functions. Framework checks scopes before calling your handler. - Task tools —
task: trueflag for long-running operations. Framework manages the full lifecycle (create, poll, progress, complete/fail/cancel). - Definition linter —
validateDefinitions()checks tools, resources, and prompts against MCP spec at startup. Name format, schema structure,.describe()presence, JSON Schema serializability, auth scope validity, annotation coherence, and URI template–params alignment. Also available as a standalone CLI (lint:mcp) and devcheck step. - Structured error handling — Handlers throw freely; the framework catches, classifies, and formats. Error factories (
notFound(),validationError(),serviceUnavailable(), etc.) for precise control when the code matters. Auto-classification from plainErrormessages when it doesn't. - Multi-backend storage —
in-memory,filesystem,Supabase,Cloudflare D1/KV/R2. Swap providers via env var without changing tool logic. Cursor pagination, batch ops, TTL, tenant isolation. - Pluggable auth —
none,jwt, oroauthmodes. JWT with local secret or OAuth with JWKS verification. - Observability — Pino structured logging with optional OpenTelemetry tracing and metrics. Request IDs, trace correlation, tool execution metrics — all automatic.
- Local + edge — Same code runs on stdio, HTTP (Hono), and Cloudflare Workers.
createApp()for Node,createWorkerHandler()for Workers. - Tiered dependencies — Core deps always installed. Parsers, sanitization, scheduling, OTEL SDK, Supabase, OpenAI — optional peers. Install what you use.
- Agent-first DX — Ships
CLAUDE.mdwith full exports catalog, patterns, and contracts. AI coding agents can build on the framework with zero ramp-up.
Quick start
bunx @cyanheads/mcp-ts-core init my-mcp-server
cd my-mcp-server
bun install
That gives you a working project with CLAUDE.md, skills, config files, and a scaffolded src/ directory. Open it in your editor, start your coding agent, and tell it what tools to build. The agent learns the framework from the included docs and skills — tool definitions, resources, services, testing patterns, all of it.
What you get
Here's what tool definitions look like:
import { tool, z } from '@cyanheads/mcp-ts-core';
export const search = tool('search', {
description: 'Search for items by query.',
input: z.object({
query: z.string().describe('Search query'),
limit: z.number().default(10).describe('Max results'),
}),
output: z.object({ items: z.array(z.string()).describe('Search results') }),
async handler(input) {
const results = await doSearch(input.query, input.limit);
return { items: results };
},
});
And resources:
import { resource, z } from '@cyanheads/mcp-ts-core';
export const itemData = resource('items://{itemId}', {
description: 'Retrieve item data by ID.',
params: z.object({ itemId: z.string().describe('Item ID') }),
async handler(params, ctx) {
return await getItem(params.itemId);
},
});
Everything registers through createApp() in your entry point:
await createApp({
name: 'my-mcp-server',
version: '0.1.0',
tools: allToolDefinitions,
resources: allResourceDefinitions,
prompts: allPromptDefinitions,
});
It also works on Cloudflare Workers with createWorkerHandler() — same definitions, different entry point.
Server structure
my-mcp-server/
src/
index.ts # createApp() entry point
worker.ts # createWorkerHandler() (optional)
config/
server-config.ts # Server-specific env vars
services/
[domain]/ # Domain services (init/accessor pattern)
mcp-server/
tools/definitions/ # Tool definitions (.tool.ts)
resources/definitions/ # Resource definitions (.resource.ts)
prompts/definitions/ # Prompt definitions (.prompt.ts)
package.json
tsconfig.json # extends @cyanheads/mcp-ts-core/tsconfig.base.json
CLAUDE.md # Points to core's CLAUDE.md for framework docs
No src/utils/, no src/storage/, no src/types-global/, no src/mcp-server/transports/ — infrastructure lives in node_modules.
Configuration
All core config is Zod-validated from environment variables. Server-specific config uses a separate Zod schema with lazy parsing.
| Variable | Description | Default |
|---|---|---|
MCP_TRANSPORT_TYPE | stdio or http | stdio |
MCP_HTTP_PORT | HTTP server port | 3010 |
MCP_HTTP_HOST | HTTP server hostname | 127.0.0.1 |
MCP_AUTH_MODE | none, jwt, or oauth | none |
MCP_AUTH_SECRET_KEY | JWT signing secret (required for jwt mode) | — |
STORAGE_PROVIDER_TYPE | in-memory, filesystem, supabase, cloudflare-d1/kv/r2 | in-memory |
OTEL_ENABLED | Enable OpenTelemetry | false |
OPENROUTER_API_KEY | OpenRouter LLM API key | — |
See CLAUDE.md for the full configuration reference.
API overview
Entry points
| Function | Purpose |
|---|---|
createApp(options) | Node.js server — handles full lifecycle |
createWorkerHandler(options) | Cloudflare Workers — returns { fetch, scheduled } |
Builders
| Builder | Usage |
|---|---|
tool(name, options) | Define a tool with handler(input, ctx) |
resource(uriTemplate, options) | Define a resource with handler(params, ctx) |
prompt(name, options) | Define a prompt with generate(args) |
appTool(name, options) | Define an MCP Apps tool with auto-populated _meta.ui |
appResource(uriTemplate, options) | Define an MCP Apps HTML resource with the correct MIME type and _meta.ui mirroring for read content |
Context
Handlers receive a unified Context object:
| Property | Type | Description |
|---|---|---|
ctx.log | ContextLogger | Request-scoped logger (auto-correlates requestId, traceId, tenantId) |
ctx.state | ContextState | Tenant-scoped key-value storage |
ctx.elicit | Function? | Ask the user for input (when client supports it) |
ctx.sample | Function? | Request LLM completion from the client |
ctx.signal | AbortSignal | Cancellation signal |
ctx.notifyResourceUpdated | Function? | Notify subscribed clients a resource changed |
ctx.notifyResourceListChanged | Function? | Notify clients the resource list changed |
ctx.progress | ContextProgress? | Task progress reporting (when task: true) |
ctx.requestId | string | Unique request ID |
ctx.tenantId | string? | Tenant ID (from JWT or 'default' for stdio) |
Subpath exports
import { createApp, tool, resource, prompt } from '@cyanheads/mcp-ts-core';
import { createWorkerHandler } from '@cyanheads/mcp-ts-core/worker';
import { McpError, JsonRpcErrorCode, notFound, serviceUnavailable } from '@cyanheads/mcp-ts-core/errors';
import { checkScopes } from '@cyanheads/mcp-ts-core/auth';
import { markdown, fetchWithTimeout } from '@cyanheads/mcp-ts-core/utils';
import { OpenRouterProvider, Gra
---
*README truncated. [View full README on GitHub](https://github.com/cyanheads/mcp-ts-core).*
Alternatives
Related Skills
Browse all skillsOfficial Google SEO guide covering search optimization, best practices, Search Console, crawling, indexing, and improving website search visibility based on official Google documentation
Create user-centered, accessible interface copy (microcopy) for digital products including buttons, labels, error messages, notifications, forms, onboarding, empty states, success messages, and help text. Use when writing or editing any text that appears in apps, websites, or software interfaces, designing conversational flows, establishing voice and tone guidelines, auditing product content for consistency and usability, reviewing UI strings, or improving existing interface copy. Applies UX writing best practices based on four quality standards — purposeful, concise, conversational, and clear. Includes accessibility guidelines, research-backed benchmarks (sentence length, comprehension rates, reading levels), expanded error patterns, tone adaptation frameworks, and comprehensive reference materials.
Automate web browser interactions using natural language via CLI commands. Use when the user asks to browse websites, navigate web pages, extract data from websites, take screenshots, fill forms, click buttons, or interact with web applications. Triggers include "browse", "navigate to", "go to website", "extract data from webpage", "screenshot", "web scraping", "fill out form", "click on", "search for on the web". When taking actions be as specific as possible.
Research a topic from the last 30 days on Reddit + X + Web, become an expert, and write copy-paste-ready prompts for the user's target tool.
Use this skill for requests related to web research; it provides a structured approach to conducting comprehensive web research
Comprehensive research, analysis, and content extraction system. USE WHEN user says 'research' (ANY form - this is the MANDATORY trigger), 'do research', 'extensive research', 'quick research', 'minor research', 'research this', 'find information', 'investigate', 'extract wisdom', 'extract alpha', 'analyze content', 'can't get this content', 'use fabric', OR requests any web/content research. Supports three research modes (quick/standard/extensive), deep content analysis, intelligent retrieval, and 242+ Fabric patterns. NOTE: For due diligence, OSINT, or background checks, use OSINT skill instead.