MCP Servers for AI Agents: Complete Tutorial (2026)
A comprehensive tutorial on building Model Context Protocol (MCP) servers for AI agents. Covers the MCP architecture, tools/resources/prompts primitives, building a custom server, connecting to Claude and other models, and production deployment patterns.
- MCP (Model Context Protocol) is an open standard that provides a universal interface between AI models and external tools, data sources, and prompts — replacing the fragmented landscape of custom function-calling integrations with a single protocol that works across models and frameworks.
- MCP servers expose three primitives: Tools (executable functions the model can invoke), Resources (data the model can read), and Prompts (reusable prompt templates) — each with typed schemas that enable automatic discovery and validation.
- Building a custom MCP server requires defining your tools with JSON Schema input parameters, implementing handler functions, and choosing a transport (stdio for local, SSE or streamable HTTP for remote) — the official SDKs for Python and TypeScript handle the protocol plumbing.
- MCP's security model uses capability-based access control where the client (host application) explicitly approves which tools a model can access, combined with input validation on the server side — never trust the model's tool call parameters without validation.
- Production MCP deployments typically use a gateway pattern where a single MCP client connects to multiple specialized servers (database, API, filesystem), each running in an isolated process with its own permissions and resource limits.
What Is MCP and Why Does It Matter?
The Model Context Protocol (MCP) is an open standard created by Anthropic that defines how AI models communicate with external tools, data sources, and prompt templates. Think of it as the USB-C of AI integrations: before MCP, every model provider had its own function-calling format, every tool required a custom integration for each model, and switching between providers meant rewriting all your tool definitions. MCP replaces this fragmentation with a single protocol that any model can speak and any tool can implement.
The problem MCP solves is fundamentally one of interoperability. Consider a practical scenario: you have built a set of internal tools for your engineering team — a database query tool, a deployment trigger, a monitoring dashboard reader, and a documentation search. Without MCP, connecting these tools to Claude requires writing Anthropic-format tool definitions. Connecting the same tools to GPT-4 requires rewriting them in OpenAI's function-calling format. Connecting them to an open-source model running on Ollama requires yet another format. And each time a provider updates their tool-use API, you update all your integrations.
With MCP, you implement each tool once as an MCP server. Any MCP-compatible client — Claude Desktop, a LangChain agent, a custom application using the MCP client SDK — can discover and use your tools without any provider-specific code. The server describes its capabilities using standard JSON Schema, and the client translates those capabilities into whatever format the underlying model expects. This separation means your tool implementations are model-agnostic and future-proof.
MCP operates on a client-server architecture with clear role separation. The MCP server is the tool provider — it exposes tools, resources, and prompts. The MCP client is the consumer — it connects to one or more servers, discovers their capabilities, and mediates between the AI model and the servers. The host application is the user-facing application (Claude Desktop, an IDE plugin, your custom agent) that contains the MCP client. This three-layer architecture keeps concerns separated: the server does not need to know which model is calling it, the client does not need to know the internal implementation of tools, and the host application does not need to understand the MCP protocol details.
As of 2026, MCP has become the de facto standard for AI tool integration. Claude supports it natively. LangChain and LangGraph have MCP client adapters. OpenAI's tools ecosystem is converging on MCP compatibility. The ecosystem of pre-built MCP servers covers databases (PostgreSQL, MySQL, SQLite), APIs (GitHub, Slack, Jira, Linear), file systems, web browsers, and hundreds of SaaS products. For most common integrations, you do not need to build a server from scratch — you configure an existing one. But understanding how to build custom servers is essential for connecting your proprietary tools and data sources. That is what this tutorial covers.
For a deeper comparison of MCP versus traditional function calling approaches, see our MCP vs Function Calling comparison. And if you are new to AI agents in general, our introduction to AI agents provides the foundational context.
The Three MCP Primitives: Tools, Resources, and Prompts
MCP organizes server capabilities into three distinct primitives, each serving a different purpose in the model-tool interaction. Understanding when to use each primitive is the key to designing effective MCP servers.
Tools are executable functions that the model can invoke to perform actions or computations. A tool has a name, a description (used by the model to decide when to invoke it), and an input schema defined in JSON Schema format. When the model decides to use a tool, it generates a tool call with arguments matching the schema. The MCP client forwards this call to the server, the server executes the function, and the result is returned to the model. Tools are the most commonly used MCP primitive — they are the equivalent of function calling in provider-specific APIs.
Examples of tools: query_database (takes a SQL query, returns results), create_jira_ticket (takes title, description, priority, returns ticket ID), deploy_service (takes service name and version, triggers deployment), send_email (takes recipient, subject, body, sends the email). The critical design principle for tools is that each tool should do one thing well. A tool called manage_database that handles queries, inserts, updates, deletes, and schema changes is too broad — the model will struggle to use it correctly. Break it into specific tools: query_database, insert_record, update_record, etc.
Resources are data sources that the model can read. Unlike tools, resources are not invoked with arbitrary parameters — they are identified by URIs and provide data in a read-only fashion. A resource has a URI pattern, a name, a description, and a MIME type. The model (or more precisely, the host application on behalf of the model) requests a resource by URI, and the server returns its content. Resources are ideal for exposing structured data that the model needs for context: configuration files, documentation, database schemas, API specifications, and knowledge bases.
Examples of resources: file:///project/README.md (project documentation), db://schema/users (the schema of the users table), api://docs/endpoints (API endpoint documentation), config://app/settings (application configuration). Resources support both static (content does not change) and dynamic (content is generated on request) patterns. A dynamic resource like metrics://dashboard/current could return the latest system metrics every time it is requested.
Prompts are reusable prompt templates that the server provides to the host application. A prompt has a name, a description, and an optional list of arguments. When the user or application selects a prompt, the server returns the expanded template with arguments filled in. Prompts are not sent directly to the model by the server — they are provided to the host application, which decides how to use them (typically by inserting them into the conversation).
Examples of prompts: code_review (takes a diff as argument, returns a structured code review prompt), sql_expert (returns a system prompt that configures the model as a SQL expert for your specific database schema), incident_response (takes an alert as argument, returns a prompt that guides the model through your incident response playbook). Prompts are particularly useful for encoding organizational knowledge and best practices into reusable templates that non-technical users can invoke.
The interaction between these primitives creates powerful patterns. A model might first read a resource (database schema) to understand the data structure, then use a tool (query_database) to retrieve specific data, guided by a prompt (sql_expert) that ensures it follows your organization's SQL conventions and security policies. Each primitive handles one aspect of the interaction cleanly.
One common design mistake is implementing everything as a tool. Reading data? Make it a resource. The difference matters because resources are explicitly read-only and discoverable by URI — the host application can prefetch them, cache them, and present them to the user in a resource browser. Tools, by contrast, imply side effects and require explicit model invocation. Using the right primitive for each capability makes your MCP server more predictable and easier to integrate.
Building a Custom MCP Server: Step by Step
Let us build a custom MCP server that provides tools for interacting with a project management system. We will use the official @modelcontextprotocol/sdk TypeScript SDK, though the Python SDK (mcp) follows the same patterns. This walkthrough focuses on architecture and design decisions rather than being a copy-paste code dump — you will understand why each piece exists so you can adapt it to your own use case.
The server will expose three tools: list_projects (returns all projects with status), create_task (creates a task in a project), and get_project_summary (returns a summary of a project's progress). It will also expose a resource for the project schema documentation and a prompt for sprint planning.
Step 1: Server initialization. Create an MCP server instance using new McpServer({ name: "project-manager", version: "1.0.0" }). The name and version are used for capability negotiation — the client knows what it is connecting to. Choose a descriptive name that clearly identifies your server's domain.
Step 2: Define tools. For each tool, you call server.tool(name, description, schema, handler). The schema is a Zod object (the TypeScript SDK uses Zod for runtime validation) that defines the input parameters. The handler is an async function that receives the validated parameters and returns a result. The result must conform to MCP's content format: an array of content blocks, each with a type (typically "text") and the content string.
For the create_task tool, the schema would include: project_id (string, required), title (string, required), description (string, optional), priority (enum of "low", "medium", "high", required), and assignee (string, optional). The handler validates that the project exists, creates the task in your project management API, and returns the created task's ID and URL. Critically, the handler should catch and handle errors gracefully — return an error content block with isError: true rather than letting exceptions propagate, so the model can understand what went wrong and potentially retry or adjust.
Step 3: Define resources. Resources are registered with server.resource(name, uri, handler). The URI can be a static string or a template with parameters (e.g., project://{projectId}/schema). The handler returns the resource content as a string with a MIME type. For our project schema documentation, the resource URI might be docs://project-manager/schema and the handler returns a markdown string describing the data model — projects have these fields, tasks have these fields, here are the valid statuses, etc. This resource helps the model understand your domain without consuming tool calls.
Step 4: Define prompts. Prompts are registered with server.prompt(name, description, argsSchema, handler). The sprint planning prompt takes a project_id argument and returns a structured prompt that guides the model through reviewing the project's backlog, identifying priorities, estimating effort, and proposing a sprint plan. The prompt can reference the project schema resource and suggest using the list_projects and get_project_summary tools as part of the workflow.
Step 5: Choose a transport. MCP supports multiple transports. StdioServerTransport communicates over stdin/stdout — the simplest option, used when the host application spawns the server as a child process. This is how Claude Desktop and most IDE integrations work. SSEServerTransport communicates over HTTP using Server-Sent Events — used for remote servers that clients connect to over the network. The newer StreamableHTTPServerTransport provides bidirectional streaming over HTTP and is becoming the preferred choice for remote deployments. For local development, use stdio. For production remote deployment, use streamable HTTP.
Step 6: Error handling and validation. Never trust the model's tool call parameters, even though the MCP SDK validates against your schema. The schema catches type errors, but your handler must validate business logic: Does the project exist? Does the user have permission? Is the assignee a valid team member? Return clear, actionable error messages — the model uses these to adjust its approach. A message like "Project 'xyz' not found. Available projects: abc, def, ghi" is infinitely more useful to the model than "Invalid project ID".
For a hands-on course that walks through building production MCP servers with real integrations, see our MCP Servers for Agents Course. The official MCP specification is also essential reading — it covers edge cases and advanced features (sampling, roots, capability negotiation) that go beyond this tutorial.
Connecting MCP Servers to Claude and Other Models
An MCP server is only useful when connected to a model through an MCP client. The connection patterns differ significantly depending on whether you are using a hosted application like Claude Desktop, a framework like LangChain, or building a custom agent.
Claude Desktop integration. Claude Desktop has native MCP support. You configure servers in the Claude Desktop configuration file (typically claude_desktop_config.json). Each server entry specifies the command to launch the server, any arguments, and environment variables. Claude Desktop spawns each server as a child process using stdio transport, discovers its capabilities, and makes them available to Claude. This is the fastest way to test an MCP server — add it to the config, restart Claude Desktop, and Claude can immediately use your tools. The configuration looks like: "project-manager": { "command": "node", "args": ["path/to/server.js"], "env": { "API_KEY": "..." } }.
LangChain/LangGraph integration. LangChain provides langchain-mcp-adapters that convert MCP tools into LangChain tool objects. You create an MCP client, connect it to your server, fetch the tools, and convert them to LangChain tools. These converted tools work exactly like any other LangChain tool — they can be bound to chat models, used in agents, and composed in LangGraph graphs. This is the recommended approach for building custom agents that use MCP tools because you get LangGraph's graph execution, checkpointing, and human-in-the-loop capabilities on top of MCP's tool standardization.
Custom client integration. If you are building your own agent framework or application, use the MCP client SDK directly. The client connects to a server, performs capability negotiation (the protocol handshake where client and server exchange supported features), and provides methods to list and call tools, read resources, and get prompts. The client handles serialization, deserialization, and transport details. Your application code works with typed tool definitions and results without dealing with the wire protocol.
Multi-server architectures. Production agents typically connect to multiple MCP servers simultaneously. Your agent might use a database server (PostgreSQL MCP), a communication server (Slack MCP), a documentation server (your custom knowledge base), and a deployment server (your CI/CD MCP). Each server runs in its own process with its own permissions. The MCP client aggregates tools from all connected servers and presents them to the model as a unified set. If two servers expose tools with the same name, the client prefixes them with the server name to avoid collisions.
When connecting servers, pay attention to tool count. Models have finite context windows and attention capacity. Connecting 10 servers with 20 tools each gives the model 200 tools to choose from — this degrades tool selection accuracy. Production systems address this with tool filtering: only expose tools relevant to the current task. Some frameworks support dynamic tool loading where the model first asks "what tools are available for database operations?" and the system loads just those tools. LangGraph's state-based routing can also conditionally expose different tool sets based on the current graph node.
Authentication patterns. MCP servers often need credentials to access external services. For stdio transport (local servers), pass credentials via environment variables in the server configuration — they are never sent over the wire. For HTTP transport (remote servers), use standard HTTP authentication (Bearer tokens, API keys in headers). The MCP specification includes a sampling capability that allows the server to request LLM completions from the client — this requires careful authentication because the server is initiating requests back to the client. Only enable sampling for trusted servers.
A practical pattern for team environments: run shared MCP servers as internal services with SSE or streamable HTTP transport, behind your corporate VPN or with OAuth authentication. Individual developers configure their Claude Desktop or custom agents to connect to these remote servers. This way, the team maintains a single set of tool implementations that everyone uses, with centralized logging, access control, and deployment. It is the MCP equivalent of internal APIs, and it works particularly well for database tools and deployment tools where you want centralized access control and audit logging.
Security Considerations for MCP Servers
MCP servers execute code based on AI model outputs. This is an inherently powerful capability and an inherently risky one. The model might be manipulated by prompt injection, it might hallucinate invalid parameters, or it might use tools in unintended ways. Robust security is not optional — it is the foundation that makes MCP servers safe to deploy.
Input validation is your first line of defense. The MCP SDK validates tool inputs against your JSON Schema, but schema validation only catches type and format errors. Your handler must validate business logic and enforce constraints the schema cannot express. If your query_database tool accepts SQL, validate that the query is read-only (no INSERT, UPDATE, DELETE, DROP). If your send_email tool accepts a recipient, validate against an allowlist of permitted domains. If your deploy_service tool accepts a version, validate that the version exists and has passed CI. Treat every tool call as untrusted input, exactly as you would treat user input in a web application.
Principle of least privilege. Each MCP server should have the minimum permissions needed for its tools. A database MCP server should connect with a read-only database user if it only exposes query tools. A GitHub MCP server should use a token scoped to only the repositories and permissions the agent needs. A filesystem MCP server should be restricted to specific directories. If a server is compromised — whether through a vulnerability in your code or through a prompt injection attack — limited permissions contain the blast radius.
Rate limiting and resource constraints. Models can generate tool calls rapidly, and a bug or prompt injection could trigger a tool call loop. Implement rate limiting at the server level: maximum calls per minute per tool, maximum concurrent calls, and maximum payload size. For tools that access external APIs, respect those APIs' rate limits and implement backpressure. For tools that query databases, set query timeouts and row limits. For tools that read files, set file size limits. These constraints prevent both accidental and malicious resource exhaustion.
Audit logging. Log every tool call with: timestamp, tool name, input parameters, result (or error), the thread/conversation ID, and the user identity if available. This audit trail is essential for debugging, compliance, and incident response. When something goes wrong — and in production it eventually will — you need to reconstruct exactly what happened. Store logs separately from the MCP server process (send them to your centralized logging system) so they survive server restarts and cannot be tampered with.
Prompt injection defense. When your MCP server returns tool results to the model, those results become part of the model's context. If a tool reads external data (web pages, emails, database records), that data could contain prompt injection attempts — text designed to manipulate the model into calling tools in unintended ways. Mitigate this by: (1) sanitizing tool results before returning them (strip or escape any instruction-like content), (2) using structured output formats (JSON, tables) rather than free text for tool results, and (3) implementing server-side guardrails that reject tool calls matching suspicious patterns regardless of what the model requests.
Transport security. For stdio transport (local servers), security is inherited from the OS process model — the server runs with the launching user's permissions. For HTTP transport (remote servers), enforce TLS (HTTPS only), authenticate clients with API keys or OAuth tokens, and restrict origins with CORS policies. Never expose MCP servers on public networks without authentication. Even on private networks, use authentication to prevent lateral movement in case of a network breach.
Secret management. MCP servers frequently need API keys, database credentials, and other secrets. Never hardcode secrets in server code. Use environment variables (for local stdio servers), your cloud provider's secret manager (AWS Secrets Manager, GCP Secret Manager, Azure Key Vault), or a dedicated solution like HashiCorp Vault. Rotate credentials regularly and ensure that credential access is logged. If your MCP server is distributed as an open-source package, provide clear documentation on how to configure credentials securely — many security incidents come from users following insecure setup guides.
For a comprehensive framework on evaluating the security of AI agent tools, see our guide on understanding AI agents. Security is not a one-time checklist — it is an ongoing practice that evolves as the MCP ecosystem matures and new attack vectors emerge.
Production Deployment Patterns for MCP Servers
Deploying MCP servers to production requires the same operational rigor as any other backend service, plus additional considerations unique to AI tool serving. Here are the deployment patterns that work at scale.
Pattern 1: Sidecar deployment. Run MCP servers as sidecar processes alongside your agent application. The agent spawns each server as a child process using stdio transport. This is the simplest deployment model — everything runs on the same machine, communication is local, and the lifecycle of servers is tied to the agent. Use this for single-machine deployments, development environments, and applications where the tool set is fixed and does not need independent scaling. The limitation is that you cannot scale servers independently of the agent, and a server crash can affect the agent process.
Pattern 2: Service-per-server deployment. Run each MCP server as an independent service (container, serverless function, or VM) with HTTP transport. The agent's MCP client connects to each server via HTTP. This enables independent scaling (scale your database MCP server separately from your email MCP server), independent deployment (update one server without restarting the agent), and isolation (a server crash does not affect other servers or the agent). This is the recommended pattern for production deployments with more than 2-3 servers or where reliability matters.
Pattern 3: MCP gateway. Deploy an MCP gateway service that sits between the agent and multiple MCP servers. The gateway handles routing, load balancing, authentication, rate limiting, and caching for all servers. The agent connects to a single gateway endpoint rather than managing connections to multiple servers. The gateway can also implement tool routing — analyzing the model's tool call request and routing it to the appropriate backend server, even if the model does not know about the server topology. This pattern adds operational complexity but provides a single control point for security, observability, and traffic management.
Containerization. Package each MCP server as a Docker container with a clear interface: HTTP port for the transport, environment variables for configuration, and a health check endpoint. Use multi-stage builds to keep images small — your MCP server probably does not need a full Node.js development environment in production. Pin your base image versions and scan for vulnerabilities. For servers that access external services, include the necessary client libraries but not the external service itself — your database MCP server connects to a separate database, it does not run one.
Observability. Production MCP servers need three pillars of observability: metrics (tool call count, latency percentiles, error rate, active connections), logs (structured logs with correlation IDs that link tool calls to agent threads), and traces (distributed traces that show the full journey from user request to agent reasoning to tool call to external API and back). Use OpenTelemetry for instrumentation — it integrates with all major observability platforms. Set up alerts on error rate spikes and latency degradation. Dashboard your tool usage patterns to understand which tools are most valuable and which are underused.
Scaling considerations. MCP servers are typically I/O bound (calling databases, APIs, reading files) rather than CPU bound. This means they scale well horizontally — add more instances behind a load balancer. For stdio-based servers, scaling means running more agent processes (each with its own server instances). For HTTP-based servers, use standard horizontal scaling with a load balancer. Stateless servers (most tool servers) scale trivially. Stateful servers (servers that maintain session state, caches, or connections) require sticky sessions or shared state stores.
CI/CD for MCP servers. Treat MCP servers as first-class services in your deployment pipeline. Automated tests should cover: schema validation (the tool schemas are valid and match your handler signatures), handler logic (unit tests for each tool handler), integration tests (the server starts, accepts connections, and serves tool calls end-to-end), and compatibility tests (the server works with the latest MCP SDK version). Deploy servers with canary or blue-green strategies — a broken MCP server silently degrades your agent's capabilities, which is harder to detect than a broken web page.
For a hands-on walkthrough of deploying MCP servers with Docker and cloud platforms, our MCP Servers for Agents Course covers the complete deployment lifecycle including monitoring, scaling, and incident response.
The MCP Ecosystem: Current State and What Is Next
The MCP ecosystem has grown rapidly since Anthropic open-sourced the specification. Understanding the current landscape and trajectory helps you make informed decisions about when to use existing servers versus building custom ones, and how to future-proof your MCP investments.
Official and community servers. The MCP specification repository maintains a registry of official and community-built servers. As of 2026, the ecosystem includes: database servers (PostgreSQL, MySQL, SQLite, MongoDB, Redis), version control (GitHub, GitLab), communication (Slack, Discord, email), project management (Jira, Linear, Asana, Notion), cloud infrastructure (AWS, GCP, Azure), web browsing (Puppeteer, Playwright), file systems (local, S3, GCS), and dozens of SaaS integrations. Before building a custom server, check the registry — there is a good chance someone has already built what you need, or at least a starting point you can fork.
SDK maturity. The official SDKs for Python and TypeScript are production-ready and actively maintained. Both support all three transports (stdio, SSE, streamable HTTP), all three primitives (tools, resources, prompts), and advanced features like sampling and roots. Community SDKs exist for Go, Rust, Java, and C#, though these vary in completeness and maintenance status. If you are building servers in a language without an official SDK, the protocol is well-documented enough to implement from scratch — it is JSON-RPC 2.0 over your chosen transport, which is straightforward to implement in any language with JSON and HTTP libraries.
Model support. Claude has the deepest MCP integration — both Claude Desktop and the Claude API support MCP natively. Other models interact with MCP through framework adapters: LangChain's MCP adapter converts MCP tools to LangChain tools usable with any supported model (GPT-4, Gemini, open-source models). The OpenAI Agents SDK is working on native MCP client support. Practically, this means you can build MCP servers today and use them with any major model through the appropriate client adapter.
Emerging patterns. Several patterns are emerging as the ecosystem matures. MCP server composition — building higher-level servers that aggregate and orchestrate multiple lower-level servers — is becoming common for complex domains. A "DevOps MCP server" might internally connect to GitHub, AWS, and PagerDuty MCP servers to provide a unified interface for deployment workflows. MCP server marketplaces are appearing where teams can publish and discover reusable servers. MCP-native monitoring tools are being built that understand the protocol and can provide tool-level observability without custom instrumentation.
What is coming next. The MCP specification continues to evolve. Active areas of development include: streaming tool results (returning results incrementally for long-running tools), tool composition hints (metadata that helps models understand which tools work well together), enhanced security primitives (fine-grained capability tokens, OAuth 2.0 integration for server-to-server authentication), and improved resource subscriptions (servers pushing resource updates to clients in real-time). The specification process is open — you can track and contribute to proposals on the MCP GitHub repository.
The strategic implication is clear: investing in MCP is a safe bet. The protocol is open, the adoption is broad, and the ecosystem is growing. Whether you are building tools for internal use, publishing tools for the community, or integrating third-party tools into your agents, MCP provides a stable foundation that will not lock you into any single model provider or framework. Start with the pre-built servers for your common integrations, build custom servers for your proprietary tools, and architect your agent to discover and use MCP tools dynamically — this gives you maximum flexibility as the ecosystem evolves.
FAQ
What is the difference between MCP tools and traditional function calling?
Traditional function calling is model-specific: you define tools in OpenAI's format for GPT, Anthropic's format for Claude, etc. MCP is a universal protocol — you define tools once in an MCP server, and any MCP-compatible client can use them with any model. MCP also adds Resources (read-only data) and Prompts (reusable templates) that function calling does not have, plus standardized discovery, transport, and security. Think of function calling as a feature of a specific model API, and MCP as an interoperability standard across all models.
Do I need to run MCP servers locally or can they be remote?
Both. MCP supports stdio transport for local servers (spawned as child processes, used by Claude Desktop and IDE integrations) and HTTP transports (SSE and streamable HTTP) for remote servers. Production deployments typically use remote servers running as independent services, while development often uses local stdio servers for simplicity. You can mix both — some servers local, some remote — in a single agent configuration.
How many MCP tools can a model handle effectively?
There is no hard protocol limit, but practical limits come from the model's context window and tool selection accuracy. Most models work well with 10-30 tools. Beyond 50 tools, selection accuracy degrades noticeably. For large tool sets, use dynamic tool loading (only expose tools relevant to the current task), or group tools behind a router that the model queries first. Quality of tool descriptions matters more than quantity — well-described tools with clear names are selected accurately even in larger sets.
Is MCP only for Claude or does it work with other models?
MCP works with any model through the appropriate client adapter. Claude has native MCP support (deepest integration). LangChain provides MCP adapters that convert MCP tools to LangChain tools, which work with GPT-4, Gemini, Llama, and any other LangChain-supported model. OpenAI is adding native MCP support. The protocol is model-agnostic by design — your MCP servers work with any model, present and future.
What programming languages can I use to build MCP servers?
Official SDKs are available for Python and TypeScript, both production-ready. Community SDKs exist for Go, Rust, Java, C#, and Ruby. Since MCP uses JSON-RPC 2.0 over standard transports (stdio, HTTP), you can implement a server in any language — the protocol is simple enough to implement from scratch if no SDK exists for your language. For most teams, Python or TypeScript SDKs are the fastest path to a working server.