Skip to content

Server capabilities not advertised — MCP Inspector shows "no capabilities" #2

@dzuluaga

Description

@dzuluaga

The server always returns empty capabilities {} in the initialize response, even when tools, prompts, or resources are registered. This causes MCP clients (including the official MCP Inspector) to disable their Tools/Prompts/Resources tabs.

Steps to Reproduce

  1. Register tools via server->AddTool(...)
  2. Start server
  3. Send initialize request
  4. Response:
{
  "result": {
    "capabilities": {},  // <-- empty, should show {"tools": {}}
    "serverInfo": {"name": "...", "version": "..."}
  }
}
  1. MCP Inspector shows "The connected server does not support any MCP capabilities" and grays out all tabs

Root Cause

Two issues:

1. Serializer hardcodes empty object — In src/shared/jsonrpc.cpp, the InitializeResult serializer:

// Line ~90 in adl_serializer<Mcp::InitializeResult>::to_json
j["capabilities"] = json::object();  // Always empty, ignores r.capabilities

This ignores the actual r.capabilities field entirely.

2. Capabilities never setServerSession::SetServerCapabilities() exists but is never called anywhere in the codebase. Even if the serializer is fixed, capabilities would still be empty because no code sets them when tools are registered.

Proposed Fix

Fix 1 — Serialize actual capabilities (src/shared/jsonrpc.cpp):

j["capabilities"] = json::object();
if (r.capabilities.tools.has_value()) { j["capabilities"]["tools"] = json::object(); }
if (r.capabilities.prompts.has_value()) { j["capabilities"]["prompts"] = json::object(); }
if (r.capabilities.resources.has_value()) { j["capabilities"]["resources"] = json::object(); }

Fix 2 — Auto-set capabilities on session creation (src/server/server_manager.cpp):

After creating a session, set default capabilities:

auto session = std::make_shared<ServerSession>(transport, config_, sessionId);
Mcp::ServerCapabilities caps;
caps.tools = Mcp::ToolsCapabilities{};
session->SetServerCapabilities(caps);

Ideally, capabilities should be set dynamically based on what's registered (tools → tools, prompts → prompts, etc.).

Impact

  • Every MCP server built with this SDK advertises zero capabilities
  • No MCP client can discover the server's tools without prior knowledge
  • MCP Inspector is unusable without this fix
  • This would likely be flagged during LF conformance review

Additional Issue: Case-Sensitive Accept Header

The server's HTTP parser rejects requests with uppercase Accept: header (e.g., Accept: application/json, text/event-stream) but accepts lowercase accept:. Per RFC 7230, HTTP headers are case-insensitive. This prevents the MCP Inspector and browsers from connecting directly — a CORS proxy is needed as a workaround.

Location: src/server/transport/streamable_http_server_transport.cpp, line ~185.

Environment

  • MCP C++ SDK from openJiuwen-ai/agent-protocol
  • Tested via MCP Inspector v0.21.1, curl, and custom web UI

Tools shows grayed out (this image contains the fixes above to fix this issue)
Image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions