Skip to content

Fix MCP tool contracts - #116

Draft
portswigger-penguin wants to merge 1 commit into
mainfrom
agent/fix-tool-contracts
Draft

Fix MCP tool contracts#116
portswigger-penguin wants to merge 1 commit into
mainfrom
agent/fix-tool-contracts

Conversation

@portswigger-penguin

Copy link
Copy Markdown
Collaborator

Summary

  • derive required fields from Kotlin constructor defaults and advertise nullable values accurately
  • validate ports, pagination values, random-string length, regexes, and HTTP/2 pseudo-headers before calling Montoya
  • accept whole JSON numbers such as 443.0 for integer parameters and ignore undeclared client arguments
  • return actionable MCP error results instead of exceptions or success-shaped error strings
  • exercise every advertised tool using only the fields its generated schema declares as required

Root cause

Schema generation treated Kotlin nullability as requiredness, while kotlinx.serialization treats constructor defaults as optionality. Nullable properties without defaults—most visibly tabName—were therefore advertised as optional but rejected during deserialization. Other constraints were neither represented in schemas nor checked consistently before reaching downstream APIs.

Impact

Schema-respecting MCP clients can omit optional values safely, clients that encode whole numbers as JSON decimals remain compatible, and invalid tool calls receive an MCP error with a concrete correction instead of an exception or successful-looking string.

Validation

  • ./gradlew test
  • generated-schema integration test invokes every Community and Professional tool with required fields only
  • focused coverage for integer coercion, nullable schemas, numeric constraints, regex errors, ports, pagination, and HTTP/2 pseudo-headers
  • fresh assertion-quality audit completed

Closes #109

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: tabName field declared as optional in JSON Schema but required at runtime

1 participant