P2: Complete MCP output, errors, discovery and remote sign-in interoperability #836

Open
opened 2026-10-02 13:23:05 +00:00 by kayg · 5 comments
Owner

Research follow-up under #484. Source snapshot: c4a61e8cf090170f35b1bed3350d9de20c83ecd5.

Generated MCP actions reuse the right API middleware and bounded dispatch. Their wire and discovery contracts need a focused interoperability slice.

Evidence in crates/calternal-server/src/mcp.rs:

  • registered_tool_router returns JSON in ContentBlock::text.
  • generated_tool_definitions has no output schema.
  • dispatch_api turns domain HTTP failures into invalid-params/internal JSON-RPC errors.
  • list_tools ignores cursors and returns the full list. Admin tools are filtered; other unsupported tools remain visible to read-only/Home-limited credentials.
  • Lists are private with zero lifetime. Four protocol revisions are supported.
  • get_info advertises tools only. Remote protected-resource authorization metadata is not supplied by this module.

Acceptance:

  1. Generate structured output and declared result schemas; retain text compatibility for older clients.
  2. Use failed tool results for domain errors and protocol errors for invalid RPC; carry safe typed details.
  3. Page deterministic discovery and filter it by current grants where reliable. Keep the actual route checks authoritative. Coordinate scoped caching with #515.
  4. Support interoperable remote sign-in discovery and audience-bound, scoped tokens through the existing auth model. A configured upstream sign-in provider is not this authorization service.
  5. Keep current and older client tests. Resources, prompts and negotiated long-work task handles are optional later improvements; ordinary job polling remains usable. Do not add a second writer or job executor.

Related #484, #204, #630 and #491. This issue does not assert an authorization bypass or require optional protocol features for parity.

Full evidence and decisions: docs/research/agent-surfaces.md on branch job/research-surfaces. No runtime change was made by the research job.

Research follow-up under #484. Source snapshot: `c4a61e8cf090170f35b1bed3350d9de20c83ecd5`. Generated MCP actions reuse the right API middleware and bounded dispatch. Their wire and discovery contracts need a focused interoperability slice. Evidence in `crates/calternal-server/src/mcp.rs`: - `registered_tool_router` returns JSON in `ContentBlock::text`. - `generated_tool_definitions` has no output schema. - `dispatch_api` turns domain HTTP failures into invalid-params/internal JSON-RPC errors. - `list_tools` ignores cursors and returns the full list. Admin tools are filtered; other unsupported tools remain visible to read-only/Home-limited credentials. - Lists are private with zero lifetime. Four protocol revisions are supported. - `get_info` advertises tools only. Remote protected-resource authorization metadata is not supplied by this module. Acceptance: 1. Generate structured output and declared result schemas; retain text compatibility for older clients. 2. Use failed tool results for domain errors and protocol errors for invalid RPC; carry safe typed details. 3. Page deterministic discovery and filter it by current grants where reliable. Keep the actual route checks authoritative. Coordinate scoped caching with #515. 4. Support interoperable remote sign-in discovery and audience-bound, scoped tokens through the existing auth model. A configured upstream sign-in provider is not this authorization service. 5. Keep current and older client tests. Resources, prompts and negotiated long-work task handles are optional later improvements; ordinary job polling remains usable. Do not add a second writer or job executor. Related #484, #204, #630 and #491. This issue does not assert an authorization bypass or require optional protocol features for parity. Full evidence and decisions: `docs/research/agent-surfaces.md` on branch `job/research-surfaces`. No runtime change was made by the research job.
Author
Owner

Started on job/surfaces-p2 at base c4a61e8cf0; implementing MCP output schemas, typed errors, paged grant-aware discovery, and remote sign-in interop.

Started on job/surfaces-p2 at base c4a61e8cf090170f35b1bed3350d9de20c83ecd5; implementing MCP output schemas, typed errors, paged grant-aware discovery, and remote sign-in interop.
Author
Owner

Confirmed in the c4a61e8cf baseline: crates/calternal-server/src/mcp.rs builds generated definitions from input_schema only, returns API 4xx/5xx through ErrorData, and ignores the tools/list cursor while filtering only admin actions. require_mcp_credential accepts bearer credentials but has no protected-resource discovery or OAuth authorization path. Route checks remain authoritative; this is an interoperability gap, not an asserted bypass.

Confirmed in the c4a61e8cf baseline: crates/calternal-server/src/mcp.rs builds generated definitions from input_schema only, returns API 4xx/5xx through ErrorData, and ignores the tools/list cursor while filtering only admin actions. require_mcp_credential accepts bearer credentials but has no protected-resource discovery or OAuth authorization path. Route checks remain authoritative; this is an interoperability gap, not an asserted bypass.
Author
Owner

Stopped at the four-hour limit in the job instructions.

Branch: job/surfaces-p2
Head: 6704892de9

Work completed:

  • Merged origin/job/research-surfaces.
  • Added two test-first regressions in crates/calternal-server/src/mcp.rs for generated output schemas and structured API errors. These changes are uncommitted.
  • Confirmed baseline gaps in generated output schemas, API error mapping, tools/list pagination, and OAuth protected-resource discovery. The earlier comments on this issue contain the evidence.

Verification:

  • Started cargo test -p calternal-server mcp::tests:: with CARGO_PROFILE_DEV_DEBUG=line-tables-only, CARGO_INCREMENTAL=0, TMPDIR=$PWD/target/tmp, and CARGO_BUILD_JOBS=4.
  • The first cold dependency build ran for 4h36 and was interrupted before the test binary finished. No test result or exit status was produced.
  • cargo fmt --check, clippy, final crate tests, adversarial probes, MCP Inspector interop, performance measurement, final origin/dev merge, and cleanup were not run.

Remaining: implement and commit #836 result schemas, structured errors, grant-aware paged discovery, OAuth metadata and audience-bound scoped sign-in; add endpoint adversarial coverage; complete focused gates and real-server/MCP-client verification. The working tree currently has only the uncommitted test changes above.

Stopped at the four-hour limit in the job instructions. Branch: job/surfaces-p2 Head: 6704892de93aec788608a8dc03f04ee75d0ed69f Work completed: - Merged origin/job/research-surfaces. - Added two test-first regressions in crates/calternal-server/src/mcp.rs for generated output schemas and structured API errors. These changes are uncommitted. - Confirmed baseline gaps in generated output schemas, API error mapping, tools/list pagination, and OAuth protected-resource discovery. The earlier comments on this issue contain the evidence. Verification: - Started `cargo test -p calternal-server mcp::tests::` with CARGO_PROFILE_DEV_DEBUG=line-tables-only, CARGO_INCREMENTAL=0, TMPDIR=$PWD/target/tmp, and CARGO_BUILD_JOBS=4. - The first cold dependency build ran for 4h36 and was interrupted before the test binary finished. No test result or exit status was produced. - `cargo fmt --check`, clippy, final crate tests, adversarial probes, MCP Inspector interop, performance measurement, final origin/dev merge, and cleanup were not run. Remaining: implement and commit #836 result schemas, structured errors, grant-aware paged discovery, OAuth metadata and audience-bound scoped sign-in; add endpoint adversarial coverage; complete focused gates and real-server/MCP-client verification. The working tree currently has only the uncommitted test changes above.
Author
Owner

Progress from job surfaces-p2 (branch job/surfaces-p2, commit 034cc12e8). Not merged yet.

Done (acceptance 1 and 2, generated tools):

  • Each generated MCP tool declares an outputSchema. A JSON route uses its OpenAPI result. A route that returns an array or a string puts the value in result, because MCP structured content must be an object. Text, byte and event tools declare the shared {headers, complete, text|base64|events} envelope. The schema drops required lists and closed objects, so a missing optional field cannot make a strict client reject a valid reply.
  • Results carry structuredContent and the same JSON as text content, so older clients keep working. A route without a declared JSON result keeps text-only output.
  • An HTTP failure from the route is now a failed tool result (isError: true) with {error: {status, code, message, details?, retry_after?}, payload?}. code is the API error code, or a status name such as conflict. payload keeps typed failure bodies (for example an Undo conflict report). Gateway HTML is never echoed. Invalid tool input stays a JSON-RPC invalid_params error.
  • Tests: generated_tools_declare_object_result_schemas, api_failures_become_structured_tool_errors (replace the unverified WIP tests, which expected an array root schema that MCP does not allow). cargo test -p calternal-server mcp::tests:: → 12 passed.

Not done yet:

  • Legacy hand-written tools still return JSON-RPC errors for HTTP failures.
  • Acceptance 3 (paged, grant-filtered discovery), 4 (remote sign-in discovery and audience-bound tokens) and 5 (older-client matrix tests) are open.
Progress from job surfaces-p2 (branch `job/surfaces-p2`, commit 034cc12e8). Not merged yet. Done (acceptance 1 and 2, generated tools): - Each generated MCP tool declares an `outputSchema`. A JSON route uses its OpenAPI result. A route that returns an array or a string puts the value in `result`, because MCP structured content must be an object. Text, byte and event tools declare the shared `{headers, complete, text|base64|events}` envelope. The schema drops `required` lists and closed objects, so a missing optional field cannot make a strict client reject a valid reply. - Results carry `structuredContent` and the same JSON as text content, so older clients keep working. A route without a declared JSON result keeps text-only output. - An HTTP failure from the route is now a failed tool result (`isError: true`) with `{error: {status, code, message, details?, retry_after?}, payload?}`. `code` is the API error code, or a status name such as `conflict`. `payload` keeps typed failure bodies (for example an Undo conflict report). Gateway HTML is never echoed. Invalid tool input stays a JSON-RPC `invalid_params` error. - Tests: `generated_tools_declare_object_result_schemas`, `api_failures_become_structured_tool_errors` (replace the unverified WIP tests, which expected an array root schema that MCP does not allow). `cargo test -p calternal-server mcp::tests::` → 12 passed. Not done yet: - Legacy hand-written tools still return JSON-RPC errors for HTTP failures. - Acceptance 3 (paged, grant-filtered discovery), 4 (remote sign-in discovery and audience-bound tokens) and 5 (older-client matrix tests) are open.
Author
Owner

Starting the follow-up slices on job/surfaces-p2 at a75e6f958fdc878160052fcb2c4fa1581d14729d. The branch base is c4faf184df726a9375ae0c13bdfb6018ac2cf57e; local origin/dev is 48c94c9776660cee105be86c5a6ace90dd425367 and will be merged once before final gates. The #836 MCP implementation and #838 CLI foundation are already committed on this branch. I am validating those slices and continuing #837 and #839–#843 with focused tests.

Starting the follow-up slices on `job/surfaces-p2` at `a75e6f958fdc878160052fcb2c4fa1581d14729d`. The branch base is `c4faf184df726a9375ae0c13bdfb6018ac2cf57e`; local `origin/dev` is `48c94c9776660cee105be86c5a6ace90dd425367` and will be merged once before final gates. The #836 MCP implementation and #838 CLI foundation are already committed on this branch. I am validating those slices and continuing #837 and #839–#843 with focused tests.
Sign in to join this conversation.
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal#836
No description provided.