Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
240 changes: 206 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@

![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)
![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-3178C6)
![MCP](https://img.shields.io/badge/MCP-1.7+-green)

A CLI tool to quickly get started building your very own MCP (Model Context Protocol) server.
A CLI tool to quickly get started building your very own MCP (Model Context Protocol) server using FastMCP

## 📋 Usage

Expand All @@ -13,23 +12,23 @@ A CLI tool to quickly get started building your very own MCP (Model Context Prot
npx @mcpdotdirect/create-mcp-server

# Or with npm
npm init @mcpdotdirect/create-mcp-server
npm init @mcpdotdirect/mcp-server
```

## 🔭 What's Included

The template includes:

- Basic server setup with both stdio and HTTP transport options
- Basic server setup with both stdio and HTTP transport options using FastMCP
- Structure for defining MCP tools, resources, and prompts
- TypeScript configuration
- Development scripts and configuration

## ✨ Features

- **FastMCP**: Built using the FastMCP framework for simpler implementation
- **Dual Transport Support**: Run your MCP server over stdio or HTTP
- **TypeScript**: Full TypeScript support for type safety
- **MCP SDK**: Built on the official Model Context Protocol SDK
- **Extensible**: Easy to add custom tools, resources, and prompts

## 🚀 Getting Started
Expand Down Expand Up @@ -71,41 +70,214 @@ After creating your project:

> **Note**: The default scripts in package.json use Bun as the runtime (e.g., `bun run src/index.ts`). If you prefer to use a different package manager or runtime, you can modify these scripts in your package.json file to use Node.js or another runtime of your choice.

## 📖 Detailed Usage

### Transport Methods

The MCP server supports two transport methods:

1. **stdio Transport** (Command Line Mode):
- Runs on your **local machine**
- Managed automatically by Cursor
- Communicates directly via `stdout`
- Only accessible by you locally
- Ideal for personal development and tools

2. **SSE Transport** (HTTP Web Mode):
- Can run **locally or remotely**
- Managed and run by you
- Communicates **over the network**
- Can be **shared** across machines
- Ideal for team collaboration and shared tools

### Running the Server Locally

#### stdio Transport (CLI Mode)

Start the server in stdio mode for CLI tools:

```bash
# Start the stdio server
npm start
# or with other package managers
yarn start
pnpm start
bun start

# Start the server in development mode with auto-reload
npm run dev
# or
yarn dev
pnpm dev
bun dev
```

#### HTTP Transport (Web Mode)

Start the server in HTTP mode for web applications:

```bash
# Start the HTTP server
npm run start:http
# or
yarn start:http
pnpm start:http
bun start:http

# Start the HTTP server in development mode with auto-reload
npm run dev:http
# or
yarn dev:http
pnpm dev:http
bun dev:http
```

By default, the HTTP server runs on port 3001. You can change this by setting the PORT environment variable:

```bash
# Start the HTTP server on a custom port
PORT=8080 npm run start:http
```

### Connecting to the Server

#### Connecting from Cursor

To connect to your MCP server from Cursor:

1. Open Cursor and go to Settings (gear icon in the bottom left)
2. Click on "Features" in the left sidebar
3. Scroll down to "MCP Servers" section
4. Click "Add new MCP server"
5. Enter the following details:
- Server name: `my-mcp-server` (or any name you prefer)
- For stdio mode:
- Type: `command`
- Command: The path to your server executable, e.g., `npm start`
- For SSE mode:
- Type: `url`
- URL: `http://localhost:3001/sse`
6. Click "Save"

#### Using mcp.json with Cursor

For a more portable configuration, create an `.cursor/mcp.json` file in your project's root directory:

```json
{
"mcpServers": {
"my-mcp-stdio": {
"command": "npm",
"args": [
"start"
],
"env": {
"NODE_ENV": "development"
}
},
"my-mcp-sse": {
"url": "http://localhost:3001/sse"
}
}
}
```

You can also create a global configuration at `~/.cursor/mcp.json` to make your MCP servers available in all your Cursor workspaces.

Note:
- The `command` type entries run the server in stdio mode
- The `url` type entry connects to the HTTP server using SSE transport
- You can provide environment variables using the `env` field
- When connecting via SSE with FastMCP, use the full URL including the `/sse` path: `http://localhost:3001/sse`

### Testing Your Server with CLI Tools

FastMCP provides built-in tools for testing your server:

```bash
# Test with mcp-cli
npx fastmcp dev server.js

# Inspect with MCP Inspector
npx fastmcp inspect server.ts
```

### Using Environment Variables

You can customize the server using environment variables:

```bash
# Change the HTTP port (default is 3001)
PORT=8080 npm run start:http

# Change the host binding (default is 0.0.0.0)
HOST=127.0.0.1 npm run start:http
```

## 🛠️ Adding Custom Tools and Resources

When adding custom tools, resources, or prompts to your MCP server:

1. Use underscores (`_`) instead of hyphens (`-`) in all resource, tool, and prompt names
```typescript
// Good: Uses underscores
server.tool(
"my_custom_tool",
"Description of my custom tool",
{
param_name: z.string().describe("Parameter description")
},
async (params) => {
// Tool implementation
}
);

// Bad: Uses hyphens, may cause issues with Cursor
server.tool(
"my-custom-tool",
"Description of my custom tool",
{
param-name: z.string().describe("Parameter description")
},
async (params) => {
// Tool implementation
}
);
```
When adding custom tools, resources, or prompts to your FastMCP server:

### Tools

```typescript
server.addTool({
name: "hello_world",
description: "A simple hello world tool",
parameters: z.object({
name: z.string().describe("Name to greet")
}),
execute: async (params) => {
return `Hello, ${params.name}!`;
}
});
```

2. This naming convention ensures compatibility with Cursor and other AI tools that interact with your MCP server
### Resources

```typescript
server.addResourceTemplate({
uriTemplate: "example://{id}",
name: "Example Resource",
mimeType: "text/plain",
arguments: [
{
name: "id",
description: "Resource ID",
required: true,
},
],
async load({ id }) {
return {
text: `This is an example resource with ID: ${id}`
};
}
});
```

### Prompts

```typescript
server.addPrompt({
name: "greeting",
description: "A simple greeting prompt",
arguments: [
{
name: "name",
description: "Name to greet",
required: true,
},
],
load: async ({ name }) => {
return `Hello, ${name}! How can I help you today?`;
}
});
```

## 📚 Documentation

For more information about FastMCP, visit [FastMCP GitHub Repository](https://github.com/punkpeye/fastmcp).

For more information about the Model Context Protocol, visit the [MCP Documentation](https://modelcontextprotocol.io/introduction).

## 📄 License
Expand Down
3 changes: 1 addition & 2 deletions bin/create-mcp-server.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { execSync } from 'child_process';

// Get the directory where the source files are stored
const __filename = fileURLToPath(import.meta.url);
Expand Down Expand Up @@ -171,7 +170,7 @@ function createProjectPackageJson() {
"typescript": "^5.8.2"
},
dependencies: {
"@modelcontextprotocol/sdk": "^1.7.0",
"fastmcp": "^1.21.0",
"cors": "^2.8.5",
"express": "^4.21.2",
"zod": "^3.24.2"
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@
"typescript": "^5.8.2"
},
"dependencies": {
"@modelcontextprotocol/sdk": "^1.7.0",
"cors": "^2.8.5",
"express": "^4.21.2",
"fastmcp": "^1.21.0",
"zod": "^3.24.2"
},
"engines": {
Expand Down
36 changes: 17 additions & 19 deletions src/core/prompts.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { FastMCP } from "fastmcp";
import { z } from "zod";

/**
* Register all prompts with the MCP server
* @param server The MCP server instance
* @param server The FastMCP server instance
*/
export function registerPrompts(server: McpServer) {
export function registerPrompts(server: FastMCP) {
// Example prompt
server.prompt(
"greeting",
"A simple greeting prompt",
{
name: z.string().describe("Name to greet")
},
(params: { name: string }) => ({
messages: [{
role: "user",
content: {
type: "text",
text: `Hello, ${params.name}! How can I help you today?`
}
}]
})
);
server.addPrompt({
name: "greeting",
description: "A simple greeting prompt",
arguments: [
{
name: "name",
description: "Name to greet",
required: true,
},
],
load: async ({ name }) => {
return `Hello, ${name}! How can I help you today?`;
}
});
}
30 changes: 17 additions & 13 deletions src/core/resources.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { FastMCP } from "fastmcp";
import * as services from "./services/index.js";

/**
* Register all resources with the MCP server
* @param server The MCP server instance
* @param server The FastMCP server instance
*/
export function registerResources(server: McpServer) {
export function registerResources(server: FastMCP) {
// Example resource
server.resource(
"example_resource",
"example://{id}",
async (uri: URL) => {
const id = uri.pathname.split('/').pop();
server.addResourceTemplate({
uriTemplate: "example://{id}",
name: "Example Resource",
mimeType: "text/plain",
arguments: [
{
name: "id",
description: "Resource ID",
required: true,
},
],
async load({ id }) {
return {
contents: [{
uri: uri.toString(),
text: `This is an example resource with ID: ${id}`
}]
text: `This is an example resource with ID: ${id}`
};
}
);
});
}
Loading