Skip to main content

Custom MCP Server

Introduction

Have you ever wanted your AI assistant to instantly understand and interact with your application's data? Instead of manually wiring up APIs or building custom integrations, you can use the Model Context Protocol (MCP) to provide your LLM (Large Language Model) with direct, secure access to your backend systems. This article is based on my personal effort to explore MCP as part of a pet project, aiming to learn how to make databases and tools accessible to AI assistants for richer, more interactive development workflows.

What is MCP?

The Model Context Protocol (MCP) is an open standard developed by Anthropic. Its goal is to connect AI assistants (like Claude or ChatGPT) to external data sources and tools in a secure, standardized way. MCP replaces fragmented integrations with a single protocol, making it easier to build AI-powered applications that interact with your data.

MCP Server Capabilities: Tools, Resources, and Prompts

An MCP server acts as a bridge between AI models and your backend systems. It provides three main capabilities:

  • Tools: Functions that AI models can call to perform specific actions, such as running a search, updating data, triggering a workflow, or calling external APIs. Use tools for operations that modify data, complex business logic, or external API calls. AI assistants will typically ask for confirmation before executing any tools.
  • Resources: Data sources that AI can query, similar to GET endpoints in REST APIs. Use resources to expose any information that could be useful for AI assistant context in your workflow. AI assistants will typically fetch resources when they conclude that it may be useful for extending the context.
  • Prompts: Pre-defined message templates to guide the AI’s interactions and queries. MCP servers can also provide prompt templates for curated, reusable prompts that are essential for a given workflow. AI assistant or user will be able to use that prompts when interacting with LLM.

MCP Architecture Overview

Here’s a diagram to visualize how the components interact:

info

In my case, the Host Application was Claude Code used from terminal integrated with Visual Studio Code.
MCP server was implementing resources that were queried from local MongoDB instance.

Use case: allowing Claude Code to access development database

In that use case, MCP streamlines implementation, testing, and debugging by allowing AI assistants to directly access and inspect live data. This enables more effective troubleshooting and validation beyond traditional log analysis or static code review.

Enhanced Debugging and Testing

When tests fail or unexpected behavior occurs, AI assistance powered by MCP can query the database to determine what actually happened. This allows for:

  • Direct inspection of live data
  • Verification of code changes
  • Automated suggestions for code fixes

Accelerating Implementation

Going beyond accessing application DB, MCPs can improve the development phase by exposing a variety of other data sources to AI assistants. These resources can include:

  • Project documentation
  • Task management systems
  • Schema repositories
  • Git history
  • API specification repositories

Practical Benefits for Agentic AI Tools

With access to these resources, agentic AI tools like Claude Code can:

  • Instantly retrieve relevant documentation and requirements
  • Check issue descriptions in task management systems
  • Validate data models and API contracts
  • Accelerate onboarding and reduce context switching
  • Inspect data samples directly in the database

MCPs in Agentic Systems

MCPs are essential not only for coding workflows but also for any kind of agentic systems. They can be leveraged during both development and runtime to provide AI-powered functionality to users, making AI-powered workflows capable to do things in real world.

Quick Tutorial: Adding MCP to Cloud Code

You can easily add MCP support to your Cloud Code project to enable your AI assistant to access live application context. Here’s a simple step-by-step guide.

  1. Init MCP Server project
tip

You can ask Claude Code itself to generate the MCP server code for your specific use case. Just describe what you want to expose, and let the AI do the heavy lifting! You can try with simple prompts like "Create MCP server for my database" or "Create MCP server for that API" or to provide more advanced context file.

If you are building with node.js, use this SDK:

npm install @modelcontextprotocol/server

There are also MCP SDKs for other languages.

import { Server } from '@modelcontextprotocol/sdk/server/index.js';

// this server wil be running locally, so stdio protocol is enough
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import {
ListResourcesRequestSchema,
ReadResourceRequestSchema,
} from '@modelcontextprotocol/sdk/types.js';

// this server will get resources from MongoDB
import { MongoClient, ObjectId } from 'mongodb';

class MyMcpServer {
private server: Server;
private mongoClient: MongoClient;

constructor() {
this.server = new Server(
{
name: 'my-mcp-server',
version: '1.0.0',
},
{
capabilities: {
resources: {}
// This server will not be exposing any tools or prompts, only resources
},
}
);
// TODO: implement resource definitions and handlers
}

async run() {
const transport = new StdioServerTransport();
await this.server.connect(transport);
}
}

const server = new MyMcpServer();
server.run();
  1. Define Resources in the server codebase

    • Create resource definitions that describe how to access your data. For example:
     this.server.setRequestHandler(ListResourcesRequestSchema, async () => {
    return {
    resources: [
    {
    uri: 'events://list',
    mimeType: 'application/json',
    name: 'Sports Events',
    description: 'List of all sports events in the database. Query params: ?fields=field1,field2 (select specific fields), ?limit=N (limit results), ?offset=N (skip N results), ?year=YYYY (filter by year), ?type=eventType (filter by event type), ?name=pattern (filter by name pattern)'
    },
    {
    uri: 'results://{event_name}',
    mimeType: 'application/json',
    name: 'Event Results by Event',
    description: 'Results for a specific event (replace {event_name} with actual event name). Query params: ?limit=N (limit results), ?offset=N (skip N results)'
    }
    ]
    };
    });
  2. Implement resource handlers

Implement resource handlers, for example:

    this.server.setRequestHandler(ReadResourceRequestSchema, async (request) => {
const { uri } = request.params;

try {
await this.mongoClient.connect();

// Parse URI and query parameters
const [baseUri, queryString] = uri.split('?');
const queryParams = this.parseQueryParams(queryString || '');

if (baseUri === 'events://list') {
// TODO implement getEventsResource method to get data from DB
return await this.getEventsResource(queryParams);
} else if (baseUri.startsWith('results://')) {
const path = baseUri.replace('results://', '');
const parts = path.split('/');
const eventName = parts[0];
// TODO implement getResultsResource
return await this.getResultsResource(eventName, queryParams);
} else {
throw new Error(`Unknown resource: ${baseUri}`);
}
} catch (error) {
return {
contents: [
{
uri: uri,
mimeType: 'text/plain',
text: `Error: ${error instanceof Error ? error.message : String(error)}`
}
]
};
}
});
  1. Add MCP server to Claude Code
claude mcp add my-mcp-server -- npm start --prefix {path to directory with your MCP server}

after running that command, test if MCP was added:

claude mcp list
  1. Test Your Integration

Type /mcp in Claude Code session. If your MCP defines any tools or prompts, you will see them. Prompts wil be visible directly on the commands list, tolls will be visible when you will select MCP server from the list and "Enter" it.

When you "Enter" given server from Claude Code, there will be also option to reconnect - has to be used in case changes were made to the server (or a new Claude Code session needs to be started, or the server needs to be run with npm run dev instead of npm start in point 4, for hot reload when server implementation changes).

To test usage of resources, prompt Claude Code to use your resources. It should automatically call your server once it concludes that access to a resource is needed for better context.

Conclusion

MCP servers are a foundational tool for feeding your AI assistant with live, actionable context. By exposing your database and backend systems as MCP resources, you enable your LLM to validate code changes, debug issues, and accelerate development. Instead of relying solely on logs or static analysis, your AI assistant can directly inspect the data that matters. As the ecosystem grows, MCP is quickly becoming the standard for AI-data integration in modern software engineering.

Resources