NimCP
A powerful, macro-based library for creating Model Context Protocol (MCP) servers in the Nim programming language.
NimCP - Easy Model Context Protocol (MCP) Servers in Nim
NimCP is a macro-based library for creating Model Context Protocol (MCP) servers in Nim. It leverages Nim's macro system to provide an incredibly easy-to-use API for building MCP servers that integrate seamlessly with LLM applications.
NOTE: 99.9% of this library was written using Claude Code!
Features
- Macro-driven API - Define servers, tools, resources, and prompts with simple, declarative syntax
- Full MCP 2024-11-05 Support - Complete implementation of MCP specification with JSON-RPC 2.0
- Multiple Transports - Supports stdio, SSE, HTTP, and WebSocket transports
- Enhanced Type System - Support for objects, unions, enums, optional types, and arrays
- Automatic Schema Generation - JSON schemas generated from Nim type signatures
- Request Context System - Progress tracking, cancellation, and request lifecycle management
- Resource URI Templates - Dynamic URI patterns with parameter extraction (
/users/{id}) - Server Composition - Compose multiple MCP servers into a single interface with prefixes and routing
- Pluggable Logging - Flexible logging system with multiple handlers, levels, and structured output
- Middleware Pipeline - Request/response transformation and processing hooks
- Fluent API - Method chaining patterns for elegant server configuration
- High Performance - Mummy based HTTP and WebSockets implementation
- Concurrent Processing - Uses the new taskpools library for stdio transport
- Minimal Dependencies - Uses only essential, well-maintained packages
Quick Start
Installation
nimble install nimcp
Simple Example
import nimcp
import strformat
let server = mcpServer("my-server", "1.0.0"):
mcpTool:
proc echo(text: string): string =
## Echo back the input text
return "Echo: " & text
mcpTool:
proc add(a: float, b: float): string =
## Add two numbers together
return $fmt"Result: {a + b}"
when isMainModule:
# Use stdio transport (default):
let transport = newStdioTransport()
transport.serve(server)
# Or use HTTP transport:
# let transport = newMummyTransport(8080, "127.0.0.1")
# transport.serve(server)
# Or use WebSocket transport for real-time communication:
# let transport = newWebSocketTransport(8080, "127.0.0.1")
# transport.serve(server)
That's it! Your MCP server is ready to run.
Core Concepts
Tools
Tools are functions that LLM applications can call. Define them with the mcpTool macro that plucks out the tool name, description, and JSON schema from your procedure signature and doc comments:
mcpTool:
proc calculate(expression: string): string =
## Perform mathematical calculations
## - expression: Mathematical expression to evaluate
# Your calculation logic here
return "Result: 42"
Context-Aware vs Regular Tools
NimCP also supports context aware tools that also receive server context for accessing server state and request information:
# Context aware tools need to have first parameter being an McpRequestContext
mcpTool:
proc notifyTool(ctx: McpRequestContext, args: JsonNode): McpToolResult =
## Log request and track processing
ctx.info("Processing notification request")
# Your notification logic here
let message = args.getOrDefault("message", %"").getStr()
ctx.info("Notification processing complete")
return McpToolResult(content: @[createTextContent("Notification: " & message)])
When to use Context-Aware Tools:
- Server-initiated events
- Access to server configuration or transport-specific features
- Custom logging or middleware integration
- Request-specific state management
Manual Registration Methods:
server.registerTool(tool, handler)- Regular toolsserver.registerToolWithContext(tool, handler)- Context-aware tools- Same pattern applies to resources and prompts
Resources
Resources provide data that can be read by LLM applications:
mcpResource("data://config", "Configuration", "Application configuration"):
proc get_config(uri: string): string =
return readFile("config.json")
Prompts
Prompts are reusable templates for LLM interactions:
mcpPrompt("code_review", "Code review prompt", @[
McpPromptArgument(name: "language", description: some("Programming language")),
McpPromptArgument(name: "code", description: some("Code to review"))
]):
proc review_prompt(name: string, args: Table[string, JsonNode]): seq[McpPromptMessage] =
let language = args.getOrDefault("language", %"unknown").getStr()
let code = args.getOrDefault("code", %"").getStr()
return @[
McpPromptMessage(
role: System,
content: createTextContent(&"Review this {language} code for best practices and potential issues.")
),
McpPromptMessage(
role: User,
content: createTextContent(code)
)
]
Manual Server Creation
For more control, you can create servers manually:
import nimcp
let server = newMcpServer("advanced-server", "2.0.0")
# Register tools manually
let tool = McpTool(
name: "custom_tool",
description: some("A custom tool"),
inputSchema: %*{"type": "object"}
)
proc customHandler(args: JsonNode): McpToolResult =
return McpToolResult(content: @[createTextContent("Custom result")])
server.registerTool(tool, customHandler)
# Run the server
try:
let transport = newStdioTransport()
transport.serve(server)
finally:
server.shutdown()
Server Composition
NimCP supports composing multiple servers into a single interface - perfect for API gateways:
import nimcp, nimcp/composed_server
# Create individual servers using macro API
let calculatorServer = mcpServer("calculator-service", "1.0.0"):
mcpTool:
proc add(a: float, b: float): string =
## Add two numbers together
return fmt"Result: {a + b}"
let fileServer = mcpServer("file-service", "1.0.0"):
mcpTool:
proc readFile(path: string): string =
## Read contents of a file
try:
return readFile(path)
except IOError as e:
return fmt"Error reading file: {e.msg}"
# Compose them into a single gateway
let apiGateway = newComposedServer("api-gateway", "1.0.0")
# Mount each service with prefixes for namespacing
apiGateway.mountServerAt("/calc", calculatorServer, some("calc_"))
apiGateway.mountServerAt("/files", fileServer, some("file_"))
# Run the composed server
let transport = newStdioTransport()
transport.serve(apiGateway)
# Tools are now available as: calc_add, file_readFile
Error Handling
NimCP automatically handles JSON-RPC errors, but you can throw exceptions in your handlers:
mcpTool:
proc validate(data: string): string =
## Validate input data
if data.len == 0:
raise newException(ValueError, "Empty data parameter")
return "Valid!"
Examples
Check out the examples/ directory for comprehensive examples and see the examples README for some more info.
Just from command line you can test and list tools with for example:
echo '{"jsonrpc": "2.0", "id": 1, "method": "tools/list"}' | ./examples/calculator_server
If you are using Claude Code, this is how you can add it as an MCP server:
- Add the MCP server to Claude Code:
claude mcp add basic_calculator --transport stdio $PWD/examples/basic_calculator
- Verify it was added:
claude mcp list
- Test the server from within Claude Code:
Once added, you should be able to use the calculator tools directly in Claude Code conversations:
- add: Add two numbers together
- multiply: Multiply two numbers
- power: Calculate exponentiation
- math://constants: Access mathematical constants resource
Example usage in Claude Code:
- "Can you add 15 and 27 for me?"
- "What's 12 raised to the power of 3?"
- "Show me the mathematical constants"
If the CLI method doesn't work, you can manually edit your MCP configuration file (usually at ~/.claude.json). Just change the path to what you have:
{
"mcpServers": {
"calculator_server": {
"type": "stdio",
"command": "/path/to/examples/calculator_server",
"args": [],
"env": {}
}
}
}
Testing
Run the test suite:
nimble test
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License. See LICENSE for details.
MCP Resources
Máy chủ liên quan
Scout Monitoring MCP
nhà tài trợPut performance and error data directly in the hands of your AI assistant.
Alpha Vantage MCP Server
nhà tài trợAccess financial market data: realtime & historical stock, ETF, options, forex, crypto, commodities, fundamentals, technical indicators, & more
Excalidraw MCP
Generate 25+ diagram types (flowchart, sequence, ER, mindmap, architecture, etc.) as Excalidraw files with natural language. CJK support, 30+ tech brand colors, Sugiyama auto-layout.
Unified Diff MCP Server
Beautiful HTML and PNG diff visualization using diff2html, designed for filesystem edit_file dry-run output with high-performance Bun runtime.
Web3 MCP Server
An MCP server for interacting with Web3 and EVM-compatible chains.
Nessus MCP Server
An MCP server for interacting with the Tenable Nessus vulnerability scanner.
HiGHS MCP Server
Provides linear programming (LP) and mixed-integer programming (MIP) optimization capabilities using the HiGHS solver.
Flame MCP Server
Provides live, up-to-date documentation for the Flame game engine.
Eterna MCP
Managed MCP server for Bybit perpetual futures trading. Isolated sub-accounts, built-in risk management, 12 trading tools.
Merge MCP Server
Integrates the Merge Unified API with any LLM provider using the MCP protocol.
d2-mcp
Create, validate, and render diagrams from D2 (Declarative Diagramming) code into SVG and PNG formats.
Remote MCP Server (Authless)
An example of a remote MCP server without authentication, deployable on Cloudflare Workers.