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
Похожие серверы
Alpha Vantage MCP Server
спонсорAccess financial market data: realtime & historical stock, ETF, options, forex, crypto, commodities, fundamentals, technical indicators, & more
llm-cli-gateway
Unified MCP server providing access to Claude Code, Codex, and Gemini CLIs through a single gateway. Features multi-LLM orchestration, persistent session management, async job execution with polling, approval gates, retry with circuit breakers, and token optimization. Install: npx -y llm-cli-gateway
Tauri Development MCP Server
Build, test, and debug mobile and desktop apps with the Tauri framework faster with automated UI interaction, screenshots, DOM state, and console logs from your app under development.
B12 Website Generator
An AI-powered website generator from B12, requiring no external data files.
MetaMCP
A proxy server that combines multiple MCP servers into a single endpoint, routing requests to the appropriate underlying server.
Sensei MCP
Expert guidance for Dojo and Cairo development on Starknet, specializing in the Dojo ECS framework for building onchain worlds.
Azure DevOps
An MCP server for interacting with Azure DevOps agents and queues.
Openapi MCP
An MCP server that lets LLMs inspect and interact with OpenAPI specifications.
swarm.at
Settlement protocol that validates agent actions before execution. Guards destructive operations with hash-chained ledger receipts, trust tiers, and 31 workflow blueprints.
Artificial Analysis
An unofficial MCP server for the Artificial Analysis API
MCP POC
A proof-of-concept MCP server built with Node.js and TypeScript, compatible with Claude Desktop.