OData MCP Bridge (Go)
About
A Go bridge providing universal access to OData v2 services through MCP tools, with support for multiple authentication methods.
Details
- Author
- oisee
- Categories
- Database, API, Other
Jump to
Using Environment Variables (More Secure)
{ "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. Theenvfield in the configuration sets environment variables specifically for that MCP server process.
Operation Filtering Configuration Examples
{ "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" ] } } } ### AI Foundry Configuration For AI Foundry integration, use the --protocol-version flag to specify the 2025-06-18 protocol: json { "mcpServers": { "odata-for-ai-foundry": { "command": "/usr/local/bin/odata-mcp", "args": [ "--service", "https://your-odata-service.com/", "--protocol-version", "2025-06-18", "--user", "your-username", "--password", "your-password" ] } } }
./odata-mcp --service https://your-service.com/odata --protocol-version "2025-06-18"
``
See the[AI Foundry Compatibility Guidefor detailed setup instructions.
The OData MCP bridge supports two transport mechanisms:
- STDIO (default)- Standard input/output communication, used by Claude Desktop
- HTTP/SSE- HTTP server with Server-Sent Events for web-based clients
πSECURITY MODEL: HTTP transport uses a strict security model.
- Localhost: Token required (
--mcp-token)
- Non-localhost: Token + TLS required, no exceptions
- All interfaces (0.0.0.0/::): Requires--allow-all-interfaces+ token + TLS
Token can be any string - for dev,
--mcp-token dev`works fine.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.
Universal Tool Mode β One Tool to Rule Them All
The biggest addition isUniversal Tool Mode(--universal), a game-changer for large OData services:
# Before: 485 tools, ~37,000 tokens, Claude says "no API available" ./odata-mcp https://large-sap-service.com/odata/ # After: 1 tool, ~900 tokens, works perfectly ./odata-mcp --universal https://large-sap-service.com/odata/
Why is it opt-in?Universal mode changes how you interact with OData:
- Standard mode: Each entity gets dedicated tools (filter_Products,get_Orders, etc.)
- Universal mode: Oneodatatool withaction,target, andparams
- Backward compatibilityβ existing configs and workflows continue working
- Discoverabilityβ per-entity tools are self-documenting; LLMs can see exactly what's available
- Simplicity for small servicesβ if you have 20 tools, per-entity mode works great
- Explicit choiceβ users should consciously choose the trade-off
- Service has 50+ entity sets
- Running multiple OData services simultaneously
- Experiencing "no API available" or tool selection failures
- Want minimal token footprint
SeeUniversal Tool Architecturefor the full story.
New--forward-mcp-headersflag enables passing HTTP headers from MCP clients to OData services:
./odata-mcp --transport streamable-http --forward-mcp-headers https://secured-service.com/odata/
- Dynamic authenticationβ pass credentials per-request instead of at startup
- Multi-tenant scenariosβ different users with different tokens
- Custom headersβX-headers flow through to OData
- AI Foundry Compatibility(v1.5.1):--protocol-versionflag for AI Foundry's2025-06-18protocol
- SAP GUID Filtering(v1.5.0): Automaticguid'...'formatting for SAP services
- Streamable HTTP Transport(v1.5.0): Modern MCP protocol with--transport streamable-http
Download the appropriate binary for your platform from thereleases page.
- 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
Building in WSL (Windows Subsystem for Linux)
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/binexists 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" ] } } }
Using Environment Variables (More Secure)
{ "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. Theenvfield in the configuration sets environment variables specifically for that MCP server process.
Security Best Practices for Claude Desktop
- Use environment variablesin theenvfield rather than hardcoding credentials inargs
- Limit entity accessusing the--entitiesflag to only expose necessary data
- Use read-only accountswhen possible for OData services
- Store configuration file securelywith 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-friendlyflag 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" ] } } }
- $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.
Operation Filtering Configuration Examples
{ "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" ] } } } ### AI Foundry Configuration For AI Foundry integration, use the --protocol-version flag to specify the 2025-06-18 protocol: json { "mcpServers": { "odata-for-ai-foundry": { "command": "/usr/local/bin/odata-mcp", "args": [ "--service", "https://your-odata-service.com/", "--protocol-version", "2025-06-18", "--user", "your-username", "--password", "your-password" ] } } }
./odata-mcp --service https://your-service.com/odata --protocol-version "2025-06-18"
See theAI Foundry Compatibility Guidefor detailed setup instructions.
The OData MCP bridge supports two transport mechanisms:
- STDIO (default)- Standard input/output communication, used by Claude Desktop
- HTTP/SSE- HTTP server with Server-Sent Events for web-based clients
πSECURITY MODEL: HTTP transport uses a strict security model.
- Localhost: Token required (--mcp-token)
- Non-localhost: Token + TLS required, no exceptions
- All interfaces (0.0.0.0/::): Requires--allow-all-interfaces+ token + TLS
Token can be any string - for dev,--mcp-token devworks fine.
Using Streamable HTTP Transport (Modern MCP Protocol)
New in v1.5.0: Support for Streamable HTTP transport (protocol version 2024-11-05)
# 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/
- POST /mcp- Main MCP endpoint (supports automatic SSE upgrade)
- GET /health- Health check endpoint
- POST /sse- Legacy SSE endpoint (for backward compatibility)
# Start server on localhost (default: localhost:8080) ./odata-mcp --transport http --mcp-token "dev" https://services.odata.org/V2/Northwind/Northwind.svc/ # Use custom localhost port ./odata-mcp --transport http --http-addr localhost:3000 --mcp-token "dev" https://services.odata.org/V2/Northwind/Northwind.svc/ # Non-localhost requires token + TLS ./odata-mcp --transport http --http-addr 192.168.1.100:8080 \ --mcp-token "my-secret-token" --tls --tls-cert cert.pem --tls-key key.pem \ https://services.odata.org/V2/Northwind/Northwind.svc/ # All interfaces requires explicit flag + token + TLS ./odata-mcp --transport http --http-addr 0.0.0.0:8080 \ --allow-all-interfaces --mcp-token "my-secret-token" \ --tls --tls-cert cert.pem --tls-key key.pem \ https://services.odata.org/V2/Northwind/Northwind.svc/
- GET /health- Health check endpoint
- GET /sse- Server-Sent Events endpoint for real-time communication
- POST /rpc- JSON-RPC endpoint for request/response communication
# Start the server ./odata-mcp --transport http https://services.odata.org/V2/Northwind/Northwind.svc/ # Open examples/sse_client.html in a web browser
# 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":{}}'
# 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
# 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 operations
- S- Search operations
- F- Filter/list operations
- G- Get (single entity) operations
- U- Update operations
- D- Delete operations
- A- Actions/function imports
- R- 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:--enableand--disablecannot be used together.
For large OData services with many entities, the standard per-entity tool generation can create hundreds of tools, causing:
- Context rot: LLMs struggle to reason when tool count exceeds ~128
- High token usage: Tool schemas can consume 15,000-40,000 tokens
- Tool selection failures: LLMs may report "no API available"
Universal mode solves this by generating a single tool that handles all operations:
# Enable universal tool mode ./odata-mcp --universal https://my-service.com/odata/ # Compare tool counts ./odata-mcp --trace https://my-service.com/odata/ # Standard: many tools ./odata-mcp --universal --trace https://my-service.com/odata/ # Universal: 1 tool
- Service has more than ~50 entity sets
- Using multiple OData services simultaneously
- Experiencing "no API available" errors with large services
{"action": "list", "target": "Products", "params": {"filter": "Price gt 100", "top": 10}} {"action": "get", "target": "Products", "params": {"key": {"ProductID": 1}}} {"action": "create", "target": "Orders", "params": {"data": {"CustomerID": "C001"}}} {"action": "call", "target": "ReleaseOrder", "params": {"OrderID": "O001"}}
# 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/``
Create a
.env`file in the working directory:Sign in to leave a review
Use Google, GitHub, or an email account so ratings stay tied to real people.
No reviews posted yet.





