Skip to content

Commit 250bcad

Browse files
feat: add API request validator tool
Add validate_api_request_tool to validate Mapbox API requests against endpoint definitions before sending them to the API. Features: - Validates required parameters are present - Checks parameter types (string, number, boolean, array, object) - Validates enum constraints for parameters with allowed values - Verifies token has required scopes for operations - Detects extra/unknown parameters with warnings - Returns detailed validation results with specific error messages - Helps prevent failed API calls by catching issues early Validation coverage: - Path, query, and body parameters - Type checking with clear error messages - Enum validation (e.g., routing profiles, geocoding modes) - Token scope verification - Case-insensitive API and operation names Implementation: - Uses endpoint definitions from mapboxApiEndpoints.ts (from PR #75) - Implements comprehensive validation logic - 19 test cases covering all validation scenarios - Proper MCP structured content with separated text and data - Updated tool registry and documentation This tool builds on top of explore_mapbox_api_tool by using the same endpoint definitions to provide validation capabilities. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent eacd6af commit 250bcad

8 files changed

Lines changed: 989 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@
99
- Optional detailed mode includes example requests and responses
1010
- Complements `get_latest_mapbox_docs_tool` by providing structured API reference data
1111
- No API access required - works with curated endpoint definitions
12+
- **API Request Validator Tool**: New `validate_api_request_tool` validates API requests before sending them
13+
- Validates required parameters are present
14+
- Checks parameter types (string, number, boolean, array, object)
15+
- Validates enum constraints for parameters with allowed values
16+
- Verifies token has required scopes for operations
17+
- Detects extra/unknown parameters with warnings
18+
- Returns detailed validation results with specific error messages
19+
- Helps prevent failed API calls by catching issues early
1220

1321
### Documentation
1422

README.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,24 @@ The `MAPBOX_ACCESS_TOKEN` environment variable is required. **Each tool requires
148148
- "What scopes do I need for the Styles API?"
149149
- "How do I use the directions API? Show me examples"
150150

151+
**validate_api_request_tool** - Validate Mapbox API requests before sending them. Checks that requests have all required parameters, correct types, valid enum values, and required token scopes. Returns detailed validation results to help catch errors early.
152+
153+
**Features:**
154+
155+
- Validates required vs optional parameters
156+
- Checks parameter types (string, number, boolean, array, object)
157+
- Validates enum constraints (e.g., routing profiles must be "driving", "walking", etc.)
158+
- Verifies token has required scopes
159+
- Detects unknown/extra parameters with warnings
160+
- Provides specific error messages for each issue
161+
162+
**Example prompts:**
163+
164+
- "Validate this geocoding request: {parameters}"
165+
- "Check if my token has the right scopes for creating a style"
166+
- "Is this directions API request valid?"
167+
- "What's wrong with this API request?"
168+
151169
### Reference Tools
152170

153171
**get_reference_tool** - Access static Mapbox reference documentation and schemas. This tool provides essential reference information that helps AI assistants understand Mapbox concepts and build correct styles and tokens.

src/tools/toolRegistry.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import { StyleBuilderTool } from './style-builder-tool/StyleBuilderTool.js';
2424
import { StyleComparisonTool } from './style-comparison-tool/StyleComparisonTool.js';
2525
import { TilequeryTool } from './tilequery-tool/TilequeryTool.js';
2626
import { UpdateStyleTool } from './update-style-tool/UpdateStyleTool.js';
27+
import { ValidateApiRequestTool } from './validate-api-request-tool/ValidateApiRequestTool.js';
2728
import { ValidateExpressionTool } from './validate-expression-tool/ValidateExpressionTool.js';
2829
import { ValidateGeojsonTool } from './validate-geojson-tool/ValidateGeojsonTool.js';
2930
import { ValidateStyleTool } from './validate-style-tool/ValidateStyleTool.js';
@@ -55,6 +56,7 @@ export const CORE_TOOLS = [
5556
new GetFeedbackTool({ httpRequest }),
5657
new ListFeedbackTool({ httpRequest }),
5758
new TilequeryTool({ httpRequest }),
59+
new ValidateApiRequestTool(),
5860
new ValidateExpressionTool(),
5961
new ValidateGeojsonTool(),
6062
new ValidateStyleTool()
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { z } from 'zod';
2+
3+
export const ValidateApiRequestInputSchema = z.object({
4+
api: z
5+
.string()
6+
.describe(
7+
'API name to validate against (e.g., "geocoding", "styles", "tokens")'
8+
),
9+
operation: z
10+
.string()
11+
.describe(
12+
'Operation ID to validate (e.g., "forward-geocode", "create-style")'
13+
),
14+
parameters: z
15+
.object({
16+
path: z
17+
.record(z.any())
18+
.optional()
19+
.describe('Path parameters as key-value pairs'),
20+
query: z
21+
.record(z.any())
22+
.optional()
23+
.describe('Query parameters as key-value pairs'),
24+
body: z
25+
.record(z.any())
26+
.optional()
27+
.describe('Body parameters as key-value pairs')
28+
})
29+
.describe('Request parameters to validate'),
30+
tokenScopes: z
31+
.array(z.string())
32+
.optional()
33+
.describe(
34+
'Token scopes to validate (optional). If provided, checks if token has required scopes for the operation.'
35+
)
36+
});
37+
38+
export type ValidateApiRequestInput = z.infer<
39+
typeof ValidateApiRequestInputSchema
40+
>;
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import { z } from 'zod';
2+
3+
const ValidationIssueSchema = z.object({
4+
type: z.enum(['error', 'warning']),
5+
field: z.string(),
6+
message: z.string(),
7+
expected: z.string().optional(),
8+
received: z.any().optional()
9+
});
10+
11+
const ParameterValidationSchema = z.object({
12+
provided: z.number(),
13+
required: z.number(),
14+
optional: z.number(),
15+
missing: z.array(z.string()),
16+
extra: z.array(z.string())
17+
});
18+
19+
const ScopeValidationSchema = z.object({
20+
hasRequired: z.boolean(),
21+
required: z.array(z.string()),
22+
provided: z.array(z.string()).optional(),
23+
missing: z.array(z.string()).optional()
24+
});
25+
26+
// Output schema defines only the structured content
27+
export const ValidateApiRequestOutputSchema = z.object({
28+
valid: z.boolean(),
29+
operation: z.object({
30+
api: z.string(),
31+
operation: z.string(),
32+
method: z.string(),
33+
endpoint: z.string()
34+
}),
35+
issues: z.array(ValidationIssueSchema),
36+
parameters: z.object({
37+
path: ParameterValidationSchema.optional(),
38+
query: ParameterValidationSchema.optional(),
39+
body: ParameterValidationSchema.optional()
40+
}),
41+
scopes: ScopeValidationSchema.optional()
42+
});
43+
44+
export type ValidateApiRequestOutput = z.infer<
45+
typeof ValidateApiRequestOutputSchema
46+
>;

0 commit comments

Comments
 (0)