🐞 Bug Summary
IBM Context Forge Gateway rejects 5 critical Loki query tools during backend registration due to overly strict validation that flags backtick (`) characters in tool descriptions as "unsafe". This results in only 7 out of 12 tools being exposed through the gateway, blocking all primary log querying functionality.
🧩 Affected Component
Select the area of the project impacted:
Specific Component: mcpgateway.services.gateway_service - Tool validation during backend registration
🔁 Steps to Reproduce
-
Deploy Grafana MCP server (grafana/mcp-grafana:latest) with Loki datasource enabled:
kubectl apply -f k8s/loki-mcp-server.yaml
-
Register the Loki MCP server as a gateway backend:
curl -X POST \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "loki_ws4r1_streamable",
"url": "http://<gateway-ip>/loki-mcp/mcp",
"description": "WS4R1 Loki MCP Server",
"transport": "STREAMABLEHTTP"
}' \
http://<gateway-ip>/mcp-gateway/gateways
-
Query the MCP Gateway for available tools:
curl -X POST "http://<gateway-ip>/mcp-gateway/mcp/" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{"jsonrpc":"2.0","method":"tools/list","params":{},"id":1}'
-
Observe only 7 tools returned instead of 12
-
Check gateway logs for validation errors:
kubectl logs -n common -l app=mcp-gateway | grep "Validation failed"
🤔 Expected Behavior
Expected: All 12 tools from Grafana MCP server should be registered and exposed:
Loki Query Tools (5) - MISSING:
query_loki_logs - Execute LogQL queries
list_loki_label_names - List available log labels
list_loki_label_values - List values for specific labels
query_loki_stats - Get log stream statistics
query_loki_patterns - Query detected log patterns
Non-Loki Tools (7) - Working:
get_annotations - Fetch Grafana annotations
get_annotation_tags - List annotation tags
get_datasource_by_name - Get datasource by name
get_datasource_by_uid - Get datasource by UID
list_datasources - List all datasources
search_dashboards - Search dashboards
search_folders - Search folders
Actual: Only 7 tools registered. All Loki query tools are rejected during validation.
📓 Logs / Error Output
2026-01-29T19:24:42 - mcpgateway.services.gateway_service - ERROR - Validation failed for tool 'list_loki_label_names': [{'type': 'value_error', 'loc': ('description',), 'msg': "Value error, Description contains unsafe characters: '`'", 'input': 'Lists all available label names (keys) found in logs within a specified Loki datasource and time range. Returns a list of unique label strings (e.g., `["app", "env", "pod"]`). If the time range is not provided, it defaults to the last hour.', 'ctx': {'error': ValueError("Description contains unsafe characters: '`'")}, 'url': 'https://errors.pydantic.dev/2.12/v/value_error'}]
2026-01-29T19:24:42 - mcpgateway.services.gateway_service - ERROR - Validation failed for tool 'list_loki_label_values': [{'type': 'value_error', 'loc': ('description',), 'msg': "Value error, Description contains unsafe characters: '`'", 'input': 'Retrieves all unique values associated with a specific `labelName` within a Loki datasource and time range. Returns a list of string values (e.g., for `labelName="env"`, might return `["prod", "staging", "dev"]`). Useful for discovering filter options. Defaults to the last hour if the time range is omitted.', 'ctx': {'error': ValueError("Description contains unsafe characters: '`'")}, 'url': 'https://errors.pydantic.dev/2.12/v/value_error'}]
2026-01-29T19:24:42 - mcpgateway.services.gateway_service - ERROR - Validation failed for tool 'query_loki_logs': [{'type': 'value_error', 'loc': ('description',), 'msg': "Value error, Description contains unsafe characters: '`'", 'input': 'Executes a LogQL query against a Loki datasource to retrieve log entries or metric values. Returns a list of results, each containing a timestamp, labels, and either a log line (`line`) or a numeric metric value (`value`). Defaults to the last hour, a limit of 10 entries, and \'backward\' direction (newest first). Supports full LogQL syntax for log and metric queries (e.g., `{app="foo"} |= "error"`, `rate({app="bar"}[1m])`). Prefer using `query_loki_stats` first to check stream size and `list_loki_label_names` and `list_loki_label_values` to verify labels exist.', 'ctx': {'error': ValueError("Description contains unsafe characters: '`'")}, 'url': 'https://errors.pydantic.dev/2.12/v/value_error'}]
2026-01-29T19:24:42 - mcpgateway.services.gateway_service - ERROR - Validation failed for tool 'query_loki_patterns': [{'type': 'value_error', 'loc': ('description',), 'msg': "Value error, Description contains unsafe characters: '`'", 'input': 'Retrieves detected log patterns from a Loki datasource for a given stream selector and time range. Returns a list of patterns, each containing a pattern string and a total count of occurrences. Patterns help identify common log structures and anomalies. The `logql` parameter must be a stream selector (e.g., `{job="nginx"}`) and does not support line filters or aggregations. Defaults to the last hour if the time range is omitted.', 'ctx': {'error': ValueError("Description contains unsafe characters: '`'")}, 'url': 'https://errors.pydantic.dev/2.12/v/value_error'}]
2026-01-29T19:24:42 - mcpgateway.services.gateway_service - ERROR - Validation failed for tool 'query_loki_stats': [{'type': 'value_error', 'loc': ('description',), 'msg': "Value error, Description contains unsafe characters: '`'", 'input': 'Retrieves statistics about log streams matching a given LogQL *selector* within a Loki datasource and time range. Returns an object containing the count of streams, chunks, entries, and total bytes (e.g., `{"streams": 5, "chunks": 50, "entries": 10000, "bytes": 512000}`). The `logql` parameter **must** be a simple label selector (e.g., `{app="nginx", env="prod"}`) and does not support line filters, parsers, or aggregations. Defaults to the last hour if the time range is omitted.', 'ctx': {'error': ValueError("Description contains unsafe characters: '`'")}, 'url': 'https://errors.pydantic.dev/2.12/v/value_error'}]
2026-01-29T19:24:42 - mcpgateway.services.gateway_service - WARNING - Tool validation completed with 5 error(s). Successfully validated 7 tool(s).
2026-01-29T19:24:42 - mcpgateway.services.gateway_service - INFO - Fetched 7 tools from gateway
Database verification:
$ kubectl exec -n common deployment/database -- psql -U postgres -d mcp \
-c "SELECT COUNT(*) FROM tools WHERE name LIKE '%loki%';"
total_tools
-------------
7
(1 row)
Direct Loki MCP server query shows all 12 tools:
$ curl -X POST "http://<gateway-ip>/loki-mcp/mcp" \
-d '{"jsonrpc":"2.0","method":"tools/list","params":{},"id":2}' | \
jq -r '.result.tools[] | .name' | wc -l
12
🧠 Environment Info
| Key |
Value |
| Version or commit |
ghcr.io/ibm/mcp-context-forge:1.0.0-BETA-2 |
| Runtime |
Python 3.11 (inferred from Pydantic v2.12) |
| Platform / OS |
Kubernetes/K3s on Ubuntu 22.04 |
| Container |
Docker (deployed in K3s cluster) |
| Backend MCP Server |
grafana/mcp-grafana:latest (v0.9.0) |
| Backend Transport |
STREAMABLEHTTP |
| Gateway Deployment |
Namespace: common, LoadBalancer: <gateway-ip> |
🧩 Additional Context
Root Cause Analysis
The validation error originates from Pydantic model validation in mcpgateway.services.gateway_service. The validator checks for "unsafe characters" in tool descriptions and rejects backticks (`).
Why Grafana MCP uses backticks:
Grafana MCP server uses backticks in descriptions for:
- Code examples:
`{app="foo"}`
- JSON examples:
`{"streams": 5}`
- Array examples:
`["app", "env"]`
- Parameter references:
`labelName`
This is standard Markdown/documentation formatting.
Impact
Critical: All primary Loki functionality is unavailable through the gateway:
- ❌ Cannot query logs
- ❌ Cannot discover labels
- ❌ Cannot get stream statistics
- ❌ Cannot analyze log patterns
- ✅ Can only list datasources and search dashboards (limited utility)
Workarounds
Temporary workaround: Connect directly to Loki MCP server (bypasses gateway):
{
"servers": {
"loki-direct": {
"type": "http",
"url": "http://<gateway-ip>/loki-mcp/mcp"
}
}
}
This works but defeats the purpose of using the gateway for aggregation, authentication, and observability.
Proposed Solutions
Option 1: Relax validation to allow backticks (RECOMMENDED)
- Backticks are safe in descriptions (not executed code)
- Standard in documentation and Markdown
- Matches MCP specification (no restriction on description content)
Option 2: Add configuration flag to disable strict validation
GATEWAY_STRICT_TOOL_VALIDATION: "false"
Option 3: Sanitize descriptions during registration
- Strip or escape backticks before validation
- Preserves security while allowing tool registration
- May reduce description clarity
Related Documentation
Testing Commands
Verify Loki MCP server tools directly:
SESSION_ID=$(curl -s -X POST "http://<gateway-ip>/loki-mcp/mcp" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}},"id":1}' \
-D - | grep -i "mcp-session-id" | cut -d' ' -f2 | tr -d '\r\n')
curl -s -X POST "http://<gateway-ip>/loki-mcp/mcp" \
-H "Mcp-Session-Id: $SESSION_ID" \
-d '{"jsonrpc":"2.0","method":"tools/list","params":{},"id":2}' | \
jq -r '.result.tools[] | .name' | sort
Expected output: 12 tools including query_loki_logs, list_loki_label_names, etc.
Verify gateway-exposed tools:
SESSION_ID=$(curl -s -X POST "http://<gateway-ip>/mcp-gateway/mcp/" \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json" \
-d '{"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}},"id":1}' \
-D - | grep -i "mcp-session-id" | cut -d' ' -f2 | tr -d '\r')
curl -s -X POST "http://<gateway-ip>/mcp-gateway/mcp/" \
-H "Authorization: Bearer $TOKEN" \
-H "Accept: application/json" \
-H "Mcp-Session-Id: $SESSION_ID" \
-d '{"jsonrpc":"2.0","method":"tools/list","params":{},"id":2}' | \
jq -r '.result.tools[] | .name' | sort
Current output: 7 tools (missing all query_loki_* and list_loki_* tools)
🐞 Bug Summary
IBM Context Forge Gateway rejects 5 critical Loki query tools during backend registration due to overly strict validation that flags backtick (`) characters in tool descriptions as "unsafe". This results in only 7 out of 12 tools being exposed through the gateway, blocking all primary log querying functionality.
🧩 Affected Component
Select the area of the project impacted:
mcpgateway- API (Gateway Service - Tool Validation)mcpgateway- UI (admin panel)mcpgateway.wrapper- stdio wrapperSpecific Component:
mcpgateway.services.gateway_service- Tool validation during backend registration🔁 Steps to Reproduce
Deploy Grafana MCP server (grafana/mcp-grafana:latest) with Loki datasource enabled:
Register the Loki MCP server as a gateway backend:
Query the MCP Gateway for available tools:
Observe only 7 tools returned instead of 12
Check gateway logs for validation errors:
🤔 Expected Behavior
Expected: All 12 tools from Grafana MCP server should be registered and exposed:
Loki Query Tools (5) - MISSING:
query_loki_logs- Execute LogQL querieslist_loki_label_names- List available log labelslist_loki_label_values- List values for specific labelsquery_loki_stats- Get log stream statisticsquery_loki_patterns- Query detected log patternsNon-Loki Tools (7) - Working:
get_annotations- Fetch Grafana annotationsget_annotation_tags- List annotation tagsget_datasource_by_name- Get datasource by nameget_datasource_by_uid- Get datasource by UIDlist_datasources- List all datasourcessearch_dashboards- Search dashboardssearch_folders- Search foldersActual: Only 7 tools registered. All Loki query tools are rejected during validation.
📓 Logs / Error Output
Database verification:
Direct Loki MCP server query shows all 12 tools:
🧠 Environment Info
ghcr.io/ibm/mcp-context-forge:1.0.0-BETA-2grafana/mcp-grafana:latest(v0.9.0)common, LoadBalancer:<gateway-ip>🧩 Additional Context
Root Cause Analysis
The validation error originates from Pydantic model validation in
mcpgateway.services.gateway_service. The validator checks for "unsafe characters" in tool descriptions and rejects backticks (`).Why Grafana MCP uses backticks:
Grafana MCP server uses backticks in descriptions for:
`{app="foo"}``{"streams": 5}``["app", "env"]``labelName`This is standard Markdown/documentation formatting.
Impact
Critical: All primary Loki functionality is unavailable through the gateway:
Workarounds
Temporary workaround: Connect directly to Loki MCP server (bypasses gateway):
{ "servers": { "loki-direct": { "type": "http", "url": "http://<gateway-ip>/loki-mcp/mcp" } } }This works but defeats the purpose of using the gateway for aggregation, authentication, and observability.
Proposed Solutions
Option 1: Relax validation to allow backticks (RECOMMENDED)
Option 2: Add configuration flag to disable strict validation
Option 3: Sanitize descriptions during registration
Related Documentation
Testing Commands
Verify Loki MCP server tools directly:
Expected output: 12 tools including query_loki_logs, list_loki_label_names, etc.
Verify gateway-exposed tools:
Current output: 7 tools (missing all query_loki_* and list_loki_* tools)