77b9b6a465
Make the agent-facing contract uniform across the whole surface: - cobra parse errors (unknown flag, arg-count) emit the JSON envelope by default, not bare prose — via a single DefaultFormatMode shared by the early resolver and ResolveDefault. - a malformed --jq is input.invalid_argument (exit 5), not internal.error. - destructive-confirmation messages name the real operation (edit/remove, not a hardcoded "delete"). - `doc wait` emits one envelope (Silent failure, no contradictory stderr); completed marshals as [] not null. - WEKNORA_AGENT_HELP covers every leaf command, enforced by a coverage drift guard; a sibling guard enforces --dry-run on every mutation. - `search docs`/`search chunks` resolve --kb through the same flag→env→project-link chain as `doc list`/`chat` (no longer a hard --kb requirement); a linked dir or WEKNORA_KB_ID now works without --kb, and an unresolved KB is local.kb_id_required (exit 1). The destructive `doc delete --all` keeps its explicit-only rule. - exit-code and batch/wait ok-semantics documented in the shared skill, README, and AGENTS.md.
59 lines
2.0 KiB
Go
59 lines
2.0 KiB
Go
package mcpcmd
|
|
|
|
import (
|
|
"github.com/spf13/cobra"
|
|
|
|
"github.com/Tencent/WeKnora/cli/internal/cmdutil"
|
|
mcpserver "github.com/Tencent/WeKnora/cli/internal/mcp"
|
|
)
|
|
|
|
// NewCmdServe builds `weknora mcp serve`. Currently stdio-only; HTTP
|
|
// (streamable / SSE) transports may be added later.
|
|
func NewCmdServe(f *cmdutil.Factory) *cobra.Command {
|
|
cmd := &cobra.Command{
|
|
Use: "serve",
|
|
Short: "Run an MCP server over stdio",
|
|
Long: `Speaks JSON-RPC 2.0 on stdin/stdout to an MCP client. Logs go to
|
|
stderr; the data channel is reserved for protocol traffic.
|
|
|
|
Authentication is inherited from the active profile (or --profile). The
|
|
server eagerly resolves the SDK client at startup - if no profile is
|
|
configured, the process exits with auth.unauthenticated before any MCP
|
|
handshake. This way an IDE-side agent sees a clear failure mode rather
|
|
than a server that handshakes successfully then errors on every tool.
|
|
|
|
To register with your MCP client, add an entry pointing at this binary
|
|
under "mcpServers":
|
|
|
|
{
|
|
"mcpServers": {
|
|
"weknora": {
|
|
"command": "weknora",
|
|
"args": ["mcp", "serve"]
|
|
}
|
|
}
|
|
}
|
|
|
|
Consult your MCP client's documentation for the exact config-file location.`,
|
|
Args: cobra.NoArgs,
|
|
RunE: func(c *cobra.Command, _ []string) error {
|
|
// Eagerly construct the SDK client. Surfaces auth /
|
|
// configuration problems before any MCP handshake.
|
|
cli, err := f.Client()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return mcpserver.RunStdio(c.Context(), cli)
|
|
},
|
|
}
|
|
cmdutil.SetAgentHelp(cmd, cmdutil.AgentHelp{
|
|
UsedFor: "run weknora as a long-lived MCP (Model Context Protocol) server over stdio for an IDE/host agent",
|
|
Output: "no stdout payload (JSON-RPC 2.0 protocol traffic); logs go to stderr",
|
|
Warnings: []string{
|
|
"this is a long-running stdio server, not a one-shot command — register it in your MCP client (command: weknora, args: [mcp, serve])",
|
|
"exits with auth.unauthenticated at startup if no profile is configured",
|
|
},
|
|
})
|
|
return cmd
|
|
}
|