Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions docs/mcp/harnesses.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,11 @@ Only tool names and server instructions load at session start; the model calls
- `ENABLE_TOOL_SEARCH` accepts `true`, `false`, `auto`, and `auto:N`.
- Older models load everything up front. So do sessions with
`CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS`, HIPAA sessions, and Azure Foundry.
- A server can keep chosen tools loaded with `_meta["anthropic/alwaysLoad"]`,
for example `get_sentry_resource`. The key is specific to Claude Code, and
long-term support is uncertain.
- A server can keep chosen tools loaded with `_meta["anthropic/alwaysLoad"]`.
We set it on `get_sentry_resource` only, through the tool's `_meta` config,
so a pasted Sentry URL works without a tool search first. The key is specific
to Claude Code, and long-term support is uncertain. A user's server-level
`alwaysLoad` setting can override it.
- Description caps: 4,096 characters for upfront tools and server instructions,
16,384 for deferred tools.
- No fixed tool cap; the context window is the limit.
Expand Down
2 changes: 2 additions & 0 deletions packages/mcp-core/scripts/measure-token-cost.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ type ToolDefinition = {
idempotentHint?: boolean;
openWorldHint?: boolean;
};
_meta?: Record<string, unknown>;
};

/**
Expand Down Expand Up @@ -94,6 +95,7 @@ function formatToolsForMCP(tools: Record<string, ToolDefinition>) {
}),
inputSchema: jsonSchema,
...(tool.annotations && { annotations: tool.annotations }),
...(tool._meta && { _meta: tool._meta }),
};
});
}
Expand Down
13 changes: 13 additions & 0 deletions packages/mcp-core/src/server.all-tools.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,19 @@ describe.skipIf(!EXPOSE_ALL_TOOLS)("buildServer with EXPOSE_ALL_TOOLS", () => {
}
});

it("asks Claude Code to load only get_sentry_resource upfront", async () => {
const listed = await withClient(
getContext(),
async (client) => (await client.listTools()).tools,
);

expect(
listed
.filter((tool) => tool._meta)
.map((tool) => [tool.name, tool._meta]),
).toEqual([["get_sentry_resource", { "anthropic/alwaysLoad": true }]]);
});

it("lists the replacements of deprecated tools instead of the tools", async () => {
const toolNames = await listToolNames(getContext());
const deprecatedTools = Object.values(tools).filter(
Expand Down
1 change: 1 addition & 0 deletions packages/mcp-core/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,7 @@ function configureServer({
inputSchema: filteredInputSchema,
outputSchema: tool.outputSchema,
annotations: tool.annotations,
_meta: tool._meta,
};
const handleToolCall = async (params: unknown): Promise<CallToolResult> => {
// Get the active MCP server span and attach request-scoped attributes.
Expand Down
3 changes: 3 additions & 0 deletions packages/mcp-core/src/tools/catalog/get-sentry-resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,9 @@ export default defineTool({
destructiveHint: false,
openWorldHint: true,
},
// Users often start from a pasted Sentry URL, so Claude Code keeps this tool
// loaded instead of deferring it behind tool search.
_meta: { "anthropic/alwaysLoad": true },

async handler(params, context: ServerContext) {
const url = params.url ?? params.issueUrl ?? params.resourceUrl;
Expand Down
5 changes: 5 additions & 0 deletions packages/mcp-core/src/tools/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,11 @@ export interface ToolConfig<
idempotentHint?: boolean;
openWorldHint: boolean;
};
/**
* Client-specific tool metadata exported as `_meta` in tools/list, such as
* `anthropic/alwaysLoad` (see docs/mcp/harnesses.md).
*/
_meta?: Record<string, unknown>;
handler: ToolHandler<TSchema, ToolOutputFor<TOutputSchema>>;
/**
* Optional hook invoked when the handler throws, for tool-specific failure
Expand Down
Loading