Advertise richer MCP server capabilities
What we checked
We read the capabilities your server declared in the initialize result and
inspected what it actually exposes over the handshake:
Why it matters
Capabilities are how a client learns what your server can do before it calls anything. The MCP spec defines three server primitives, tools, resources and prompts, so a server that declares just a couple of bare tools is using one of the three primitives and leaving the rest unused. One that also exposes resources, prompts, and structured tool results gives the model typed, machine-readable data it can chain into the next step instead of re-parsing prose.
Structured output is the highest-leverage of these. When a tool returns free
text, the model has to guess at the shape of the answer. When it returns
structured content described by an outputSchema, the client gets a predictable,
typed object: fewer parsing errors, more reliable agent loops.
How to fix it
Declare the capabilities that fit your server and implement them honestly. Concretely: surface more of the core primitives where they’re useful, and have tools return structured output rather than only text. The snippets below are minimal and conceptual; check your SDK version’s docs for the exact structured output API, as it has evolved across releases.
// @modelcontextprotocol/sdk - a tool with an output schema returns
// structured content the client can consume as typed data.
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { z } from "zod";
const server = new McpServer({ name: "my-server", version: "1.0.0" });
server.registerTool(
"get_weather",
{
description: "Current weather for a city.",
inputSchema: { city: z.string().describe("City name, e.g. 'Berlin'") },
// Declaring an output schema is what makes the result 'structured'.
outputSchema: { tempC: z.number(), conditions: z.string() },
},
async ({ city }) => {
const data = { tempC: 21, conditions: "Clear" };
return {
content: [{ type: "text", text: JSON.stringify(data) }],
structuredContent: data,
};
},
);
// McpServer advertises the matching capabilities from what you register. # Official 'mcp' SDK (FastMCP) - a typed return annotation lets the SDK
# generate an output schema and emit structured content automatically.
from pydantic import BaseModel
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("my-server")
class Weather(BaseModel):
temp_c: float
conditions: str
@mcp.tool()
def get_weather(city: str) -> Weather:
"""Current weather for a city."""
return Weather(temp_c=21.0, conditions="Clear")
# Because the tool returns a typed model, FastMCP exposes an outputSchema
# and returns structured content alongside the text. How we re-check
We re-read your declared capabilities and tool outputs on the next capture: a crawl for a hosted endpoint, or a fresh sandbox run of your published package. As you add primitives or return structured content, the coverage and capability signals update on the following score refresh.
Give this to your AI
Paste this into Claude Code (or any coding agent) from inside your server's repository. It states the failing signal, the outcome we re-check for, and the format the fix has to take.
Context: this repository publishes an MCP server, either as a hosted endpoint or as a package on a registry such as npm or PyPI. VerifyMCP's capabilities check found a narrow surface, which means the server uses only a slice of the three MCP primitives (tools, resources, prompts) and its tools return free text rather than typed, structured results. Goal: tools with a natural typed result declare an `outputSchema` and return matching `structuredContent`, so the next capture records structured output, with declared capabilities matching what's implemented. Do this: 1. Audit the registered tools; for each one whose result has an obvious typed shape (numbers, records, lists), add an `outputSchema` (or use an SDK-native typed return, e.g. a Pydantic model in FastMCP) and return `structuredContent` alongside the existing text `content`. 2. Consider whether resources or prompts would genuinely help this server; if so, implement and register them rather than leaving them declared but empty. 3. Re-run the `initialize` handshake and confirm the capability object the SDK advertises now matches what you actually implemented. Rules: - Never declare a capability (`resources`, `prompts`, structured output) the server doesn't actually implement; the check reads the real handshake and tool responses, not the manifest's intentions. - Don't bolt on a prompt or resource you won't maintain purely to raise coverage, a focused tools-only server can be excellent as-is. - Keep `structuredContent` consistent with the text `content` you already return, don't let the two drift apart. Report back: which tools or primitives you changed, and the `initialize` response (or an MCP inspector session) showing the advertised capabilities match the implementation. Reference: https://verifymcp.io/docs/remote/capabilities