mateclaw/mateclaw-server
倪程伟 758bdbb94b
feat(mcp): STDIO MCP server 透传认证用户身份(opt-in per server) (#460)
* feat(mcp): forward authenticated user identity to opt-in STDIO MCP servers

A STDIO MCP server is one shared subprocess per configuration; its env is fixed
at spawn and STDIO has no per-request header channel, so per-user identity must
travel in-band with each tool call. Previously nothing carried it, so an MCP
server could not call its downstream REST backend on behalf of the acting user.

Inject the authenticated username (from ToolExecutionContext) into each tool
call's JSON arguments under the reserved key `__mateclaw_user__`, for servers an
operator explicitly opts in via `mateclaw.mcp.identity-forward.servers` (by name
or id). The MCP server reads/strips it and forwards on-behalf-of alongside its
own backend API key.

- McpIdentityForwardProperties: per-server opt-in allowlist (name or id).
- IdentityForwardingToolCallback: wraps an MCP callback, merges the username
  into the args; injected by trusted code, overwrites any LLM-supplied value
  (no spoofing); forwards unchanged when there is no user or args aren't an
  object/are malformed.
- McpClientManager: captures server names; wraps opt-in servers' callbacks
  inside the prefix wrapper (so name-prefixing / return-direct still see the raw
  delegate). Non-opt-in servers are untouched — username never leaks to them.
- Tests: injection, LLM-value overwrite, empty/non-object/malformed inputs,
  no-user passthrough, opt-in matching by id/name.
- Docs (zh/en mcp.md): opt-in config, `__mateclaw_user__` contract, FastMCP
  Python skeleton, trust model.

Default off (empty allowlist) — zero behavior change for existing servers.
Plaintext username suits a trusted-network REST backend keyed by an API key;
a signed short-lived token is noted as the stronger-isolation follow-up.

* feat(mcp): add signed-token trust model for MCP identity forwarding

Plaintext username forwarding makes the REST backend trust an unverifiable
assertion from the (shared, LLM-adjacent) MCP service — a confused-deputy model.
Add an opt-in signed-token mode so identity crosses the trust boundary as a
short-lived RS256 JWT the backend can verify with a public key.

- McpIdentityForwardProperties: nested `token` config (enabled, issuer,
  ttl-seconds, key-id, private-key-pem, audiences) + USER_ARG/TOKEN_ARG keys.
- McpIdentityForwardService: resolves the injection — plaintext username
  (__mateclaw_user__) when token mode off, else a minted RS256 JWT
  (__mateclaw_token__) with sub=user, aud=server, short exp, jti. Lazy key
  parse; fail-closed when token mode is on but the key is missing/unparseable
  (no silent downgrade to plaintext). Signs with MateClaw's private key so the
  backend only needs the public key (cannot mint/impersonate).
- IdentityForwardingToolCallback: now delegates the what-to-inject decision to
  the service (keyed by per-server audience); static withClaim() keeps the
  JSON-merge logic (overwrites LLM-supplied key, leaves non-object/malformed
  args untouched).
- McpClientManager: injects the service; passes service + audience through the
  wrap path for opt-in servers only.
- Tests: token mint+verify (with an in-test RSA keypair, asserting sub/aud/iss/
  exp/jti), plaintext mode, no-user and no-key fail-closed, audience resolution.
- Docs (zh/en): token config, key generation, claims, REST-side verification
  example, public-key distribution + JWKS-endpoint follow-up.

Default unchanged: token.enabled=false → plaintext (back-compat); whole feature
still opt-in per server and off by default.
2026-07-01 18:51:08 +08:00
..
src feat(mcp): STDIO MCP server 透传认证用户身份(opt-in per server) (#460) 2026-07-01 18:51:08 +08:00
Dockerfile fix(docker): honor SPRING_PROFILES_ACTIVE instead of pinning the mysql profile 2026-06-14 16:47:16 +08:00
pom.xml fix(db): make KingbaseES driver opt-in and restore default SSRF guard 2026-06-14 10:34:35 +08:00
settings.xml build(maven): declare US + CN repositories in pom.xml, drop opaque mirror 2026-04-25 09:56:17 +08:00