Skip to content

feat(den-mcp): expose bounded input schemas in capability search and refuse un-constructible executes#2758

Open
benjaminshafii wants to merge 1 commit into
devfrom
feat/mcp-search-input-schema
Open

feat(den-mcp): expose bounded input schemas in capability search and refuse un-constructible executes#2758
benjaminshafii wants to merge 1 commit into
devfrom
feat/mcp-search-input-schema

Conversation

@benjaminshafii

Copy link
Copy Markdown
Member

Summary

search_capabilities on /mcp/agent returned external MCP tool matches with pathParams: [], queryParams: [], hasBody: true — the live inputSchema (which listExternalMcpTools already fetches, and which the admin route /v1/mcp-connections/:id/tools already returns) was discarded. The calling model had to guess tool arguments, producing empty/garbage payload calls at providers (the SyntaxError: Empty JSON string class of failures seen in an enterprise ServiceNow debugging session).

What changed

  • inputSummary on external tool matches (searchExternalCapabilities): a bounded rendering of the tool's JSON schema — { required, properties: { name: { type, description, enum } }, truncated? }:
    • caps: 24 properties (required-first, rest alphabetical), 120-char descriptions, 8 enum values, ~1.5KB serialized total (shrinks property list until under budget); truncated: true whenever anything was cut;
    • shallow rendering: nested objects → "object", arrays → "array<primitive>"/"array"; defensive parsing with type guards throughout.
  • schemaHash: sha256 of the recursively key-sorted schema JSON, first 12 hex chars — detects provider schema drift between search and execute.
  • Execute guard: executeExternalCapability with an empty args object now pre-checks the live tool schema; if the tool declares non-empty required, it returns a structured missing_required_arguments error naming the fields and carrying inputSummary + schemaHash instead of forwarding an empty payload to the provider. The pre-check is best-effort (discovery failure falls through to the normal call path) and is skipped entirely when args are non-empty — zero added latency on the happy path.
  • search_capabilities tool description mentions inputSummary.

Testing

  • pnpm --filter @openwork-ee/den-api exec bun test test/external-capabilities-input-schema.test.ts5 pass (summary bounding + truncation flag, hash stability across key order, empty-args refusal with required fields and no provider call, empty-args passthrough when nothing required, non-empty args skip the pre-check).
  • pnpm --filter @openwork-ee/den-api exec bun test test/external-capabilities-search-divergence.test.ts17 pass, 0 fail (unchanged behavior preserved).
  • pnpm --filter @openwork-ee/den-api exec tsc --noEmit — clean.
  • Results reproduced independently by a second run after implementation.

No video/fraimz attached: Den API/MCP surface change covered by the unit tests above. Reviewer repro: connect any external MCP whose tool declares required fields, run search_capabilities (observe inputSummary/schemaHash on the match), then execute_capability with an empty body (observe missing_required_arguments naming the fields, provider untouched).

Notes

@vercel

vercel Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
openwork-app Ready Ready Preview, Comment Jul 14, 2026 8:52pm
openwork-den Ready Ready Preview, Comment Jul 14, 2026 8:52pm
openwork-den-worker-proxy Ready Ready Preview, Comment Jul 14, 2026 8:52pm
openwork-landing Ready Ready Preview, Comment, Open in v0 Jul 14, 2026 8:52pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
openwork-diagnostics Skipped Skipped Jul 14, 2026 8:52pm

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.

1 participant