Skip to content
Merged
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
39 changes: 39 additions & 0 deletions docs/adding-tools.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,51 @@ export default defineTool({
regionUrl: z.string().optional().describe("Optional region URL"),
yourParam: z.string().describe("What values are expected"),
},
annotations: {
readOnlyHint: true,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
// Implementation here
},
});
```

### Safety Annotations

**REQUIRED**: All tools must include safety annotations for MCP directory compliance.

**Available annotations:**
- `readOnlyHint` (boolean): Tool doesn't modify data
- `destructiveHint` (boolean): Tool may modify/delete existing data
- `idempotentHint` (boolean): Repeated calls with same arguments have no additional effect
- `openWorldHint` (boolean): Tool interacts with external services (default: true for API calls)

**Annotation patterns:**

```typescript
// Read-only tools (queries, lists, searches)
annotations: {
readOnlyHint: true,
openWorldHint: true,
}

// Create tools (additive, non-destructive)
annotations: {
readOnlyHint: false,
destructiveHint: false,
openWorldHint: true,
}

// Update tools (modify existing data)
annotations: {
readOnlyHint: false,
destructiveHint: true,
idempotentHint: true, // Same update twice = same result
openWorldHint: true,
}
```

### Writing LLM-Friendly Descriptions

Critical for LLM success:
Expand Down
1 change: 1 addition & 0 deletions packages/mcp-server/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,7 @@ export async function configureServer({
tool.name,
tool.description,
modifiedInputSchema,
tool.annotations,
async (
params: any,
extra: RequestHandlerExtra<ServerRequest, ServerNotification>,
Expand Down
5 changes: 5 additions & 0 deletions packages/mcp-server/src/tools/analyze-issue-with-seer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ export default defineTool({
.describe("Optional custom instruction for the AI analysis")
.optional(),
},
annotations: {
readOnlyHint: false,
destructiveHint: false,
openWorldHint: true,
},
Comment thread
codyde marked this conversation as resolved.
Comment thread
codyde marked this conversation as resolved.
async handler(params, context: ServerContext) {
const apiService = apiServiceFromContext(context, {
regionUrl: params.regionUrl,
Expand Down
5 changes: 5 additions & 0 deletions packages/mcp-server/src/tools/create-dsn.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ export default defineTool({
.trim()
.describe("The name of the DSN to create, for example 'Production'."),
},
annotations: {
readOnlyHint: false,
destructiveHint: false,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
const apiService = apiServiceFromContext(context, {
regionUrl: params.regionUrl,
Expand Down
5 changes: 5 additions & 0 deletions packages/mcp-server/src/tools/create-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ export default defineTool({
),
platform: ParamPlatform.optional(),
},
annotations: {
readOnlyHint: false,
destructiveHint: false,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
const apiService = apiServiceFromContext(context, {
regionUrl: params.regionUrl,
Expand Down
5 changes: 5 additions & 0 deletions packages/mcp-server/src/tools/create-team.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ export default defineTool({
regionUrl: ParamRegionUrl.optional(),
name: z.string().trim().describe("The name of the team to create."),
},
annotations: {
readOnlyHint: false,
destructiveHint: false,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
const apiService = apiServiceFromContext(context, {
regionUrl: params.regionUrl,
Expand Down
4 changes: 4 additions & 0 deletions packages/mcp-server/src/tools/find-dsns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ export default defineTool({
regionUrl: ParamRegionUrl.optional(),
projectSlug: ParamProjectSlug,
},
annotations: {
readOnlyHint: true,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
const apiService = apiServiceFromContext(context, {
regionUrl: params.regionUrl,
Expand Down
4 changes: 4 additions & 0 deletions packages/mcp-server/src/tools/find-organizations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ export default defineTool({
inputSchema: {
query: ParamSearchQuery.optional(),
},
annotations: {
readOnlyHint: true,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
// User data endpoints (like /users/me/regions/) should never use regionUrl
// as they must always query the main API server, not region-specific servers
Expand Down
4 changes: 4 additions & 0 deletions packages/mcp-server/src/tools/find-projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ export default defineTool({
regionUrl: ParamRegionUrl.optional(),
query: ParamSearchQuery.optional(),
},
annotations: {
readOnlyHint: true,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
const apiService = apiServiceFromContext(context, {
regionUrl: params.regionUrl,
Expand Down
4 changes: 4 additions & 0 deletions packages/mcp-server/src/tools/find-releases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ export default defineTool({
.describe("Search for versions which contain the provided string.")
.optional(),
},
annotations: {
readOnlyHint: true,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
const apiService = apiServiceFromContext(context, {
regionUrl: params.regionUrl,
Expand Down
4 changes: 4 additions & 0 deletions packages/mcp-server/src/tools/find-teams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ export default defineTool({
regionUrl: ParamRegionUrl.optional(),
query: ParamSearchQuery.optional(),
},
annotations: {
readOnlyHint: true,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
const apiService = apiServiceFromContext(context, {
regionUrl: params.regionUrl,
Expand Down
4 changes: 4 additions & 0 deletions packages/mcp-server/src/tools/get-doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ export default defineTool({
"The documentation path (e.g., '/platforms/javascript/guides/nextjs.md'). Get this from search_docs results.",
),
},
annotations: {
readOnlyHint: true,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
setTag("doc.path", params.path);

Expand Down
4 changes: 4 additions & 0 deletions packages/mcp-server/src/tools/get-event-attachment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,10 @@ export default defineTool({
attachmentId: ParamAttachmentId.optional(),
regionUrl: ParamRegionUrl.optional(),
},
annotations: {
readOnlyHint: true,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
const apiService = apiServiceFromContext(context, {
regionUrl: params.regionUrl,
Expand Down
4 changes: 4 additions & 0 deletions packages/mcp-server/src/tools/get-issue-details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ export default defineTool({
eventId: z.string().trim().describe("The ID of the event.").optional(),
issueUrl: ParamIssueUrl.optional(),
},
annotations: {
readOnlyHint: true,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
const apiService = apiServiceFromContext(context, {
regionUrl: params.regionUrl,
Expand Down
4 changes: 4 additions & 0 deletions packages/mcp-server/src/tools/get-trace-details.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ export default defineTool({
regionUrl: ParamRegionUrl.optional(),
traceId: ParamTraceId,
},
annotations: {
readOnlyHint: true,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
// Validate trace ID format
if (!/^[0-9a-fA-F]{32}$/.test(params.traceId)) {
Expand Down
4 changes: 4 additions & 0 deletions packages/mcp-server/src/tools/search-docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ export default defineTool({
.optional(),
guide: ParamSentryGuide.optional(),
},
annotations: {
readOnlyHint: true,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
let output = `# Documentation Search Results\n\n`;
output += `**Query**: "${params.query}"\n`;
Expand Down
4 changes: 4 additions & 0 deletions packages/mcp-server/src/tools/search-events/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ export default defineTool({
.default(false)
.describe("Include explanation of how the query was translated"),
},
annotations: {
readOnlyHint: true,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
const apiService = apiServiceFromContext(context, {
regionUrl: params.regionUrl,
Expand Down
4 changes: 4 additions & 0 deletions packages/mcp-server/src/tools/search-issues/handler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ export default defineTool({
.default(false)
.describe("Include explanation of how the query was translated"),
},
annotations: {
readOnlyHint: true,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
const apiService = apiServiceFromContext(context, {
regionUrl: params.regionUrl,
Expand Down
6 changes: 6 additions & 0 deletions packages/mcp-server/src/tools/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ export interface ToolConfig<
description: string;
inputSchema: TSchema;
requiredScopes: Scope[];
annotations: {
readOnlyHint?: boolean;
destructiveHint?: boolean;
idempotentHint?: boolean;
openWorldHint?: boolean;
};
handler: (
params: z.infer<z.ZodObject<TSchema>>,
context: ServerContext,
Expand Down
6 changes: 6 additions & 0 deletions packages/mcp-server/src/tools/update-issue.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ export default defineTool({
status: ParamIssueStatus.optional(),
assignedTo: ParamAssignedTo.optional(),
},
annotations: {
readOnlyHint: false,
destructiveHint: true,
idempotentHint: true,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
const apiService = apiServiceFromContext(context, {
regionUrl: params.regionUrl,
Expand Down
6 changes: 6 additions & 0 deletions packages/mcp-server/src/tools/update-project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ export default defineTool({
"The team to assign this project to. Note: this will replace the current team assignment.",
),
},
annotations: {
readOnlyHint: false,
destructiveHint: true,
idempotentHint: true,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
const apiService = apiServiceFromContext(context, {
regionUrl: params.regionUrl,
Expand Down
4 changes: 4 additions & 0 deletions packages/mcp-server/src/tools/whoami.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ export default defineTool({
].join("\n"),
inputSchema: {},
requiredScopes: [], // No specific scopes required - uses authentication token
annotations: {
readOnlyHint: true,
openWorldHint: true,
},
async handler(params, context: ServerContext) {
// User data endpoints (like /auth/) should never use regionUrl
// as they must always query the main API server, not region-specific servers
Expand Down
Loading