mcp-server
The MCP Server is a comprehensive server implementation of the Model Context Protocol designed for real-time communication with AI models. It features a clean architecture, extensive tooling, and multiple transport options. Built for developers, it offers logging, error handling, and is highly extensible.
MCP Server
A robust server implementation of the Model Context Protocol (MCP) that supports multiple transport methods (SSE and STDIO) for real-time communication with AI models.
π Features
- Full MCP Implementation: Complete and standard-compliant implementation of the Model Context Protocol
- Multiple Transports: Seamless communication via SSE (Server-Sent Events) and STDIO
- Robust Architecture: Built on Clean Architecture and SOLID principles for maintainability and extensibility
- Powerful Tooling: Easily extensible tools, resources, and prompts
- Developer-Friendly: Comprehensive logging, error handling, and testing support
ποΈ Architecture
The project follows a clean, layered architecture adhering to SOLID principles:
Layer | Responsibility | Components |
---|---|---|
Domain | Core business logic | Interfaces, Models, Entities |
Application | Use cases, application flow | Services, Use Cases, DTOs |
Infrastructure | Technical concerns | Implementations, Adapters, External services |
Presentation | User interface | API Controllers, HTTP endpoints |
Architectural Diagram
βββββββββββββββββββββββ βββββββββββββββββββββββ
β Presentation β β Application β
β Layer β β Layer β
β - Express API βββββββΆβ - Use Cases β
β - Controllers β β - Services β
βββββββββββββββββββββββ ββββββββββββ¬βββββββββββ
β
βΌ
βββββββββββββββββββββββ βββββββββββββββββββββββ
β Infrastructure β β Domain β
β Layer ββββββββ Layer β
β - Implementations β β - Interfaces β
β - Adapters β β - Models β
βββββββββββββββββββββββ βββββββββββββββββββββββ
π» Requirements
- Node.js 18 or higher
- Yarn or npm package manager
π¦ Installation
# Clone the repository
git clone https://github.com/your-username/mcp-server.git
cd mcp-server
# Install dependencies
yarn install
# Build the project
yarn build
π Running the Server
# Start the server
yarn start
# Build and start in one command (for development)
yarn rebuild
By default, the server runs on port 3001. You can configure this using the PORT
environment variable.
π Transport Options
The MCP server supports two transport methods:
Transport | Description | Use Case |
---|---|---|
SSE | Server-Sent Events over HTTP | Web applications, browser clients |
STDIO | Standard input/output streams | CLI tools, local applications |
π£οΈ API Endpoints
- SSE:
/sse
- Establish SSE connections for real-time communication - Messages:
/messages
- Send JSON-RPC messages to the server
π§ͺ Testing
Use the official MCP Inspector tool to test your server implementation:
- Build and start your MCP Server
yarn build
yarn rebuild # if using SSE transport (builds & starts)
# OR
yarn start # manual start
- Run the inspector against your server
npx @modelcontextprotocol/inspector node build/index.js
- Access to Inspecto UI http://127.0.0.1:6274 π
π§© Extending Functionality
Adding a New Tool
// tools/custom/my-tool.ts
import { z } from "zod";
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { ITool } from "../core/domain/interfaces/tool.interface.js";
import { ILogger } from "../core/domain/interfaces/logger.interface.js";
export class MyTool implements ITool {
private readonly logger: ILogger;
constructor(logger: ILogger) {
this.logger = logger;
}
public register(server: McpServer): void {
server.tool(
"my-tool",
"Description of my tool",
{
param1: z.string().describe("Parameter description"),
},
async ({ param1 }) => {
this.logger.info(`MyTool called with param1: ${param1}`);
return {
content: [
{
type: "text",
text: `Result: ${param1}`,
},
],
};
},
);
this.logger.info("MyTool registered");
}
}
Adding a New Resource
// resources/custom/my-resource.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { IResource } from "../core/domain/interfaces/resource.interface.js";
import { ILogger } from "../core/domain/interfaces/logger.interface.js";
export class MyResource implements IResource {
private readonly logger: ILogger;
constructor(logger: ILogger) {
this.logger = logger;
}
public register(server: McpServer): void {
server.resource('my-resource', 'my-data.json', async () => {
this.logger.info('My resource accessed');
return {
contents: [
{
uri: 'my-data.json',
text: JSON.stringify({ key: "value" }, null, 2),
mimeType: 'application/json',
},
],
};
});
this.logger.info('My resource registered');
}
}
Adding a New Prompt
// prompts/custom/my-prompt.ts
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { IPrompt } from "../core/domain/interfaces/prompt.interface.js";
import { ILogger } from "../core/domain/interfaces/logger.interface.js";
export class MyPrompt implements IPrompt {
private readonly logger: ILogger;
constructor(logger: ILogger) {
this.logger = logger;
}
public register(server: McpServer): void {
server.prompt(
'my-prompt',
'Description of my prompt',
() => {
this.logger.info('My prompt accessed');
return {
messages: [
{
role: 'user',
content: {
type: 'text',
text: 'Initial user message',
},
},
{
role: 'assistant',
content: {
type: 'text',
text: 'Initial assistant response',
},
},
],
};
},
);
this.logger.info('My prompt registered');
}
}
π SOLID Principles Applied
Principle | Implementation |
---|---|
Single Responsibility | Each class has one clear responsibility |
Open/Closed | System can be extended without modifying existing code |
Liskov Substitution | Derived types can be substituted for their base types |
Interface Segregation | Specific interfaces for specific clients |
Dependency Inversion | High-level modules depend on abstractions |
π License
This project is licensed under the MIT License - see the LICENSE file for details.