How to Build an MCP Server: SDK vs OpenAPI
Learn how to build an MCP server: define tools, choose local or remote transport, add auth and tests, then compare custom code with OpenAPI conversion.
The short answer
To build an MCP server, start with one user workflow, describe a small set of tools around that workflow, validate every input, connect the tools to an existing backend, and test both allowed and denied behavior in a real MCP client. Then choose a deployment model: local stdio for a trusted single-user workflow, or remote HTTP with authentication and operational controls for shared access.
Do not begin with a framework or an MCP server generator. First decide whether you need new server behavior at all.
- Build a custom MCP server when a useful tool must orchestrate several systems, transform data, enforce domain-specific rules, or expose MCP resources and prompts.
- Reuse an existing OpenAPI API when the desired actions already exist as well-designed REST operations. An OpenAPI-to-MCP layer can publish those operations without creating and maintaining a second application.
This guide explains both paths. datamcp provides hosted MCP access for PostgreSQL and OpenAPI sources; it does not host arbitrary custom MCP server code. If your workflow requires a custom implementation, use an official MCP SDK and operate that service yourself or through an appropriate application host.
Build an MCP server or reuse OpenAPI?
The fastest implementation is often the one you do not need to build.
| Question | Custom MCP server | OpenAPI-to-MCP conversion |
|---|---|---|
| Starting point | A new agent capability | An existing REST API and OpenAPI 3.x contract |
| Tool design | Purpose-built around user goals | Derived from discoverable API operations |
| Multi-step workflows | Implemented inside one tool | Usually composed by the client across API calls |
| Transformations | Arbitrary code and validation | Limited to the API and conversion layer |
| MCP capabilities | Tools, resources, prompts | API-focused discovery and call tools |
| Hosting | You choose and operate it | Provider-managed in a hosted conversion model |
| Authentication | You implement the required model | Limited to supported client and upstream methods |
| Maintenance | Code, dependencies, protocol, deployment | Specification accuracy, API compatibility, provider behavior |
Use the OpenAPI-to-MCP versus custom server comparison for the complete architecture decision. Continue with the steps below when custom code is justified.
Step 1: Define one user workflow
Write the workflow as a result, not as a technology:
- “Find an order, verify its payment state, and open a support case.”
- “Read a repository issue and prepare a release checklist.”
- “Inspect an account and explain why access was denied.”
Avoid a vague objective such as “give the model access to our backend.” That produces a large tool surface with unclear permissions and unpredictable results.
For the first version, record:
- who will use the server
- which MCP clients must connect
- which backend systems are required
- which reads and writes are allowed
- which data must never be returned
- how access is revoked
- what evidence is needed after a failure
A narrow workflow makes tool design, authorization, tests, and incident response much easier.
Step 2: Design tools around user intent
A tool should represent a meaningful action with a stable name, a concise description, a bounded input schema, and a predictable result.
Prefer:
get_order_status(order_id)
create_support_case(order_id, reason)
over:
run_backend_request(method, path, body)
The generic request tool exposes implementation details and asks the model to reconstruct application policy. Purpose-built tools let the server validate identifiers, enforce allowed transitions, and return only the fields needed by the workflow.
For every tool, define:
- Name: stable, verb-first, and distinct from neighboring tools.
- Description: explain when the tool should and should not be used.
- Inputs: reject unknown fields, invalid formats, oversized values, and ambiguous identifiers.
- Output: return bounded structured data instead of an unfiltered backend response.
- Side effects: state whether the tool reads, creates, updates, deletes, sends, or publishes anything.
- Permission: identify the user, role, tenant, project, and environment required for execution.
Tool descriptions are part of the runtime interface. Treat them like API documentation and test whether an MCP client selects the correct tool from realistic prompts.
Step 3: Choose local or remote transport
The deployment model determines where credentials live and who must operate the server.
Local MCP server
A local server commonly runs as a child process beside the client and communicates over stdio.
Choose local when:
- one trusted developer uses the server
- the backend is local or available only from that machine
- offline operation matters
- the user is comfortable managing local dependencies and secrets
The client configuration must specify the command, arguments, and environment. Every machine becomes a separate deployment that needs updates and troubleshooting.
Remote MCP server
A remote server exposes MCP over HTTP and can serve several users and clients from one maintained deployment.
Choose remote when:
- users need a stable shared endpoint
- backend credentials should not be copied to every client
- authentication and revocation must be centralized
- one team owns updates, monitoring, and availability
Remote operation adds public transport security, authentication, authorization, rate limiting, logging, deployment, and incident response. The MCP server hosting guide compares those responsibilities in detail.
Step 4: Implement authentication and backend boundaries
Authentication proves who is calling. Authorization decides what that caller may do. Backend permissions limit what the server can do even when its own policy fails.
Keep these boundaries separate:
MCP client identity → MCP server policy → backend identity and permissions
For a remote server:
- validate every protected request
- bind tokens to the intended resource
- expire and revoke credentials
- authorize each tool and resource independently
- keep backend credentials out of prompts and client configuration
- use a dedicated least-privilege backend identity
- preserve tenant and object-level authorization inside the application
Do not treat a successful OAuth login as permission to call every tool. The MCP authentication and authorization guide separates client identity, OAuth scopes, MCP policy, and backend grants.
Step 5: Add limits, errors, and observability
Production behavior includes failure paths, not only successful handlers.
Set explicit limits for:
- input length and array size
- backend timeout
- returned rows or objects
- response payload size
- retries and concurrency
- expensive queries or external calls
Return errors that help the client recover without leaking credentials, stack traces, internal hostnames, or sensitive records. Distinguish invalid input, authentication failure, permission denial, missing data, rate limiting, dependency failure, timeout, and internal error.
Record enough structured context to investigate a request:
- request and session identifiers
- authenticated actor and client
- selected tool
- policy decision
- backend target
- duration and outcome
- redacted error category
Do not log secrets by default. Raw prompts, tool arguments, SQL, API bodies, and results may contain customer data. The MCP logging and observability guide provides a practical event model and redaction checklist.
Step 6: Test with a real MCP client
Unit tests for handlers are necessary but not sufficient. Test the complete path from client discovery to backend enforcement.
Use a matrix like this:
| Test | Expected result |
|---|---|
| List capabilities | Only intended tools, resources, and prompts appear |
| Valid read | Bounded result with the expected fields |
| Invalid input | Clear validation error; backend is not called |
| Forbidden operation | Permission denial at the MCP layer |
| Backend denial | Least-privilege backend identity rejects the operation |
| Cross-tenant identifier | No data disclosure and no side effect |
| Timeout | Controlled error without runaway retries |
| Revoked credential | Existing client configuration stops working |
| Oversized response | Result is bounded or rejected safely |
Also test tool selection. Give the client prompts that are incomplete, ambiguous, adversarial, and outside the intended workflow. A server is not ready merely because a manually selected tool succeeds.
Step 7: Deploy and own the server
Before publishing a remote endpoint, assign ownership for:
- runtime and dependency updates
- MCP protocol compatibility
- authentication configuration
- backend credential rotation
- monitoring and alert response
- backups and recovery where state exists
- abuse handling and rate limits
- vulnerability remediation
- user offboarding and revocation
- incident communication
Pin dependencies, automate tests, separate development and production credentials, and use a staged deployment path. Document how to disable the server without waiting for a new application release.
If no team owns those responsibilities, the system is not a managed service; it is an unattended integration with production access.
MCP server builder and generator tradeoffs
An MCP server builder or generator can reduce boilerplate. It cannot decide the correct tool boundary, authorization model, backend permissions, data policy, or operational owner.
Evaluate generated output as production code:
- Who maintains the generator and generated dependencies?
- Does regeneration overwrite manual security fixes?
- Are inputs validated strictly?
- Where are backend secrets stored?
- Is authentication included or left to the deployer?
- Can tool visibility and permissions be narrowed?
- How are errors and sensitive fields logged?
- Can the server be tested and upgraded without the generator?
Generated code is useful when the result is small, reviewable, and owned by the team. It is risky when a large tool surface is published directly from an internal API without design or permission review.
When OpenAPI to MCP is the better path
Do not create duplicate handler code when an existing REST API already owns the required behavior and authorization.
OpenAPI conversion is a strong fit when:
- the API publishes an accurate OpenAPI 3.x specification
- required AI actions map to existing operations
- the API already validates users, tenants, objects, and business rules
- a supported service credential is sufficient
- the specification and API are reachable by the hosted layer
- MCP tools are enough and custom resources or prompts are not required
datamcp can connect a public OpenAPI 3.x specification or supported Swagger UI or Redoc page, store supported upstream credentials, publish a hosted MCP endpoint, and restrict visible operations and HTTP methods per link. It exposes schema-aware discovery and call tools rather than generating one custom tool for every endpoint.
It is not the right path for private-network deployment, arbitrary custom server code, upstream OAuth lifecycle, mTLS, or workflows that must orchestrate several API calls inside one atomic tool.
Follow the Swagger to MCP tutorial to test an existing API, or review the OpenAPI to MCP product page for the current hosted boundary.
Cost checklist: build versus managed conversion
Custom code has two costs: implementation and ownership.
Estimate:
- tool and schema design
- backend integration
- authentication and authorization
- hosting and environments
- logs, metrics, alerts, and incident handling
- security review and dependency updates
- client compatibility testing
- ongoing changes to workflows and protocol behavior
A hosted conversion has a smaller code burden but a narrower capability boundary. Evaluate provider pricing, supported credentials, network reachability, specification quality, policy controls, and the migration path if requirements later demand custom code.
The correct choice is the least complex architecture that satisfies the workflow and security boundary—not the option with the shortest initial demo.
Build MCP server FAQ
What is the fastest way to build an MCP server?
For a custom capability, start with an official MCP SDK, one read-only tool, strict input validation, and a local client test. If the capability already exists as a REST operation, connecting its OpenAPI contract may be faster than creating another service.
Do I need an MCP server generator?
No. A generator can create scaffolding, but the important work is tool design, permissions, backend integration, testing, and operations. Use generated code only when your team can review and maintain the result.
Should an MCP server be local or remote?
Use local stdio for a trusted single-user workflow or local-only backend. Use remote HTTP when several users need a maintained shared endpoint with centralized authentication and revocation.
Can OpenAPI generate a complete custom MCP server?
OpenAPI describes REST operations, not every possible MCP resource, prompt, workflow, or domain transformation. Conversion works when API operations already match the desired tools. Build custom code when the useful capability is new behavior.
Does datamcp host custom MCP server code?
No. datamcp currently creates hosted MCP access for PostgreSQL and OpenAPI sources. It does not run arbitrary custom MCP implementations or proxy arbitrary third-party MCP servers.
Next step
If the required workflow already exists in a REST API, connect a reduced OpenAPI surface and test one read-only operation. If the workflow requires custom orchestration, begin with one official SDK tool, a least-privilege backend identity, and the denial tests from this guide.
The OpenAPI-to-MCP versus custom server comparison provides the decision framework; the production MCP security checklist covers the controls to verify before real data is connected.
Related articles
OpenAPI to MCP vs Custom MCP Server: How to Choose
Compare OpenAPI-to-MCP conversion with a custom MCP server across tool design, authentication, workflows, hosting, maintenance, security, and cost.
TutorialHow to Turn Swagger into an MCP Server
Turn an OpenAPI 3.x or Swagger documentation URL into a hosted remote MCP endpoint. Configure auth, read-only access, and test real API calls.
Already have an OpenAPI contract?
Connect the specification and publish a hosted MCP endpoint without maintaining custom server code.
Create OpenAPI MCP linkExplore OpenAPI to MCP · Questions? Read the docs or view pricing.