Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
YouTube Security VideosGoogle Cloud Tech: Vibe coding in the pit lane 🏁(23.09.2026 um 01:00 Uhr)
Sichere ProgrammierungBuild an Explainable Vendor-Risk Gate in Node.js(23.09.2026 um 00:27 Uhr)
Sichere ProgrammierungFrom p=none to Enforcement: A Working Sequence for DMARC Rollout(23.09.2026 um 00:40 Uhr)
Sichere ProgrammierungWhen OPA's Bundle Loader Runs Past a `.manifest` Typo(23.09.2026 um 00:53 Uhr)
Sichere ProgrammierungGovernance Attack Surface Review: Bybit(23.09.2026 um 01:00 Uhr)
Linux Tipps & HardeningOpenShot video editor is now available as a snap(23.09.2026 um 00:09 Uhr)
KI & AI VideosAI Revolution: AI Robots Are Beating Humans Now(23.09.2026 um 00:32 Uhr)
YouTube Security VideosGoogle Cloud Tech: Vibe coding in the pit lane 🏁(23.09.2026 um 01:00 Uhr)
Sichere ProgrammierungBuild an Explainable Vendor-Risk Gate in Node.js(23.09.2026 um 00:27 Uhr)
Sichere ProgrammierungFrom p=none to Enforcement: A Working Sequence for DMARC Rollout(23.09.2026 um 00:40 Uhr)
Sichere ProgrammierungWhen OPA's Bundle Loader Runs Past a `.manifest` Typo(23.09.2026 um 00:53 Uhr)
Sichere ProgrammierungGovernance Attack Surface Review: Bybit(23.09.2026 um 01:00 Uhr)
Linux Tipps & HardeningOpenShot video editor is now available as a snap(23.09.2026 um 00:09 Uhr)
KI & AI VideosAI Revolution: AI Robots Are Beating Humans Now(23.09.2026 um 00:32 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

Build Your First MCP Server in 30 Minutes

MCP (Model Context Protocol) is an open standard that lets AI agents connect to external tools and data sources. Instead of building a custom integration for every AI client, you build one MCP server, and any compatible client (Claude,…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

MCP (Model Context Protocol) is an open standard that lets AI agents connect to external tools and data sources. Instead of building a custom integration for every AI client, you build one MCP server, and any compatible client (Claude, Cursor, Windsurf, custom agents) can plug into it.



This guide walks you through building an MCP server from scratch using TypeScript and the official SDK. By the end, you'll have a working server that Claude can connect to and query.



Prerequisites:




  • Node.js 18+ installed

  • TypeScript basics

  • A dataset or API you want to expose (we'll use a simple in-memory store)









1. Project setup



Create a new project and install the MCP SDK:




mkdir my-mcp-server && cd my-mcp-server
npm init -y
npm install @modelcontextprotocol/sdk express zod
npm install -D typescript @types/express @types/node
npx tsc --init






Update your tsconfig.json with these essentials:




{
"compilerOptions": {
"target": "ES2022",
"module": "Node16",
"moduleResolution": "Node16",
"outDir": "./dist",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true
}
}






Your project structure will look like this:




my-mcp-server/
├── src/
│ ├── server.ts ← entry point
│ └── tools/
│ └── customers.ts ← your first tool
├── tsconfig.json
└── package.json









2. Create the server



The MCP server is an Express app with the SDK wired into it. The SDK handles protocol negotiation, JSON-RPC framing, and tool discovery. You just register your tools and pick a transport.




// src/server.ts
import express from 'express'
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'
import {
StreamableHTTPServerTransport
} from '@modelcontextprotocol/sdk/server/streamableHttp.js'
import { registerTools } from './tools/customers.js'

const app = express()
app.use(express.json())

// Health check
app.get('/health', (req, res) => res.sendStatus(200))

// MCP endpoint
app.post('/mcp', async (req, res) => {
// Create a fresh server + transport per request (stateless)
const server = new McpServer({
name: 'my-mcp-server',
version: '1.0.0',
})

// Register all tools on this server instance
registerTools(server)

const transport = new StreamableHTTPServerTransport({
sessionIdGenerator: undefined, // stateless
enableJsonResponse: true,
})

await server.connect(transport)
await transport.handleRequest(req, res, req.body)

res.on('finish', () => {
transport.close()
server.close()
})
})

// Reject session-based requests (we're stateless)
app.get('/mcp', (req, res) => res.sendStatus(405))
app.delete('/mcp', (req, res) => res.sendStatus(405))

const PORT = process.env.PORT || 4006
app.listen(PORT, () => {
console.log(`MCP server running on port ${PORT}`)
})







Why stateless? By creating a fresh server per request with no session tracking, any instance behind a load balancer can handle any request. No sticky sessions, no shared session store. Start here and only add sessions if you need server-initiated push.







3. Add your first tool



A tool is a function the AI can call. It has a name, a description (which the AI reads to decide when to call it), an input schema (validated with Zod), and a handler.



Let's build a simple customer lookup tool:




// src/tools/customers.ts
import { z } from 'zod'
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'

// Sample data — replace with your database
const customers = [
{ id: '1', name: 'Alice Chen', company: 'Acme Corp', plan: 'enterprise' },
{ id: '2', name: 'Bob Rivera', company: 'StartupXYZ', plan: 'starter' },
{ id: '3', name: 'Carol Zhang', company: 'BigCo Inc', plan: 'pro' },
{ id: '4', name: 'David Park', company: 'TechFlow', plan: 'enterprise' },
]

export function registerTools(server: McpServer) {

// Tool 1: Search customers by name
server.tool(
'searchCustomers',
'Search customers by name. Returns matching customers '
+ 'with their company and plan.',
{
query: z.string().describe('Name or partial name to search'),
},
async ({ query }) => {
const results = customers.filter(c =>
c.name.toLowerCase().includes(query.toLowerCase())
)

if (!results.length) {
return { content: [{ type: 'text', text: 'No customers found.' }] }
}

const table = results
.map(c => `| ${c.name} | ${c.company} | ${c.plan} |`)
.join('\n')

return {
content: [{
type: 'text',
text: `| Name | Company | Plan |\n|---|---|---|\n${table}`,
}],
}
}
)

// Tool 2: Get customer by ID
server.tool(
'getCustomer',
'Get detailed information about a specific customer by ID.',
{
customerId: z.string().describe('The customer ID'),
},
async ({ customerId }) => {
const customer = customers.find(c => c.id === customerId)

if (!customer) {
return { content: [{ type: 'text', text: 'Customer not found.' }] }
}

return {
content: [{
type: 'text',
text: [
`**${customer.name}**`,
`Company: ${customer.company}`,
`Plan: ${customer.plan}`,
].join('\n'),
}],
}
}
)
}






A few things to notice:




  • The description is critical. The AI reads it to decide when to call your tool. Be specific about what the tool does and what it returns.

  • The input schema uses Zod. The SDK validates inputs automatically and returns errors to the AI if validation fails.

  • The handler returns a content array with text blocks. Markdown formatting works well because the AI renders it for the user.






4. Run it



Add a build and start script to package.json:




{
"scripts": {
"build": "tsc",
"start": "node dist/server.js",
"dev": "tsc --watch & node --watch dist/server.js"
}
}









npm run build && npm start
# MCP server running on port 4006






Test it with a quick curl:




curl -X POST http://localhost:4006/mcp \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {},
"clientInfo": { "name": "test", "version": "1.0" }
}
}'










5. Connect Claude



To connect your server to Claude Desktop, add it to your Claude configuration file:




// ~/.claude/claude_desktop_config.json
{
"mcpServers": {
"my-server": {
"url": "http://localhost:4006/mcp"
}
}
}






Restart Claude Desktop. You should see your tools listed in the tools menu. Try asking Claude: "Search for a customer named Alice" and watch it call your searchCustomers tool.



For Claude Code (CLI), add it to your project's .mcp.json:




{
"mcpServers": {
"my-server": {
"type": "url",
"url": "http://localhost:4006/mcp"
}
}
}









6. Add more tools



You now have the pattern. To add more tools, create new files in src/tools/ and register them on the server. Some guidelines from building production MCP servers:






Write good descriptions



The AI picks tools based on the description. A vague description like "Get data" will confuse the model. Be specific:




// Bad — the AI doesn't know when to use this
'Get data from the system'

// Good — clear about what, when, and what it returns
'Search customers by name. Returns matching customers '
+ 'with their company name and subscription plan. '
+ 'Use this when the user asks about a specific customer '
+ 'or wants to find customers by name.'









Start broad, split later



It's tempting to create many small, focused tools. In practice, the AI is better at using fewer, broader tools. Start with one tool per entity (e.g. getCustomer returns everything about a customer) and only split when responses are too large for the context window.






Return markdown



Markdown tables, bold text, and lists render well in AI clients. Structure your responses so the AI can present them clearly to the user. Include enough context that the AI doesn't need to call another tool to make sense of the data.






7. Add authentication



The server above has no auth. Anyone who can reach it can call your tools. For local development that's fine. For anything else, you need authentication.



MCP uses OAuth 2.0. The SDK provides middleware for the token exchange. You provide the identity verification and consent flow.




// src/auth.ts
import {
mcpAuthRouter,
requireBearerAuth,
} from '@modelcontextprotocol/sdk/server/auth/router.js'

// The auth router handles /register, /authorize, /token
// You provide the OAuthServerProvider implementation
app.use(mcpAuthRouter({
provider: yourOAuthProvider,
issuerUrl: new URL('https://your-server.com'),
}))

// Protect MCP endpoints with bearer auth
app.use(
'/mcp',
requireBearerAuth({ verifier: yourOAuthProvider })
)






The OAuthServerProvider interface requires you to implement:





  • authorize() — Verify the user's identity. If your product already has sign-in, reuse that session instead of making users log in again.


  • challengeForAuthorization() — Redirect to your login page when there's no existing session.


  • exchangeAuthorizationCode() — Swap the auth code for access + refresh tokens.


  • exchangeRefreshToken() — Issue a new access token from a refresh token.


  • verifyAccessToken() — Validate the token on every request and return the user identity.




Tip: Store OAuth state (auth codes, refresh tokens, client registrations) in Redis, not in memory. In-memory state doesn't survive restarts and isn't shared across instances. Use atomic GET-and-DELETE for code exchange to prevent replay attacks.







8. Production checklist



Before deploying, walk through these:





  • Rate limit auth endpoints. Your /register, /authorize, and /token endpoints are public. Without rate limiting, they're open to abuse. A fixed-window limiter in Redis works well. Decide what happens when Redis is down (fail open? in-memory fallback?).


  • Wrap tool output. Your tools return data from your database. That data was entered by users who can type anything, including text that looks like instructions to the AI. Wrap responses in an explicit boundary marker.


  • Log safely. A database error might include the full SQL query with user data. Log the error class and code, never the message or query parameters.


  • Enforce tenancy. If your product is multi-tenant, extract the tenant ID from the verified token and include it in every database query. Never accept tenant ID as tool input.


  • Set token TTLs. Access tokens: 1 hour. Refresh tokens: 7 days. Service tokens (if calling internal APIs): 2 minutes. Short-lived tokens limit blast radius.


  • SSE heartbeats. If you use SSE for notifications, send a ping every 25-30 seconds. Load balancers kill idle connections after 30-60 seconds.









Going deeper



This guide gets you to a working server. Taking it to production involves more decisions: two-token auth patterns, stateless transport tradeoffs, rate limiter fallback strategies, prompt injection protection, and multi-tenant security.



I wrote a detailed post covering all of these based on building a production MCP server for a multi-tenant SaaS product:



👉 Building a Production MCP Server: Auth, Transport, and the Hard Parts






If you found this useful, follow me for more posts on building AI-powered products in production.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Build Your First MCP Server in 30 Minutes

Thematisch verwandte Begriffe: Build, Your, First, Server · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-58268 | SIPGO is a library for writing SIP services in the GO language. Prior to…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick