Initial minimal mcp server for KorAP
diff --git a/mcp/server.go b/mcp/server.go
new file mode 100644
index 0000000..b6d7b10
--- /dev/null
+++ b/mcp/server.go
@@ -0,0 +1,64 @@
+package mcp
+
+import (
+	"context"
+	"fmt"
+
+	"github.com/mark3labs/mcp-go/mcp"
+	"github.com/mark3labs/mcp-go/server"
+)
+
+// Server wraps the mcp-go server with KorAP-specific functionality
+type Server struct {
+	mcpServer *server.MCPServer
+	name      string
+	version   string
+}
+
+// NewServer creates a new KorAP MCP server
+func NewServer(name, version string) *Server {
+	mcpServer := server.NewMCPServer(
+		name,
+		version,
+		server.WithToolCapabilities(true),
+	)
+
+	return &Server{
+		mcpServer: mcpServer,
+		name:      name,
+		version:   version,
+	}
+}
+
+// AddTool registers a new tool with the server
+func (s *Server) AddTool(name, description string, inputSchema map[string]interface{}, handler func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error)) error {
+	if name == "" {
+		return fmt.Errorf("tool name cannot be empty")
+	}
+	if description == "" {
+		return fmt.Errorf("tool description cannot be empty")
+	}
+
+	// Create tool using mcp-go's NewTool function
+	tool := mcp.NewTool(name, mcp.WithDescription(description))
+
+	// Add the tool and handler to the MCP server
+	s.mcpServer.AddTool(tool, handler)
+
+	return nil
+}
+
+// Serve starts the MCP server using stdio transport
+func (s *Server) Serve() error {
+	return server.ServeStdio(s.mcpServer)
+}
+
+// GetMCPServer returns the underlying mcp-go server for advanced usage
+func (s *Server) GetMCPServer() *server.MCPServer {
+	return s.mcpServer
+}
+
+// GetServerInfo returns server information
+func (s *Server) GetServerInfo() (string, string) {
+	return s.name, s.version
+}
diff --git a/mcp/server_test.go b/mcp/server_test.go
new file mode 100644
index 0000000..a0073c3
--- /dev/null
+++ b/mcp/server_test.go
@@ -0,0 +1,52 @@
+package mcp
+
+import (
+	"context"
+	"testing"
+
+	"github.com/mark3labs/mcp-go/mcp"
+	"github.com/stretchr/testify/assert"
+)
+
+func TestNewServer(t *testing.T) {
+	server := NewServer("test-server", "1.0.0")
+	assert.NotNil(t, server)
+
+	name, version := server.GetServerInfo()
+	assert.Equal(t, "test-server", name)
+	assert.Equal(t, "1.0.0", version)
+}
+
+func TestAddTool(t *testing.T) {
+	server := NewServer("test-server", "1.0.0")
+
+	// Test adding a valid tool
+	err := server.AddTool("test-tool", "A test tool", map[string]interface{}{
+		"type": "object",
+		"properties": map[string]interface{}{
+			"input": map[string]interface{}{
+				"type": "string",
+			},
+		},
+	}, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
+		return mcp.NewToolResultText("test result"), nil
+	})
+
+	assert.NoError(t, err)
+
+	// Test adding tool with empty name
+	err = server.AddTool("", "description", map[string]interface{}{}, nil)
+	assert.Error(t, err)
+	assert.Contains(t, err.Error(), "tool name cannot be empty")
+
+	// Test adding tool with empty description
+	err = server.AddTool("name", "", map[string]interface{}{}, nil)
+	assert.Error(t, err)
+	assert.Contains(t, err.Error(), "tool description cannot be empty")
+}
+
+func TestGetMCPServer(t *testing.T) {
+	server := NewServer("test-server", "1.0.0")
+	mcpServer := server.GetMCPServer()
+	assert.NotNil(t, mcpServer)
+}