Skip to content

feat(cli): markkit mcp stdio server exposing the markkit tool - #41

Merged
chaliy merged 17 commits into
mainfrom
claude/project-thread-mwewa8
Oct 27, 2026
Merged

chaliy merged 17 commits into
mainfrom
claude/project-thread-mwewa8

Conversation

@chaliy

@chaliy chaliy commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Requested by Михайло · project thread

What changed

New markkit mcp subcommand: a Model Context Protocol server over stdio that exposes the markkit tool (MarkkitTool) to MCP clients (Claude Code, Claude Desktop, Cursor, etc.).

  • Methods: initialize (negotiates 2025-06-18 / 2025-03-26 / 2024-11-05), ping, tools/list, tools/call; notifications get no reply.
  • tools/call returns the tool result as text content plus structuredContent; bad arguments and extraction failures come back as isError: true results with the localized message, internal errors go to stderr only.
  • Flags: --no-url (offline, url source removed from the schema), --max-size, --max-output-chars, --main-content, --locale.
  • Each stdin line is capped (base64 of --max-size + 1 MiB); oversized lines are drained without buffering and answered with -32700, session continues.
  • URL calls keep the core SSRF guard.

Client config: {"mcpServers": {"markkit": {"command": "markkit", "args": ["mcp"]}}}

Docs: new knowledge/integrations/mcp-server.md, threat-model attack-surface row for MCP messages, README, CHANGELOG, log.

Why

Roadmap initiative 8 ("tool - yes, mcp server - very optional"). Lets any MCP client use markkit with no glue code, built on the tool contract from #19.

Before / After

Before: no MCP entry point; markkit mcp is an unknown subcommand.

After:

$ printf '%s\n' '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18"}}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"markkit","arguments":{"html":"<h1>Smoke</h1><p>ok</p>"}}}' | markkit mcp
{"id":1,"jsonrpc":"2.0","result":{"capabilities":{"tools":{"listChanged":false}},"instructions":"markkit: converts web pages ...","protocolVersion":"2025-06-18","serverInfo":{...}}}
{"id":2,"jsonrpc":"2.0","result":{"content":[{"text":"{\"format\":\"html\",\"markdown\":\"# Smoke\\n\\nok\\n\",...}","type":"text"}],"isError":false,"structuredContent":{...}}}

Tests: 10 unit tests in mcp.rs + 3 end-to-end tests spawning the binary (tests/mcp_integration.rs), incl. metadata-address SSRF block, --no-url, malformed/oversized messages. cargo test --workspace, clippy -D warnings, fmt, check-okf all pass locally.

Risk

  • Low: additive subcommand; markkit-cli now enables markkit's tool feature (adds tower/base64 to the CLI build only).
  • Untrusted stdin is bounded per line and requests are sequential.

Checklist

  • Tests added or updated
  • Backward compatibility considered

chaliy added 13 commits October 26, 2026 23:32
Opt-in `tool` feature adds markkit::tool: MarkkitToolBuilder -> MarkkitTool
-> single-use ToolExecution, mirroring bashkit's tool module. One call
converts a url, html or base64 document to Markdown; args validated before
execution, base64 bounded before decode, URL via the SSRF guard, output
capped by max_output_chars. Adds Markkit::extract_url_document.
wasm-bindgen build of markkit (html, docx, spreadsheet, tool) for
wasm32-unknown-unknown: single-threaded, no COOP/COEP, no URL fetching.
Markkit class with validated camelCase options plus MarkkitTool. Node
tests, CI job gating Check, and an OIDC npm publisher.
Node functions take an optional trailing MarkkitOptions object with every
builder field plus URL policy (allowPrivateNetworks, allowedHosts,
maxRedirects, maxProcessingSecs); same camelCase shape as the WASM package.
Adds extractDocument/extractDocumentSync with title, format, warnings and
stats, and node --test binding tests in js.yml.
@chaliy chaliy self-assigned this Oct 27, 2026
@chaliy
chaliy merged commit 6414478 into main Oct 27, 2026
11 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