A Go implementation of the OData to Model Context Protocol (MCP) bridge, providing universal access to OData services through MCP tools.
This is a Go port of the Python OData-MCP bridge implementation, designed to be easier to run on different operating systems with better performance and simpler deployment. It supports both OData v2 and v4 services.
- Streamable HTTP Transport: Modern MCP protocol (2024-11-05) support with
--transport streamable-http
- Single
/mcp
endpoint with automatic SSE upgrade - Bidirectional communication and session management
- Better alignment with Python MCP ecosystem
- Backward compatibility with legacy SSE endpoints
- Single
- Universal OData Support: Works with both OData v2 and v4 services
- Dynamic Tool Generation: Automatically creates MCP tools based on OData metadata
- Multiple Authentication Methods: Basic auth, cookie auth, and anonymous access
- SAP OData Extensions: Full support for SAP-specific OData features including CSRF tokens
- Comprehensive CRUD Operations: Generated tools for create, read, update, delete operations
- Advanced Query Support: OData query options ($filter, $select, $expand, $orderby, etc.)
- Function Import Support: Call OData function imports as MCP tools
- Flexible Tool Naming: Configurable tool naming with prefix/postfix options
- Entity Filtering: Selective tool generation with wildcard support
- Cross-Platform: Native Go binary for easy deployment on any OS
- Read-Only Modes: Restrict operations with
--read-only
or--read-only-but-functions
- MCP Protocol Debugging: Built-in trace logging with
--trace-mcp
for troubleshooting - Service-Specific Hints: Flexible hint system with pattern matching for known service issues
- Full MCP Compliance: Complete protocol implementation for all MCP clients
- Multiple Transports: Support for stdio (default), HTTP/SSE, and Streamable HTTP (2024-11-05 protocol)
Download the appropriate binary for your platform from the releases page.
Pre-built binaries are available for:
- Linux (amd64)
- Windows (amd64)
- macOS (Intel and Apple Silicon)
git clone https://github.com/oisee/odata_mcp_go.git
cd odata_mcp_go
go build -o odata-mcp cmd/odata-mcp/main.go
# Build for current platform
make build
# Build for all platforms
make build-all
# Build for all platforms with WSL integration (copies to /mnt/c/bin)
make build-all-wsl
# Build and test
make dev
# Check current version
make version
# See all options
make help
# Build for current platform
./build.sh
# Build for all platforms
./build.sh all
# See all options
./build.sh help
# Using Make
make build-linux # Linux (amd64)
make build-windows # Windows (amd64)
make build-macos # macOS (Intel + Apple Silicon)
# WSL-specific builds (copies Windows binary to /mnt/c/bin)
make build-windows-wsl # Build Windows + WSL integration
make build-all-wsl # Build all platforms + WSL integration
# Using build script
./build.sh linux # Linux (amd64)
./build.sh windows # Windows (amd64)
./build.sh macos # macOS (Intel + Apple Silicon)
# Manual Go build
GOOS=linux GOARCH=amd64 go build -o odata-mcp-linux cmd/odata-mcp/main.go
GOOS=windows GOARCH=amd64 go build -o odata-mcp.exe cmd/odata-mcp/main.go
# Build Docker image
make docker
# Or manually
docker build -t odata-mcp .
# Run in container
docker run --rm -it odata-mcp --help
When building in WSL, you can use special targets that automatically copy the Windows binary to your Windows file system:
# Build all platforms and copy Windows binary to C:\bin
make build-all-wsl
# Build only Windows and copy to C:\bin
make build-windows-wsl
Note: These commands will check if /mnt/c/bin
exists and skip the copy if not found, so they're safe to use on any system.
Claude Desktop uses the stdio transport by default. Here are example configurations:
The Claude Desktop configuration file location varies by platform:
- Windows:
%APPDATA%\Claude\claude_desktop_config.json
- macOS:
~/Library/Application Support/Claude/claude_desktop_config.json
- Linux:
~/.config/Claude/claude_desktop_config.json
{
"mcpServers": {
"northwind-v2": {
"command": "C:/bin/odata-mcp.exe",
"args": [
"--service",
"https://services.odata.org/V2/Northwind/Northwind.svc/",
"--tool-shrink"
]
},
"northwind-v4": {
"command": "C:/bin/odata-mcp.exe",
"args": [
"--service",
"https://services.odata.org/V4/Northwind/Northwind.svc/",
"--tool-shrink"
]
}
}
}
{
"mcpServers": {
"my-sap-service": {
"command": "/usr/local/bin/odata-mcp",
"args": [
"--service",
"https://my-sap-system.com/sap/opu/odata/sap/MY_SERVICE/",
"--user",
"myusername",
"--password",
"mypassword",
"--tool-shrink",
"--entities",
"Products,Orders,Customers"
]
}
}
}
{
"mcpServers": {
"my-secure-service": {
"command": "/usr/local/bin/odata-mcp",
"args": [
"--service",
"https://my-service.com/odata/",
"--tool-shrink"
],
"env": {
"ODATA_USERNAME": "myusername",
"ODATA_PASSWORD": "mypassword"
}
}
}
}
Note: Claude Desktop currently doesn't support reading environment variables from your system. The env
field in the configuration sets environment variables specifically for that MCP server process.
- Use environment variables in the
env
field rather than hardcoding credentials inargs
- Limit entity access using the
--entities
flag to only expose necessary data - Use read-only accounts when possible for OData services
- Store configuration file securely with appropriate file permissions
Note: Claude Desktop does not currently support API key authentication for MCP servers. All MCP servers run locally with the same permissions as Claude Desktop itself.
{
"mcpServers": {
"production-readonly": {
"command": "/usr/local/bin/odata-mcp",
"args": [
"--service",
"https://production.company.com/odata/",
"--read-only",
"--tool-shrink"
],
"env": {
"ODATA_USERNAME": "readonly_user",
"ODATA_PASSWORD": "readonly_pass"
}
},
"dev-with-functions": {
"command": "/usr/local/bin/odata-mcp",
"args": [
"--service",
"https://dev.company.com/odata/",
"--read-only-but-functions",
"--trace-mcp" // Enable debugging
]
}
}
}
The Claude Code CLI has stricter property name validation than other Claude tools. If you encounter errors like:
API Error: 400 {"type":"error","error":{"type":"invalid_request_error","message":"tools.17.custom.input_schema.properties: Property keys should match pattern ^[a-zA-Z0-9_.-]{1,64}$"}}
Use the --claude-code-friendly
flag to remove the $
prefix from OData parameter names:
{
"mcpServers": {
"northwind-claude-code": {
"command": "/usr/local/bin/odata-mcp",
"args": [
"--service",
"https://services.odata.org/V2/Northwind/Northwind.svc/",
"--claude-code-friendly", // Removes $ from parameter names
"--tool-shrink"
]
}
}
}
This transforms parameter names:
$filter
→filter
$select
→select
$expand
→expand
$orderby
→orderby
$top
→top
$skip
→skip
$count
→count
The server internally maps these friendly names back to their OData equivalents when making requests.
{
"mcpServers": {
"large-service-readonly": {
"command": "/usr/local/bin/odata-mcp",
"args": [
"--service",
"https://large-erp.company.com/odata/",
"--disable", "cud", // Disable create, update, delete
"--tool-shrink",
"--entities", "Orders,Products,Customers"
],
"env": {
"ODATA_USERNAME": "readonly_user",
"ODATA_PASSWORD": "readonly_pass"
}
},
"minimal-tools": {
"command": "/usr/local/bin/odata-mcp",
"args": [
"--service",
"https://api.company.com/odata/",
"--enable", "gf", // Only get and filter operations
"--tool-shrink"
]
},
"no-actions": {
"command": "/usr/local/bin/odata-mcp",
"args": [
"--service",
"https://api.company.com/odata/",
"--disable", "a", // Disable all function imports/actions
"--verbose"
]
}
}
}
### Transport Options
The OData MCP bridge supports two transport mechanisms:
1. **STDIO (default)** - Standard input/output communication, used by Claude Desktop
2. **HTTP/SSE** - HTTP server with Server-Sent Events for web-based clients
> đź”’ **SECURITY WARNING**: The HTTP/SSE transport has **NO AUTHENTICATION** - anyone who can connect can access your OData service!
>
> **By default, HTTP transport is restricted to localhost only for security.**
>
> Safer usage scenarios:
> - Local development (localhost only) - **DEFAULT & RECOMMENDED**
> - Behind a reverse proxy with authentication
> - Private networks with proper firewall rules (requires expert flag)
>
> **NEVER expose the HTTP transport to the internet without additional security measures!**
>
> 🤖 **REMEMBER**: Skynet happened because open MCP-SSE ports were exposed to the internet with sudo rights. Protect the planet, protect humanity - do not use SSE/HTTP transport until it becomes more mature from a security perspective.
#### Using Streamable HTTP Transport (Modern MCP Protocol)
**New in v1.5.0**: Support for Streamable HTTP transport (protocol version 2024-11-05)
```bash
# Start server with Streamable HTTP (recommended for modern clients)
./odata-mcp --transport streamable-http https://services.odata.org/V2/Northwind/Northwind.svc/
# Use custom localhost port
./odata-mcp --transport streamable-http --http-addr localhost:3000 https://services.odata.org/V2/Northwind/Northwind.svc/
Streamable HTTP endpoints:
POST /mcp
- Main MCP endpoint (supports automatic SSE upgrade)GET /health
- Health check endpointPOST /sse
- Legacy SSE endpoint (for backward compatibility)
# Start server on localhost (default: localhost:8080)
./odata-mcp --transport http https://services.odata.org/V2/Northwind/Northwind.svc/
# Use custom localhost port
./odata-mcp --transport http --http-addr localhost:3000 https://services.odata.org/V2/Northwind/Northwind.svc/
# IPv4 localhost
./odata-mcp --transport http --http-addr 127.0.0.1:8080 https://services.odata.org/V2/Northwind/Northwind.svc/
# IPv6 localhost
./odata-mcp --transport http --http-addr [::1]:8080 https://services.odata.org/V2/Northwind/Northwind.svc/
# ⚠️ DANGEROUS: Expose to network (NOT RECOMMENDED!)
# Only use if you understand the security implications
./odata-mcp --transport http --http-addr 0.0.0.0:8080 --i-am-security-expert-i-know-what-i-am-doing https://services.odata.org/V2/Northwind/Northwind.svc/
Legacy HTTP/SSE endpoints:
GET /health
- Health check endpointGET /sse
- Server-Sent Events endpoint for real-time communicationPOST /rpc
- JSON-RPC endpoint for request/response communication
-
Using the provided HTML client:
# Start the server ./odata-mcp --transport http https://services.odata.org/V2/Northwind/Northwind.svc/ # Open examples/sse_client.html in a web browser
-
Using curl:
# Test SSE endpoint curl -N -H 'Accept: text/event-stream' http://localhost:8080/sse # Test RPC endpoint curl -X POST http://localhost:8080/rpc \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'
-
Using the test scripts:
# Test SSE with interactive script ./test_sse.sh # Test HTTP/RPC communication ./test_http_rpc.sh
# Using positional argument
./odata-mcp https://services.odata.org/V2/Northwind/Northwind.svc/
# Using --service flag
./odata-mcp --service https://services.odata.org/V2/Northwind/Northwind.svc/
# Using environment variable
export ODATA_SERVICE_URL=https://services.odata.org/V2/Northwind/Northwind.svc/
./odata-mcp
# Basic authentication
./odata-mcp --user admin --password secret https://my-service.com/odata/
# Cookie file authentication
./odata-mcp --cookie-file cookies.txt https://my-service.com/odata/
# Cookie string authentication
./odata-mcp --cookie-string "session=abc123; token=xyz789" https://my-service.com/odata/
# Environment variables
export ODATA_USERNAME=admin
export ODATA_PASSWORD=secret
./odata-mcp https://my-service.com/odata/
# Use custom prefix instead of postfix
./odata-mcp --no-postfix --tool-prefix "myservice" https://my-service.com/odata/
# Use custom postfix
./odata-mcp --tool-postfix "northwind" https://my-service.com/odata/
# Use shortened tool names
./odata-mcp --tool-shrink https://my-service.com/odata/
# Filter to specific entities (supports wildcards)
./odata-mcp --entities "Products,Categories,Order*" https://my-service.com/odata/
# Filter to specific functions (supports wildcards)
./odata-mcp --functions "Get*,Create*" https://my-service.com/odata/
# Hide all modifying operations (create, update, delete, and functions)
./odata-mcp --read-only https://my-service.com/odata/
./odata-mcp -ro https://my-service.com/odata/ # Short form
# Hide create/update/delete but allow function imports
./odata-mcp --read-only-but-functions https://my-service.com/odata/
./odata-mcp -robf https://my-service.com/odata/ # Short form
Fine-grained control over which operation types are available. Operation types are:
C
- Create operationsS
- Search operationsF
- Filter/list operationsG
- Get (single entity) operationsU
- Update operationsD
- Delete operationsA
- Actions/function importsR
- Read operations (expands to S, F, G)
# Enable only read operations (search, filter, get)
./odata-mcp --enable "r" https://my-service.com/odata/
./odata-mcp --enable "sfg" https://my-service.com/odata/ # Same as above
# Disable all modifying operations
./odata-mcp --disable "cud" https://my-service.com/odata/
# Enable only get and filter operations
./odata-mcp --enable "gf" https://my-service.com/odata/
# Disable actions/function imports
./odata-mcp --disable "a" https://my-service.com/odata/
# Case-insensitive
./odata-mcp --disable "CUD" https://my-service.com/odata/
Note: --enable
and --disable
cannot be used together.
# Enable verbose output
./odata-mcp --verbose https://my-service.com/odata/
# Trace mode - show all tools without starting server
./odata-mcp --trace https://my-service.com/odata/
# Enable MCP protocol trace logging (saves to temp directory)
./odata-mcp --trace-mcp https://my-service.com/odata/
# Linux/WSL: /tmp/mcp_trace_*.log
# Windows: %TEMP%\mcp_trace_*.log
The OData MCP bridge includes a flexible hint system to provide guidance for services with known issues or special requirements:
# Use default hints.json from binary directory
./odata-mcp https://my-service.com/odata/
# Use custom hints file
./odata-mcp --hints-file /path/to/custom-hints.json https://my-service.com/odata/
# Inject hint directly from command line
./odata-mcp --hint "Remember to use \$expand for complex queries" https://my-service.com/odata/
# Combine file and CLI hints (CLI has higher priority)
./odata-mcp --hints-file custom.json --hint '{"notes":["Override note"]}' https://my-service.com/odata/
Flag | Description | Default |
---|---|---|
--service |
OData service URL | |
-u, --user |
Username for basic auth | |
-p, --password |
Password for basic auth | |
--cookie-file |
Path to cookie file (Netscape format) | |
--cookie-string |
Cookie string (key1=val1; key2=val2) | |
--tool-prefix |
Custom prefix for tool names | |
--tool-postfix |
Custom postfix for tool names | |
--no-postfix |
Use prefix instead of postfix | false |
--tool-shrink |
Use shortened tool names | false |
--entities |
Comma-separated entity filter (supports wildcards) | |
--functions |
Comma-separated function filter (supports wildcards) | |
--sort-tools |
Sort tools alphabetically | true |
-v, --verbose |
Enable verbose output | false |
--debug |
Alias for --verbose | false |
--trace |
Show tools and exit (debug mode) | false |
--trace-mcp |
Enable MCP protocol trace logging | false |
--read-only, -ro |
Hide all modifying operations | false |
--read-only-but-functions, -robf |
Hide create/update/delete but allow functions | false |
--enable |
Enable only specified operation types (C,S,F,G,U,D,A,R) | |
--disable |
Disable specified operation types (C,S,F,G,U,D,A,R) | |
--hints-file |
Path to hints JSON file | hints.json in binary dir |
--hint |
Direct hint JSON or text from CLI | |
--transport |
Transport type: 'stdio', 'http' (SSE), or 'streamable-http' | stdio |
--http-addr |
HTTP server address (with --transport http/streamable-http) | localhost:8080 |
--i-am-security-expert-i-know-what-i-am-doing |
DANGEROUS: Allow non-localhost HTTP transport | false |
--legacy-dates |
Enable legacy date format conversion | true |
--no-legacy-dates |
Disable legacy date format conversion | false |
--convert-dates-from-sap |
Convert SAP date formats in responses | false |
--response-metadata |
Include __metadata blocks in responses | false |
--pagination-hints |
Add pagination information to responses | false |
--max-response-size |
Maximum response size in bytes | 5MB |
--max-items |
Maximum number of items in response | 100 |
--verbose-errors |
Provide detailed error context | false |
--claude-code-friendly, -c |
Remove $ prefix from OData parameters for Claude Code CLI compatibility | false |
Variable | Description |
---|---|
ODATA_SERVICE_URL or ODATA_URL |
OData service URL |
ODATA_USERNAME or ODATA_USER |
Username for basic auth |
ODATA_PASSWORD or ODATA_PASS |
Password for basic auth |
ODATA_COOKIE_FILE |
Path to cookie file |
ODATA_COOKIE_STRING |
Cookie string |
Create a .env
file in the working directory:
ODATA_SERVICE_URL=https://my-service.com/odata/
ODATA_USERNAME=admin
ODATA_PASSWORD=secret
The bridge automatically generates MCP tools based on the OData service metadata:
For each entity set, the following tools are generated (if the entity set supports the operation):
filter_{EntitySet}
- List/filter entities with OData query optionscount_{EntitySet}
- Get count of entities with optional filtersearch_{EntitySet}
- Full-text search (if supported by the service)get_{EntitySet}
- Get a single entity by keycreate_{EntitySet}
- Create a new entity (if allowed)update_{EntitySet}
- Update an existing entity (if allowed)delete_{EntitySet}
- Delete an entity (if allowed)
Each function import is mapped to an individual tool with the function name.
odata_service_info
- Get metadata and capabilities of the OData service
# Connect to the public Northwind OData v2 service
./odata-mcp --trace https://services.odata.org/V2/Northwind/Northwind.svc/
# This will show generated tools like:
# - filter_Products_for_northwind
# - get_Products_for_northwind
# - filter_Categories_for_northwind
# - get_Orders_for_northwind
# - etc.
# Connect to the public Northwind OData v4 service
./odata-mcp --trace https://services.odata.org/V4/Northwind/Northwind.svc/
# OData v4 is automatically detected and handled appropriately
# Supports v4 specific features like:
# - $count parameter instead of $inlinecount
# - contains() filter function
# - New data types (Edm.Date, Edm.TimeOfDay, etc.)
# Connect to SAP service with CSRF token support
./odata-mcp --user admin --password secret \
https://my-sap-system.com/sap/opu/odata/sap/SERVICE_NAME/
While maintaining the same CLI interface and functionality, this Go implementation offers:
- Better Performance: Native compiled binary with lower memory usage
- Easier Deployment: Single binary with no runtime dependencies
- Cross-Platform: Native binaries for Windows, macOS, and Linux
- Type Safety: Go's type system provides better reliability
- Simpler Installation: No need for Python runtime or package management
This project uses automatic versioning based on git tags and commit history:
- Tagged releases: Uses git tags (e.g.,
v1.0.0
) - Development builds: Uses
0.1.<commit-count>
format - Uncommitted changes: Appends
-dirty
suffix
# Check current version
make version
# Create a release
git tag -a v1.0.0 -m "Release v1.0.0"
git push origin v1.0.0
See VERSIONING.md for detailed versioning guide.
This project uses automated GitHub Actions for releases. See RELEASING.md for the release process.
If you're experiencing issues with MCP clients (Claude Desktop, RooCode, GitHub Copilot):
-
Enable trace logging to diagnose protocol issues:
./odata-mcp --trace-mcp https://my-service.com/odata/
Then check the trace file in your temp directory.
-
Common issues and solutions:
- Tools not appearing: Ensure the service URL is correct and accessible
- Validation errors: Update to the latest version which includes MCP compliance fixes
- Connection failures: Check authentication credentials and network connectivity
-
Service-specific hints: The
odata_service_info
tool now includes automatic hints for known problematic services
See TROUBLESHOOTING.md for detailed troubleshooting guide.
The OData MCP bridge includes a sophisticated hint system that helps users work around known service issues and provides implementation guidance.
Create a hints.json
file with the following structure:
{
"version": "1.0",
"hints": [
{
"pattern": "*/sap/opu/odata/*",
"priority": 10,
"service_type": "SAP OData Service",
"known_issues": ["List of known issues"],
"workarounds": ["List of workarounds"],
"field_hints": {
"FieldName": {
"type": "Edm.String",
"format": "Expected format",
"example": "12345",
"description": "Field description"
}
},
"examples": [
{
"description": "Example description",
"query": "filter_EntitySet with $filter=...",
"note": "Additional note"
}
]
}
]
}
The hint system supports wildcard patterns:
*
matches any sequence of characters?
matches a single character- Multiple patterns can match the same service (hints are merged by priority)
The bridge includes default hints for common services:
- SAP OData Services (
*/sap/opu/odata/*
): General SAP OData guidance including the critical workaround for HTTP 501 errors using$expand
- SAP PO Tracking (
*SRA020_PO_TRACKING_SRV*
): Specific hints for purchase order tracking including field formatting - Northwind Demo (
*Northwind*
): Identifies the public demo service
Hints appear in the odata_service_info
tool response under implementation_hints
:
# View hints for your service
./odata-mcp https://my-service.com/odata/
# Then call the odata_service_info tool in your MCP client
# The response includes:
{
"implementation_hints": {
"service_type": "SAP OData Service",
"known_issues": [...],
"workarounds": [...],
"field_hints": {...},
"examples": [...],
"hint_source": "Hints file: hints.json"
}
}
This project includes comprehensive security measures to prevent credential leaks. See SECURITY.md for details.
Important: Never commit .zmcp.json
or any files containing real credentials.
- QUICK_REFERENCE.md - Quick command reference
- HINTS.md - Complete guide to the service hints system
- TROUBLESHOOTING.md - Common issues and solutions
- SECURITY.md - Security considerations
- CHANGELOG.md - Version history and changes
Contributions are welcome! Please feel free to submit issues and pull requests.
For questions and community discussion, visit our GitHub Discussions.
For development setup and testing:
# Run tests
make test
# Run with verbose output for debugging
./odata-mcp --verbose --trace-mcp https://my-service.com/odata/
# Check MCP compliance
./simple_compliance_test.sh
This project is licensed under the MIT License - see the LICENSE file for details.