Skip to content

feat(mcp): add structured tool metadata#657

Merged
DeusData merged 9 commits into
mainfrom
feat/mcp-protocol-2025-11-25
Jun 28, 2026
Merged

feat(mcp): add structured tool metadata#657
DeusData merged 9 commits into
mainfrom
feat/mcp-protocol-2025-11-25

Conversation

@DeusData

@DeusData DeusData commented Jun 27, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add latest MCP tool metadata by emitting title and broad object outputSchema for every tool, and explicitly declaring capabilities.tools.listChanged=false during initialization.
  • Add JSON-RPC tools/list cursor pagination with nextCursor, while keeping the internal all-tools list helper intact.
  • Add structuredContent for successful tool results whose text payload is a JSON object, while preserving the existing serialized JSON text block for backwards compatibility.
  • Fix notifications/cancelled handling to cancel only when params.requestId matches the active JSON-RPC request id, including string ids.
  • Add local-only operational logs for the MCP stdio server and graph UI HTTP server: request event, method, status, duration, and byte counts.
  • Add graph UI stability fixes from open issues: cap large graph rendering, avoid high-DPI WebGL/MSAA black-canvas failures, surface truncation to users, and resolve the UI index subprocess when the binary was launched from PATH.
  • Add graph UI UX/i18n fixes: local en/zh message catalog, Accept-Language detection, config set ui-lang, non-ASCII project-name encoding, optional index project-name override, custom path entry, root-drive buttons, folder filtering, keyboard navigation, and per-row quick indexing.

Protocol Gap Analysis

Official MCP currently redirects /specification to version 2025-11-25, marked latest:
https://modelcontextprotocol.io/specification/2025-11-25

Implemented in this PR:

Remaining gaps after this PR:

  • Network MCP transports remain intentionally out of scope. This binary remains local/stdio-first for MCP protocol handling in this PR.
  • Tool definitions still do not expose annotations, icons, or task execution metadata.
  • Server features are still tools-only: no prompts/resources/completions/logging utilities are exposed as MCP capabilities.
  • Client-facing features such as roots, sampling, and elicitation are not requested by this server today; future support should be deliberate because they add security/consent surface.

Local Logging Design

  • Logs are local process output only: stderr plus the optional in-process graph UI ring sink.
  • No log upload, network sink, or managed log-file writer is introduced.
  • CBM_LOG_FORMAT=text|json is explicit-only. Unset format env keeps the current local format.
  • JSON logs use the same local schema as text logs: level, event, and caller-provided key/value fields.
  • Text logs sanitize control characters to prevent multi-line/log-injection records.
  • MCP request logs include protocol, method, optional tool, status, and duration. Tool params, request bodies, headers, tokens, and secrets are deliberately not logged.
  • Graph UI HTTP access logs include component, method, query-stripped path, status, duration, request bytes, and response bytes. Query strings and fragments are deliberately stripped before logging.
  • Level mapping for HTTP operations: 2xx/3xx at info, 4xx at warn, 5xx at error.

Graph UI Issue Analysis

Queried the open UX/UI/search issue set and targeted the highest stability and adoption blockers first.

Implemented in this PR:

Open follow-up areas intentionally left outside this PR:

  • Watcher/config-ignore UX work remains deferred.
  • Add a --host parameter for UI #229 host binding remains deferred because it changes the UI server's local-only security posture and should land as an explicit opt-in design.

Stability Impact

  • The main stability win from the protocol/logging work is local observability: MCP and graph UI operations now have request-level timing/status signals without requiring debug logging or protocol stdout pollution.
  • MCP stdout remains reserved for JSON-RPC; operational logs still go to stderr.
  • JSON formatting is available only as a local structured format while preserving current local text logs.
  • Redaction guards cover the highest-risk path: MCP params and HTTP query values containing token=secret must not appear in logs.
  • The graph UI no longer attempts to lay out or render 50k-node payloads by default, avoiding the browser-freeze and process-kill class of failures while still reporting total graph size.
  • The high-DPI canvas path now avoids the renderbuffer allocation failure reported on large displays.
  • The i18n path is local only: /api/ui-config reads local config and request headers, and the frontend uses a bundled local message catalog.
  • Non-ASCII project-name encoding avoids lossy CJK path conversion while keeping project DB names portable and validator-safe.

Tests

  • PASS: make -B -j4 -f Makefile.cbm build/c/test-runner after merging main to refresh the LSP amalgamation object.
  • PASS: make -j4 -f Makefile.cbm build/c/test-runner before the main merge.
  • PASS: build/c/test-runner str_util fqn mcp ui cli
  • PASS: build/c/test-runner httpd outside the sandbox because localhost bind is blocked in the sandbox.
  • PASS: npm run test in graph-ui
  • PASS: npm run build in graph-ui (Vite emits the existing large chunk warning)
  • PASS: log suite slice via build/c/test-runner | awk 'flag && /^=== str_util ===/{exit} /^=== log ===/{flag=1} flag{print}'
  • PASS: MCP suite slice via build/c/test-runner | awk 'flag && /^=== language ===/{exit} /^=== mcp ===/{flag=1} flag{print}'
  • PASS: HTTP suite slice via build/c/test-runner | awk 'flag && /^=== security ===/{exit} /^=== httpd ===/{flag=1} flag{print}' outside the sandbox because localhost bind is blocked in the sandbox.
  • PASS: clang-format --dry-run -Werror src/foundation/log.c src/foundation/log.h tests/test_log.c tests/test_httpd.c
  • PASS: clang-format --dry-run -Werror -lines=416:438 tests/test_mcp.c
  • PASS: git diff --check
  • BLOCKED: make -j4 -f Makefile.cbm test currently fails outside this change with offline/graph-dump failures (4675 passed, 836 failed, including pipeline.err phase=dump, no graph DB, and Could not resolve host: github.com).
  • BLOCKED: scripts/lint.sh currently fails outside this change on existing clang-tidy findings in files such as internal/cbm/cbm.c, src/store/store.c, src/watcher/watcher.c, and src/pipeline/pass_lsp_cross.h. The touched source formatting check passes.

DeusData added 9 commits June 28, 2026 01:37
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
The CI lint gate (scripts/lint.sh --ci, clang-format-20) flagged 7 files whose
new lines were not run through the project formatter. Reformat only those lines
(line wrapping / continuation alignment) — no behavior change.

Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
@DeusData DeusData merged commit 4ab00df into main Jun 28, 2026
13 checks passed
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