This document contains detailed information for developers working with the MCP Private GitHub Search project.
- Node.js v18 or higher
- pnpm v7 or higher
- VS Code with Dev Containers extension (optional but recommended)
- Clone the repository
git clone https://github.com/Hint-Services/mcp-private-github-search.git
cd mcp-private-github-search- Install dependencies
pnpm install- Build the project
pnpm run buildpnpm run watchpnpm run inspectorThe MCP TypeScript SDK provides core classes for building servers:
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const server = new Server({
name: "mcp-private-github-search",
version: "1.0.0",
capabilities: {
tools: {}, // Enable tools capability
resources: {}, // Enable resource access
prompts: {}, // Enable prompt handling
streaming: true, // Enable streaming responses
},
});
// Connect transport
const transport = new StdioServerTransport();
await server.connect(transport);mcp-private-github-search/
├── .devcontainer/ # Dev container configuration
│ └── devcontainer.json
├── src/
│ ├── index.ts # MCP Server main entry point
│ └── github/ # GitHub API integration
│ ├── client.ts # GitHub client implementation
│ ├── rate-limiter.ts # Rate limiting functionality
│ └── types.ts # TypeScript type definitions
├── docs/ # Documentation
├── package.json # Project configuration
└── tsconfig.json # TypeScript configuration
-
Build the project:
npm run build
Compiles your TypeScript source and sets file permissions for the main entry point.
-
Watch mode:
npm run watch
Automatically recompiles TypeScript files whenever changes are made, ideal for active development.
-
Run with inspector:
npm run inspector
Launches the server alongside a debugging tool, enabling you to trace issues, set breakpoints, and inspect variables in real time.
MCP tools must return responses in a specific format to ensure proper communication with AI hosts. Here's the structure:
interface ToolResponse {
content: ContentItem[];
isError?: boolean;
metadata?: Record<string, unknown>;
}
interface ContentItem {
type: string;
text?: string;
mimeType?: string;
data?: unknown;
}Supported content types include:
text: Plain text contentcode: Code snippets with optional language specificationimage: Base64-encoded images with MIME typefile: File content with MIME typeerror: Error messages (whenisErroris true)
Example response:
return {
content: [
{
type: "text",
text: "Operation completed successfully",
},
{
type: "code",
text: "console.log('Hello, World!')",
mimeType: "application/javascript",
},
],
};When developing MCP tools, follow these security guidelines:
-
Input Validation:
- Always validate input parameters using Zod schemas
- Implement strict type checking
- Sanitize user inputs before processing
- Use the
strict()option in schemas to prevent extra properties
-
Error Handling:
- Never expose internal error details to clients
- Implement proper error boundaries
- Log errors securely
- Return user-friendly error messages
-
Resource Management:
- Implement proper cleanup procedures
- Handle process termination signals
- Close connections and free resources
- Implement timeouts for long-running operations
-
API Security:
- Use secure transport protocols
- Implement rate limiting
- Store sensitive data securely
- Use environment variables for configuration
Example secure tool implementation:
const SecureSchema = z.object({
input: z
.string()
.min(1)
.max(1000)
.transform((str) => str.trim())
.pipe(z.string().regex(/^[a-zA-Z0-9\s]+$/)),
});
server.tool("secure_tool", SecureSchema.shape, async (params) => {
try {
// Implement rate limiting
await rateLimiter.checkLimit();
// Process validated input
const result = await processSecurely(params.input);
return {
content: [
{
type: "text",
text: result,
},
],
};
} catch (error) {
// Log error internally
logger.error(error);
// Return safe error message
return {
content: [
{
type: "text",
text: "An error occurred processing your request",
},
],
isError: true,
};
}
});MCP supports streaming responses for long-running operations:
server.tool("stream_data", StreamSchema.shape, async function* (params) {
for (const chunk of dataStream) {
yield {
content: [
{
type: "text",
text: chunk,
},
],
};
}
});You can define custom content types for specialized data:
interface CustomContent extends ContentItem {
type: "custom";
data: {
format: string;
value: unknown;
};
}Implement proper async handling:
server.tool("async_operation", AsyncSchema.shape, async (params) => {
const operation = await startAsyncOperation();
while (!operation.isComplete()) {
await operation.wait();
}
return {
content: [
{
type: "text",
text: await operation.getResult(),
},
],
};
});Use Jest for testing your tools:
describe("Calculator Tool", () => {
let server: McpServer;
beforeEach(() => {
server = new McpServer({
name: "test-server",
version: "1.0.0",
});
registerCalculatorTool(server);
});
test("adds numbers correctly", async () => {
const result = await server.executeTool("calculate", {
a: 5,
b: 3,
operation: "add",
});
expect(result.content[0].text).toBe("8");
});
});-
MCP Inspector:
npm run inspector
Provides real-time inspection of:
- Tool registration
- Request/response flow
- Error handling
- Performance metrics
-
Logging:
function logMessage(level: "info" | "warn" | "error", message: string) { console.error(`[${level.toUpperCase()}] ${message}`); }
-
Error Tracking:
process.on("uncaughtException", (error: Error) => { logMessage("error", `Uncaught error: ${error.message}`); // Implement error reporting });
MCP supports multiple transport protocols:
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
const transport = new StdioServerTransport();
await server.connect(transport);import { WebSocketServerTransport } from "@modelcontextprotocol/sdk/server/websocket.js";
const transport = new WebSocketServerTransport({
port: 3000,
});
await server.connect(transport);import { Transport } from "@modelcontextprotocol/sdk/server/transport.js";
class CustomTransport implements Transport {
// Implement transport methods
}Configure server capabilities:
const server = new McpServer({
name: "mcp-server",
version: "1.0.0",
capabilities: {
tools: {}, // Enable tools capability
streaming: true, // Enable streaming support
customContent: ["myFormat"], // Define custom content types
metadata: true, // Enable metadata support
},
});This MCP server template supports multiple AI platforms out of the box:
-
Claude Desktop:
- Provides a chat-based environment
- Supports all MCP capabilities
- Ideal for conversational AI interactions
-
Cursor:
- AI-powered development environment
- Full tool integration support
- Perfect for coding assistance
-
Windsurf:
- Modern AI development platform
- Complete MCP protocol support
- Streamlined workflow integration
-
Cline:
- Command-line AI interface
- Tool-focused interactions
- Efficient terminal-based usage
-
TypeScript:
- Native TypeScript support
- Type-safe tool development
- Seamless SDK integration
Cursor is another AI development environment that supports MCP. To incorporate your server into Cursor:
-
Build your server:
npm run build
Ensure an executable
index.jsis generated in thebuilddirectory. -
In Cursor, go to
Settings>Features>MCP: Add a new MCP server. -
Register your server:
- Select
stdioas the transport type. - Provide a descriptive
Name. - Set the command, for example:
node /path/to/your/mcp-server/build/index.js.
- Select
-
Save your configuration.
Cursor then detects and lists your tools. During AI-assisted coding sessions or prompt-based interactions, it will call your MCP tools whenever relevant. You can also instruct the AI to use a specific tool by name.
Claude Desktop provides a chat-based environment where you can leverage MCP tools. To include your server:
-
Build your server:
npm run build
Confirm that no errors occur and that the main script is generated in
build. -
Modify
claude_desktop_config.json:{ "mcpServers": { "mcp-server": { "command": "node", "args": ["/path/to/your/mcp-server/build/index.js"] } } }Provide the path to your compiled main file along with any additional arguments.
-
Restart Claude Desktop to load the new configuration.
When you interact with Claude Desktop, it can now invoke the MCP tools you have registered. If a user's request aligns with any of your tool's functionality, Claude will prompt to use that tool.
- Use TypeScript for better type checking, clearer code organization, and easier maintenance over time.
- Adopt consistent patterns for implementing tools:
- Keep each tool in its own file
- Use descriptive schemas with proper documentation
- Implement comprehensive error handling
- Return properly formatted content
- Include thorough documentation:
- Add JSDoc comments to explain functionality
- Document parameters and return types
- Include examples where helpful
- Leverage the inspector for debugging:
This helps you:
npm run inspector
- Test tool functionality
- Debug request/response flow
- Verify schema validation
- Check error handling
- Test comprehensively before deployment:
- Verify input validation
- Test error scenarios
- Check response formatting
- Ensure proper integration with hosts
- Follow MCP best practices:
- Use proper content types
- Implement proper error handling
- Validate all inputs and outputs
- Handle network requests safely
- Format responses consistently
Test the date calculation logic:
describe("getCommitHistory date calculations", () => {
it("should calculate correct date range for 7 days", () => {
const since = new Date();
since.setDate(since.getDate() - 7);
// Test logic
});
});Test with actual GitHub API:
describe("getCommitHistory integration", () => {
it("should fetch commits without diffs", async () => {
// Test basic functionality
});
it("should fetch commits with diffs", async () => {
// Test with includeDiffs: true
});
});When testing the tool (which includes diffs by default), be aware of:
- Increased API calls (one per commit for diff details)
- Potential rate limiting with larger commit counts
- Larger response sizes due to diff content
- Lower default maxCommits (25) to balance performance
If you have developed new tools or made local modifications and wish to share them, consider publishing your customized server:
- Create an account on Smithery.
- Follow their deployment instructions to bundle and publish your MCP server.
- Other users can then run your server through Smithery by referencing your unique package name.
Smithery offers:
- A centralized registry to discover and share MCP servers.
- Simplified deployment, removing repetitive setup.
- A community-driven approach where developers contribute diverse tools.
- Easy integration with popular AI hosts.
For additional guidance: